首先要知道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()方法中
case DIALOG_CREATE_SHORTCUT: return new CreateShortcut().createDialog();
找到create上左圖這個dialog的代碼,下面的方法是給dialog添加一個adapter,第二個參數是click事件的listener
builder.setAdapter(mAdapter, this);
在其adapter中,發現其每一列就是個textview,通過:
textView.setCompoundDrawablesWithIntrinsicBounds(item.image, null, null, null);
這個方法可以在textview的左、上、右、下添加圖片,無添加就為null。跟蹤onclick()方法,在pickShortcut() 方法中:
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);...startActivityForResult(pickIntent, REQUEST_PICK_SHORTCUT);
所以上右圖其實是一個dialog樣式的activity。
2、這個dialog樣式的activity經常可以碰到,比如有時你點擊一個連結,如果你裝了多個瀏覽器,就會彈出這個activity讓你選擇哪個瀏覽器。其實就是ActivityPicker.java這個類。
跟蹤其onCreate()方法:
// Build list adapter of pickable itemsList<PickAdapter.Item> items = getItems();mAdapter = new PickAdapter(this, items);
跟蹤getItems()方法,可以知道這個activityPicker中顯示了兩種資料,第一種便是上右圖的第一項:
// Add any injected pick itemsfinal Intent intent = getIntent();ArrayList<String> labels = intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);
第二種便是在系統中查詢一個Intent,就是上面一步中啟動ActivityPicker的pickIntent中的name為Intent.EXTRA_INTENT的extraData,並且對其排序,是按照查詢得出的activity的label或者name排序的:
List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent, 0 /* no flags */);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()方法中跟下去:
case REQUEST_PICK_SHORTCUT: processShortcut(data); break;
if中是處理如果你當時點擊的是第一項Applications時會繼續彈出一個ActivityPicker,列出所有安裝程式的入口activity的捷徑。
我們則進到else中,我們會發現它會啟動剛返回的那個activity,所以我們點擊建立ApiDemos的shortcut時,它會先啟動下這個具有Intent.ACTION_CREATE_SHORTCUT的activity,再退出。接著再返回到Launcher.java中,繼續跟下去,completeAddShortcut()方法就是具體的將這個shortcut添加到workspace上的方法,繼續跟蹤addShortcut()方法到infoFromShortcutIntent()中:
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);..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:
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
基本分析完畢,附上一張時序圖:
下面再看ApiDemos中那個例子,在app/LauncherShortcuts.java中,首先在manifest中:
<activity-alias android:name=".app.CreateShortcuts" android:targetActivity=".app.LauncherShortcuts" android:label="@string/sample_shortcuts"> <!-- This intent-filter allows your shortcuts to be created in the launcher. --> <intent-filter> <action android:name="android.intent.action.CREATE_SHORTCUT" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter></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)指向了自己。最後別忘了:
setResult(RESULT_OK, intent);
通過其返回到Launcher中。
有時我們會看到有些應用一安裝完就在案頭添加了一個shortcut或是程式中可以點擊一下按鈕就在案頭建立一個shortcut,這時我們要用到Launcher中的一個廣播接收者,在Launcher的manifest檔案中:
<receiver android:name="com.android.launcher2.InstallShortcutReceiver" android:permission="com.android.launcher.permission.INSTALL_SHORTCUT"> <intent-filter> <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" /> </intent-filter></receiver>
大家可以去看下這個廣播接收者的源碼。
下面通過一個例子來說明下用法:通過點擊一個按鈕在案頭建立一個shortcut。
TestCreateShortcut.java
public class TestCreateShortcut extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test_shortcut);Button button = (Button) findViewById(R.id.install);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();//install_shortcut actionintent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");//點擊shortcut時進入的activity,這裡是自己intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(TestCreateShortcut.this, TestCreateShortcut.class));//shortcut的nameintent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "MyShortcut");Parcelable iconResource = Intent.ShortcutIconResource.fromContext(TestCreateShortcut.this, R.drawable.icon);//shortcut的iconintent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,iconResource);//是否可以重複放置shortcut,預設trueintent.putExtra("duplicate", false);sendBroadcast(intent);}});}}
還有別忘了在你的manifest檔案中加上這個許可權:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
OK.