2012-10-31 4 views
22

In che modo Nova gestisce questo? Sto letteralmente cercando di fare esattamente la stessa cosa: fornire agli utenti un pulsante da premere per cancellare e scegliere il loro nuovo launcher predefinito.Cancellazione e impostazione dell'applicazione domestica predefinita

sono in grado di ottenere il nome di default app e visualizzarla:

 private String getPrefered(Intent i) { 
     PackageManager pm = this.getActivity().getPackageManager(); 
     final ResolveInfo mInfo = pm.resolveActivity(i, 0); 
     return (String) pm.getApplicationLabel(mInfo.activityInfo.applicationInfo); 
    } 

dove Intent i è

Intent home = new Intent("android.intent.action.MAIN"); 
     home.addCategory("android.intent.category.HOME"); 

Poi chiamo il ResolveActivity sistema,

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); 
    } 

Il picker viene visualizzato e funziona correttamente, ma in realtà non imposta o cancella qualsiasi v alori. Durante il debug, sembra che mi manchi qualche extra? Quando chiamo il metodo makePrefered, ricevo il seguente messaggio di log,

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 

Quando uso l'attuazione Nova vedo tutto questo però,

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 
  1. Come posso arrivare lì e vedere cosa viene inviato insieme a quel pacchetto?
  2. Come posso cancellare l'app preferita? Non dirmi che non puoi, ho visto abbastanza di quelle risposte. Nova lo fa e lo fa esattamente come vorrei.

risposta

44

Il codice per eseguire questa operazione è in realtà solo un lavoro molto intelligente.

Quando un componente con

 <category android:name="android.intent.category.HOME" /> 

è abilitata, in genere da una installazione di una nuova applicazione casa, l'applicazione iniziale predefinita ottiene cancellati.

Per sfruttare questo vantaggio creando un'attività vuota con il componente home come questo.

<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>  

Quando si desidera impostare la nuova impostazione predefinita, si attiva questa componente, quindi chiamare l'intento di casa e quindi disattivare nuovamente il componente di casa falso.

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); 
    } 

Il risultato finale è che il sistema pensa una nuova casa applicazione è stata installata, in modo che il valore predefinito viene cancellata che consente di impostare la vostra con autorizzazioni speciali.

Grazie a Kevin di TeslaCoil e NovaLauncher per le informazioni su come è fatto!

+0

Ho provato questo in 4.2.2 e non funziona ... Solo quando si installa un nuovo Home Launcher il comportamento è quello che hai descritto. – TacB0sS

+0

Dunno. Havent ci ha provato da un po '. – r2DoesInc

+1

Ho provato su 4.2.2 con il mio Nexus 4, e funziona. –

3

La soluzione di r2DoesInc non funziona sul mio dispositivo di test 4.2.2.
La mia soluzione: Disattivare quindi riattivare HomeActivity della mia app, non deve creare 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); 
2

Io uso il seguente codice su Android 4.1.2 con un'applicazione chiosco-mode piattaforma firmato su un tablet industriale.Utilizza il deprecato PackageManager.addPreferredActivity(), ma il vantaggio è che funziona senza interazione dell'utente. Funziona anche dopo che il launcher Android standard è stato scelto con l'opzione "always".

// 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; } 
+0

Come hai richiesto l'autorizzazione android.permission.SET_PREFERRED_APPLICATIONS su 4.1.2 ?? Vedo che è deprecato "Questa costante è stata dichiarata obsoleta nel livello API 7". – umesh

+0

@umesh Ho appena aggiunto SET_PREFERRED_APPLICATIONS al file manifest. È deprecato, ma funziona con API 16 (Android 4.1.2). –