简单分析Android中添加shortcut方面的源码 .

来源:互联网 发布:淘宝联盟教程 编辑:程序博客网 时间:2024/04/30 10:42

首先要知道Launcher,就是主屏幕,它是Android系统启动后所加载的第一个程序,如下,主屏幕分成两部分,Workspace和Hotseats,而shortcut就是添加在workspace上的,这上面还可以添加诸如widget、文件夹等。这儿说的shortcut是指跳转到具体功能的快捷方式,而不是简单的程序的入口图标,APIDemos中有一个添加shortcut的例子,我们稍后分析它。


这儿以Android2.3的模拟器分析添加shortcut有关的源码,要添加shortcut,一般是摁menu键选择Add或长摁主屏幕,弹出菜单选择相应的shortcut,如下:

关于获取Android的源码和将源码导入到eclipse中,可以参看我前面的文章,首先找到Launcher的源码,在<源码目录>\packages\apps\Launcher2下。

1、从manifest文件中可以知道主屏幕就是Launcher.java这个activity,可以看下其布局文件,找到onOptionsItemSelected()方法,跟下去在onCreateDialog()方法中

[java] view plaincopyprint?
  1. case DIALOG_CREATE_SHORTCUT:  
  2.                 return new CreateShortcut().createDialog();  
找到create上左图这个dialog的代码,下面的方法是给dialog添加一个adapter,第二个参数是click事件的listener

[java] view plaincopyprint?
  1. builder.setAdapter(mAdapter, this);  

在其adapter中,发现其每一列就是个textview,通过:

[java] view plaincopyprint?
  1. textView.setCompoundDrawablesWithIntrinsicBounds(item.image, nullnullnull);  
这个方法可以在textview的左、上、右、下添加图片,无添加就为null。跟踪onclick()方法,在pickShortcut() 方法中:

[java] view plaincopyprint?
  1. Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
  2. ...  
  3. startActivityForResult(pickIntent, REQUEST_PICK_SHORTCUT);  
所以上右图其实是一个dialog样式的activity。

2、这个dialog样式的activity经常可以碰到,比如有时你点击一个链接,如果你装了多个浏览器,就会弹出这个activity让你选择哪个浏览器。其实就是ActivityPicker.java这个类。

跟踪其onCreate()方法:

[java] view plaincopyprint?
  1. // Build list adapter of pickable items  
  2. List<PickAdapter.Item> items = getItems();  
  3. mAdapter = new PickAdapter(this, items);  
跟踪getItems()方法,可以知道这个activityPicker中显示了两种数据,第一种便是上右图的第一项:

[java] view plaincopyprint?
  1. // Add any injected pick items   
  2. final Intent intent = getIntent();  
  3. ArrayList<String> labels = intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);  
第二种便是在系统中查询一个Intent,就是上面一步中启动ActivityPicker的pickIntent中的name为Intent.EXTRA_INTENT的extraData,并且对其排序,是按照查询得出的activity的label或者name排序的:

[java] view plaincopyprint?
  1. List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent, 0 /* no flags */);  
  2. Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager));  
所以系统中有Intent.ACTION_CREATE_SHORTCUT这个IntentFilter的activity都会显示在上右图中的列表中。

3、点击这个picker中ApiDemos,触发onclick(),会带着指向有Intent.ACTION_CREATE_SHORTCUT的activity的Intent返回到Launcher.java中。在onActivityResult()方法中跟下去:

[java] view plaincopyprint?
  1. case REQUEST_PICK_SHORTCUT:  
  2.          processShortcut(data);  
  3.          break;  
if中是处理如果你当时点击的是第一项Applications时会继续弹出一个ActivityPicker,列出所有安装程序的入口activity的快捷方式。

我们则进到else中,我们会发现它会启动刚返回的那个activity,所以我们点击创建ApiDemos的shortcut时,它会先启动下这个具有Intent.ACTION_CREATE_SHORTCUT的activity,再退出。接着再返回到Launcher.java中,继续跟下去,completeAddShortcut()方法就是具体的将这个shortcut添加到workspace上的方法,继续跟踪addShortcut()方法到infoFromShortcutIntent()中:

[java] view plaincopyprint?
  1. Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);  
  2.  String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
  3. Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);  
  4. ..  
  5. Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);  
上面的代码是在你的有Intent.ACTION_CREATE_SHORTCUT的activity中所要返回给Launcher.java的Intent中所要的ExtraData,第一个代表跳转到你这个shortcut所指向的那个具体功能的activity的Intent,第二个指该shortcut在桌面的name,第三与第四任选一个代表该shortcut在桌面的icon。

4、继续跟踪completeAddShortcut()中的createShortcut()方法,发现shortcut也是个textview,只不过这次是把icon添加到了text的上方,点击这个shortcut触发onclick(),就会启动你的具体功能的activity:

[java] view plaincopyprint?
  1. Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);  
基本分析完毕,附上一张时序图:


下面再看ApiDemos中那个例子,在app/LauncherShortcuts.java中,首先在manifest中:

[java] view plaincopyprint?
  1. <activity-alias android:name=".app.CreateShortcuts"  
  2.             android:targetActivity=".app.LauncherShortcuts"  
  3.             android:label="@string/sample_shortcuts">  
  4.             <!--  This intent-filter allows your shortcuts to be created in the launcher. -->  
  5.             <intent-filter>  
  6.                 <action android:name="android.intent.action.CREATE_SHORTCUT" />  
  7.                 <category android:name="android.intent.category.DEFAULT" />  
  8.             </intent-filter>  
  9. </activity-alias>  
它推荐使用activity-alias来提供CREATE_SHORTCUT这个IntentFilter,这样可以通过label和icon属性来自定义picker那个activity中显示这个shortcut的名称和图标,<action android:name="android.intent.action.CREATE_SHORTCUT" />分析在上面第二步。回到这个activity中,在setupShortcut()方法中,设置了上面第三步中所描述Intent,这个activity同时是那个当点击shortcut时所指向的那个具体功能的activity,所以intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)指向了自己。最后别忘了:

[java] view plaincopyprint?
  1. setResult(RESULT_OK, intent);  
通过其返回到Launcher中。

有时我们会看到有些应用一安装完就在桌面添加了一个shortcut或是程序中可以点击一下按钮就在桌面创建一个shortcut,这时我们要用到Launcher中的一个广播接收者,在Launcher的manifest文件中:

[html] view plaincopyprint?
  1. <receiver  
  2.             android:name="com.android.launcher2.InstallShortcutReceiver"  
  3.             android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">  
  4.             <intent-filter>  
  5.                 <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />  
  6.             </intent-filter>  
  7. </receiver>  
大家可以去看下这个广播接收者的源码。
下面通过一个例子来说明下用法:通过点击一个按钮在桌面创建一个shortcut。

TestCreateShortcut.java

[java] view plaincopyprint?
  1. public class TestCreateShortcut extends Activity {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.test_shortcut);  
  6.         Button button = (Button) findViewById(R.id.install);  
  7.         button.setOnClickListener(new OnClickListener() {  
  8.             @Override  
  9.             public void onClick(View v) {  
  10.                 Intent intent = new Intent();  
  11.                 //install_shortcut action  
  12.                 intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");  
  13.                 //点击shortcut时进入的activity,这里是自己  
  14.                 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(  
  15.                         TestCreateShortcut.this, TestCreateShortcut.class));  
  16.                 //shortcut的name   
  17.                 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "MyShortcut");  
  18.                 Parcelable iconResource = Intent.ShortcutIconResource  
  19.                         .fromContext(TestCreateShortcut.this, R.drawable.icon);  
  20.                 //shortcut的icon   
  21.                 intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,  
  22.                         iconResource);  
  23.                 //是否可以重复放置shortcut,默认true  
  24.                 intent.putExtra("duplicate"false);  
  25.                 sendBroadcast(intent);  
  26.             }  
  27.         });  
  28.     }  
  29. }  
还有别忘了在你的manifest文件中加上这个权限:

[html] view plaincopyprint?
  1. <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>  
原创粉丝点击