快捷方式分类
Android快捷方式分为两种:应用快捷方式和固定快捷方式。它们分别长这个样子:
[站外图片上传中...(image-af1729-1630936305703)]
App shortcuts就是应用快捷方式,长按App图标弹出。
Pinned shortcuts就是固定快捷方式,固定显示在桌面上,跟Windows系统的桌面快捷方式一样。
应用快捷方式
应用快捷方式有如下几个特点:
- 在Android 7.1中引入应用快捷方式功能,之前的Android系统不支持。
- 最多可以添加五个,但是只能显示四个。
- 分为静态快捷方式和动态快捷方式
- 在Android 7.1中加入了ShortcutManager类,用于管理应用快捷方式。但是7.1中的ShortcutManager只能添加应用快捷方式,不能添加固定快捷方式。
- 在Android 8.0中,Google扩充了ShortcutManager,使8.0中的ShortcutManager统一管理所有的快捷方式。因此8.0中的ShortcutManager可以添加固定快捷方式,且添加应用快捷方式的API也有所调整。
- 不需要申请额外的系统权限。
静态快捷方式
静态快捷方式最适合在用户与应用互动的整个生命周期内使用一致结构链接到内容的应用。简单来说就是这个快捷方式适合那种不会变化的情况,比如设置闹钟、查看日历。
静态快捷方式通过xml配置的方式添加,且运行过程中不能更改,具体代码直接参考官方文档。
动态快捷方式
动态快捷方式用于应用中与上下文相关的操作。简单来说就是在运行过程中可以实时更新的快捷方式。比如,查询当地天气,当用户的定位改变后,在应用运行期就要更新查询天气的快捷方式(刷新快捷方式中的位置数据)。
动态快捷方式通过代码添加,需要使用ShortcutManager类,在运行过程中可以随时更改,具体代码直接参考官方文档。
固定快捷方式
固定方式有如下几个特点:
- 所有Android版本都有,独立显示在桌面上。
- 没有数量限制。
- 在Android 8.0以下,通过发送系统广播的方式添加。
- 在Android 8.0及以上,通过ShortcutManager添加。
- 在Android 8.0以下,需要申请额外的系统权限,且启动的Activity/Service需要设置exported=true。
-
在Android 8.0及以上,由ShortcutManager类统一管理,不需要申请额外的系统权限,且不需要设置exported=true,只是在添加快捷方式的过程中,需要用户同意。
在Android 8.0以下添加固定快捷方式
- 申请系统权限
如果没有权限,不能创建固定快捷方式<!-- android o 以下创建桌面快捷方式需要如下权限--> <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" /> <!-- 添加快捷方式 --> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <!-- 移除快捷方式 --> <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> <!-- 查询快捷方式 --> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
- 设置快捷启动的Activity/Service
必须设置exported=true,否则快捷方式不能启动。<activity android:name=".MainActivity2" android:exported = "true"> </activity>
- 添加固定快捷方式的代码
fun addDeskTopShortCutUnderO() { //创建Intent对象 val shortcutIntent = Intent() //设置点击快捷方式,进入指定的Activity shortcutIntent.component = ComponentName(requireActivity().packageName, "com.example.myapplication.MainActivity2") //给Intent添加 对应的flag shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or Intent.FLAG_ACTIVITY_NEW_TASK) //传递参数 shortcutIntent.putExtra("key1", "value1") shortcutIntent.putExtra("key2", "value2") val resultIntent = Intent() //设置Action resultIntent.action = "com.android.launcher.action.INSTALL_SHORTCUT" //设置快捷方式的图标 resultIntent.putExtra( Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext( activity, R.drawable.ic_launcher_background ) ) //设置快捷方式的名称 resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "shortCut") //设置启动的Intent resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent) //发送广播,通知系统创建桌面快捷方式 requireActivity().sendBroadcast(resultIntent) }
在Android 8.0及以上添加固定快捷方式
- 因为ShortcutManager统一管理Android的所有快捷方式,所以不需要额外申请任何系统权限,也不需要额外设置Activity/Service。
- 添加固定快捷方式的代码
@RequiresApi(api = Build.VERSION_CODES.O)
fun addNewDesktopShotCut() {
val shortcutManager = requireContext().getSystemService(ShortcutManager::class.java)
if (shortcutManager!!.isRequestPinShortcutSupported) {
val intent = Intent(activity, MainActivity2::class.java)
intent.setAction(Intent.ACTION_VIEW) //必须设置,可以直接使用Intent.ACTION_VIEW
intent.putExtra("key", "value") //传递参数
val pinShortcutInfo = ShortcutInfo.Builder(context, "shortcutId")
.setShortLabel("shortCut")
.setLongLabel("desktopShotCut")
.setIcon(Icon.createWithResource(context, R.drawable.ic_launcher_background))
.setIntent(intent)
.build()
val pinnedShortcutCallbackIntent =
shortcutManager.createShortcutResultIntent(pinShortcutInfo)
val successCallback = PendingIntent.getBroadcast(
context, /* request code */ 0,
pinnedShortcutCallbackIntent, /* flags */ 0
)
shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.intentSender)
}
}
使用ShortcutManagerCompat添加固定快捷方式
ShortcutManagerCompat是androidx提供的类,用于兼容Android 8.0以下的系统。ShortcutManagerCompat可以让我们使用统一的API,在所有Android系统上,管理所有的快捷方式。
因此使用ShortcutManagerCompat添加固定快捷方式,可以屏蔽Android系统的差异,是目前的最优解。
- 引入依赖
implementation "androidx.core:core:1.6.0-rc01"
- 添加固定快捷方式的代码
/**
* 测试在android 6.0 和 android 8.0 系统上都可以
* 使用androidx库,兼容高低系统版本
*/
fun addDeskTopShortCutCompat() {
if (ShortcutManagerCompat.isRequestPinShortcutSupported(requireActivity())) {
val intent = Intent(activity, MainActivity2::class.java)
intent.setAction(Intent.ACTION_VIEW) //必须设置,否则报错
intent.putExtra("key", "value")
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) //设不设置都行
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) //设不设置都行
val pinShortcutInfo = ShortcutInfoCompat.Builder(requireContext(), "shortcutCompatId")
.setShortLabel("shortCutCompat")
.setLongLabel("desktopShotCutCompat")
.setIcon(
IconCompat.createWithResource(
requireContext(),
R.drawable.ic_launcher_background
)
)
.setIntent(intent)
.build()
val pinnedShortcutCallbackIntent =
ShortcutManagerCompat.createShortcutResultIntent(requireContext(), pinShortcutInfo)
val successCallback = PendingIntent.getBroadcast(
context, /* request code */ 0,
pinnedShortcutCallbackIntent, /* flags */ PendingIntent.FLAG_UPDATE_CURRENT
)
ShortcutManagerCompat.requestPinShortcut(
requireContext(),
pinShortcutInfo,
successCallback.intentSender
)
}
}
- 虽然使用统一的API,但是在Android 8.0以下的系统上,仍然需要申请系统权限和设置快捷启动的Activity/Service的
exported=true
。