Vivo创建桌面快捷方式

系统分析

Posted by JovenHe on June 22, 2021

首先添加一个桌面快捷方式,这里的快捷方式不是静态快捷方式,也不是动态快捷方式,而是固定在桌面上的固定快捷方式

fun addShortcut(context: Context, name: String, drawable: Drawable, id: String) {
        XLog.d(TAG, "addShortcut: name = $name")
        var shortcutManager = context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
        if (shortcutManager.isRequestPinShortcutSupported()) {
            var shortcutInfoIntent = Intent(context, ShortcutActivity::class.java);
            shortcutInfoIntent.setAction(Intent.ACTION_VIEW)
            shortcutInfoIntent.putExtra(ShortcutActivity.Id, id)

            //当添加快捷方式的确认弹框确认后,将被回调
            var intentReceiver = Intent(context, ShortcutReceiver::class.java)
            intentReceiver.putExtra(ShortcutReceiver.Id, id)
            var shortcutCallbackIntent = PendingIntent.getBroadcast(context, 0,
                    intentReceiver, PendingIntent.FLAG_UPDATE_CURRENT);
            var info = ShortcutInfoCompat.Builder(context, id)
                    .setIcon(IconCompat.createWithBitmap(BitmapUtil.drawable2Bitmap(drawable)))
                    .setShortLabel(name)
                    .setIntent(shortcutInfoIntent)
                    .build()
            //这里第二个参数可以传一个回调,用来接收当快捷方式被创建时的响应
            var requestPinShortcut = ShortcutManagerCompat.requestPinShortcut(context, info, shortcutCallbackIntent.intentSender)
            XLog.d(TAG, "addShortcut: requestPinShortcut $requestPinShortcut")
        }
    }

可以看到就是添加一个桌面快捷方式,点击后跳转到ShortcutActivity,传递值为id,弹窗确认后ShortcutReceiver会接收到id值,ShortcutReceiver需要在清单文件中声明

以上操作在华为手机是没有问题的,但在vivo上却没有任何反应,没有报错,甚至requestPinShortcut也为true。

个人猜想是权限问题,所以在设置-应用与权限-权限管理-桌面快捷方式里允许该应用,再次运行就可以直接生成桌面图标了

vivo_shortcut_settings.png

vivo这一点比华为上要好,华为是每次添加都要弹出确认框让用户确认,vivo只需要打开桌面快捷方式权限就可以了。那么vivo只需要判断和跳转,就可以使用了

直接adb查看当前页

vivo_shortcut_权限页面.png

跳转可以直接使用

val intent = Intent()
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        intent.component = ComponentName("com.bbk.launcher2", "com.bbk.launcher2.installshortcut.PurviewActivity")
                        mContext.startActivity(intent)

在studio中导出系统应用BBKLauncher2.apk,并用jadx反编译打开

vivo_shortcut_PurviewActivity.png

看到只有一个fragment,直接去fragment中找相应adapter

vivo_shortcut_adapter_setCheck.png

能看到很关键的设置adapter中是否选中的判断,显示判断是否是系统白名单应用,不是的话,判断mo8553e方法的值,直接查找该值的设置方法

vivo_shortcut_adapter_addData.png

mo8542a就是设置方法,而f5507f就是adapter的数据,那真正的数据来源就是mo8508b方法

vivo_shortcut_contentResolver.png

可以看到是通过getContentResolver获取ContentProvider中的数据进行筛选处理的,转换代码得到

                var uri = Uri.parse("content://com.bbk.launcher2.settings/favorites")
                var query = mContext.contentResolver.query(uri, null, " itemType = ?", arrayOf("30"), null);
                if (query != null && query.count > 0) {
                    var idIndex = query.getColumnIndexOrThrow("_id");
                    var intentIndex = query.getColumnIndexOrThrow("intent");
                    var shortcutPermissionIndex = query.getColumnIndexOrThrow("shortcutPermission");
                    while (query.moveToNext()) {
                        val long = query.getLong(idIndex)
                        val intent = query.getString(intentIndex)
                        val shortcutPermission = query.getInt(shortcutPermissionIndex)
                        var unflattenFromString = ComponentName.unflattenFromString(intent)
                        XLog.d(TAG, "initView: getShortcutPerBtn id=$long packageName= ${unflattenFromString!!.packageName} shortcutPermission= $shortcutPermission")
                    }
                    query.close()
                }

日志如下

vivo_shortcut_contentResolver_result.png

真正显示的时候是没有系统应用的,是做了筛选。手动打开一个优酷

vivo_shortcut_contentResolver_result2.png

可以看到shortcutPermission值确实发生了变化

那我们直接使用adapter中check的判断,完整代码如下

var packageName = mContext.packageName
            GlobalScope.launch {
                var uri = Uri.parse("content://com.bbk.launcher2.settings/favorites")
                var query = mContext.contentResolver.query(uri, null, " itemType = ?", arrayOf("30"), null);
                if (query != null && query.count > 0) {
                    var idIndex = query.getColumnIndexOrThrow("_id");
                    var intentIndex = query.getColumnIndexOrThrow("intent");
                    var shortcutPermissionIndex = query.getColumnIndexOrThrow("shortcutPermission");
                    while (query.moveToNext()) {
                        val long = query.getLong(idIndex)
                        val intent = query.getString(intentIndex)
                        val shortcutPermission = query.getInt(shortcutPermissionIndex)
                        var unflattenFromString = ComponentName.unflattenFromString(intent)
                        XLog.d(TAG, "initView: getShortcutPerBtn id=$long packageName= ${unflattenFromString!!.packageName} shortcutPermission= $shortcutPermission")
                        if (unflattenFromString!!.packageName == packageName && shortcutPermission != 0 && shortcutPermission != 16){
                            val intent = Intent()
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                            intent.component = ComponentName("com.bbk.launcher2", "com.bbk.launcher2.installshortcut.PurviewActivity")
                            mContext.startActivity(intent)
                            query.close()
                            return@launch
                        }
                    }
                    query.close()
                }
            }

至此分析结束