android 壁纸设置分析

最近组织上派遣了我一个任务,最终目的只有一个,就是看看launcher你的wallpaper设置的流程。

废话不多说,直接看源码。

tips:在com.android.launcher2.Launcher类内有一个方法叫做startWallpaper(),很明显此方法就是设置壁纸的关键所在。

要说我是怎么知道的,大概老外起名字也不是随便起的,要是找类似的功能,比如创建快捷方式,在Launcher类里

按快捷键CTRL+O 键入对应的英文比如(*shortcut*),列出来的方法看名字也能猜出来对吧。同上,wallpaper就是这么找到的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private void startWallpaper() \{
        showWorkspace(true);
        final Intent pickWallpaper = new Intent(Intent.ACTION\_SET\_WALLPAPER);
        Intent chooser = Intent.createChooser(pickWallpaper,
                getText(R.string.chooser\_wallpaper));
        // NOTE: Adds a configure option to the chooser if the wallpaper supports it
        //       Removed in Eclair MR1
//        WallpaperManager wm = (WallpaperManager)
//                getSystemService(Context.WALLPAPER\_SERVICE);
//        WallpaperInfo wi = wm.getWallpaperInfo();
//        if (wi != null && wi.getSettingsActivity() != null) \{
//            LabeledIntent li = new LabeledIntent(getPackageName(),
//                    R.string.configure\_wallpaper, 0);
//            li.setClassName(wi.getPackageName(), wi.getSettingsActivity());
//            chooser.putExtra(Intent.EXTRA\_INITIAL\_INTENTS, new Intent\[\] \{ li \});
//        \}
        startActivityForResult(chooser, REQUEST\_PICK\_WALLPAPER);
    \}
``` 
以上代码中Intent的chooser静态方法没有使用过,没有关系,看对应的api就是了。
```java
#### public static [Intent][] createChooser ([Intent][] target, [CharSequence][] title) ####
Added in  [API level 1][]
Convenience function for creating a [ACTION\_CHOOSER][ACTION_CHOOSER] Intent.
Builds a new [ACTION\_CHOOSER][ACTION_CHOOSER] Intent that wraps the given target intent, also optionally supplying a title. If the target intent has specified[FLAG\_GRANT\_READ\_URI\_PERMISSION][FLAG_GRANT_READ_URI_PERMISSION] or [FLAG\_GRANT\_WRITE\_URI\_PERMISSION][FLAG_GRANT_WRITE_URI_PERMISSION], then these flags will also be set in the returned chooser intent, with its ClipData set appropriately: either a direct reflection of [getClipData()][getClipData] if that is non-null, or a new ClipData build from [getData()][getData].

Parameters












targetThe Intent that the user will be selecting an activity to perform.
titleOptional title that will be displayed in the chooser.

Returns

很明显这个方法是将该IntentFIlter中符合该Intent的activity全都列出来,然后第二个参数就是展示的chooser的标题。

当点击对应的item就会打开对应的activity,而launcher源码中存在一个对应的activity,清单文件中有提及到。

```xml

<activity
            android:name="com.android.launcher2.WallpaperChooser"
            style="@style/Theme.WallpaperPicker"
            android:label="@string/pick_wallpaper"
            android:icon="@drawable/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>
            <meta-data android:name="android.wallpaper.preview"
                android:resource="@xml/wallpaper_picker_preview" />
        </activity>

plain 因此顺藤摸瓜,看看设置壁纸是如何实现的。找到WallpaperChooser类,查看源码java
public class WallpaperChooser extends Activity {
private static final String TAG = “Launcher.WallpaperChooser”;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.wallpaper_chooser_base);


        Fragment fragmentView =
                getFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment);
        Log.i(TAG, "wallpaper"+(fragmentView==null));
        // TODO: The following code is currently not exercised. Leaving it here in case it
        // needs to be revived again.
        if (fragmentView == null) {
            /* When the screen is XLarge, the fragment is not included in the layout, so show it
             * as a dialog
             */
            DialogFragment fragment = WallpaperChooserDialogFragment.newInstance();
            fragment.show(getFragmentManager(), "dialog");
        }
    }
}

plain 事实上在对应的layout上有如下xml



``` plain

实际是使用了WallpaperChooserDialogFragment,注释说了如果是Xlarge屏幕,没有显示该fragment,则获得WallpaperChooserDialogFragment对象

大概看到应该是在倒数第二句话中使用了一个fragment 选择壁纸。继续找到WallpaperChooserDialogFragment.类,果然
```java
private void selectWallpaper(int position) {
try {
WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(
Context.WALLPAPER_SERVICE);
wpm.setResource(mImages.get(position));
Activity activity = getActivity();
activity.setResult(Activity.RESULT_OK);
activity.finish();
} catch (IOException e) {
Log.e(TAG, “Failed to set wallpaper: “ + e);
}
}

// Click handler for the Dialog's GridView
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    selectWallpaper(position);
}

plain 这一段就是真正的实现壁纸设置的方法。使用WallpaperManager.setResource(arg0)设置。java
activity.setResult(Activity.RESULT_OK);
``` plain
将会在Launcher你的onActivityResult方法接收到,

此时也就是设置了对应的壁纸。

android 壁纸设置分析http://blog.csdn.net/q13073451412/article/details/9063283