Android 7.1 新特性:快捷方式 Shortcuts 詳解

Android 7.1 新特性:快捷方式 Shortcuts 詳解

一、Shortcuts 介紹

Android 7.1 允許 App 自定義 Shortcuts,類似 iOS 的 3D touch。通過在桌面長按 App 彈出 Shortcut 列表,點(diǎn)擊某個(gè) Shortcut 快速進(jìn)入某項(xiàng)操作,同時(shí) Shortcut 可以拖動(dòng)到桌面進(jìn)行固定,如下圖:

android-7.1-app-shortcuts

1. Shortcuts 作用及分類

Shortcuts 為 App 常用操作提供了快速訪問的方式,如上面日歷的新建提醒。

這個(gè)功能目前只能在 Android 7.1 系統(tǒng)桌面進(jìn)行使用,這個(gè)依然保留著“應(yīng)用抽屜”古老設(shè)計(jì)的產(chǎn)品國內(nèi)應(yīng)該沒多少用戶。三方桌面可以通過 API 接入這個(gè)功能。
目前支持 Shortcut 的應(yīng)用主要還是 Google 的 App,看到有即刻的朋友說他們在 7.1 系統(tǒng)發(fā)布時(shí)快速支持了這個(gè)功能并上線,速度很贊。

類似 BroadcastReceiver 可通過靜態(tài)和動(dòng)態(tài)方式注冊,Shortcuts 也可以通過靜態(tài)和動(dòng)態(tài)方式添加。

2. 靜態(tài) Shortcuts(Static Shortcuts)

靜態(tài) ShortcutsStatic Shortcuts通過在 Manifest 中聲明添加。缺點(diǎn)是不可以修改,只能通過應(yīng)用升級來添加新的靜態(tài) Shortcuts。添加主要分為兩步:

2.1 AndroidManifest.xml 的 Main Launcher 對應(yīng)的 Activity 內(nèi)添加 meta-data meta-data nameandroid.app.shortcuts,如下:

<application
    ……>
    <activity android:name=".main.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>

必須在 Main Launcher 對應(yīng)的 Activity 內(nèi)設(shè)置,其中android:resource指向定義了 shortcuts 的資源文件。

2.2 資源文件中定義具體的 shortcuts
res 目錄下新建 xml 文件夾,并新建 shortcuts.xml 文件,內(nèi)容如下:

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <shortcut
        android:enabled="true"
        android:icon="@drawable/search"
        android:shortcutId="search"
        android:shortcutDisabledMessage="@string/disabled"
        android:shortcutLongLabel="@string/menu_label"
        android:shortcutShortLabel="@string/launcher_label">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="cn.trinea.android.demo.SearchActivity"
            android:targetPackage="cn.trinea.android.demo"/>
        <intent
            ……/>
    </shortcut>
    ……
</shortcuts>

以shortcuts元素為根,可以包含多個(gè)shortcut元素,每個(gè)shortcut元素表示一個(gè) shortcut。其中屬性分別表示:

  1. shortcutId表示 shortcut 唯一標(biāo)識符,相同的 shortcutId 會(huì)被覆蓋。必須字段。
  2. shortcutShortLabel為將 shortcut 拖動(dòng)到桌面時(shí)顯示的名字,官方建議不超過 10 個(gè)字符,必須字段。
  3. shortcutLongLabel為 shortcut 列表中每個(gè) shortcut 的名字,不宜過長,如果過長或未設(shè)置默認(rèn)會(huì)顯示 ShortLabel,官方建議不超過 25 個(gè)字符。可選字段。
  4. icon為 shortcut 的 icon,在列表展示和拖動(dòng)到桌面時(shí)顯示需要,可選字段。
  5. enabled表示 shortcut 是否可用,false 表示禁用。xml 中這個(gè)屬性幾乎沒有被設(shè)置為 false 的實(shí)際場景,具體原因可見6.7 如何更好的刪除(廢棄)老的 Shortcut中介紹。
  6. shortcutDisabledMessage為已固定在桌面的 shortcut 被 Disabled 后點(diǎn)擊時(shí)的 Toast 提示內(nèi)容。可選字段。
  7. intent為點(diǎn)擊 shortcut 時(shí)響應(yīng)的 Intent,必須字段。

這里可以添加多個(gè) Intent,但點(diǎn)擊時(shí)不會(huì)啟動(dòng)所有 Intent,而是啟動(dòng)最后一個(gè) Intent,在這個(gè) Intent 回退時(shí)會(huì)啟動(dòng)它前面一個(gè) Intent,相當(dāng)于自動(dòng)將所有 Intent 添加到了堆棧。
對于先跳轉(zhuǎn)到某個(gè)頁面,Back 鍵希望退回主頁而不是結(jié)束 App 這類場景,多個(gè) Intents 挺實(shí)用的。

intent可設(shè)置屬性包括:
android:action、android:data、android:mimeType、android:targetClass、android:targetPackage
其中android:action為必須屬性。

3. 動(dòng)態(tài) Shortcuts(Dynamic Shortcuts)

動(dòng)態(tài) ShortcutsDynamic Shortcuts 通過 ShortcutManager API 進(jìn)行操作。可以動(dòng)態(tài)添加、修改、刪除。

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) {
    return;
}

ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
    .setShortLabel("trinea.cn")
    .setLongLabel("Open trinea.cn")
    .setDisabledMessage("Disabled")
    .setIcon(Icon.createWithResource(context, R.drawable.trinea_cn))
    .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.trinea.cn/")))
    .build();
shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));

通過ShortcutInfo.Builder新建 ShortcutInfo,再通過shortcutManager添加即可。其他:

  1. setDynamicShortcuts(List)可以替換并添加所有 shortcut 列表;
  2. addDynamicShortcuts(List)可以添加新的 shortcut 到列表,超過最大個(gè)數(shù)會(huì)報(bào)異常;
  3. updateShortcuts(List)可以更新一組 shortcuts;
  4. removeDynamicShortcuts(List)和removeAllDynamicShortcuts() 可以刪除部分或所有 shortcuts。

ShortcutInfo的屬性與 xml 中定義字段含義一致,shortcutId shortcutShortLabel intent 是必須設(shè)置的字段,并且intent必須設(shè)置Action。

4. 固定的 Shortcuts(Pinned Shortcuts)

指通過拖動(dòng)固定到桌面的 Shortcuts,App 不可以添加、修改、刪除這些 Shortcuts,只能禁用他們。即便 App 內(nèi)刪除了某個(gè) Shorcut,對應(yīng)的已固定到桌面的 Shortcuts 也不會(huì)被刪除。

可以通過:

  1. getPinnedShortcuts()得到所有固定的 Shortcuts 的信息。
  2. disableShortcuts(List)或disableShortcuts(List, CharSequence)禁用動(dòng)態(tài)的 Shortcuts。

對于靜態(tài)的 Shortcuts 需要在資源文件中設(shè)置android:enabled="false"進(jìn)行禁用,不過沒有必要,靜態(tài) Shortcuts 可直接通過刪除達(dá)到禁用的效果,具體原因可見6.7 如何更好的刪除(廢棄)老的 Shortcut中介紹。

靜態(tài) Shortcuts 和動(dòng)態(tài) Shortcuts 是有最大個(gè)數(shù)限制的,默認(rèn)為 5,超過最大個(gè)數(shù)后添加會(huì)報(bào)異常。而固定的 Shortcuts 并沒有個(gè)數(shù)限制,并且固定的 Shortcut 對應(yīng)的 Shortcut 即便被動(dòng)態(tài)刪除了,依然可以通過 id 進(jìn)行 Update 操作。

5. 其他

5.1 動(dòng)態(tài) Shortcuts 與靜態(tài) Shortcuts 區(qū)別

  1. 靜態(tài) Shortcuts 只能通過升級應(yīng)用修改,動(dòng)態(tài) Shortcuts 隨時(shí)可以修改;
  2. 靜態(tài) Shortcuts 的 Intent 無法設(shè)置 Flag,默認(rèn)為FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TASK Flag,即若應(yīng)用運(yùn)行中會(huì)清除所有已存在的 Activity。動(dòng)態(tài) Shortcuts 的 Intent 可以設(shè)置 Flag;
  3. 靜態(tài) Shortcuts 的rank系統(tǒng)默認(rèn)根據(jù)聲明順序設(shè)置,動(dòng)態(tài) Shortcuts 的rank可以通過setRank(int rank)接口主動(dòng)設(shè)置,rank 不能小于 0,值越大表示在 shortcut 列表展示時(shí)離 App Icon 越遠(yuǎn)。靜態(tài) Shortcuts 默認(rèn)比動(dòng)態(tài) Shortcuts 離 App Icon 更近。
  4. 靜態(tài) Shortcuts 刪除可以直接刪除,動(dòng)態(tài) Shortcuts 建議通過禁用刪除;

5.2 動(dòng)態(tài) Shortcuts 操作的頻率問題

當(dāng)應(yīng)該完全退到后臺(無 Activity 或 Service 在前臺時(shí)),其操作 Shortcut(包括添加、刪除、修改) 的頻率是受限的。可通過isRateLimitingActive()查詢是否已受限,true表示已受限。

5.3 跟蹤 Shorcut 使用情況

在 Shortcut 被選擇或者其關(guān)聯(lián)的操作被操作時(shí)需調(diào)用reportShortcutUsed(String shortcutId)接口上報(bào)數(shù)據(jù),為了方便啟動(dòng)器收集應(yīng)用 Shortcuts 使用情況,以便未來進(jìn)行預(yù)測或者向開發(fā)者展示哪些操作適合作為 Shortcuts 以及其優(yōu)先級。

PS:這個(gè)接口其實(shí)挺尷尬的,一方面需要 App 主動(dòng)上報(bào),侵入性太強(qiáng)。另一方面這個(gè)預(yù)測功能未來也不好加到 Shortcuts 推薦里,更多是個(gè)開發(fā)工具相關(guān)功能。
最好是由啟動(dòng)器自己純粹收集 Shortcut 被選擇的使用情況數(shù)據(jù),而不需要統(tǒng)計(jì) Shortcut 被關(guān)聯(lián)操作通過其他方式調(diào)用的使用情況數(shù)據(jù)。至于哪些操作適合作為 Shortcuts,開發(fā)者大可通過其他監(jiān)控 SDK 去判斷。

5.4 應(yīng)用備份

如果應(yīng)用通過備份恢復(fù)到另外一臺機(jī)器上,固定的 Shortcuts 是可以直接恢復(fù)的,不過啟動(dòng)器不保存這些 Shortcut 的 icon,所以應(yīng)用內(nèi)需要存在這些 icon 對應(yīng)的資源以便啟動(dòng)器能找到。

靜態(tài) Shortcuts 需要應(yīng)用重新安裝、升級才能生效。
動(dòng)態(tài) Shortcuts 需要相應(yīng)代碼被執(zhí)行過才能生效。

二、Shortcuts 一些實(shí)踐&問題

6. 最佳實(shí)踐

這塊官網(wǎng)已經(jīng)給出了一部分建議,包括:

  1. 設(shè)計(jì)上和系統(tǒng) App 的 Shortcuts 保持一致。
  2. 最多添加 4 個(gè) Shortcuts 以保持在啟動(dòng)器中顯示的樣式最佳
    目前雖然說是 5 個(gè),但實(shí)際最多只能添加 4 個(gè),可見7.2 Shortcut 添加或修改無效中介紹。
  3. 限制 Label 長度
    其中shortcutShortLabel建議不超過 10 個(gè)字符,shortcutLongLabel 建議不超過 25 個(gè)字符。這塊可能有些問題,可見7.1 LongLabel 和 ShortLabel中介紹。
  4. 記錄 Shortcut 及其對應(yīng)操作使用記錄。
    這個(gè)在5.3 跟蹤 Shorcut 使用情況中已經(jīng)介紹了。
  5. 只在 Shortcut 意義不變的情況下更新,否則新增。
  6. 動(dòng)態(tài) Shortcuts 在 BackUp 恢復(fù)后不可以直接恢復(fù),考慮適時(shí)新增或更新已有的 Shortcuts
    除了以上這些外,個(gè)人覺得還有幾點(diǎn)需要遵守:
  7. 如何更好的刪除(廢棄)老的 Shortcut
    這里主要考慮到刪除老的 Shortcut,可能會(huì)影響已經(jīng)固定的 Shortcut。
    對于靜態(tài) Shortcuts,直接刪除配置文件中對應(yīng)的 Shortcut 即可,系統(tǒng)桌面會(huì)將已固定的該 Shortcut 置灰,點(diǎn)擊會(huì)提示 shortcutDisabledMessage。
    對于動(dòng)態(tài) Shortcuts 建議通過禁用的方式而不是直接刪除的方式,因?yàn)橐呀?jīng)刪除的動(dòng)態(tài) Shortcut 如果被固定了依然是可用的,所以希望該入口不可用最好的方式是禁用。
  8. 始終設(shè)置shortcutDisabledMessage
    根據(jù)上面的介紹廢棄老的 Shortcut 較好的方式是禁用,通過自定義shortcutDisabledMessage去更友好的提示用戶。
  9. 動(dòng)態(tài)添加 Shortcut 前需要判斷 API 版本不小于 25
    否則在低版本會(huì)報(bào) ClassNotFoundException 異常。

7. 一些問題

7.1 LongLabel 和 ShortLabel

LongLabel和ShortLabel的含義,官方 API 文檔解釋的并不是很清楚。
在 Nexus 6 上測試,當(dāng) LongLabel 長度大于 17 個(gè)小寫字符時(shí),會(huì)顯示 ShortLabel,而不是 LongLabel。這里的界限長度跟大小寫、空格都有關(guān),應(yīng)該是受限于桌面 Shortcuts 列表 Item 的寬度!

7.2 Shortcut 添加、修改、點(diǎn)擊無效

可能原因:

  1. shortcutId 被覆蓋
    shortcutId 是唯一標(biāo)識,相同 shortcutId 會(huì)被覆蓋。
  2. intent 不對
    intent 必須設(shè)置 android:action 屬性,同時(shí)目標(biāo) Activity 必須有效即已在 Manifest 中聲明。
  3. 后臺 App 有頻率限制
    當(dāng)應(yīng)該完全退到后臺(無 Activity 或 Service 在前臺時(shí)),其操作 Shortcut(包括添加、刪除、修改) 的頻率是受限的。可通過isRateLimitingActive()查詢是否已受限,true表示已受限。
    若已受限,可通過開發(fā)者選項(xiàng)中“重置 ShortcutManager 調(diào)用頻率限制”或命令行adb shell cmd shortcut reset-throttling [ --user USER-ID ]解決。
  4. Shortcut 個(gè)數(shù)限制
    雖然官方文檔介紹靜態(tài)和動(dòng)態(tài) Shortcut 總和不能超過 5 個(gè),通過getMaxShortcutCountPerActivity()得到的也是 5,但實(shí)際測試下來是不超過4個(gè)!即靜態(tài)和動(dòng)態(tài)shortcuts加起來總數(shù)最多是五個(gè).
    當(dāng)我們嘗試添加第六個(gè)shortcut時(shí), 應(yīng)用會(huì)拋出異常:
    java.lang.IllegalArgumentException: Max number of dynamic shortcuts exceeded.
    雖然總數(shù)限制是5個(gè), 但是當(dāng)我正好有5個(gè)(2個(gè)靜態(tài) + 3個(gè)動(dòng)態(tài))的時(shí)候, 長按只顯示了4個(gè)shortcuts.
android-7.1-app-shortcuts數(shù)量的限制

7.3 getIntents() 有 Bug

getIntents() 實(shí)現(xiàn) 中可以看出未做mIntents是否為 null 及 empty 的判斷,在 null 時(shí)會(huì)出現(xiàn):

java.lang.NullPointerException: Attempt to get length of null array

的異常。

8. 三方桌面支持 Shortcuts——LauncherApps

如果三方桌面希望支持這個(gè)特性,請參考 LauncherApps API 介紹,不過只有系統(tǒng)默認(rèn)桌面才有權(quán)限得到其他 App Shortcuts 信息。

可通過hasShortcutHostPermission()查看是否擁有權(quán)限,如果沒有權(quán)限,會(huì)報(bào)如下異常:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xx/com.xx.XXActivity}: 
java.lang.SecurityException: Caller can't access shortcut information
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)

通過getShortcuts API 獲取到所有 Shortcuts 信息。

參考:
App Shortcuts的官方文檔: App Shortcuts
Exploring Android Nougat 7.1 App Shortcuts

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,468評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內(nèi)容