如何收听哪个应用程序已被选为启动器应用程序?

Posted

技术标签:

【中文标题】如何收听哪个应用程序已被选为启动器应用程序?【英文标题】:How can I listen to which app has been chosen as Launcher Application? 【发布时间】:2019-03-31 11:07:38 【问题描述】:

我尝试实现允许用户选择默认 android 的默认启动器应用程序的功能。另外,我需要接收选择了哪个应用程序的信息。但这种方法存在问题。

要让用户选择启动器应用程序,我们可以简单地启动给定的意图:

val selector = Intent(Intent.ACTION_MAIN)
selector.addCategory(Intent.CATEGORY_HOME)
selector.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(selector)

它会导致这样的对话框:

我观察到,如果我使用startActivity,启动器应用程序设置得很好并且按预期工作,但如果我使用startActivityForResult,那么我会得到一些回调,但启动器应用程序根本不会设置.此外,onActivityResult 收到的意图没有什么有趣的。

然后,我尝试改用IntentSender。

代码如下:

val selector = Intent(Intent.ACTION_MAIN)
selector.addCategory(Intent.CATEGORY_HOME)
selector.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val receiver = Intent(this, MyBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, receiver, PendingIntent.FLAG_UPDATE_CURRENT)
val chooser = Intent.createChooser(selector, "Select a Home app", pendingIntent.intentSender);
startActivity(chooser)

接收器如下所示:

class MyBroadcastReceiver: BroadcastReceiver() 
    override fun onReceive(context: Context, intent: Intent) 
        val componentName = intent.extras.getParcelable<ComponentName>(Intent.EXTRA_CHOSEN_COMPONENT)
        //com.example.myapp if my app was choosen
        val pkg = componentName.packageName
    

这会导致默认选择器,没有“JUST ONCE”或“ALWAYS”选项。我没有确切的图片,但它看起来与这张相似:

以某种方式起作用,在接收器的onReceive 方法中,我得到ComponenName 对象,该对象包含选定的应用程序packageName。问题是 - 再次 - 未设置启动器应用程序!

所以问题是:如何让用户设置启动器应用程序,并接收他选择的信息?

【问题讨论】:

【参考方案1】:

尝试使用以下代码:

PackageManager localPackageManager = getPackageManager();
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
String launcherName = localPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY).activityInfo.packageName;
Log.e("Current launcher Package Name:",launcherName);

【讨论】:

我应该在哪里使用它? 您可以在 onResume 方法中使用它,从那里启动此意图 但我需要用户先选择应用程序,如果我在创建选择器后立即调用它,这将是旧的家庭应用程序信息 你试过onResume方法吗?我相信它会起作用,因为一旦启动器更改,您将通过另一个应用程序更改启动器,它将返回到我们的应用程序,并将调用您启动意图的活动的 onResume 方法。如果我不理解您的痛苦,请纠正/解释我。 我最终将我的应用程序声明为android:launchMode="singleTask"。这样,我可以检测到我的应用程序和另一个应用程序之间的变化 - 如果我选择我的应用程序作为启动器,应用程序将因为singleTask 而重新启动,并且在onResume 我可以用你的方法(或任何方法检测到)点)如果我的应用程序是启动器。同样,当我的应用主页应用时,我选择了另一个应用,我的应用将关闭,因为主页应用发生了变化。当我再次打开应用程序(通过图标)时,再次在onResume 中检查我的应用程序是否是启动器。它远非我想要的完美,但我最终得到了这样的解决方案。【参考方案2】:

使用getPreferredActivities(),您可以检索用户喜欢的所有活动。这也应该包括启动器。

然后你可以尝试实现一个getPreferredLauncher() 函数来获取当前的Launcher。但由于无法监听此更改,您必须在 Service 内主动查询它,或者在您假设数据可能已更改时进行查询:

fun PackageManager.getPreferredLauncher(): ComponentName? 
    val filters = mutableListOf<IntentFilter>()
    val components = mutableListOf<ComponentName>()
    getPreferredActivities(filters, components, null)
    filters.forEachIndexed  (i, it) ->
        if (it.hasAction(ACTION_MAIN) && it.hasCategory(CATEGORY_LAUNCHER))
            return@getPreferredLauncher components[i]
    
    return null

请将此代码视为草稿,因为我没有任何设置来实际运行它。

【讨论】:

感谢您的回答。它按预期工作,但问题是如何倾听实际变化。 就像我说的,没有办法准确地听取这些信息。因此,您必须偶尔从服务或活动中查询它。

以上是关于如何收听哪个应用程序已被选为启动器应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

事务(进程 ID 120)与另一个进程在锁资源上死锁,并已被选为死锁牺牲品。重新运行事务

事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。在 sql server 2014 中

在 Java 中,哪个重载会被选为 null?

如何使 ListView 的第一项在启动时被选为默认值?

SQL 过程超时

错误:错误状态:流已被收听