前言
自Android 7.1.1 (即API = 25)開始支持shortcuts快捷方式,有點類似iphone 的 3D touch功能,在桌面長按app,會彈出一個菜單,其中有幾個事先定義好的菜單,當然還有分享和卸載,它的存在就是爲了讓用戶在不打開app的情況下快速啓動app內的其他功能模塊,比如說掃一掃、歷史記錄、全局搜索、熱門相冊、拍照識花等一些常用功能
開始使用
分類
App快捷方式
這類快捷方式需要用戶長按App圖標纔會彈出,可以對它執行的操作包括:添加、刪除、更新、禁用。
角標快捷方式
顧名思義,是把App宿主圖標放在右下角的快捷方式,它是怎麼產生的呢,是在App快捷方式彈出來的前提下,用戶再長按某一個快捷方式,按住拖動到桌面空白處即可產生角標快捷方式,對它執行的操作包括:添加、更新,此類快捷方式無法通過代碼刪除,只能用戶長按移除!Android8.0,系統才支持增加禁用角標快捷方式,
Androidx配置
1、gradle.properties中添加androidx支持
android.useAndroidX=true
android.enableJetifier=true
2、執行菜單重構 > 遷移到AndroidX
類似廣播一樣,可以靜態xml實現,也可以用java代碼動態實現
靜態實現
1、在res目錄下新建一個目錄,名叫xml,在這個xml目錄下新建一個xml文件,名叫shortcuts.xml文件,在其中添加shortcut標籤對,最多可添加 4 個,順序添加,在app長按時就是逆序顯示
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:shortcutDisabledMessage="@string/disable_msg_1"
android:shortcutId="cut_id_1"
android:shortcutLongLabel="@string/long_msg_1"
android:shortcutShortLabel="@string/short_msg_1">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.xmliu.itravel.ui.SplashActivity"
android:targetPackage="com.xmliu.itravel" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
<shortcut
android:enabled="false"
android:icon="@mipmap/ic_launcher"
android:shortcutDisabledMessage="@string/disable_msg_2"
android:shortcutId="cut_id_2"
android:shortcutLongLabel="@string/long_msg_2"
android:shortcutShortLabel="@string/short_msg_2">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.xmliu.myshortcutsdemo.MainActivity"
android:targetPackage="com.xmliu.myshortcutsdemo" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
</shortcuts>
首先來解釋一下其中的幾個屬性含義
- enabled:是否可用,和shortcutDisabledMessage搭配使用
- shortcutDisabledMessage:不可用時點擊子菜單時的文字提示,意思就是說當你長按app出現這兩個菜單時,你再長按其中一個菜單A,就可以把菜單A拖到桌面其他空白位置上繼續做成一個快捷方式,這時這個快捷方式的圖標右下角會有該app的小圖標提醒你這是哪個app的二級快捷方式,如果這個時候你在xml代碼裏把這個二級快捷方式的enable設置爲false,重新運行後,你會發現這個二級快捷方式已經變成灰色了,此時再點它就會提示這個shortcutDisabledMessage屬性鎖設置的值
- shortcutShortLabel:短標題,建議10個字符,二級快捷方式的標題默認會使用短標題
- shortcutLongLabel:長標題,建議25個字符,一般這種長按app彈出的菜單默認使用shortcutLongLabel,只有當shortcutLongLabel太長時,纔會使用shortcutShortLabel
- action:一個行爲,正常我們跳轉界面的話會使用View
- targetPackage:菜單跳轉的目標包名,這裏我設置成跳轉到另外一個我的app,這裏如果設置的包名在手機裏沒有的話,會提示找不到包名
- targetClass:菜單跳轉的目標類名,指定要跳轉哪一個界面,如果在上面的包名下沒有找到目標類名,會提示找不到
- categories :種類,這裏默認是android.shortcut.conversation,代表一個快捷方式會話
注意這裏的intent可以是多個
如果你的快捷方式與多個意圖相關聯,請將它們添加到這裏,列表中的最後一個意圖決定了用戶最先看到的內容。
如果你的快捷方式與多個意圖相關聯,系統將在資源文件中啓動與該快捷方式的最後一個意圖相對應的活動,
並在後方堆棧中執行其他活動 。在這種情況下,當用戶選擇快捷方式然後按下後退鍵時,您的應用程序將啓
動與資源文件中列出的快捷方式的倒數第二個意向對應的活動。這種行爲模式會一直重複按下後退按鈕,直
到用戶清除快捷方式創建的後臺堆棧。當用戶下一次按下後退按鈕時,系統將其導航回啓動器。
https://blog.csdn.net/MakerCloud/article/details/80842491
然後看一下其中string.xml下面的文字引用
<string name="short_msg_1">短按1</string>
<string name="long_msg_1">長名稱顯示不下就用短名稱1</string>
<string name="disable_msg_1">無效1</string>
<string name="short_msg_2">短按2</string>
<string name="long_msg_2">長名稱顯示不下嗎2</string>
<string name="disable_msg_2">無效2</string>
2、到全局清單配置文件中添加聲明這個shortcuts
<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>
注意:這裏只能添加到入口類這個activity裏
3、最後,到桌面長按app圖標看效果
動態實現
注意:如果manifest配置了shortcuts.xml,那麼會優先顯示靜態,只有靜態快捷方式圖標不滿足最大數量時,纔會去加載動態快捷方式
對動態快捷方式的操作又增加、刪除、修改、查詢,簡稱CRUD,就跟操作sql語句一樣
1、增加
添加角標快捷方式
shortcutManager.requestPinShortcut(ShortcutInfo info, PendingIntent.getIntentSender() intentSender);
添加App快捷方式
shortcutManager.addDynamicShortcuts(List<ShortcutInfo> infoList);
2、禁用(刪除)
讓某些快捷方式無效
shortcutManager.disableShortcuts(Arrays.asList(shortcutInfo.getId()), "暫無該快捷方式");
移除某些快捷方式
shortcutManager.removeDynamicShortcuts(Arrays.asList(shortcutInfo.getId()));
作者注:我覺得remove方法和disable方法都是讓某些快捷方式失效,實驗下來,發現確實是這樣
3、修改(更新)
shortcutManager.updateShortcuts(Arrays.asList(info));
4、查詢
獲取App快捷方式列表
List<ShortcutInfo> shortcutInfoList = shortcutManager.getDynamicShortcuts();
獲取角標快捷方式列表
List<ShortcutInfo> shortcutInfoList = shortcutManager.getPinnedShortcuts();
完整代碼
package com.xmliu.myshortcutsdemo;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ShortcutManager shortcutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
shortcutManager = getSystemService(ShortcutManager.class);
shortcutManager.getDynamicShortcuts();
Button delete = findViewById(R.id.delete);
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// addPinnedShortcuts("xml2);
// updateDynamicShortcuts("xml2");
// removeItem("xml2");
// removeShortcut("xml2");
deletePinnedShortcut("xml2");
}
});
initShortcuts();
}
/**
* 設置快捷方式
*/
private void initShortcuts() {
List<ShortItem> menuList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
ShortItem item = new ShortItem();
item.setShort_id("xml" + i);
item.setShort_name("張" + i);
item.setLong_name("同學:張" + i);
item.setRes(Icon.createWithResource(this, R.mipmap.ic_launcher));
menuList.add(item);
}
List<ShortcutInfo> infoList = new ArrayList<>();
for (int i = 0; i < shortcutManager.getMaxShortcutCountPerActivity(); i++) {
ShortItem item = menuList.get(i);
Intent intent = new Intent(this, SecondActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra("msg", "來自" + item.getShort_name() + "的視頻通話邀請");
ShortcutInfo info = new ShortcutInfo.Builder(this, item.getShort_id())
.setShortLabel(item.getShort_name())
.setLongLabel(item.getLong_name())
.setIcon(item.getRes())
.setIntent(intent)
.build();
infoList.add(info);
}
shortcutManager.setDynamicShortcuts(infoList);
}
/**
* 刪除功能1
*
* @param sid
*/
private void removeItem(String sid) {
List<ShortcutInfo> list = shortcutManager.getPinnedShortcuts();
for (ShortcutInfo shortcutInfo : list) {
if (shortcutInfo.getId().equals(sid)) {
shortcutManager.disableShortcuts(Arrays.asList(shortcutInfo.getId()), "暫無該快捷方式");
}
}
// shortcutManager.removeDynamicShortcuts(Arrays.asList(sid));
}
/**
* 刪除功能2
*
* @param shortId
*/
private void removeShortcut(String shortId) {
List<ShortcutInfo> infoList = shortcutManager.getDynamicShortcuts();
String shortcutId = null;
for (ShortcutInfo shortcutInfo : infoList) {
if (shortId.equals(shortcutInfo.getId())) {
shortcutId = shortcutInfo.getId();
}
}
if (shortcutId == null) {
Toast.makeText(this, "快捷方式不存在", Toast.LENGTH_SHORT).show();
} else {
List<String> list = new ArrayList<>();
list.add(shortcutId);
// shortcutManager.removeDynamicShortcuts(list);
shortcutManager.disableShortcuts(list, "暫無該同事");
Toast.makeText(this, "刪除快捷方式成功", Toast.LENGTH_SHORT).show();
}
}
/**
* 刪除功能3
* 禁用快捷方式(固定、動態、靜態)
*/
private void deletePinnedShortcut(String shortId) {
List<ShortcutInfo> shortcutInfoList = shortcutManager.getPinnedShortcuts();
for (ShortcutInfo info : shortcutInfoList) {
Log.i("xunming", "ShortcutInfo:" + info.getId());
if (info.getId().equals(shortId)) {
List<String> list = new ArrayList<>();
list.add(shortId);
shortcutManager.disableShortcuts(list, "快捷方式已失效");
}
}
}
/**
* 更新動態快捷鍵
*/
private void updateDynamicShortcuts(String shortId) {
List<ShortcutInfo> shortcutInfoList = shortcutManager.getDynamicShortcuts();
for (ShortcutInfo info : shortcutInfoList) {
if (info.getId().equals(shortId)) {
info = new ShortcutInfo.Builder(this, shortId)
.setShortLabel("Short" + System.currentTimeMillis())
.setLongLabel("Long" + System.currentTimeMillis())
.setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher))
.setIntent(new Intent(this, SecondActivity.class).setAction(Intent.ACTION_VIEW))
.build();
shortcutManager.updateShortcuts(Arrays.asList(info));
}
}
}
/**
* 添加固定快捷方式 可以添加多個,但如果僅添加一個的話建議每次添加前查看已添加的固定快捷鍵列表
*/
private void addPinnedShortcuts(String shortId) {
List<ShortcutInfo> shortcutInfoList = shortcutManager.getPinnedShortcuts();
for (ShortcutInfo info : shortcutInfoList) {
Log.i("xunming", "ShortcutInfo:" + info.getId());
}
if (shortcutManager.isRequestPinShortcutSupported()) {
ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder(this, shortId).build();
Intent pinnedShortcutCallbackIntent = shortcutManager.createShortcutResultIntent(pinShortcutInfo);
PendingIntent successCallback = PendingIntent.getBroadcast(this, 0, pinnedShortcutCallbackIntent, 0);
shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.getIntentSender());
}
}
}