文章目录
- 前言
- 开始使用
- 分类
- App快捷方式
- 角标快捷方式
- Androidx配置
- 静态实现
- 动态实现
- 1、增加
- 2、禁用(删除)
- 3、修改(更新)
- 4、查询
- 完整代码
前言
自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
<?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可以是多个
如果你的快捷方式与多个意图相关联,请将它们添加到这里,列表中的最后一个意图决定了用户最先看到的内容。
如果你的快捷方式与多个意图相关联,系统将在资源文件中启动与该快捷方式的最后一个意图相对应的活动,
并在后方堆栈中执行其他活动 。在这种情况下,当用户选择快捷方式然后按下后退键时,您的应用程序将启
动与资源文件中列出的快捷方式的倒数第二个意向对应的活动。这种行为模式会一直重复按下后退按钮,直
到用户清除快捷方式创建的后台堆栈。当用户下一次按下后退按钮时,系统将其导航回启动器。
然后看一下其中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());
}
}
}