Android App Shortcuts——實現應用快捷方式

  • 時間:2019-06-11 04:08 作者:Android開發架構 來源:Android開發架構 閱讀:41
  • 掃一掃,手機訪問
摘要:之前玩手機的時候偶然發現了一個效果,長按應用圖標會顯示出幾個快捷方式(相似IOS系統的3D Touch功能),點擊后可以直接進入相應的頁面,不需要點擊應用圖標來啟動應用,并且快捷方式可以放到桌面上單獨顯示,就像下圖這樣:索性就來研究一下這個效果是如何實現的,通過查閱網絡上的資料,理解到該效果是通過A

之前玩手機的時候偶然發現了一個效果,長按應用圖標會顯示出幾個快捷方式(相似IOS系統的3D Touch功能),點擊后可以直接進入相應的頁面,不需要點擊應用圖標來啟動應用,并且快捷方式可以放到桌面上單獨顯示,就像下圖這樣:

索性就來研究一下這個效果是如何實現的,通過查閱網絡上的資料,理解到該效果是通過Android 7.1(API level 25)版本的新特性App Shortcuts來實現的。納尼!Android 7.1版本就已經增加了,我竟然現在才知道(o(╥﹏╥)o)。不過既然清楚了實現方式,下面就來具體研究一下這個App Shortcuts特性。

什么是App Shortcuts

App Shortcuts是Android 7.1的新特性,指長按app圖標出現的快捷方式,可以為app的關鍵功能增加更快捷的入口而無需打開app,點擊快捷方式可以訪問相應的應用功能,,這種快捷方式也可以被拖拽到桌面單獨放置,成為單獨的桌面快捷方式。
每個快捷方式都引用了一個或者多個Intent,點擊快捷方式會啟動Intent所指定的的操作,可以為任何Intent的操作創立一個快捷方式。

App Shortcuts的實現

Shortcuts的實現有三種形式:靜態快捷方式動態快捷方式固定快捷方式,下面我們就具體看一下這三種類型的快捷方式分別是如何實現的。

靜態快捷方式

靜態快捷方式(Static shortcuts),是在資源文件中配置的快捷方式。創立靜態快捷方式有以下幾個步驟:

1)在資源文件res下新建xml目錄,新建文件shortcuts.xml,文件名不是固定的。

<?xml version="1.0" encoding="utf-8"?><shortcuts xmlns:android="http://schemas.android.com/apk/res/android">    <shortcut        android:icon="@drawable/ic_settings"        android:shortcutId="setting"        android:shortcutLongLabel="@string/shortcut_setting_long"        android:shortcutShortLabel="@string/shortcut_setting_short">        <intent            android:action="com.example.shortcutstest.SETTING"            android:targetClass="com.example.shortcutstest.SettingActivity"            android:targetPackage="com.example.shortcutstest" />    </shortcut></shortcuts>

根節點shortcuts下可以增加一個或者多個shortcut標簽,每個shortcut表示一個快捷方式,內部配置了快捷方式的詳細信息,包括名稱、圖標以及要啟動的Intent等,shortcut標簽常用的幾個屬性如下:

  • android:shortcutId:快捷方式的id,需要保證是唯一的。不能將此屬性的值設置為資源字符串,例如@string/foo

  • android:shortcutLongLabel:快捷方式的長名稱,假如有足夠的空間,Launcher會優先顯示長名稱,假如可能,將長度限制為25個字符。此屬性的值必需是資源字符串,例如@string/shortcut_long_label

  • android:shortcutShortLabel:快捷方式的短名稱,長名稱顯示不下的情況下才會顯示短名稱,假如可能,將長度限制為10個字符。此屬性的值必需是資源字符串,例如 @string/shortcut_short_label

  • android:icon:快捷方式的圖標。

  • android:shortcutDisabledMessage:當客戶嘗試啟動已禁用的快捷方式時提醒的信息,用于向客戶解釋為什么禁用該快捷方式。假如android:enabled="true",即快捷方式是啟用的,那么此屬性的值無效。此屬性的值必需是資源字符串,例如@string/shortcut_disabled_message

  • android:enabled:能否啟用快捷方式,該值為true時,客戶點擊快捷方式可以啟動指定的Intent操作;該值為false時,還需要指定android:shortcutDisabledMessage,當客戶點擊快捷方式時會提醒該信息。禁用的快捷方式不會顯示出來,因而假如要禁用快捷方式,一般還是直接從xml文件中移除比較好。

上面的幾個屬性中,android:shortcutIdandroid:shortcutShortLabel是必需要配置的,否則快捷方式不會顯示,其余幾個都是可選擇的。

還需要在shortcut標簽內部配置Intent,指定點擊快捷方式時要執行的操作,和Activity的intent-filter相似,intent標簽有以下幾個屬性:

  • android:action:指定Intent要啟動的操作或者任務,該屬性必需要指定,否則不會顯示快捷方式。

  • android:targetClass:要跳轉的目標類。

  • android:targetPackage:要跳轉的目標應用包名。

關于Intent的配置測試了一下,假如只配置了action,在目標Activity的intent-filter中指定相同的action(注意不要不記得指定categoryandroid.intent.category.DEFAULT),就像Activity的隱式跳轉那樣,點擊快捷方式是可以啟動Activity的;假如intent-filter中指定的action不匹配或者者沒有配置intent-filter,點擊快捷方式會提醒“未安裝該應用”,這時假如同時配置了targetClasstargetPackage(兩個都要配置,否則也會提醒“未安裝該應用”),即可以正常跳轉了。

一個快捷方式可以配置多個Intent,點擊快捷方式后會顯示最后一個Intent指定的Activity,并將前幾個Intent指定的Activity加入到返回棧中。比方下面的配置,點擊快捷方式后,最后會顯示SettingActivity,點擊返回鍵會返回到MainActivity。

<intent    android:action="android.intent.action.MAIN"    android:targetClass="com.example.shortcutstest.MainActivity"    android:targetPackage="com.example.shortcutstest" /><intent    android:action="com.example.shortcutstest.SETTING"    android:targetClass="com.example.shortcutstest.SettingActivity"    android:targetPackage="com.example.shortcutstest" />

此外,shortcut標簽下還可以配置一個categories標簽,為應用程序快捷方式執行的操作類型提供分組,例如創立新的聊天消息,目前官方只提供了android.shortcut.conversation

2 在AndroidManifest.xml文件中配置
<application    android:allowBackup="true"    android:icon="@mipmap/ic_launcher"    android:label="@string/app_name"    android:roundIcon="@mipmap/ic_launcher_round"    android:supportsRtl="true"    android:theme="@style/AppTheme">    <activity android:name=".MainActivity">        <intent-filter>            <action android:name="android.intent.action.MAIN" />            <category android:name="android.intent.category.LAUNCHER" />        </intent-filter>        <meta-data            android:name="android.app.shortcuts"            android:resource="@xml/shortcuts" />    </activity></application>

需要注意,配置快捷方式的Activity必需滿足actionandroid.intent.action.MAIN并且categoryandroid.intent.category.LAUNCHER,即應用啟動頁面。
這樣就創立好了靜態快捷方式,最終實現的效果如下:

image.gif

靜態快捷方式的配置盡管很簡單,但也是有數量限制的,最多只能顯示4個,假如配置了超過4個,多余的則不會顯示,應用并不會報錯。
動態快捷方式。

除了靜態快捷方式,系統還提供了更加靈活的方式來增加快捷方式,即動態快捷方式(Dynamic Shortcuts),可以在應用運行過程中增加快捷方式。官方提供了一個類ShortcutManager,可以實現快捷方式的創立、升級和刪除等操作。

創立快捷方式

首先通過getSystemService(ShortcutManager.class)取得ShortcutManager對象。而后使用ShortcutInfo.Builder來構建快捷方式,采用建造者模式配置快捷方式的信息,方法名都很清楚,和靜態快捷方式的配置對照著看即可以,這里就不具體說了。最后調用ShortcutManagersetDynamicShortcuts()方法來設置快捷方式。完整代碼如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {    ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);    Intent settingIntent = new Intent(this, SettingActivity.class);    settingIntent.setAction("com.example.shortcutstest.SETTING");    ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, "setting")            .setShortLabel("設置")            .setLongLabel("設置")            .setIcon(Icon.createWithResource(this, R.drawable.ic_settings))            .setIntent(settingIntent)            .build();    shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutInfo));}

假如需要配置多個Intent也是可以的,在構建ShortcutInfo時調用setIntents()方法即可以了,參數傳入一個Intent數組。實現的效果和靜態快捷方式一樣,顯示最后一個Intent指定的Activity,并將前幾個Intent指定的Activity增加到返回棧中。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {    ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);    Intent mainIntent = new Intent(this, MainActivity.class);    mainIntent.setAction(Intent.ACTION_MAIN);    Intent settingIntent = new Intent(this, SettingActivity.class);    settingIntent.setAction("com.example.shortcutstest.SETTING");    ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, "setting")            .setShortLabel("設置")            .setLongLabel("設置")            .setIcon(Icon.createWithResource(this, R.drawable.ic_settings))            .setIntents(new Intent[]{mainIntent, settingIntent})            .build();    shortcutManager.setDynamicShortcuts(Arrays.asList(shortcutInfo));}

動態快捷方式也是有數量限制的,調用ShortcutManager的getMaxShortcutCountPerActivity()方法可以獲取Shortcut的最大個數(靜態和動態總共),該方法返回值是5,也就是最多可以增加5個快捷方式,但是實際上每個Launcher最多只能顯示4個快捷方式。針對快捷方式數量限制,我在自己的手機上測試了一下,情況如下:

1.靜態快捷方式等于或者超過5個,不配置動態快捷方式,應用不會報錯,最后只顯示4個快捷方式。
2.動態快捷方式配置5個,不配置靜態快捷方式,應用不會報錯,最后只顯示4個快捷方式。
3.動態快捷方式超過5個,不配置靜態快捷方式,應用拋出錯誤Max number of dynamic shortcuts exceeded
4.靜態快捷方式+動態快捷方式等于5個,最后只顯示4個快捷方式。
5.靜態快捷方式+動態快捷方式超過5個,應用拋出錯誤Max number of dynamic shortcuts exceeded

由此可以發現,靜態快捷方式和動態快捷方式最多能增加5個,但是實際上最多只能顯示4個,因而我們還是應該控制快捷方式的數量不超過4個,否則可能會導致應用Crash。
對于快捷方式的顯示順序,最前面顯示的是靜態快捷方式,而后是動態快捷方式,對于同一類快捷方式,內部默認是按照增加的順序排列的,即先增加的快捷方式顯示在前面,后增加的顯示在后面。這里所說的“前面”和“后面”是先相對于應用圖標而言的,越靠近應用圖標則順序越靠前(靠上還是靠下與應用圖標在屏幕中的位置有關),反之則靠后,如下圖所示。

可以通過ShortcutInfo的getRank()方法取得快捷方式的順序,數值為非負的連續整數,從0開始,值越小則順序越靠前。

// 取得所有的靜態快捷方式List<ShortcutInfo> staticShortcutList = shortcutManager.getManifestShortcuts();for (ShortcutInfo shortcutInfo : staticShortcutList) {    Log.e("TAG", "靜態快捷方式" + shortcutInfo.getId() + "的順序為:"            + shortcutInfo.getRank());}// 取得所有的動態快捷方式List<ShortcutInfo> dynamicShortcutList = shortcutManager.getDynamicShortcuts();for (ShortcutInfo shortcutInfo : dynamicShortcutList) {    Log.e("TAG", "動態快捷方式" + shortcutInfo.getId() + "的順序為:"            + shortcutInfo.getRank());}

在構建ShortcutInfo時可以調用ShortcutInfo.BuildersetRank()方法來改變默認的順序。盡管ShortcutInfo本身也有setRank()方法,但是該方法是@hide的,因而只有動態快捷方式才能改變顯示順序。
此外,addDynamicShortcuts()方法也可以用于增加動態快捷方式,從字面意思上我們也能知道它和setDynamicShortcuts()的不同,同樣可以增加快捷方式,setDynamicShortcuts()會覆蓋原有的快捷方式,而addDynamicShortcuts()是將快捷方式增加到原有的快捷方式列表中。

升級快捷方式

通過ShortcutManager的updateShortcuts(List<ShortcutInfo> shortcutInfoList)方法可以升級現有的快捷方式,構建ShortcutInfo時需要指定相同的id,根據id去找到要升級的快捷方式。需要注意只有動態快捷方式和后面要說的固定快捷方式才能升級,假如傳入了一個靜態快捷方式的id,應用會拋出錯誤Manifest shortcut ID=XX may not be manipulated via APIs

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);Intent intent = new Intent(this, SettingActivity.class);intent.setAction("com.example.shortcutstest.SETTING");ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, "setting")        .setShortLabel("設置升級")        .setLongLabel("設置升級")        .setIcon(Icon.createWithResource(this, R.drawable.ic_settings))        .setIntent(intent)        .build();shortcutManager.updateShortcuts(Arrays.asList(shortcutInfo));
刪除快捷方式

通過ShortcutManager的removeDynamicShortcuts(List<String> shortcutIds)方法可以刪除動態快捷方式,參數傳入要刪除的快捷方式id列表。和升級一樣,假如傳入靜態快捷方式的id會報錯。

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);mShortcutManager.removeDynamicShortcuts(Arrays.asList("setting"));

此外,還有一個removeAllDynamicShortcuts()方法,可以用來刪除所有的動態快捷方式。

需要注意,假如在刪除之前將快捷方式固定到了桌面上(這種稱作固定快捷方式,后面還會提到),在刪除之后該快捷方式的圖標不會消失,點擊后仍然可以完成正常跳轉。這種固定在桌面上的快捷方式只能客戶手動來移除,因而更好的一種做法是在刪除快捷方式后判斷該快捷方式能否被固定到了桌面上,假如是的話就再禁用該快捷方式,并提醒客戶該快捷方式已被刪除,禁用快捷方式的方法下面會提到。

// 取得所有的固定快捷方式List<ShortcutInfo> pinnedShortcutList = shortcutManager.getPinnedShortcuts();for (ShortcutInfo shortcutInfo : pinnedShortcutList) {    if (shortcutInfo.getId().equals("setting")) {        // 禁用被刪除的快捷方式        mShortcutManager.disableShortcuts(Arrays.asList("call"), "該快捷方式已被刪除");    }}
禁用快捷方式

通過ShortcutManagerdisableShortcuts()方法可以禁用快捷方式,第一個參數傳入要禁用的快捷方式id列表,第二個參數是disabledMessage,用于提醒客戶禁用快捷方式的起因,該參數也可以不傳。同樣地,不能通過該方法禁用靜態快捷方式,禁用靜態快捷方式是通過在xml文件中配置來實現的。

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);shortcutManager.disableShortcuts(Arrays.asList("setting"), "該快捷方式已被禁用");

禁用之后,長按應用圖標不會顯示該快捷方式,假如此前將快捷方式固定到了桌面上,禁用后圖標會變成灰色,點擊圖標會彈出提醒信息,即上面傳入的第二個參數disabledMessage,沒有傳的話就提醒默認信息。

固定快捷方式

固定快捷方式(Pinned shortcuts)指的是在桌面上顯示為一個圖標的快捷方式,下圖為官方給出的示用意。我們已經知道了可以通過拖拽來把創立好的靜態/動態快捷方式固定在桌面上,接下來詳情一下如何直接創立固定快捷方式。

在Android 8.0(API level 26)及更高版本上,系統支持直接創立固定快捷方式,創立的步驟如下:

1、通過ShortcutManager的isRequestPinShortcutSupported()方法判斷能否支持固定快捷方式,返回true表示支持,false表示不支持,該方法是Android 8.0才有的,因而在調用前需要判斷一下。也可以使用ShortcutManagerCompat.isRequestPinShortcutSupported(context)方法,該方法兼容了Android 8.0以下版本。

2、創立一個ShortcutInfo對象,指定要固定的快捷方式,假如要固定的是已經創立好的快捷方式,那么在構建ShortcutInfo時只要要傳id即可以了,需要注意固定的快捷方式不能是已禁用的,否則應用會報錯;假如要固定一個新的快捷方式,就像創立動態快捷方式那樣構建一個ShortcutInfo就好了。

3、通過requestPinShortcut()方法來固定快捷方式,該方法有兩個參數對象,第一個參數是我們上面創立好的ShortcutInfo對象,第二個參數是一個IntentSender對象,可以通過PendingIntent.getIntentSender()來取得,當固定快捷方式成功后,會執行該Intent指定的操作,包括啟動Activity、發送廣播等,假如固定快捷方式成功后不需要做額外解決的話該參數傳null即可以。

完整代碼如下:

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);if (shortcutManager.isRequestPinShortcutSupported()) {Intent intent = new Intent(this, SettingActivity.class);intent.setAction("com.example.shortcutstest.NAVIGATION");ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder(this, "navigation")        .setShortLabel("導航")        .setLongLabel("導航")        .setIcon(Icon.createWithResource(this, R.drawable.ic_navigation))        .setIntent(intent)        .build();// 注冊固定快捷方式成功廣播IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("com.example.shortcutstest.PINNED_BROADCAST");PinnedReceiver receiver = new PinnedReceiver();registerReceiver(receiver, intentFilter);Intent pinnedShortcutCallbackIntent = new Intent("com.example.shortcutstest.PINNED_BROADCAST");PendingIntent successCallback = PendingIntent.getBroadcast(this, 0,        pinnedShortcutCallbackIntent, 0);shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.getIntentSender());

這里注冊一個廣播接收器,當固定快捷方式成功時會發送廣播,我們可以在onReceive()方法中增加少量邏輯。

public class PinnedReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        Toast.makeText(context, "固定快捷方式成功", Toast.LENGTH_SHORT).show();    }}

固定快捷方式會彈出一個提醒對話框,客戶點擊確認后才會將快捷方式增加到桌面,并執行requestPinShortcut()方法第二個參數指定的操作。

和靜態/動態快捷方式不同,固定快捷方式是沒有數量限制的。動態快捷方式的升級和禁用方法也可以用在固定快捷方式中,但是固定快捷方式是無法通過代碼動態刪除的,只能通過客戶的手動操作才能刪除,以下三種方式可以刪除固定快捷方式:

  • 長按圖標移除

  • 進入應用設置頁面,選擇清理數據

  • 卸載應用

總結

本文主要詳情了Android 7.1版本的新特性——App shortcuts,即應用快捷方式,為客戶提供了App常用功能的快捷入口,省去了打開App跳轉指定頁面的操作。快捷方式有三種形式:

1)靜態快捷方式:在xml文件中配置,應用安裝之后無法進行升級、刪除和禁用,有數量限制。

2)動態快捷方式:在應用運行時通過代碼動態創立快捷方式,可以動態升級、刪除和禁用,有數量限制。

3)固定快捷方式:以桌面圖標的形式顯示,可以通過拖拽來把已創立好的靜態/動態快捷方式固定在桌面上。Android 8.0及以上版本支持直接創立固定快捷方式,需要客戶手動確認后才會創立桌面圖標,可以動態升級和禁用,刪除只能通過客戶手動操作,沒有數量限制。

最后說一下我自己的看法,盡管這個特性非常方便,但是它有一個很大的缺點就是不容易被發現,預計很多人可能還不知道這個功能,畢竟我們只有在卸載應用時才會長按應用圖標,而且現在使用了該特性的應用也不是很多,連微信這種主流App都沒有使用。作為開發者我們不光自己要理解這些特性,也應該讓更多的人理解到這樣的少量便捷特性。
本文的相關代碼我已經上傳到了github,大家假如有需要的話可以參考一下。

Demo地址: StephenZKCurry/ShortcutsTest

更多資料分享歡迎Android工程師朋友們加入安卓開發技術進階互助:856328774免費提供安卓開發架構的資料(包括Fultter、高級UI、性能優化、架構師課程、 NDK、Kotlin、混合式開發(ReactNative+Weex)和一線互聯網公司關于Android面試的題目匯總。
  • 全部評論(0)
最新發布的資訊信息
【系統環境|服務器應用】在CentOS 7上如何安裝Gogs 0.11.53(2020-02-10 10:14)
【系統環境|】淘碼庫,據消息稱已被調查。淘碼庫源碼網,已經無法訪問!(2020-01-14 04:13)
【系統環境|服務器應用】Discuz隱藏后臺admin.php網址修改路徑(2019-12-16 16:48)
【系統環境|服務器應用】2020新網站如何讓百度快速收錄網站首頁最新方法,親測有用!免費(2019-12-16 16:46)
【系統環境|服務器應用】Discuz發布帖子時默認顯示第一個主題分類的修改方法(2019-12-09 00:13)
【系統環境|軟件環境】Android | App內存優化 之 內存泄漏 要點概述 以及 處理實戰(2019-12-04 14:27)
【系統環境|軟件環境】MySQL InnoDB 事務(2019-12-04 14:26)
【系統環境|軟件環境】vue-router(單頁面應用控制中心)常見用法(2019-12-04 14:26)
【系統環境|軟件環境】Linux中的Kill命令(2019-12-04 14:26)
【系統環境|軟件環境】Linux 入門時必學60個文件解決命令(2019-12-04 14:26)
手機二維碼手機訪問領取大禮包
返回頂部
广东11选5今天开奖