Comment diable Nova gère-t-elle cela? J'essaie littéralement de faire exactement la même chose: fournir aux utilisateurs un bouton à appuyer pour effacer et choisir leur nouveau lanceur par défaut.
Je peux obtenir le nom de l'application par défaut et l'afficher:
private String getPrefered(Intent i) {
PackageManager pm = this.getActivity().getPackageManager();
final ResolveInfo mInfo = pm.resolveActivity(i, 0);
return (String) pm.getApplicationLabel(mInfo.activityInfo.applicationInfo);
}
où Intent i
est
Intent home = new Intent("Android.intent.action.MAIN");
home.addCategory("Android.intent.category.HOME");
Ensuite, j'appelle le système ResolveActivity,
private void makePrefered() {
Intent selector = new Intent("Android.intent.action.MAIN");
selector.addCategory("Android.intent.category.HOME");
selector.setComponent(new ComponentName("Android", "com.Android.internal.app.ResolverActivity"));
startActivity(selector);
}
Le sélecteur apparaît et fonctionne correctement, mais il ne définit ni n'efface aucune valeur. Pendant le débogage, il semble que je manque des extras? Lorsque j'appelle la méthode makePrefered
, j'obtiens le message de journal suivant,
I/ActivityManager( 602): START {act=Android.intent.action.MAIN cat=[Android.intent.category.HOME] cmp=Android/com.Android.internal.app.ResolverActivity u=0} from pid 22641
Lorsque j'utilise l'implémentation Nova, je vois tout cela cependant,
I/PackageManager( 602): Result set changed, dropping preferred activity for Intent { act=Android.intent.action.MAIN cat=[Android.intent.category.HOME] flg=0x10200000 (has extras) } type null
I/ActivityManager( 602): START {act=Android.intent.action.MAIN cat=[Android.intent.category.HOME] flg=0x10200000 cmp=Android/com.Android.internal.app.ResolverActivity (has extras) u=0} from pid 22905
I/ActivityManager( 602): START {act=Android.intent.action.MAIN cat=[Android.intent.category.HOME] flg=0x10200000 cmp=com.mycolorscreen.canvas/.Launcher (has extras) u=0} from pid 22905
Le code pour ce faire est en fait juste un travail très intelligent.
Lorsqu'un composant avec
<category Android:name="Android.intent.category.HOME" />
est activé, généralement à partir d'une installation d'une nouvelle application domestique, l'application domestique par défaut est effacée.
Pour en profiter en créant une activité vide avec le composant home comme celui-ci.
<activity
Android:name="com.t3hh4xx0r.haxlauncher.FakeHome"
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>
Lorsque vous souhaitez définir votre nouvelle valeur par défaut, vous activez ce composant, puis appelez l'intention d'accueil, puis désactivez à nouveau votre faux composant d'origine.
public static void makePrefered(Context c) {
PackageManager p = c.getPackageManager();
ComponentName cN = new ComponentName(c, FakeHome.class);
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
c.startActivity(selector);
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}
Le résultat final est que le système pense qu'une nouvelle application domestique a été installée, donc la valeur par défaut est effacée vous permettant de définir la vôtre sans autorisations spéciales.
Merci à Kevin de TeslaCoil et NovaLauncher pour les informations sur la façon de procéder!
J'utilise le code suivant sur Android 4.1.2 avec une application en mode kiosque signée par la plate-forme sur une tablette industrielle. Il utilise la PackageManager.addPreferredActivity()
obsolète, mais l'avantage est que il fonctionne sans interaction de l'utilisateur. Il fonctionne même après que le lanceur standard Android a été choisi avec l'option "toujours").
// Requires permission SET_PREFERRED_APPLICATIONS.
public static boolean setPreferredHomeActivity (Context context, String packageName, String className) {
ComponentName oldPreferredActivity = getPreferredHomeActivity(context);
if (oldPreferredActivity != null && packageName.equals(oldPreferredActivity.getPackageName()) && className.equals(oldPreferredActivity.getClassName())) {
return false; }
if (oldPreferredActivity != null) {
context.getPackageManager().clearPackagePreferredActivities(oldPreferredActivity.getPackageName()); }
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);
ComponentName[] currentHomeActivities = getActivitiesListByActionAndCategory(context, Intent.ACTION_MAIN, Intent.CATEGORY_HOME);
ComponentName newPreferredActivity = new ComponentName(packageName, className);
context.getPackageManager().addPreferredActivity(filter, IntentFilter.MATCH_CATEGORY_EMPTY, currentHomeActivities, newPreferredActivity);
return true; }
private static ComponentName getPreferredHomeActivity (Context context) {
ArrayList<IntentFilter> filters = new ArrayList<>();
List<ComponentName> componentNames = new ArrayList<>();
context.getPackageManager().getPreferredActivities(filters, componentNames, null);
for (int i = 0; i < filters.size(); i++) {
IntentFilter filter = filters.get(i);
if (filter.hasAction(Intent.ACTION_MAIN) && filter.hasCategory(Intent.CATEGORY_HOME)) {
return componentNames.get(i); }}
return null; }
private static ComponentName[] getActivitiesListByActionAndCategory (Context context, String action, String category) {
Intent queryIntent = new Intent(action);
queryIntent.addCategory(category);
List<ResolveInfo> resInfos = context.getPackageManager().queryIntentActivities(queryIntent, PackageManager.MATCH_DEFAULT_ONLY);
ComponentName[] componentNames = new ComponentName[resInfos.size()];
for (int i = 0; i < resInfos.size(); i++) {
ActivityInfo activityInfo = resInfos.get(i).activityInfo;
componentNames[i] = new ComponentName(activityInfo.packageName, activityInfo.name); }
return componentNames; }
la solution de r2DoesInc ne fonctionne pas sur mon appareil de test 4.2.2.
Ma solution: désactiver puis réactiver HomeActivity de mon application, il n'est pas nécessaire de créer FakeHome
PackageManager p = getPackageManager();
ComponentName cN = new ComponentName(this, HomeActivity.class);
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
startActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
p.setComponentEnabledSetting(cN, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
En prenant la réponse de @ Bruce (sans utiliser une fausse activité domestique) plus loin, vous pouvez utiliser PackageManager.setComponentEnabledSetting pour d'abord désactiver le composant, puis résoudre l'Activité pour l'intention d'origine (plutôt que d'utiliser startActivity), puis activer le composant, puis démarrerActivité avec l'intention.
Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
PackageManager pm = getPackageManager();
ResolveInfo rInfo = pm.resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (!rInfo.activityInfo.packageName.equals(getPackageName())) { // your app is not the default HOME
ComponentName cn = <ComponentName object of your home activity>
pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
startActivity(homeIntent);
}