閱讀263 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Luncher修改wallpaper(壁紙)源碼跟蹤(代碼實現過程分析)

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

https://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');  

       二.當我們按下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.    }  

我們看到:

而它調用的事件是

[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的實現。因為他是通過一個類似廣播的機製。

下一篇日誌https://blog.csdn.net/aomandeshangxiao/article/details/6768249 中,將為大家詳細介紹Intent.createChooser()的用法。


我所寫的簡單的小例子:https://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
再看看下麵的這個圖:


壁紙對應的是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>  

如下定義,或許你有了些許明白,看下https://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="https://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按鈕,效果如下:




我這個網速太不給力了,弄的心煩意燥,大家看到我自己寫的demo在圖片中得到了顯示,這也是在上一篇 https://blog.csdn.net/aomandeshangxiao/article/details/6767423中給大家看的圖片,為什麼我的選項多了一個。說到這裏,想必大家都明白了這個原理了,中秋節還有幾分鍾就要到了,祝福大家中秋愉快。


上麵所說的簡單的小例子下載地址:https://download.csdn.net/detail/aomandeshangxiao/3593740


最後更新:2017-04-04 07:03:49

  上一篇:go ThreadLocal實現方式&amp;使用介紹---無鎖化線程封閉
  下一篇:go 我問自己代言,甄嬛篇