Android-Shortcuts,让你在系统桌面上为所欲为

文章介绍了Android中动态快捷方式的创建、管理,包括setDynamicShortcuts方法、ShortcutInfo配置、桌面快捷方式的创建与限制,以及如何处理快捷方式的显示顺序、intent配置、更新和限制等问题。此外,还提到了一些进阶使用技巧,如移除快捷方式、系统设置变化对Shortcuts的影响和频率限制。
摘要由CSDN通过智能技术生成

android:name=“android.app.shortcuts”
android:resource=“@xml/shortcuts” />

创建新的资源文件:res/xml/shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>

具体参数配置说明如下:

如果有数据的传递,要有对应的解析

if (getIntent().getData() != null && TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
Uri uri = getIntent().getData();
List pathSegments = uri.getPathSegments();
if (pathSegments != null && pathSegments.size() > 0) {
tvTest.setText(pathSegments.get(0));
}
}

最终的运行效果:

创建动态快捷方式

动态快捷方式提供向指向应用内特定的跳转或数据传递,这些跳转和数据可能会在应用执行中发生变化。

此时需要借助 ShortcutManager 提供的 API 来完成动态快捷方式的相应操作:

  • 创建: 使用 setDynamicShortcuts() 重新定义动态快捷方式的完整列表
  • 添加: 使用 addDynamicShortcut() 来扩充现有的动态快捷方式列表
  • **更新: **使用 updateShortcuts() 方法进行更新现有的动态快捷方式列表
  • 删除: 使用 removeDynamicShortcuts() 移除一组动态快捷方式,或者使用 removeAllDynamicShortcuts() 移除所有动态快捷方式

以创建为例,其他差不多,自行尝试,具体的操作可参考下面的代码:

1. 创建 ShortcutInfo 对象

@TargetApi(Build.VERSION_CODES.N_MR1)
private ShortcutInfo createShortcutInfo1() {
return new ShortcutInfo.Builder(this, ID_DYNAMIC_1)
.setShortLabel(getString(R.string.dynamic_shortcut_short_label1))
.setLongLabel(getString(R.string.dynamic_shortcut_long_label1))
.setIcon(Icon.createWithResource(this, R.drawable.add))
.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(“http://xiaweizi.cn/”)))
.build();
}

2. 调用 setDynamicShortcuts() 覆盖掉之前的,重新设置新的动态快捷方式列表

private void setDynamicShortcuts() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
List shortcutInfo = new ArrayList<>();
shortcutInfo.add(createShortcutInfo1());
shortcutInfo.add(createShortcutInfo2());
if (shortcutManager != null) {
shortcutManager.setDynamicShortcuts(shortcutInfo);
}
}
}

3. 可以配置 label 的字体颜色

@TargetApi(Build.VERSION_CODES.N_MR1)
private ShortcutInfo createShortcutInfo2() {
Intent intent = new Intent(this, TestActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(“key”, “fromDynamicShortcut”);
ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.BLUE);
String label = getResources().getString(R.string.dynamic_shortcut_short_label2);
SpannableStringBuilder colouredLabel = new SpannableStringBuilder(label);
colouredLabel.setSpan(colorSpan, 0, label.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
return new ShortcutInfo.Builder(this, ID_DYNAMIC_2)
.setShortLabel(colouredLabel)
.setLongLabel(getString(R.string.dynamic_shortcut_long_label2))
.setIcon(Icon.createWithResource(this, R.drawable.link))
.setIntent(intent)
.build();
}

最终的运行效果:

创建桌面快捷方式

在 Android 8.0(API26)或者更高的版本上,可以创建桌面快捷方式。与静态和动态快捷方式不同,桌面快捷方式支持在设备上单独的 icon 展示。

如果想创建桌面快捷方式,按照以下步骤进行完成:

1. 使用 isRequestPinShortcutSupported() 来验证设备是否支持应用创建桌面快捷方式
2. 根据快捷方式是否已经存在,用下面两种方式之一来创建 ShortcutInfo 对象:
3. 如果快捷方式已经存在,请创建仅包含现有快捷方式 id 的 ShortcutInfo 对象,系统自动查找并带上与快捷方式有关的所有相关数据
**4.**如果要固定新的快捷方式,请创建一个 ShortcutInfo 对象,其中包含新的快捷方式 id、意图和短标签
5. 尝试通过调用 requestPinShortcut() 将快捷方式固定到设备桌面上,在此过程中,可以传入 pendingIntent 对象,该对象仅在快捷方式成功固定时告知应用。

具体的代码可参考下面:

private void createPinnedShortcuts() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
if (shortcutManager != null && shortcutManager.isRequestPinShortcutSupported()) {
Intent intent = new Intent(this, TestActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(“key”, “fromPinnedShortcut”);
ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder(this, “my-shortcut”)
.setShortLabel(getString(R.string.pinned_shortcut_short_label2))
.setLongLabel(getString(R.string.pinned_shortcut_long_label2))
.setIcon(Icon.createWithResource(this, R.drawable.add))
.setIntent(intent)
.build();
Intent pinnedShortcutCallbackIntent = shortcutManager.createShortcutResultIntent(pinShortcutInfo);
PendingIntent successCallback = PendingIntent.getBroadcast(this, 0,
pinnedShortcutCallbackIntent, 0);
boolean b = shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.getIntentSender());
Utils.showToast(this, "set pinned shortcuts " + (b ? “success” : “failed”) + “!”);
}
}
}

最终运行效果:

好了,基础简单的使用就介绍到这了,相信对 Shortcuts 的使用场景和具体实现都有一定的了解了,接下来开始介绍进阶的使用。

##Shortcuts进阶使用

快捷方式创建完成后,可能还需要对其进行管理,比如动态更新或者禁用某些快捷方式,此时就需要了解一些进阶的使用了。

移除 Shortcut

对于 静态快捷方式 而言,其在一开始就打包到了 apk 或者 apk bundle 中,是不允许对其进行更改的,除非发布新的版本覆盖掉之前的快捷方式,不然会一直存在。

对于 动态快捷方式 ,既然可以在代码中进行创建,同样也可以在代码中进行移除,这个之前也介绍过。

而对于 桌面快捷方式,它直接展示在桌面上,始终可见,仅在以下情况才能删除桌面快捷方式。

  • 用户主动移除
  • 卸载与快捷方式的应用
  • 用户在应用信息中,清除全部的缓存数据
Shortcut 展示顺序

对于一个应用上所有的快捷方式,展示的规则按照以下顺序:

  1. 静态快捷方式: isDeclaredInManifest() 放回 true 的快捷方式
  2. 动态快捷方式:ShortcutInfo.isDynamic() 返回 true 的快捷方式

在每种快捷方式中,又会按照 ShortcutInfo.getRank() 按等级递增的顺序排序。等级是非负的,连续的整数, 调用 updateShortcuts(List),addDynamicShortcuts(List) 或 setDynamicShortcuts(List) 时,可以更新现有快捷方式的等级。

排名是自动调整的,因此它们对于每种类型的快捷方式都是唯一的。 例如,有三个 rank 分别为 0、1和2 的动态快捷方式,此时再添加一个 rank 为 1 的动态快捷方式放在第二的位置上,那最后两个就会被顺延一个位置,rank 变成 2和3。

Shortcut intents 配置

如果希望应用在用户激活快捷方式时执行多项操作,则可以将其配置为触发后多项活动。你可以通过分配多个 intent,启动一个 activity 到另一个 activity,具体的要取决你快捷方式的类型。

使用 ShortcutInfo.Builder 创建快捷方式时,可以使用 setIntents() 而不是 setIntent()。通过调用 setIntents() 你可以在用户点击快捷方式时触发多个 activity,将除列表中最后一个 activity 之外的所有 activity 放在后续堆栈中。如果此时点击返回按钮,会按照之前存储的堆栈 activity 顺序进行展示,而不是直接回到首页。

比如按照下面代码配置多个 intent:

@TargetApi(Build.VERSION_CODES.N_MR1)
private ShortcutInfo createShortcutInfo1() {
Intent intent1 = new Intent(Intent.ACTION_VIEW, Uri.parse(“http://xiaweizi.cn/”));
Intent intent = new Intent(this, TestActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(“key”, “fromDynamicShortcut”);
return new ShortcutInfo.Builder(this, ID_DYNAMIC_1)
.setShortLabel(getString(R.string.dynamic_shortcut_short_label1))
.setLongLabel(getString(R.string.dynamic_shortcut_long_label1))
.setIcon(Icon.createWithResource(this, R.drawable.add))
.setIntents(new Intent[]{intent, intent1})
.build();
}

那么它会一次触发 intent 和 intent1,此时 intent 被压入 intent1 的栈底,点击返回,则展示 intent 的信息。如图:

还有一个问题,静态快捷方式是不能拥有自定的 intent flag 的,静态快捷方式始终设置为 Intent.FLAG_ACTIVITY_NEW_TASK 和 Intent.FLAG_ACTIVITY_CLEAR_TASK 这意味着,当应用程序已经在运行时,启动静态快捷方式时,应用中所有的活动都将被销毁。

如果不希望出现这种情况,可以使用 trampoline activity,或者在 Activity.onCreate(Bundle) 中启动一个 不可见的 activity,然后调用 Activity.finish()。

1. 在 AndroidManifest.xml 中, trampoline activity 应用设置 android:taskAffinity=“”。

2. 在快捷方式资源文件中,静态快捷方式中的 intent 应引用 trampoline activity。

更新 pinned Shortcuts

每个应用最多包含 getMaxShortcutCountPerActivity() 个快捷方式,其中包括动态和静态的总和。但是桌面快捷方式的数量是不限制的。

当动态快捷方式被放置到桌面时,即使代码中将该动态快捷方式移除,桌面的还依然存在,因此对于桌面的快捷方式是不止 getMaxShortcutCountPerActivity 的限制的。

假设 getMaxShortcutCountPerActivity() 的值为4:

  1. 聊天应用程序发布四个动态快捷方式,表示最近的四个对话(c1,c2,c3,c4)
  2. 用户将所有的快捷方式复制到桌面
  3. 然后用户又启动三个额外的最近对话(c5,c6和c7),这是重新发布更新动态快捷方式,那新的快捷方式列表为:c4,c5,c6,c7。改应用必须删除过 c1,c2喝c3,因为只能展示四个快捷方式,但是桌面已经保存的这三个快捷方式是可以正常访问的。

用户现在其实可以总共访问七个快捷方式,其中包括四个最大的动态快捷方式和桌面的三个快捷方式
4. 应用程序可以使用 updateShortcuts(List) 来更新上述七个任意快捷方式
5. 使用 addDynamicShortcuts() 和 setDynamicShortcuts() 同样可以更新具有相同 shortcutId 的快捷方式对象,但是他们不能跟新非动态的快捷方式。

系统设置更改

系统设置的更改,比如修改系统的语言,Shortcuts 是不能动态更新的,此时需要创建广播监听 Intent.ACTION_LOCALE_CHANGED ,当收到广播时重新更新快捷方式,保证快捷方式展示没有问题。

处理前:

处理后:

track Shortcuts

为了确定静态和动态快捷方式以哪种方式出现,每次启动都会检查快捷方式的激活历史记录。可以通过调用 reportShortcutUsed() 方法传入其 shortcutId,提高 action 的响应速度。

ShortCuts 频率限制

当使用 setDynamicShortcuts()、addDynamicShortcuts() 和 updateDynamicShortcuts() 方法时,需要注意的是,你可能在后台调用这方法是有固定的次数限制的,那可以调用方法的次数限制就是 rate limiting。此功能用于防止 ShortcutManager过度消耗设备资源。

当处于 rate limiting 中,isRateLimitingActive() 返回 true,但是在某些操作执行会重置这个值,因此即使是在后台应用程序也可以调用 shortcutManager方法,直到再次达到速率限制。这些操作包括:

  1. 应用再次回到前台
  2. 系统区域设置更改
  3. 用户在通知栏处理嵌入的交互操作

如果在开发或者测试中遇到次数被限制的情况,可以在 开发者选项中 -> 重置 ShortcutsManager 调用频率限制 来恢复。或者使用 adb 命令

adb shell cmd shortcut reset-throttling [ --user your-user-id ]

##建议
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

《设计思想解读开源框架》

第一章、 热修复设计

  • 第一节、 AOT/JIT & dexopt 与 dex2oat

  • 第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题

  • 第三节、热修复设计之热修复原理

  • 第四节、Tinker 的集成与使用(自动补丁包生成)

    第二章、 插件化框架设计

  • 第一节、 Class 文件与 Dex 文件的结构解读

  • 第二节、 Android 资源加载机制详解

  • 第三节、 四大组件调用原理

  • 第四节、 so 文件加载机制

  • 第五节、 Android 系统服务实现原理

    第三章、 组件化框架设计

  • 第一节、阿里巴巴开源路由框——ARouter 原理分析

  • 第二节、APT 编译时期自动生成代码&动态类加载

  • 第三节、 Java SPI 机制

  • 第四节、 AOP&IOC

  • 第五节、 手写组件化架构

    第四章、图片加载框架

  • 第一节、图片加载框架选型

  • 第二节、Glide 原理分析

  • 第三节、手写图片加载框架实战

    第五章、网络访问框架设计

  • 第一节、网络通信必备基础

  • 第二节、OkHttp 源码解读

  • 第三节、Retrofit 源码解析

    第六章、 RXJava 响应式编程框架设计

  • 第一节、链式调用

  • 第二节、 扩展的观察者模式

  • 第三节、事件变换设计

  • 第四节、Scheduler 线程控制

    第七章、 IOC 架构设计

  • 第一节、 依赖注入与控制反转

  • 第二节、ButterKnife 原理上篇、中篇、下篇

  • 第三节、Dagger 架构设计核心解密

    第八章、 Android 架构组件 Jetpack

  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期


    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期

    [外链图片转存中…(img-vdINSCTp-1712694457667)]
    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
    [外链图片转存中…(img-Ofm0MeH7-1712694457667)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值