Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)

http://blog.csdn.net/aomandeshangxiao/article/details/6767423

http://blog.csdn.net/aomandeshangxiao/article/details/6768249


  以下将为大家简单的分析一下源代码中luncher修改壁纸的过程(以下代码均来自Luncher源代码):

      一.当我们在luncher界面按下menu的时候,第三个选项就是Wallpaper,定义如下(源码1116行,局部),menu.add第二项既是选择wallpaper:

[java] view plaincopy
  1. public boolean onCreateOptionsMenu(Menu menu) {  
  2.        if (isWorkspaceLocked()) {  
  3.            return false;  
  4.        }  
  5.   
  6.        super.onCreateOptionsMenu(menu);  
  7.   
  8.        menu.add(MENU_GROUP_ADD, MENU_ADD, 0, R.string.menu_add)  
  9.                .setIcon(android.R.drawable.ic_menu_add)  
  10.                .setAlphabeticShortcut('A');  
  11.        menu.add(MENU_GROUP_WALLPAPER, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)  
  12.                 .setIcon(android.R.drawable.ic_menu_gallery)  
  13.                 .setAlphabeticShortcut('W');  
Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)
       二.当我们按下Wallpaper触发什么事件呢?看一下代码(源代码1171行):

[java] view plaincopy
  1. @Override  
  2.    public boolean onOptionsItemSelected(MenuItem item) {  
  3.        switch (item.getItemId()) {  
  4.            case MENU_ADD:  
  5.                addItems();  
  6.                return true;  
  7.            case MENU_WALLPAPER_SETTINGS:  
  8.                startWallpaper();  
  9.                return true;  
  10.            case MENU_SEARCH:  
  11.                onSearchRequested();  
  12.                return true;  
  13.            case MENU_NOTIFICATIONS:  
  14.                showNotifications();  
  15.                return true;  
  16.        }  
  17.   
  18.        return super.onOptionsItemSelected(item);  
  19.    }  

我们看到:Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)

而它调用的事件是

[java] view plaincopy
  1. startWallpaper();  

你们看到的图片跟我的都不一样,呵呵,这是因为我写了一个很简单的demo,然后就系统给调用了,所以你们看到一个比你们多了一个wallpaperdemo。在下一篇日志中,我会说下这个demo是如何实现的。

三.下面让我们看下startWallpaper()这个方法(源代码1370行):

[java] view plaincopy
  1. private void startWallpaper() {  
  2.         closeAllApps(true);  
  3.         final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);  
  4.         Intent chooser = Intent.createChooser(pickWallpaper,  
  5.                 getText(R.string.chooser_wallpaper));  
  6.         // NOTE: Adds a configure option to the chooser if the wallpaper supports it  
  7.         //       Removed in Eclair MR1  
  8. //        WallpaperManager wm = (WallpaperManager)  
  9. //                getSystemService(Context.WALLPAPER_SERVICE);  
  10. //        WallpaperInfo wi = wm.getWallpaperInfo();  
  11. //        if (wi != null && wi.getSettingsActivity() != null) {  
  12. //            LabeledIntent li = new LabeledIntent(getPackageName(),  
  13. //                    R.string.configure_wallpaper, 0);  
  14. //            li.setClassName(wi.getPackageName(), wi.getSettingsActivity());  
  15. //            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { li });  
  16. //        }  
  17.         startActivityForResult(chooser, REQUEST_PICK_WALLPAPER);  
  18.     }  
很多人可能会对他是如何实现跳转设置的呢?Intent.createChooser()这个方法的实现原理赶到好奇,因为你在Luncher源代码里面找不到Live Wallpapers和Galleryde的实现。因为他是通过一个类似广播的机制。

下一篇日志http://blog.csdn.net/aomandeshangxiao/article/details/6768249 中,将为大家详细介绍Intent.createChooser()的用法。


我所写的简单的小例子:http://download.csdn.net/detail/aomandeshangxiao/3593740


简单的分析了一下源代码,在

[java] view plaincopy
  1. final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);  
  2.         Intent chooser = Intent.createChooser(pickWallpaper,  
  3.                 getText(R.string.chooser_wallpaper));  

处百思不得其解,后来在网上找,也没有很透彻的解释。先看下它的官方文档吧:

[java] view plaincopy
  1. public static Intent createChooser (Intent target, CharSequence title)  
  2. Since: API Level 1  
  3.   
  4. Convenience function for creating a ACTION_CHOOSER Intent.  
  5. Parameters  
  6. target  The Intent that the user will be selecting an activity to perform.  
  7. title   Optional title that will be displayed in the chooser.  
  8. Returns  
  9.   
  10.     * Return a new Intent object that you can hand to Context.startActivity() and related methods.   


在google上面也找了下,慢慢的有些明白,在一篇文章中看到这么一段话:

这里是要找到所有能处理Intent.ACTION_SET_WALLPAPER请求的activity,其字符串表示为android.intent.action.SET_WALLPAPER。使用Eclipse搜索之后,在以下应用的AndroidManifest.xml文件都找到了能处理这个请求的activity:
packages/apps/Gallery
packages/apps/Launcher2
packages/wallpapers/LivePicker
再看看下面的这个图:
Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)

壁纸对应的是Launcher2里面的WallpaperChooser.activity。动态壁纸对应的是packages/wallpapers/LivePicker的LiveWallpaperListActivity,他们的共同点 就是在AndroidManifest.xml都有
[html] view plaincopy
  1. <intent-filter>  
  2.                <action android:name="android.intent.action.SET_WALLPAPER" />  
  3.                <category android:name="android.intent.category.DEFAULT" />  
  4.            </intent-filter>  

如下定义,或许你有了些许明白,看下http://groups.google.com/group/android-developers/browse_thread/thread/9d376a94066057a4这里面的解释,我英语不是太好,按照我自己的理解就是,你如果像下面这样
[html] view plaincopy
  1. Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);  
  2.         Intent chooser = Intent.createChooser(pickWallpaper,  
建立一个intent chooser,系统会寻找所有activity,然后把有
[html] view plaincopy
  1. <intent-filter>  
  2.                <action android:name="android.intent.action.SET_WALLPAPER" />  
  3.                <category android:name="android.intent.category.DEFAULT" />  
  4.            </intent-filter>  
定义的activity形成列表提供给使用者。为了验证我的想法,个人写了一个很简单的小例子,MainActivity代码如下:
[java] view plaincopy
  1. public class MainActivity extends Activity {  
  2.     /** Called when the activity is first created. */  
  3. private Button button;  
  4.     @Override  
  5.     public void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(R.layout.main);  
  8.           
  9.         button=(Button)findViewById(R.id.wallpaperButton);  
  10.         button.setOnClickListener(new View.OnClickListener() {  
  11.   
  12. @Override  
  13. public void onClick(View v) {  
  14. // TODO Auto-generated method stub  
  15. final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);  
  16.        Intent chooser = Intent.createChooser(pickWallpaper,"tese the ACTION_SET_WALLPAPER");  
  17.        startActivity(chooser);  
  18. }  
  19. });  
  20.     }  
  21. }  
还有一个demo,代码如下
[java] view plaincopy
  1. public class Demo extends Activity {  
  2.   
  3.   
  4. @Override  
  5. protected void onCreate(Bundle savedInstanceState) {  
  6. // TODO Auto-generated method stub  
  7. super.onCreate(savedInstanceState);  
  8. setContentView(R.layout.demo);  
  9. }  
  10. }  

demo.xml文件里面只有一个textview很简单。
然后是AndroidManifest.xml文件:
[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="cn.demo"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.   
  7.   
  8.   
  9.   
  10.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  11.         <activity android:name=".MainActivity"  
  12.                   android:label="@string/app_name">  
  13.             <intent-filter>  
  14.                 <action android:name="android.intent.action.MAIN" />  
  15.                 <category android:name="android.intent.category.LAUNCHER" />  
  16.             </intent-filter>  
  17.         </activity>  
[java] view plaincopy
  1. <activity android:name=".Demo">  
[java] view plaincopy
  1. <intent-filter>  
[java] view plaincopy
  1.             <action android:name="android.intent.action.SET_WALLPAPER" />  
  2.             <category android:name="android.intent.category.DEFAULT" />  
  3.         </intent-filter>  
  4.     </activity>  
  5. </application>  
  6. /manifest>  



注意:
 
[html] view plaincopy
  1. </activity>  
  2. <activity android:name=".Demo">  
  3. <intent-filter>  
  4.                 <action android:name="android.intent.action.SET_WALLPAPER" />  
  5.                 <category android:name="android.intent.category.DEFAULT" />  
  6.             </intent-filter>  
  7.         </activity>  


我在这里面加了intent适配器 
<action android:name="android.intent.action.SET_WALLPAPER" />


运行下程序,点击button按钮,效果如下:

Luncher修改wallpaper(壁纸)源码跟踪(代码实现过程分析)


我这个网速太不给力了,弄的心烦意燥,大家看到我自己写的demo在图片中得到了显示,这也是在上一篇 http://blog.csdn.net/aomandeshangxiao/article/details/6767423中给大家看的图片,为什么我的选项多了一个。说到这里,想必大家都明白了这个原理了,中秋节还有几分钟就要到了,祝福大家中秋愉快。


上面所说的简单的小例子下载地址:http://download.csdn.net/detail/aomandeshangxiao/3593740


上一篇:VB.NET 中的ref 和C#中的ref 格式区别


下一篇:Centos环境下将修改后的MAC地址永久保存的正确