锁屏壁纸 的保存位置在/data/system/users/0
root@**:/data/system/users/0 # ls -la
-rw-rw---- system system 73728 1970-01-14 09:26 accounts.db
-rw------- system system 8720 1970-01-14 09:26 accounts.db-journal
-rw------- system system 406 2017-03-03 18:52 appwidgets.xml
drwx------ system system 1970-01-14 09:26 fpdata
-rwx------ system system 1525422 2017-03-06 11:57 lock_wallpaper
-rw------- system system 149 2017-03-06 11:57 lock_wallpaper_info.xml
-rw------- system system 1550 2017-03-05 16:56 notificationSubscript.xml
-rw-rw---- system system 4153 2017-03-06 15:09 package-restrictions.xml
drwxrwx--x system system 1970-01-14 09:26 registered_services
-rw------- system system 16990 2017-03-06 14:06 runtime-permissions.xml
-rw------- system system 7032 2017-03-06 09:07 settings_global.xml
-rw------- system system 5090 2017-03-06 09:07 settings_secure.xml
-rw------- system system 6148 2017-03-06 15:11 settings_system.xml
-rwx------ system system 1525422 2017-03-06 11:57 wallpaper
-rw------- system system 99 2017-03-06 11:57 wallpaper_info.xml
root@**:/data/system/users/0 # pwd
/data/system/users/0
详http://blog.csdn.net/sssheiye/article/details/52052544
gallery入口选择图片设置为锁屏壁纸
方案:
1:在data/system/users/0/这个目录建立一个存放锁屏图片资源的文件lockwallpaper
2:将gallery选择的图片保存当锁屏时调用该保存的图片资源
3:将图片资源作为SystemUI中NotificationPanelView的背景
第一,二步:放在一块讲
我们知道桌面壁纸是把图片存在/data/system/users/0/wallpaper 里面,所以我们要想办法在这个目录建立一个lockwallpaper。
实现相关代码路径:
frameworks/base/core/Java/Android/app/WallpaperManager.java
frameworks/base/core/java/android/app/IWallpaperManagerCallback.aidl
frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
- frameworks/base/core/java/android/app/WallpaperManager.java
- public class WallpaperManager {
- private static String TAG = "WallpaperManager";
- ... ...
- //{hss add for lockscreen wallpaper start
- private static final String WALLPAPERDIR = "/data/system/users/0";
- static final String LOCKWALLPAPERNAME = "lockwallpaper";
- private final Context mContext;
- <... ... ...>
- /**
- * Retrieve the current system wallpaper; if
- * no wallpaper is set, the system built-in static wallpaper is returned.
- * This is returned as an
- * abstract Drawable that you can install in a View to display whatever
- * wallpaper the user has currently set.
- *
- * @return Returns a Drawable object that will draw the wallpaper.
- */
- public Drawable getDrawable() {//获取wallpaper资源
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
- if (bm != null) {
- Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
- dr.setDither(false);
- return dr;
- }
- return null;
- }
- //hss add for lockscreen wallpaper start 模仿桌面壁纸获取Drrawable资源
- public Drawable getLockScreenDrawable() {
- Bitmap bm = sGlobals.getCurrentLockScreenWallpaperLocked(mContext);
- if (bm != null) {
- Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
- dr.setDither(false);
- return dr;
- }
- return null;
- }
- <... ... ...>
- static class Globals extends IWallpaperManagerCallback.Stub {//内部类
- private IWallpaperManager mService;
- private Bitmap mWallpaper;
- private Bitmap mDefaultWallpaper;
- private static final int MSG_CLEAR_WALLPAPER = 1;
- <pre name="code" class="java"><... ... ...>
- private Bitmap getCurrentWallpaperLocked(Context context) {//hss find 获取当前的wallpaper
- if (mService == null) {
- Log.w(TAG, "WallpaperService not running");
- return null;
- }
- try {
- Bundle params = new Bundle();
- ParcelFileDescriptor fd = mService.getWallpaper(this, params);
- if (fd != null) {
- try {
- BitmapFactory.Options options = new BitmapFactory.Options();
- //M: Enable PQ support for all static wallpaper bitmap decoding
- options.inPostProc = true;
- options.inPostProcFlag = 1;
- return BitmapFactory.decodeFileDescriptor(
- fd.getFileDescriptor(), null, options);
- } catch (OutOfMemoryError e) {
- Log.w(TAG, "Can't decode file", e);
- } finally {
- try {
- fd.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- } catch (RemoteException e) {
- // Ignore
- }
- return null;
- }
- //hss add for lockscreen wallpaper start 模范获取桌面壁纸协议恶搞获取当前的lockscreen wallpaper
- public Bitmap getCurrentLockScreenWallpaperLocked(Context context) {// 获取当前的lockscreen wallpaper
- if (mService == null) {
- Log.w(TAG, "WallpaperService not running");
- return null;
- }
- try {
- Bundle params = new Bundle();
- ParcelFileDescriptor fd = mService.getLockScreenWallpaper(this, params);//该方法定义在WallpaperManagerService.java
- if (fd != null) {
- try {
- BitmapFactory.Options options = new BitmapFactory.Options();
- //M: Enable PQ support for all static wallpaper bitmap decoding
- options.inPostProc = true;
- options.inPostProcFlag = 1;
- return BitmapFactory.decodeFileDescriptor(
- fd.getFileDescriptor(), null, options);
- } catch (OutOfMemoryError e) {
- Log.w(TAG, "Can't decode file", e);
- } finally {
- try {
- fd.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- } catch (RemoteException e) {
- // Ignore
- }
- return null;
- }
- //hss add for lockscreen wallpaper end
- }
- //这个是存设置桌面壁纸的方法,我们仿照它写一个锁屏壁纸的数据写入setLockScreenStream
- public void setStream(InputStream data) throws IOException {
- if (sGlobals.mService == null) {
- Log.w(TAG, "WallpaperService not running");
- return;
- }
- try {
- ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, mContext.getOpPackageName());
- if (fd == null) {
- return;
- }
- FileOutputStream fos = null;
- try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- setWallpaper(data, fos);
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- } catch (RemoteException e) { // Ignore } } //将选好的图片流写到指定路径
- private void setWallpaper(InputStream data, FileOutputStream fos) throws IOException {
- byte[] buffer = new byte[32768];
- int amt;
- while ((amt=data.read(buffer)) > 0) {
- fos.write(buffer, 0, amt);
- }
- }
- //模仿写一个设置锁屏壁纸,将图片存入到指定路径下
- public void setLockScreenStream(InputStream data) throws IOException {
- if (sGlobals.mService == null) {
- return;
- }
- if(data==null)
- { Log.w(TAG, "hss data==null");
- //模仿桌面壁纸如果图片不存在,就以默认壁纸作为锁屏壁纸来设置
- data=sGlobals.openDefaultWallpaperRes(mContext);
- }
- try {
- ParcelFileDescriptor fd = sGlobals.mService.setLockScreenWallpaper(null,
- mContext.getOpPackageName());//该方法定义在WallpaperManagerService.java
- if (fd == null) {
- Log.w(TAG, "hss fd==null");
- return;
- }
- FileOutputStream fos = null;
- try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- setWallpaper(data, fos);
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- Log.w(TAG, "hss wallpaperpath="+WALLPAPERDIR+"/"+LOCKWALLPAPERNAME);
- }
- }
在WallpaperManager类中,我们按照桌面壁纸方法,添加了三个方法:
得到锁屏壁纸drawable getLockScreenDrawable存壁纸资源 setLockScreenStream真正获取锁屏壁纸资源的方法 getCurrentLockScreenWallpaperLocked 。同时实际的锁屏资源的存取都是通过远程调用WallpaperManagerService.java这个service的两个方法(getLockScreenWallpaper,setLockScreenWallpaper)来实现的。所以我们需要通过aidl来实现。如下在IWallpaperManagerCallback添加两个方法,实现在WallpaperManagerService中添加:
- frameworks/base/core/java/android/app/IWallpaperManagerCallback.aidl
- ** @hide */
- interface IWallpaperManager {
- /**
- * Set the wallpaper.
- */
- ParcelFileDescriptor setWallpaper(String name, in String callingPackage);
- /**
- * Set the lockscreen wallpaper.
- */
- ParcelFileDescriptor setLockScreenWallpaper(String name, in String callingPackage);
- /**
- * Get the wallpaper.
- */
- ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
- out Bundle outParams);
- /**
- * Get the lockscreen wallpaper.
- */
- ParcelFileDescriptor getLockScreenWallpaper(IWallpaperManagerCallback cb,
- out Bundle outParams);
- ... ... ...
- }
在WallpaperManagerService.java中实现
- frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
- public class WallpaperManagerService extends IWallpaperManager.Stub {
- static final String TAG = "WallpaperManagerService";
- static final boolean DEBUG = true;
- final Object mLock = new Object[0];
- ... ...
- //这个是桌面壁纸获取
- public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
- Bundle outParams) {
- synchronized (mLock) {
- // This returns the current user's wallpaper, if called by a system service. Else it
- // returns the wallpaper for the calling user.
- int callingUid = Binder.getCallingUid();
- int wallpaperUserId = 0;
- if (callingUid == android.os.Process.SYSTEM_UID) {
- wallpaperUserId = mCurrentUserId;
- } else {
- wallpaperUserId = UserHandle.getUserId(callingUid);
- }
- WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
- if (wallpaper == null) {
- return null;
- }
- try {
- if (outParams != null) {
- outParams.putInt("width", wallpaper.width);
- outParams.putInt("height", wallpaper.height);
- }
- wallpaper.callbacks.register(cb);
- File f = new File(getWallpaperDir(wallpaperUserId), mWallpaperFileName);
- if (!f.exists()) {
- return null;
- }
- return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
- } catch (FileNotFoundException e) {
- /* Shouldn't happen as we check to see if the file exists */
- Slog.w(TAG, "Error getting wallpaper", e);
- }
- return null;
- }
- }
- //add by hss for lockscreen wallpaper start 仿照桌面壁纸获取写一个获取锁屏壁纸资源
- public ParcelFileDescriptor getLockScreenWallpaper(IWallpaperManagerCallback cb,
- Bundle outParams) {
- synchronized (mLock) {
- // This returns the current user's wallpaper, if called by a system service. Else it
- // returns the wallpaper for the calling user.
- int callingUid = Binder.getCallingUid();
- int wallpaperUserId = 0;
- WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
- if (wallpaper == null) {
- return null;
- }
- try {
- if (outParams != null) {
- outParams.putInt("width", wallpaper.width);
- outParams.putInt("height", wallpaper.height);
- }
- wallpaper.callbacks.register(cb);
- File f = new File(getWallpaperDir(wallpaperUserId), LOCKWALLPAPER);
- if (!f.exists()) {
- return null;
- }
- return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
- } catch (FileNotFoundException e) {
- /* Shouldn't happen as we check to see if the file exists */
- Slog.w(TAG, "Error getting wallpaper", e);
- }
- return null;
- }
- }</span>
- //add by hss for lockscreen wallpaper end
- ... ... ...
- //这个是设置壁纸资源
- public ParcelFileDescriptor setWallpaper(String name, String callingPackage) {//hss find here for set wallpaper
- checkPermission(android.Manifest.permission.SET_WALLPAPER);
- if (!isWallpaperSupported(callingPackage)) {
- return null;
- }
- synchronized (mLock) {
- if (DEBUG) Slog.v(TAG, "setWallpaper");
- // /M: To support Smart Book @ {
- if (isSmartBookSupport()) {
- mHaveUsedSmartBook = false;
- }
- // /@ }
- int userId = UserHandle.getCallingUserId();
- WallpaperData wallpaper = getWallpaperSafeLocked(userId);
- final long ident = Binder.clearCallingIdentity();
- try {
- ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
- if (pfd != null) {
- wallpaper.imageWallpaperPending = true;
- }
- return pfd;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
- ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
- if (name == null) name = "null";
- try {
- File dir = getWallpaperDir(wallpaper.userId);
- if (!dir.exists()) {
- dir.mkdir();
- FileUtils.setPermissions(
- dir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
- Slog.v(TAG, "hss dir.getPath()"+dir.getPath()+"/"+name);
- File file = new File(dir, mWallpaperFileName);
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
- MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
- if (!SELinux.restorecon(file)) {
- return null;
- }
- wallpaper.name = name;
- return fd;
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Error setting wallpaper", e);
- }
- return null;
- }
- //hss add for lockscreenwallpaper start仿照桌面设置壁纸资源写一个设置锁屏壁纸
- public ParcelFileDescriptor setLockScreenWallpaper(String name, String callingPackage) {//hss find here for set wallpaper
- checkPermission(android.Manifest.permission.SET_WALLPAPER);
- if (!isWallpaperSupported(callingPackage)) {
- return null;
- }
- synchronized (mLock) {
- if (DEBUG) Slog.v(TAG, "setLockScreenWallpaper");
- // /M: To support Smart Book @ {
- if (isSmartBookSupport()) {
- mHaveUsedSmartBook = false;
- }
- WallpaperData wallpaper = getWallpaperSafeLocked(0);//userId
- final long ident = Binder.clearCallingIdentity();
- try {
- ParcelFileDescriptor pfd = updateLockScreenWallpaperBitmapLocked(name, wallpaper);
- if (pfd != null) {
- wallpaper.imageWallpaperPending = true;
- }
- return pfd;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
- ParcelFileDescriptor updateLockScreenWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
- if (name == null) name = "";
- try {
- File dir = getWallpaperDir(0);//wallpaper.userId
- if (!dir.exists()) {
- dir.mkdir();
- FileUtils.setPermissions(
- dir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
- File file = new File(dir, LOCKWALLPAPER);
- Slog.v(TAG, "hss file.getPath()"+file.getPath());
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
- MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
- if (!SELinux.restorecon(file)) {
- Slog.v(TAG, "hss return null");
- return null;
- }
- wallpaper.name = name;
- return fd;
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Error setting lockscreenwallpaper", e);
- }
- return null;
- }</span>
- //hss add for lockscreenwallpaper end
- ... ... ...
- }
到此已经可以实现锁屏壁纸的存取了。不过由于android6.0对权限的限制,我们需要在/data/system/users/0/目录创建的lockwallpaper里面写入图片资源还要加下Linux权限
/device/mediatek/common/sepolicy/file_contexts.te
- /data/system/users/[0-9]+/lockwallpaper u:object_r:wallpaper_file:s0
带三步:最后一步就是在systemui中去设置这个壁纸了,也就是NotificationPanelView的背景
- public class NotificationPanelView extends PanelView implements
- ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
- View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
- KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
- HeadsUpManager.OnHeadsUpChangedListener {
- ... ... ...
- public void setBarState(int statusBarState, boolean keyguardFadingAway,
- boolean goingToFullShade) {
- int oldState = mStatusBarState;
- boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
- setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
- setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
- mStatusBarState = statusBarState;
- mKeyguardShowing = keyguardShowing;
- <span style="color:#009900;"> //hss add for lockscreen wallpaper start
- Bitmap bm = getCurrentWallpaperLocked();
- //hss add for lockscreen wallpaper end
- if (bm!=null&&(mStatusBarState == StatusBarState.SHADE_LOCKED || mStatusBarState == StatusBarState.KEYGUARD)) {
- Log.w(TAG, "hss add for getCurrentWallpaperLocked not null...");
- Drawable dr = new BitmapDrawable(mContext.getResources(), generateBitmap(bm, 480, 1280));
- dr.setDither(false);
- setBackground(dr);
- //setBackgroundResource(R.drawable.lockwallpaper);
- } else {
- Log.w(TAG, "hss add for getCurrentWallpaperLocked null...");
- setBackgroundResource(0);
- }
- ///@}
- </span>if (goingToFullShade || (oldState == StatusBarState.KEYGUARD
- && statusBarState == StatusBarState.SHADE_LOCKED)) {
- animateKeyguardStatusBarOut();
- animateHeaderSlidingIn();
- } else if (oldState == StatusBarState.SHADE_LOCKED
- ... ... ...
- }
- ... ... ...
- }