Launcher壁纸来源

来源:互联网 发布:java校验图片尺寸 编辑:程序博客网 时间:2024/05/17 04:12

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)为空。

        // Populate the built-in wallpapers        ArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();        mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);        SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(getContext(), wallpapers);        populateWallpapersFromAdapter(mWallpapersView, ia, false);        // Populate the saved wallpapers        mSavedImages = new SavedWallpaperImages(getContext());        mSavedImages.loadThumbnailsAndImageIdList();        populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);        // Populate the live wallpapers        //......        // Populate the third-party wallpaper pickers

就目前来说,初次调试,只有预编译进入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) { // partner为空            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);            }            // Add system wallpapers            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")) {                        // it is a thumbnail                        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();//来自应用内部R.array.extra_wallpapers;        //从array中获取到了壁纸1        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()) {            // Add an entry for the default wallpaper (stored in system resources)            WallpaperTileInfo defaultWallpaperInfo =                    (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)                    ? getPreKKDefaultWallpaperInfo()                    : getDefaultWallpaper();// 来自getDefaultWallpaper方法, 壁纸2            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()方法。
default wallpaper

经过断点调试,发现来自/data/user/0/com.tct.launcher/files目录,其中有张生成的jpg图片,被命名为:24_Y8KU2000CH00_default_thumb2.jpg。
default wallpaper shortcut

这就时我们系统中第一张壁纸。经过再三验证,此图片即来自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,都在这儿了。
这里写图片描述

原创粉丝点击