如何以编程方式设置默认应用程序启动器?
How to set default app launcher programmatically?
我正在创建一个可通过 google 下载的启动器(信息亭)应用程序。首次安装此应用程序时,用户可以选择默认启动器(我的或库存的)。如果用户没有将我的应用程序设置为默认启动器,我将尝试手动启动它。我希望在出现该对话框时强制用户选择始终而不是仅一次,否则该对话框将继续定期出现并显示友好消息。这是我迄今为止尝试过的。
我创建了一个方法来检查我的应用程序是否是默认的
/**
* method checks to see if app is currently set as default launcher
* @return boolean true means currently set as default, otherwise false
*/
private boolean isMyAppLauncherDefault() {
final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
List<IntentFilter> filters = new ArrayList<IntentFilter>();
filters.add(filter);
final String myPackageName = getPackageName();
List<ComponentName> activities = new ArrayList<ComponentName>();
final PackageManager packageManager = (PackageManager) getPackageManager();
packageManager.getPreferredActivities(filters, activities, null);
for (ComponentName activity : activities) {
if (myPackageName.equals(activity.getPackageName())) {
return true;
}
}
return false;
}
然后我尝试启动选择器
/**
* method starts an intent that will bring up a prompt for the user
* to select their default launcher. It comes up each time it is
* detected that our app is not the default launcher
*/
private void launchAppChooser() {
Log.d(TAG, "launchAppChooser()");
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
当我这样做时,我无法在我的应用程序和标准启动器之间进行选择。我尝试使用 startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS"));
并在我的应用程序和股票启动器之间进行选择,但是,我没有始终或仅一次获得选项。
我可以为此创建自定义对话框而不是启动选择器,但我需要知道如何以编程方式设置默认应用程序启动器。提前致谢!
I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up
除非 Android.
中存在一些安全漏洞,否则这是不可能的,除非是在已获得 root 权限的设备上
When I do this I am not receiving the choice between my app and the stock launcher
正确。如果已经选择了默认值,这将简单地启动默认值。
I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.
正确。 createChooser()
强制选择,但不允许设置默认值。
这实际上可以通过一些变通方法实现:
创建一个空的 Activity
作为名为 FakeLauncherActivity
的启动器。将其作为 disabled 组件添加到您的清单中:
<activity
android:name="com.path.to.your.FakeLauncherActivity"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
检查您想要的启动器 activity 是否是默认启动器(使用您问题中的 isMyAppLauncherDefault()
)。
如果没有,请让用户选择首选启动器 activity,如下所示:
public static void resetPreferredLauncherAndOpenChooser(Context context) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, com.path.to.your.FakeLauncherActivity.class);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
selector.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(selector);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
}
此方法暂时启用 FakeLauncherActivity
,这会导致可用启动器活动集发生变化,从而迫使 Android 忘记其默认启动器。你会看到类似...
521-735/system_process I/PackageManager﹕ Result set changed, dropping preferred activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 } type null
...在您的日志中。
该方法然后简单地打开一个启动器意图,您可以在其中看到所有已安装的启动器和按钮 "Always" / "Just once"。
最后,该方法再次禁用 FakeLauncherActivity
,因此它不会显示在列表中。
您可以根据需要多次重复该操作,并且只有在您想要的启动器 activity 设置为默认启动器时才让用户继续。
问题中的 isMyAppLauncherDefault() 函数由于某种原因并不总是有效。
此代码可能更适合确定主屏幕的默认包。
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
String currentHomePackage = resolveInfo.activityInfo.packageName;
如果您正在实施 Google EMM 解决方案(专用设备):
https://developer.android.com/work/dpc/dedicated-devices/cookbook
// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);
// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);
AndroidQ(API29)有RoleManager。假设您的应用是启动器。
[AndroidManifest.xml]
<activity
... />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
// Perhaps log the result here.
}
}
private fun showLauncherSelection() {
val roleManager = requireActivity().getSystemService(Context.ROLE_SERVICE)
as RoleManager
if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME) &&
!roleManager.isRoleHeld(RoleManager.ROLE_HOME)
) {
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
startForResult.launch(intent)
}
}
当您调用 showLauncherSelection()
时,您应该会看到类似于以下内容的对话框。
还有ROLE_BROWSER
、ROLE_DIALER
、ROLE_SMS
等其他角色
我正在创建一个可通过 google 下载的启动器(信息亭)应用程序。首次安装此应用程序时,用户可以选择默认启动器(我的或库存的)。如果用户没有将我的应用程序设置为默认启动器,我将尝试手动启动它。我希望在出现该对话框时强制用户选择始终而不是仅一次,否则该对话框将继续定期出现并显示友好消息。这是我迄今为止尝试过的。
我创建了一个方法来检查我的应用程序是否是默认的
/**
* method checks to see if app is currently set as default launcher
* @return boolean true means currently set as default, otherwise false
*/
private boolean isMyAppLauncherDefault() {
final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
List<IntentFilter> filters = new ArrayList<IntentFilter>();
filters.add(filter);
final String myPackageName = getPackageName();
List<ComponentName> activities = new ArrayList<ComponentName>();
final PackageManager packageManager = (PackageManager) getPackageManager();
packageManager.getPreferredActivities(filters, activities, null);
for (ComponentName activity : activities) {
if (myPackageName.equals(activity.getPackageName())) {
return true;
}
}
return false;
}
然后我尝试启动选择器
/**
* method starts an intent that will bring up a prompt for the user
* to select their default launcher. It comes up each time it is
* detected that our app is not the default launcher
*/
private void launchAppChooser() {
Log.d(TAG, "launchAppChooser()");
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
当我这样做时,我无法在我的应用程序和标准启动器之间进行选择。我尝试使用 startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS"));
并在我的应用程序和股票启动器之间进行选择,但是,我没有始终或仅一次获得选项。
我可以为此创建自定义对话框而不是启动选择器,但我需要知道如何以编程方式设置默认应用程序启动器。提前致谢!
I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up
除非 Android.
中存在一些安全漏洞,否则这是不可能的,除非是在已获得 root 权限的设备上When I do this I am not receiving the choice between my app and the stock launcher
正确。如果已经选择了默认值,这将简单地启动默认值。
I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.
正确。 createChooser()
强制选择,但不允许设置默认值。
这实际上可以通过一些变通方法实现:
创建一个空的 Activity
作为名为 FakeLauncherActivity
的启动器。将其作为 disabled 组件添加到您的清单中:
<activity
android:name="com.path.to.your.FakeLauncherActivity"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
检查您想要的启动器 activity 是否是默认启动器(使用您问题中的 isMyAppLauncherDefault()
)。
如果没有,请让用户选择首选启动器 activity,如下所示:
public static void resetPreferredLauncherAndOpenChooser(Context context) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, com.path.to.your.FakeLauncherActivity.class);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
selector.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(selector);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
}
此方法暂时启用 FakeLauncherActivity
,这会导致可用启动器活动集发生变化,从而迫使 Android 忘记其默认启动器。你会看到类似...
521-735/system_process I/PackageManager﹕ Result set changed, dropping preferred activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 } type null
...在您的日志中。
该方法然后简单地打开一个启动器意图,您可以在其中看到所有已安装的启动器和按钮 "Always" / "Just once"。
最后,该方法再次禁用 FakeLauncherActivity
,因此它不会显示在列表中。
您可以根据需要多次重复该操作,并且只有在您想要的启动器 activity 设置为默认启动器时才让用户继续。
问题中的 isMyAppLauncherDefault() 函数由于某种原因并不总是有效。 此代码可能更适合确定主屏幕的默认包。
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
String currentHomePackage = resolveInfo.activityInfo.packageName;
如果您正在实施 Google EMM 解决方案(专用设备):
https://developer.android.com/work/dpc/dedicated-devices/cookbook
// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);
// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);
AndroidQ(API29)有RoleManager。假设您的应用是启动器。
[AndroidManifest.xml]
<activity
... />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
// Perhaps log the result here.
}
}
private fun showLauncherSelection() {
val roleManager = requireActivity().getSystemService(Context.ROLE_SERVICE)
as RoleManager
if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME) &&
!roleManager.isRoleHeld(RoleManager.ROLE_HOME)
) {
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
startForResult.launch(intent)
}
}
当您调用 showLauncherSelection()
时,您应该会看到类似于以下内容的对话框。
还有ROLE_BROWSER
、ROLE_DIALER
、ROLE_SMS
等其他角色