如何收听哪个应用程序已被选为启动器应用程序?
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)与另一个进程在锁资源上死锁,并已被选为死锁牺牲品。重新运行事务