使用意图选择家庭启动器应用程序
choosing home launcher app using intents
我正在编写一个 Android 应用程序,其中包含一个 activity,启用后应充当家庭启动器 activity。
为此,我在使用 CATEGORY_HOME
作为意图类别调用 startActivityForResult 之前启用 activity,以便能够选择 activity 作为主页启动器 activity。 activity 被选中后禁用,仅在启用时启用 home 键启动。
我的问题是当要求用户选择启动器 activity 的提示出现并且用户选择默认主页 activity 而不是自定义启动器 activity 时,随后的选择器意图失败,只会导致显示主屏幕。
这是启动启动器 activity 选择器的代码:
PackageManager pm = getActivity().getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(getActivity(), CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
startActivityForResult(i, REQUEST_CODE_ENABLE_HOME_LAUNCHER);
当显示启动器选择器并且用户选择设备的默认启动器 activity 而不是自定义启动器时,我的应用程序将最小化并显示主屏幕。重新进入应用程序并重复选择器过程会导致启动器选择器不再显示,而是显示主屏幕。
有解决办法吗?如何从用户选择不正确的家庭启动器中恢复 activity?
我找到了解决问题的办法。我用以下代码替换了上面的代码:
PackageManager pm = getActivity().getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(getActivity(), CustomLauncherActivity.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
writeSetupFlag(true);
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
注意添加到意图中的标志(FLAG_ACTIVITY_NEW_TASK
和 FLAG_ACTIVITY_SINGLE_TOP
)以及将 startActivityForResult
更改为简单的 'startActivity'。
writeSetupFlag
向 SharedPreferences
写入一个标志,指示已显示选择器:
private void writeSetupFlag(boolean bInSetup) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(getString(R.string.setup_flag_active), bInSetup);
editor.commit();
}
这使我们能够确定之前是否显示过选择器。因此,假设用户在选择过程中选择了错误的主页 activity(即不是我们的 activity),将显示主页屏幕。重新启动应用程序将触发读取写入的标志,我们可以检测到显示了选择器,但用户选择了错误的启动器。
所以我们可以先检查我们的 activity 是否被设置为主页启动器:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_ALL);
pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
String currentHomePackage = resolveInfo.activityInfo.packageName;
String customlauncherpackage = context.getApplicationContext().getPackageName();
现在如果我们的 activity 不是主启动器,我们检查设置标志:
if (!currentHomePackage.equals(customlauncherpackage)) {
boolean bChooserShown;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
bChooserShown = sharedPreferences.getBoolean(getString(R.string.setup_flag_active), false);
if (bChooserShown) {
//Display a dialog to the user indicating that they selected the wrong launcher before and will have to reset the launcher from settings.
... dialog here ...
//Then redirect to settings
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
Intent i = new Intent(Settings.ACTION_HOME_SETTINGS, null);
startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
} else {
Intent i = new Intent(Settings.ACTION_SETTINGS, null);
startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
}
}
else {
//do chooser process
}
因此,通过使用 SharedPreferences
中的标志,我们可以在显示选择器时从用户选择不正确的主页启动器应用程序中恢复过来。
我有确切的东西要添加到我的一个项目中。
我在 Github 上找到了一个 开源 Android Launcher 项目,我确信我会在其中找到这个功能。
我想直接从我的 Android 应用程序中启动更改默认主页启动器应用程序,而不必启动 Intent 以进入设置并从设置中更改主页启动器应用程序。
下图显示结果:(插图取自 Google 的照片)
感谢此开源启动器项目。
https://github.com/Neamar/KISS/
从以下文件中选取了工作代码并进行了一些修改。
https://github.com/Neamar/KISS/blob/master/app/src/main/java/fr/neamar/kiss/preference/DefaultLauncherPreference.java
第 1 步:创建一个名为 DummyActivity.java
的空 Activity
package com.packagedomain.projectname;
import android.app.Activity;
/**
* An empty activity used for changing Android's Default Launcher
*/
public class DummyActivity extends Activity {
}
第 2 步:在 AndroidManifest.xml 文件
中添加以下内容 Activity
请注意 Activity 默认情况下处于禁用状态。
<activity
android:name=".DummyActivity"
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>
最后一步:在您的应用中添加以下函数,并在单击特定 UI View/Button 时调用它。
public void startChangeDefaultLauncherIntent() {
// get context (in order to avoid multiple get() calls)
Context context = getContext();
// get packet manager
PackageManager packageManager = context.getPackageManager();
// get dummyActivity
ComponentName componentName = new ComponentName(context, DummyActivity.class);
// enable dummyActivity (it starts disabled in the manifest.xml)
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
// create a new (implicit) intent with MAIN action
Intent intent = new Intent(Intent.ACTION_MAIN);
// add HOME category to it
intent.addCategory(Intent.CATEGORY_HOME);
// launch intent
context.startActivity(intent);
// disable dummyActivity once again
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
我正在编写一个 Android 应用程序,其中包含一个 activity,启用后应充当家庭启动器 activity。
为此,我在使用 CATEGORY_HOME
作为意图类别调用 startActivityForResult 之前启用 activity,以便能够选择 activity 作为主页启动器 activity。 activity 被选中后禁用,仅在启用时启用 home 键启动。
我的问题是当要求用户选择启动器 activity 的提示出现并且用户选择默认主页 activity 而不是自定义启动器 activity 时,随后的选择器意图失败,只会导致显示主屏幕。
这是启动启动器 activity 选择器的代码:
PackageManager pm = getActivity().getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(getActivity(), CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
startActivityForResult(i, REQUEST_CODE_ENABLE_HOME_LAUNCHER);
当显示启动器选择器并且用户选择设备的默认启动器 activity 而不是自定义启动器时,我的应用程序将最小化并显示主屏幕。重新进入应用程序并重复选择器过程会导致启动器选择器不再显示,而是显示主屏幕。
有解决办法吗?如何从用户选择不正确的家庭启动器中恢复 activity?
我找到了解决问题的办法。我用以下代码替换了上面的代码:
PackageManager pm = getActivity().getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(getActivity(), CustomLauncherActivity.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
writeSetupFlag(true);
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
注意添加到意图中的标志(FLAG_ACTIVITY_NEW_TASK
和 FLAG_ACTIVITY_SINGLE_TOP
)以及将 startActivityForResult
更改为简单的 'startActivity'。
writeSetupFlag
向 SharedPreferences
写入一个标志,指示已显示选择器:
private void writeSetupFlag(boolean bInSetup) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(getString(R.string.setup_flag_active), bInSetup);
editor.commit();
}
这使我们能够确定之前是否显示过选择器。因此,假设用户在选择过程中选择了错误的主页 activity(即不是我们的 activity),将显示主页屏幕。重新启动应用程序将触发读取写入的标志,我们可以检测到显示了选择器,但用户选择了错误的启动器。
所以我们可以先检查我们的 activity 是否被设置为主页启动器:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_ALL);
pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
String currentHomePackage = resolveInfo.activityInfo.packageName;
String customlauncherpackage = context.getApplicationContext().getPackageName();
现在如果我们的 activity 不是主启动器,我们检查设置标志:
if (!currentHomePackage.equals(customlauncherpackage)) {
boolean bChooserShown;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
bChooserShown = sharedPreferences.getBoolean(getString(R.string.setup_flag_active), false);
if (bChooserShown) {
//Display a dialog to the user indicating that they selected the wrong launcher before and will have to reset the launcher from settings.
... dialog here ...
//Then redirect to settings
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
Intent i = new Intent(Settings.ACTION_HOME_SETTINGS, null);
startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
} else {
Intent i = new Intent(Settings.ACTION_SETTINGS, null);
startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
}
}
else {
//do chooser process
}
因此,通过使用 SharedPreferences
中的标志,我们可以在显示选择器时从用户选择不正确的主页启动器应用程序中恢复过来。
我有确切的东西要添加到我的一个项目中。 我在 Github 上找到了一个 开源 Android Launcher 项目,我确信我会在其中找到这个功能。
我想直接从我的 Android 应用程序中启动更改默认主页启动器应用程序,而不必启动 Intent 以进入设置并从设置中更改主页启动器应用程序。 下图显示结果:(插图取自 Google 的照片)
感谢此开源启动器项目。
https://github.com/Neamar/KISS/
从以下文件中选取了工作代码并进行了一些修改。 https://github.com/Neamar/KISS/blob/master/app/src/main/java/fr/neamar/kiss/preference/DefaultLauncherPreference.java
第 1 步:创建一个名为 DummyActivity.java
的空 Activity
package com.packagedomain.projectname;
import android.app.Activity;
/**
* An empty activity used for changing Android's Default Launcher
*/
public class DummyActivity extends Activity {
}
第 2 步:在 AndroidManifest.xml 文件
中添加以下内容 Activity请注意 Activity 默认情况下处于禁用状态。
<activity
android:name=".DummyActivity"
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>
最后一步:在您的应用中添加以下函数,并在单击特定 UI View/Button 时调用它。
public void startChangeDefaultLauncherIntent() {
// get context (in order to avoid multiple get() calls)
Context context = getContext();
// get packet manager
PackageManager packageManager = context.getPackageManager();
// get dummyActivity
ComponentName componentName = new ComponentName(context, DummyActivity.class);
// enable dummyActivity (it starts disabled in the manifest.xml)
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
// create a new (implicit) intent with MAIN action
Intent intent = new Intent(Intent.ACTION_MAIN);
// add HOME category to it
intent.addCategory(Intent.CATEGORY_HOME);
// launch intent
context.startActivity(intent);
// disable dummyActivity once again
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}