android Launcher源码解析07:Workspace 02——设置壁纸

      本文分为两个部分,第一部分介绍launcher中如何设置壁纸;第二部分介绍WallpaperChooser;    

1、设置壁纸  

 长按 Home 可以弹出下面的 Dialog(图 1)

      

其中有一项就是选择 “壁纸”,当选择之后,出现一个选择器(不是 Dialog)哟!(图 2)


这个时候,你可以选择是一般的壁纸,还是比较炫的动态壁纸或者是从设备中寻找存在的照片(如果没有还可以照相)等。

那麽代码是如何调用的呢?看下图:


调用关系不算复杂,当然我们还可以使用菜单来启用添加选项,最终还是调用 

startWallpaper  
方法。

    private void startWallpaper() {
        closeAllApps(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 调用相关的 Activity。

首先,你得搞清楚 Intent.ACTION_SET_WALLPAPER 表示什么含义以及它的真实值,这查看 API 文档就会明白。

public static final String ACTION_SET_WALLPAPER  
  
Since: API Level 1  
Activity Action: Show settings for choosing wallpaper  
Input: Nothing.  
Output: Nothing.  
Constant Value: "android.intent.action.SET_WALLPAPER"  
该 Intent 常量是一个 String,表示启用设置壁纸的 Activity,也就是说只要我们的系统中有这样的 Activity(action 为  android.intent.action.SET_WALLPAPER )就可以出现在选择器中。

那麽,原生的 android 系统中有三个(从图2可以看出)这样的 Activity,下面细细说来!

1). WallpaperChooser.java

这是 Launcher 中的一个类,主要是选择壁纸的操作,和 Launcher.java 在一个包下面。通过 Launcher 的 Manifest.xml 文件就可以看到答案:

</activity>  
<activity android:name="com.android.launcher2.WallpaperChooser" android:label="@string/pick_wallpaper" android:icon="@drawable/ic_launcher_wallpaper" android:screenOrientation="nosensor" android:finishOnCloseSystemDialogs="true">  
<intent-filter>  
<action android:name="android.intent.action.SET_WALLPAPER"/>  
<category android:name="android.intent.category.DEFAULT"/>  
</intent-filter>  
</activity>  
2). LiveWallpaperListActivity.java

位于  /packages/wallpapers/LivePicker/src/com/android/wallpaper/livepicker 下面,主要是选择动态壁纸。其 Manifest.xml 文件:

<activity android:name="LiveWallpaperListActivity"  
            android:icon="@drawable/ic_launcher_live_wallpaper"  
            android:label="@string/live_wallpaper_picker_title"  
            android:theme="@android:style/Theme.NoTitleBar"  
            android:screenOrientation="nosensor">  
            <intent-filter>  
                <action android:name="android.service.wallpaper.LIVE_WALLPAPER_CHOOSER" />  
                <action android:name="android.intent.action.SET_WALLPAPER" />  
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>  
        </activity>  
3). Photographs.java

在以前的版本中,android 使用的是Gallery,现在改变为 Gallery3D,位于 /packages/apps/Gallery3D/src/com/cooliris/media,对应的 Manifest.xml 文件可自行查阅。

        相信,大家看完会有一个疑问,为什么Launcher代码中的WallpaperChooser.java与设置壁纸的对话框会有关联。这里猜测是跟Manifest.xml 文件中的配置有关。

<intent-filter>  
<action android:name="android.intent.action.SET_WALLPAPER"/>  
<category android:name="android.intent.category.DEFAULT"/>  
</intent-filter>  

2、WallpaperChooser

    这个activity的显示内容:


其配置文件为:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView android:id="@+id/wallpaper"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1.0"
        android:scaleType="fitCenter" />

    <Gallery android:id="@+id/gallery"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
        
    <Button android:id="@+id/set"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/wallpaper_instructions"
        android:layout_gravity="center_horizontal" />

</LinearLayout>
       从上面我们可以看出,这里包含三个部分内容:ImageView,Gallery ,Button;其中 Gallery显示的是缩略图,而ImageView现实的是大图。在drawable-hdpi文件夹中,我们可以看到有类似:wallpaper_bluedotgrid_small.jpg和wallpaper_bluedotgrid.jpg这样的图形,所以很明显,带后缀_small的就是缩略图。

private void findWallpapers() {
        mThumbs = new ArrayList<Integer>(24);//存放缩略图id
        mImages = new ArrayList<Integer>(24);//存放大图id

        final Resources resources = getResources();
        // Context.getPackageName() may return the "original" package name,
        // com.android.launcher3; Resources needs the real package name,
        // com.android.launcher. So we ask Resources for what it thinks the
        // package name should be.
        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
        //对于这里的R.array.wallpapers很多人会有疑问,因为我们在values文件夹中,并不能找到有命名为wallpapers这样的array 
              //找了很久以后,在values-hdpi和values-mdpi文件夹下,分别有一个wallpapers.xml文件
        addWallpapers(resources, packageName, R.array.wallpapers);
        addWallpapers(resources, packageName, R.array.extra_wallpapers);//values文件夹下extra_wallpapers.xml
    }

    private void addWallpapers(Resources resources, String packageName, int list) {
        final String[] extras = resources.getStringArray(list);
        for (String extra : extras) {
            int res = resources.getIdentifier(extra, "drawable", packageName);
            if (res != 0) {
                final int thumbRes = resources.getIdentifier(extra + "_small",
                        "drawable", packageName);//寻找后缀为_small的图片的ID

                if (thumbRes != 0) {
                    mThumbs.add(thumbRes);
                    mImages.add(res);
                    // Log.d(TAG, "addWallpapers: [" + packageName + "]: " + extra + " (" + res + ")");
                }
            }
        }
    }
        点击button按钮设置壁纸:

    /*
     * When using touch if you tap an image it triggers both the onItemClick and
     * the onTouchEvent causing the wallpaper to be set twice. Ensure we only
     * set the wallpaper once.
     */
    private void selectWallpaper(int position) {
        if (mIsWallpaperSet) {
            return;
        }

        mIsWallpaperSet = true;
        try {
            WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
            wpm.setResource(mImages.get(position));
            setResult(RESULT_OK);
            finish();
        } catch (IOException e) {
            Log.e(TAG, "Failed to set wallpaper: " + e);
        }
    }
        另外,在选择 Gallery 中的某一张图以后,ImageView会显示对应大图。这里存在一个问题,如果图片太大,就会出现内存溢出的问题。因此使用了BitmapFactory.Options来规避这个问题。对于BitmapFactory.Options可以参考博文《android基础知识37:BitmapFactory.Options》,另外,对于AsyncTask可以看博文《android基础知识02——线程安全5: AsyncTask》。


参考资料:
Launcher: 设置壁纸_源码跟踪

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值