Launcher是个特殊APK,但说到底还是个应用,想要在上面展示壁纸,自然是来自应用本身,要么就是Framework public资源。
首先,根据长按Launcher主界面空白处,弹出的wallpaper按钮的响应事件来看。
View wallpaperButton = findViewById(R.id.wallpaper_button);
wallpaperButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (!mWorkspace.isSwitchingState()) {
onClickWallpaperPicker(arg0);
}
}
});
wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
调用到的方法如下
/**
* Event handler for the wallpaper picker button that appears after a long press
* on the home screen.
*/
protected void onClickWallpaperPicker(View v) {
if (LOGD) Log.d(TAG, "onClickWallpaperPicker");
startActivityForResult(new Intent(Intent.ACTION_SET_WALLPAPER).setPackage(getPackageName()),
REQUEST_PICK_WALLPAPER);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onClickWallpaperPicker(v);
}
}
通过startActivity的方式启动Wallpaper选择界面,看看本应用中注册了SET_WALLPAPAER的Activity.
<activity
android:name="com.tct.launcher.wallpaperpicker.WallpaperPickerActivity"
android:theme="@style/Theme.WallpaperPicker"
android:label="@string/pick_wallpaper"
android:icon="@mipmap/ic_launcher_wallpaper"
android:finishOnCloseSystemDialogs="true"
android:process=":wallpaper_chooser">
<intent-filter>
<action android:name="android.intent.action.SET_WALLPAPER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
经过adb命令确认,正是该Activity被启动,下方可以看到默认的壁纸和许多的候选壁纸。
界面效果如下
接下来的问题是默认壁纸哪儿来以及后面的17张候选壁纸怎么来,或者怎么定制的。
根据SDK工具hierarchyviewer得的文件布局节点如下
发现这个master_wallpaper_list是个水平线性布局,来自WallpaperPickerActivity的onCreate()方法,布局代码如下:
<HorizontalScrollView
android:id="@+id/wallpaper_scroll_container"
android:scrollbarSize="@dimen/horizontal_scrollbar_size"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/master_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
<LinearLayout
android:id="@+id/live_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
<LinearLayout
android:id="@+id/third_party_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>
</HorizontalScrollView>
项目用到的是wallpaper_list这个线性布局,另外两个(live_wallpaper_list和third_party_wallpaper_list)为空。
ArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();
mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(getContext(), wallpapers);
populateWallpapersFromAdapter(mWallpapersView, ia, false);
mSavedImages = new SavedWallpaperImages(getContext());
mSavedImages.loadThumbnailsAndImageIdList();
populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);
就目前来说,初次调试,只有预编译进入APK和系统的(FRM) wallpaper资源了,经过几番调试,当前只有两张wallpaper,一张备选一张默认,塞进bundle的有两张。
下面看看findBundledWallpapers方法从哪里取得的图片
@SuppressWarnings("deprecation")
private ArrayList<WallpaperTileInfo> findBundledWallpapers() {
final PackageManager pm = getContext().getPackageManager();
final ArrayList<WallpaperTileInfo> bundled = new ArrayList<WallpaperTileInfo>(24);
Partner partner = Partner.get(pm);
if (partner != null) {
final Resources partnerRes = partner.getResources();
final int resId = partnerRes.getIdentifier(Partner.RES_WALLPAPERS, "array",
partner.getPackageName());
if (resId != 0) {
addWallpapers(bundled, partnerRes, partner.getPackageName(), resId);
}
File systemDir = partner.getWallpaperDirectory();
if (systemDir != null && systemDir.isDirectory()) {
for (File file : systemDir.listFiles()) {
if (!file.isFile()) {
continue;
}
String name = file.getName();
int dotPos = name.lastIndexOf('.');
String extension = "";
if (dotPos >= -1) {
extension = name.substring(dotPos);
name = name.substring(0, dotPos);
}
if (name.endsWith("_small")) {
continue;
}
File thumbnail = new File(systemDir, name + "_small" + extension);
Bitmap thumb = BitmapFactory.decodeFile(thumbnail.getAbsolutePath());
if (thumb != null) {
bundled.add(new FileWallpaperInfo(file, new BitmapDrawable(thumb)));
}
}
}
}
Pair<ApplicationInfo, Integer> r = getWallpaperArrayResourceId();
if (r != null) {
try {
Resources wallpaperRes = getContext().getPackageManager()
.getResourcesForApplication(r.first);
addWallpapers(bundled, wallpaperRes, r.first.packageName, r.second);
} catch (PackageManager.NameNotFoundException e) {
}
}
if ((partner == null || !partner.hideDefaultWallpaper()) && loadDefaultWallpaperForCustomization()) {
WallpaperTileInfo defaultWallpaperInfo =
(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
? getPreKKDefaultWallpaperInfo()
: getDefaultWallpaper();
if (defaultWallpaperInfo != null) {
bundled.add(0, defaultWallpaperInfo);
}
}
return bundled;
}
其中wallpaper1很容易理解,即预置在Launcher应用内部的R.array资源,本机调试只预置了一张图片,这也是后面要讲到的Launcher该如何定制自己的备选壁纸,即通过overlay的方式,增加图片和项。
<resources>
<string-array name="extra_wallpapers" translatable="false">
<item>wallpaper1</item>
</string-array>
</resources>
接下来看默认的那张壁纸哪儿,看getDefaultWallpaper()方法。
经过断点调试,发现来自/data/user/0/com.tct.launcher/files目录,其中有张生成的jpg图片,被命名为:24_Y8KU2000CH00_default_thumb2.jpg。
这就时我们系统中第一张壁纸。经过再三验证,此图片即来自FRM。
/frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.png
其将被编入framework-res.apk。
/system/framework/framework-res.apk=android
预置自己的备选壁纸
除了在上面提到的FRM中替换默认的那张壁纸外,还可以通过overlay的方式替换原本预编译在launcher中的array资源,R.array.extra_wallpapers,并加入对应的图片资源即可。
/vendor/overlay/SimpleLauncherRes-overlay.apk=com.simple.launcher.overlay
上面的WallpaperPickerActivity界面对应的备用wallpaper正是来自于覆盖的R.array.extra_wallpapers,反编译后得到的图片如下,从1至17,都在这儿了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)