【详细】长按APP图标弹出快捷方式,ShortCut功能实现

Shortcuts介绍

Android7.1(API Level 25)及以上系统可以自定义Shortcuts,通过在桌面上长按App Icon弹出Shortcut列表,点击某个shortcut可使用户快捷得打开App里常用的或推荐的任务。国内各个厂商基本上在安卓8.0上集成了该功能。见下图

  

1.1 Shortcuts的简单作用

每个Shortcut可以关联一个或多个intents,每个intent启动一个指定的action; 官方给出了几个可以作为shortcut的例子,比如:

在地图类app中,指导用户到特定的位置;
在社交类app中,发送消息给一个朋友;
在媒体类app中,播放视频的下一片段;
在游戏类app中,下载最后保存的要点;
在实际开发中,我们具体想让哪些操作作为快捷方式,可自行定义。

1.2 静态实现

1. 在app的AndroidManifest.xml文件中,找到MainActivity,即设置了action为

<action android:name=”android.intent.action.MAIN” />,且category设置为

<category android:name=”android.intent.category.LAUNCHER” />的activity;

为其添加<meta-data>….</meta-data>指向定义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>


2. 创建定义AppShortcuts的资源文件,res/xml/shortcuts.xml文件 

<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/tools">
 
    <!-- 第一个静态shortcut -->
    <shortcut
        android:shortcutId="static_one"
        android:enabled="true"
        android:icon="@mipmap/icon_diamond"
        android:shortcutLongLabel="@string/static_one_long_label"
        android:shortcutDisabledMessage="@string/static_disabled_message"
        android:shortcutShortLabel="@string/static_one_short_label">
        <!--
            一个shortcut,当有多个intents与之相关联时,在用户启动该shortcut时,最先呈现给用户的是
            <intent>...</intent>集合中最后一个intent操作事件。
            即这里创建了一个intent的回退栈,最后一个才是被快捷方式打开的那个。
        -->
        <intent
            android:action="android.intent.action.MAIN"
            android:targetPackage="com.example.butterknifetest"
            android:targetClass="com.example.butterknifetest.MainActivity"/>
 
        <intent
            android:action="android.intent.action.MAIN"
            android:targetPackage="com.example.butterknifetest"
            android:targetClass="com.example.butterknifetest.AndroidTestActivity"/>
 
        <!--
        最后这个是要打开的intent,前边的intent表示点击返回时依次回退的intent。
        如果不设置回退intent,则按返回键会返回桌面。
        -->
        <intent
            android:action="android.intent.action.MAIN"
            android:targetPackage="com.example.butterknifetest"
            android:targetClass="com.example.butterknifetest.TestActivit"/>
 
    </shortcut>
    <!-- 第二个静态shortcut -->
    <shortcut
        android:shortcutId="static_two"
        android:enabled="true"
        android:icon="@mipmap/icon_star"
        android:shortcutLongLabel="@string/static_two_long_label"
        android:shortcutDisabledMessage="@string/static_disabled_message"
        android:shortcutShortLabel="@string/static_two_short_label">
 
        <intent
            android:action="android.intent.action.MAIN"
            android:targetPackage="com.example.butterknifetest"
            android:targetClass="com.example.butterknifetest.MainActivity"/>
        
        <!--
        最后这个是要打开的intent,前边的intent表示点击返回时依次回退的intent。
        如果不设置回退intent,则按返回键会返回桌面。
        -->

        <intent
            android:action="android.intent.action.MAIN"
            android:targetPackage="com.example.butterknifetest"
            android:targetClass="com.example.butterknifetest.TestActivity"/>
 
    </shortcut>
 
 
</shortcuts>

<shortcut/> 标签内容只少要设置一个intent,即图标指向的intent。

如果有多个,最后一个是最终指向的intent,之前的则认为是打开后,点击返回键时依次回退的intent。


3. 属性讲解

以shortcuts元素为根,可以包含多个shortcut元素,每个shortcut元素标示一个shortcut。其中属性分别标示:

shortcutId:shortcut唯一标识符,相同的shortcutId会被覆盖。(必设属性)
enable:shortcut是否启用,true启用,false是禁用(若设置为false,不如删除掉该快捷方式)(可选属性)
icon:显示在快捷方式左边的图标。(可选属性)
shortcutLongLabel:当launcher的空间足够时将会显示shortcut的长文本描述,不宜过长,如果过长或未设置时会显示shortcutShortLabel (可选属性)
shortcutShortLabel : shortcut的简要说明,这项是必须的。(必设属性)
intent : 这里定义快捷方式被点击之后将会打开的intent (必设属性)
shortcutDisabledMessage : 当你禁用了shortcut之后,它将不会显示在用户长按应用图标后打开的快捷方式里,但是用户可以把一个快捷方式拖拽到launcher的某个页面成为Pinned Shortcut,被禁用之后这个快捷方式就会显示为灰色,点击这个Pinned Shortcut则会显示一个内容为shortcutDisabledMessage的Toast。(可选属性) 

1.3 动态实现

        代码创建Dynamic shortcut,需要使用API ShortcutManager和ShortcutInfo.Builder;通过ShortcutInfo.Builder新建ShortcutInfo,再通过ShortcutManager添加即可。动态shortcut可以在运行时动态改变内容,无需重写部署App。下面直接看代码,而不在叙述创建的具体步骤:

public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //要确保API Level 大于等于 25才可以创建动态shortcut,否则会报异常。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
            initDynamicShortcuts();
        }
    }
 
    /**
     * 为App创建动态Shortcuts
     */
    private void initDynamicShortcuts() {
        //①、创建动态快捷方式的第一步,创建ShortcutManager
        ShortcutManager scManager = getSystemService(ShortcutManager.class);
        //②、构建动态快捷方式的详细信息
        ShortcutInfo scInfoOne  = new ShortcutInfo.Builder(this, "dynamic_one")
                .setShortLabel("Dynamic Web site")
                .setLongLabel("to open Dynamic Web Site")
                .setIcon(Icon.createWithResource(this, R.mipmap.tool_music_icon))
                .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com")))
                .build();
 
       ShortcutInfo scInfoTwo = new ShortcutInfo.Builder(this, "dynamic_two")
                .setShortLabel("Dynamic Activity")
                .setLongLabel("to open dynamic one activity")
                .setIcon(Icon.createWithResource(this, R.mipmap.tool_luck_icon))
                .setIntents(new Intent[]{
                                    new Intent(Intent.ACTION_MAIN, Uri.EMPTY, this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK),//加该FLAG的目的是让MainActivity作为根activity,清空已有的任务
                                    new Intent(DynamicASOneActivity.ACTION)
                            })
                .build();
        //③、为ShortcutManager设置动态快捷方式集合
        scManager.setDynamicShortcuts(Arrays.asList(scInfoOne, scInfoTwo));
 
        //如果想为两个动态快捷方式进行排序,可执行下面的代码
        ShortcutInfo dynamicWebShortcut = new ShortcutInfo.Builder(this, "dynamic_one")
                .setRank(0)
                .build();
        ShortcutInfo dynamicActivityShortcut = new ShortcutInfo.Builder(this, "dynamic_two")
                .setRank(1)
                .build();
 
        //④、更新快捷方式集合
        scManager.updateShortcuts(Arrays.asList(dynamicWebShortcut, dynamicActivityShortcut));
    }
}


ShortcutManager API可以帮助我们实现新建、更新、移除快捷方式的操作:

新建:方法setDynamicShortcuts() 可以添加或替换所有的shortcut;方法addDynamicShortcuts() 来添加新的shortcut到列表中,超过最大个数会报异常
更新:方法updateShortcuts(List shortcutInfoList) 更新已有的动态快捷方式;
删除:方法removeDynamicShortcuts(List shortcutIds) 根据动态快捷方式的ID,删除已有的动态快捷方式;方法removeAllDynamicShortcuts() 删除掉app中所有的动态快捷方式;
List<ShortcutInfo> getDynamicShortcuts() : 得到所有的动态shortcuts;
--------------------- 
作者:HL是限量版 
来源:优快云 
原文:https://blog.youkuaiyun.com/m0_37218227/article/details/84071043 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think> 我们正在讨论的是Android 11系统上如何实现按应用图标弹出应用管理功能。根据之前的对话,用户可能是在开发一个Launcher(启动器)应用,或者需要定制系统Launcher的功能。引用[3]提到在Launcher3中修改按菜单选项的方法,这为我们提供了线索。 在Android系统中,按应用图标弹出的菜单(称为App Shortcuts)通常由Launcher应用控制。原生Android的Launcher3代码中,按菜单的选项是在`getSupportedShortcuts()`方法中定义的。根据引用[3],我们可以通过修改该方法来移除或添加菜单项。 用户希望弹出的是“应用管理”功能,而不是标准的Shortcuts。我们可能需要添加一个新的菜单项,点击后跳转到系统设置中的应用管理页面。 下面分步骤说明: ### 1. 修改getSupportedShortcuts方法 在Launcher3的源码中,找到`getSupportedShortcuts()`方法(通常在`Launcher.java`或类似的文件中)。该方法返回一个`Stream<ShortcutFactory>`,其中包含了按菜单的选项。我们需要添加一个新的菜单项,比如叫做“应用管理”。 参考引用[3]的做法,我们可以自定义一个`ShortcutFactory`,并在`getSupportedShortcuts()`的返回流中加入它。 ### 2. 创建自定义ShortcutFactory 创建一个新的`ShortcutFactory`实现类,用于生成“应用管理”的菜单项。示例代码如下: ```java private static final ShortcutFactory APP_MANAGEMENT = new ShortcutFactory() { @Override public List<Shortcut> getShortcuts(Launcher launcher, ItemInfo info) { if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { return Collections.singletonList(new ManagementShortcut(launcher, info)); } return Collections.emptyList(); } @Override public boolean supports(AppInfo info) { return true; // 支持所有应用 } }; ``` 然后在`getSupportedShortcuts()`方法中,将自定义的`APP_MANAGEMENT`加入到返回的流中: ```java protected Stream<ShortcutFactory> getSupportedShortcuts() { return Stream.of( APP_MANAGEMENT, // 添加的应用管理菜单项 APP_INFO, // 原有的应用信息 WIDGETS, // 微件 // ... 其他原有项 ); } ``` ### 3. 实现ManagementShortcut类 `ManagementShortcut`是一个具体的快捷方式项,需要继承`Shortcut`类,并实现点击事件。点击后,我们需要启动系统设置中的应用信息页面。 ```java public class ManagementShortcut extends Shortcut { public ManagementShortcut(Launcher launcher, ItemInfo info) { super(launcher, info); } @Override public void onClick(View view) { // 启动应用管理页面 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", mItemInfo.getTargetPackage(), null)); mLauncher.startActivitySafely(view, intent, this); } @Override public Drawable getIcon(IconCache iconCache, Context context) { // 返回一个图标,可以使用系统图标 return context.getDrawable(android.R.drawable.ic_menu_manage); } @Override public CharSequence getLabel(Context context) { return context.getString("应用管理"); // 需要字符串资源 } } ``` ### 4. 注意事项 - **权限问题**:启动系统设置页面不需要特殊权限。 - **兼容性**:不同的设备厂商可能有不同的设置页面路径,上述使用的`Settings.ACTION_APPLICATION_DETAILS_SETTINGS`是标准的Android设置页面,通常兼容Android 11及以上。 - **系统Launcher定制**:如果用户正在开发自己的Launcher,以上代码可以直接集成。如果是修改系统Launcher(如AOSP中的Launcher3),则需要重新编译系统或Launcher模块。 ### 5. 测试 在Android 11设备或模拟器上测试按应用图标,应该能看到“应用管理”菜单项,点击后跳转到应用设置页面。 ### 引用说明 以上实现参考了原生Launcher3的代码结构和引用[3]中提到的修改方法,通过移除或添加`ShortcutFactory`来定制按菜单[^3]。 §§相关问题§§ 1. 如何为不同的应用显示不同的按菜单项? 2. 在非系统Launcher中如何实现按菜单定制? 3. Android 11中启动应用管理页面的其他方法有哪些? </think> 在Android 11系统中实现按应用图标弹出应用管理功能,需通过修改Launcher源码实现。以下是具体实现步骤和技术要点: ### 1. 修改Shortcut生成逻辑 在Launcher源码中定位菜单项生成位置(通常是`Launcher.java`或`ShortcutFactory.java`): ```java // 修改getSupportedShortcuts()方法 protected Stream<ShortcutFactory> getSupportedShortcuts() { return Stream.of( APP_MANAGEMENT, // 新增的应用管理项 WIDGETS, INSTALL ); } ``` 其中`APP_MANAGEMENT`是需要自定义的新组件[^3]。 ### 2. 实现应用管理快捷方式 ```java // 自定义ShortcutFactory实现 private static final ShortcutFactory APP_MANAGEMENT = new ShortcutFactory() { @Override public List<Shortcut> getShortcuts(Launcher launcher, ItemInfo info) { return Collections.singletonList(new ManagementShortcut(launcher, info)); } @Override public boolean supports(AppInfo info) { return true; // 支持所有应用 } }; // 实现具体快捷方式 public class ManagementShortcut extends Shortcut { public ManagementShortcut(Launcher launcher, ItemInfo info) { super(launcher, info); } @Override public void onClick(View view) { // 启动应用详情页 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + mItemInfo.getTargetPackage())); mLauncher.startActivitySafely(view, intent, this); } @Override public Drawable getIcon(IconCache iconCache, Context context) { return context.getDrawable(android.R.drawable.ic_menu_manage); } @Override public CharSequence getLabel(Context context) { return context.getString("应用管理"); // 字符串资源 } } ``` ### 3. 权限配置 在`AndroidManifest.xml`中添加权限声明: ```xml <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES"/> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/> ``` ### 4. 兼容性处理 Android 11中需添加包可见性声明: ```xml <queries> <intent> <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" /> </intent> </queries> ``` ### 效果说明 实现后将具备以下特性: 1. 图标显示"应用管理"选项 2. 点击后跳转系统应用详情页 3. 支持所有第三方应用 4. 使用系统标准设置界面($$ \int_{\text{package}}^{\text{settings}} \,d\text{Activity} $$) ### 注意事项 1. 此修改需基于AOSP源码编译 2. 不同Android版本需调整`ShortcutFactory`实现 3. 系统签名权限可能涉及厂商定制[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值