日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 5.1 壁纸路径,RTFSC – Android5.1 壁纸设置流程简析 – RustFisher

發布時間:2023/12/10 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 5.1 壁纸路径,RTFSC – Android5.1 壁纸设置流程简析 – RustFisher 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android5.1 壁紙設置流程淺析

Ubuntu14.04 ?Android5.1 ?Source Insight3

這里只是簡單分析一下5.1里是如何設置壁紙的;這個流程和4.4有一些不同。但基本都是找個地方存放壁紙文件,需要的時候讀取,設置的時候更新

這里只看設置的過程。權當參考。

機器使用launcher3,在桌面上長按,底部顯示設置壁紙的入口。

進入設置壁紙界面,觀察log可知,此界面屬于Trebuchet。也是launcher3

點擊設置壁紙按鈕,發現整個標題欄都有響應。在以下文件中可以找到相關定義:

/*— ↓ — WallpaperPickerActivity.java *********/

//Action bar//Show the custom action bar view

final ActionBar actionBar =getActionBar();

actionBar.setCustomView(R.layout.actionbar_set_wallpaper);

actionBar.getCustomView().setOnClickListener(newView.OnClickListener() {

@Overridepublic voidonClick(View v) {if (mSelectedTile != null) {

WallpaperTileInfo info=(WallpaperTileInfo) mSelectedTile.getTag();

info.onSave(WallpaperPickerActivity.this);

}else{//no tile was selected, so we just finish the activity and go back

setResult(Activity.RESULT_OK);

finish();

}

}

});

mSetWallpaperButton=findViewById(R.id.set_wallpaper_button);/*— ↑ — (packages/apps/Trebuchet/WallpaperPicker/src/com/android/launcher3/) *********/

整個 actionBar都拿來響應點擊。info是 WallpaperTileInfo抽象類的對象,有5個子類。

這樣系統能根據圖片來選擇使用哪一個子類。再調用 onSave方法。以FileWallpaperInfo類為例。

它復寫了 onSave方法

/*— ↓ — WallpaperPickerActivity.java *********/@Overridepublic voidonSave(WallpaperPickerActivity a) {

a.setWallpaper(Uri.fromFile(mFile),true);

}/*— ↑ — (packages/apps/Trebuchet/WallpaperPicker/src/com/android/launcher3/) *********/

因為WallpaperPickerActivity 繼承自 WallpaperCropActivity

setWallpaper方法在 WallpaperCropActivity中找到;傳入了Uri和一個boolean值

/*↓ — WallpaperCropActivity.java *********/

protected void setWallpaper(Uri uri, final booleanfinishActivityWhenDone) {int rotation = getRotationFromExif(this, uri);

BitmapCropTask cropTask= newBitmapCropTask(this, uri, null, rotation, 0, 0, true, false, null);final Point bounds =cropTask.getImageBounds();

Runnable onEndCrop= newRunnable() {public voidrun() {

updateWallpaperDimensions(bounds.x, bounds.y);if(finishActivityWhenDone) {

setResult(Activity.RESULT_OK);

finish();

}

}

};

cropTask.setOnEndRunnable(onEndCrop);

cropTask.setNoCrop(true);

cropTask.execute();

}/*↑ — (packages/apps/trebuchet/wallpaperpicker/src/com/android/launcher3) *********/

以上代碼可以看出,它啟動了一個異步任務 ?BitmapCropTask extends AsyncTask?;把一些列參數都傳入了cropTask

啟動一個線程onEndCrop,等待任務結束

進入BitmapCropTask看,系統做了什么工作

這是setWallpaper使用的構造方法

/*↓ — WallpaperCropActivity.java *********/

publicBitmapCropTask(Context c, Uri inUri,

RectF cropBounds,int rotation, int outWidth, intoutHeight,boolean setWallpaper, booleansaveCroppedBitmap, Runnable onEndRunnable) {

mContext=c;

mInUri=inUri;

init(cropBounds, rotation,

outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);

}//……

private void init(RectF cropBounds, int rotation, int outWidth, intoutHeight,boolean setWallpaper, booleansaveCroppedBitmap, Runnable onEndRunnable) {

Log.d(“rust”,”init after bitmapcroptask”);

mCropBounds=cropBounds;

mRotation= rotation; //傳入各項參數

mOutWidth =outWidth;

mOutHeight=outHeight;

mSetWallpaper=setWallpaper;

mSaveCroppedBitmap=saveCroppedBitmap;

mOnEndRunnable=onEndRunnable;

}//…… 在這里處理任務,啟動 cropBitmap()

@OverrideprotectedBoolean doInBackground(Void… params) {returncropBitmap();

}//……

public booleancropBitmap() {boolean failure = false;

WallpaperManager wallpaperManager= null;if(mSetWallpaper) {

wallpaperManager=WallpaperManager.getInstance(mContext.getApplicationContext());

}if (mSetWallpaper &&mNoCrop) {try{

InputStream is= regenerateInputStream(); //獲得InputStream

if (is != null) {

wallpaperManager.setStream(is);//把is寫進去,從這里進入到wallpaperManager

Utils.closeSilently(is);

}

}catch(IOException e) {

Log.w(LOGTAG,“cannot write stream to wallpaper”, e);

failure= true;

}return !failure;

}else { //順利的話不會進入這里//……//Helper to setup input stream

privateInputStream regenerateInputStream() {if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {

Log.w(LOGTAG,“cannot read original file, no input URI, resource ID, or ” +

“image byte array given”);

}else{try{

String filepath=mInFilePath;if(mInUri != null){

filepath=DrmHelper.getFilePath(mContext, mInUri);

}if(DrmHelper.isDrmFile(filepath)){byte[] bytes =DrmHelper.getDrmImageBytes(filepath);return new ByteArrayInputStream(bytes); //返回一個ByteArray

}/*↑ — (packages/apps/trebuchet/wallpaperpicker/src/com/android/launcher3) *********/

調用了wallpaperManager.setStream(is);進入?WallpaperManager.java?看看

/*↓ — WallpaperManager.java *********/

public void setStream(InputStream data) throws IOException { //luncher3 里直接調用了這個方法

if (sGlobals.mService == null) { //WallpaperCropActivity 調用

Log.w(TAG, “WallpaperService not running”);return;

}try{

ParcelFileDescriptor fd= sGlobals.mService.setWallpaper(null); //利用service得到fd

if (fd == null) { //這里要去WallpaperManagerService里找到對應方法

return;

}

FileOutputStream fos= null;try{

fos= newParcelFileDescriptor.AutoCloseOutputStream(fd);

setWallpaper(data, fos);//寫入壁紙數據

} finally{if (fos != null) {

fos.close();

}

}

}catch(RemoteException e) {//Ignore

}

}//…… 在這里寫入壁紙,寫入過程結束,Manager完成任務

private voidsetWallpaper(InputStream data, FileOutputStream fos)throwsIOException {byte[] buffer = new byte[32768];intamt;while ((amt=data.read(buffer)) > 0) {

fos.write(buffer,0, amt);

}

}/*↑ — (framework/base/core/java/android/app) *********/

再來看Globals extends IWallpaperManagerCallback.Stub

包含成員變量 IWallpaperManager mService,通過

Globals(Looper looper) {

IBinder b=ServiceManager.getService(Context.WALLPAPER_SERVICE);

mService=IWallpaperManager.Stub.asInterface(b);

}

調用?WallpaperManagerService.java?里的setWallpaper方法

Service的作用

進入WallpaperManagerService看看,是如何返回ParcelFileDescriptor值的

/*↓ — WallpaperManagerService.java *********/

public ParcelFileDescriptor setWallpaper(String name) { //供 WallpaperManager 調用

checkPermission(android.Manifest.permission.SET_WALLPAPER);synchronized(mLock) {if (DEBUG) Slog.v(TAG, “setWallpaper”);int userId =UserHandle.getCallingUserId();

WallpaperData wallpaper=mWallpaperMap.get(userId);if (wallpaper == null) {throw new IllegalStateException(“Wallpaper not yet initialized for user ” +userId);

}final long ident =Binder.clearCallingIdentity();try{

ParcelFileDescriptor pfd=updateWallpaperBitmapLocked(name, wallpaper);if (pfd != null) {//啟動下面的方法

wallpaper.imageWallpaperPending = true;

}return pfd; //返回ParcelFileDescriptor值給WallpaperManager

} finally{

Binder.restoreCallingIdentity(ident);

}

}

}

ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {if (name == null) name = “”;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);

}

File file= new File(dir, WALLPAPER); //創建一個新的文件

ParcelFileDescriptor fd =ParcelFileDescriptor.open(file,

MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);if (!SELinux.restorecon(file)) {return null;

}

wallpaper.name=name;return fd; //返回ParcelFileDescriptor值

} catch(FileNotFoundException e) {

Slog.w(TAG,“Error setting wallpaper”, e);

}return null;

}private static File getWallpaperDir(int userId) { //取得壁紙文件

returnEnvironment.getUserSystemDirectory(userId);

}/*↑ — (framework/base/services/core/java/com/android/server/wallpaper/) *********/

至此一個簡單的流程就結束了

我們可反過來看

壁紙文件是存在?Environment.getUserSystemDirectory(userId)?這個路徑下

WallpaperManagerService取到這個文件后,將其打開為ParcelFileDescriptor形式,交給WallpaperManager

WallpaperManager把launcher傳來的數據寫入這個文件中

小結一下:

選定壁紙,點擊按鈕,launcher把壁紙信息給WallpaperManager;

WallpaperManagerService把存放壁紙的文件打開,交給WallpaperManager

WallpaperManager把壁紙信息寫入;一次設置壁紙的動作就完成了

這里傳輸數據使用到engine,一個挺有意思的東西。

總結

以上是生活随笔為你收集整理的android 5.1 壁纸路径,RTFSC – Android5.1 壁纸设置流程简析 – RustFisher的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。