2010-10-01 11 views
23

per qualche requisito specifico sono tenuto a cambiare Android predefinito applicazione Home con la mia domanda iniziale personalizzata (un ambiente all'interno del mio app che si alternerà iniziale predefinita = mia domanda o casa precedente)Android: il cambiamento di default casa Application

Non voglio che l'utente viaggi le impostazioni di Android che sono molto complicate.

uno può dare una mano come dove si registra launcher.apk per impostazione predefinita applicazione domestica o come cambiare la situazione

L'unica cosa che ho trovato è stato che vecchia domanda: How to change default Android's Desktop application?

ma nessuna risposta affatto.

Ho visto HomeSwitcher nel mercato che fa il trucco, ma nessuna risposta per lo sviluppatore che potrebbe certamente essere occupato.

EDIT

Ho trovato questo sul web http://www.mail-archive.com/[email protected]/msg74167.html

Ma ho avuto lo stesso problema:

questo è il mio codice:

private void makePreferred() { 
      PackageManager pm = getPackageManager(); 
      IntentFilter f = new IntentFilter("android.intent.action.MAIN"); 
      f.addCategory("android.intent.category.HOME"); 
      f.addCategory("android.intent.category.DEFAULT"); 
      ComponentName cn = new ComponentName("com.example.android.home", "com.example.android.home.Home"); 
      pm.addPreferredActivity(f, IntentFilter.MATCH_CATEGORY_EMPTY, null, cn); 

ho il set android.permission.SET_PREFERRED_APPLICATIONS nel manifest . Dopo aver eseguito il codice sopra, i log affermano che è stato aggiunto come previsto (gli stessi registri di quando spuntano "Rendi predefinito" dall'elenco IntentResolver). Tuttavia, quando procedo cliccando casa, l'elenco mostra ancora in piedi ei registri dire:

INFO/PackageManager(52): Result set changed, dropping preferred 
activity for Intent { act=android.intent.action.MAIN cat= 
[android.intent.category.HOME] flg=0x10200000 } type null 

così sembra il resolver elimina la voce predefinita. Sto facendo qualcosa di sbagliato, o si tratta di una misura di sicurezza? Quali sono le idee dietro a questo?

+1

Sono abbastanza sicuro che non si può costringere un utente di utilizzare il vostro intento come impostazione predefinita per qualsiasi cosa - dovrebbe essere sempre la loro scelta. Registrarlo come intento domestico dovrebbe essere sufficiente per consentire all'utente di ottenere una finestra di dialogo che chiede quale app di casa desidera avviare. –

+0

Questo non è possibile A MENO CHE tu stia lavorando con una build primaria per un telefono e anche allora è ancora rischioso. Considera di dire al tuo richiedente NO. Perché questo non è un comportamento atteso dal punto di vista di un'app. – JoxTraex

risposta

8

Ho fatto una ricerca approfondita su questo e a partire da 2.2 non c'è modo di farlo. L'unico modo è usare un po 'di hacking, ma questa app ha messo i telefoni Samsung di recente nel ciclo infinito, quindi è un approccio rischioso.

se si guarda il codice sorgente froyo here di classe packagemanager, si vedrà questo piccolo stato nel metodo addPreferredActivity:

if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) 
        < Build.VERSION_CODES.FROYO) { 
       Slog.w(TAG, "Ignoring addPreferredActivity() from uid" 
         + Binder.getCallingUid()); 
       return; 
      } 

HomeSwitcher non funziona correttamente su 2,2 dal momento che utilizza questo metodo e sviluppatore fatto un commento sulla pagina di app "Froyo (2.2) non è supportata a causa del cambiamento API"

+0

L'OP non sta colpendo quella domanda. Il suo errore è "abbandonare l'attività preferita ..." che viene generata più avanti nel codice. Tutto ciò che controlla non ti impedisce di chiamare addPreferredActivity da un'applicazione che non è stata costruita contro Froyo. –

7

"set di risultati cambiato" significa che l'insieme di pacchetti corrispondenti che l'intento è cambiato dal set specificato quando è c ha corretto il valore predefinito -, quindi il valore predefinito non è più valido. La tua lista di componenti (che stai attualmente impostando su null) deve contenere tutte le app homescreen presenti sul dispositivo, non solo le tue.

Ecco il codice di esempio che ho testato (utilizzando adb shell am start http://www.google.co.uk/) e utilizzato per impostare il browser predefinito.XXX rappresenta un nome cliente che ho dovuto oscurare.

Si noti che per chiamare addPreferredActivity è necessario aver compilato una versione sdk minima di 8 (2.2) ed è necessario aver specificato l'autorizzazione SET_PREFERRED_APPLICATIONS. Tale autorizzazione è il livello di protezione 2, quindi è necessario essere firmati con lo stesso certificato di PackageManager.

IntentFilter filter = new IntentFilter(); 
filter.addAction("android.intent.action.VIEW"); 
filter.addCategory("android.intent.category.DEFAULT"); 
filter.addDataScheme("http"); 
Context context = getApplicationContext(); 
ComponentName component = new ComponentName("com.opera.mini.XXX", "com.opera.mini.XXX.CustomerBrowser"); 
ComponentName[] components = new ComponentName[] {new ComponentName("com.android.browser", "com.android.browser.BrowserActivity"), 
                component}; 
pm.addPreferredActivity(filter, IntentFilter.MATCH_CATEGORY_SCHEME, components, component); 

ETA: se hai contrassegnato questa risposta, potresti farmi sapere perché. Il codice che ho postato sopra è testato e funzionante ...

+6

come firmarlo con lo stesso certificato? – hoffmanc

+0

Voglio anche implementarlo, voglio cambiare il launcher predefinito dopo il primo avvio. Ho inserito il codice nel costruttore di PackageManagerService, ma ha sempre avuto esito negativo. Puoi dirmi se voglio farlo, quale posizione dovrei inserire il codice? grazie mille! – alexunder

+0

@hoffmanc avresti bisogno delle chiavi di piattaforma con cui è stato costruito il sistema operativo. A meno che tu non stia costruendo e firmando la tua ROM, non avresti accesso a questi. – amitav13

0

Questo codice funziona sul mio dispositivo ICS: utilizzo un servizio che è sensibile ad alcune chiamate, una di queste si chiama SET_PREFERRED_LAUNCHER, la metti in un pacchetto il tuo nuovo default pacchetto Launcher (PREFERRED_PACKAGE_KEY) ed è l'attività (PREFERRED_ACTIVITY_KEY)

Method installPackageMethod = null; 
Method deletePackageMethod = null; 
Method setPreferredActivityMethod = null; 
Method replacePreferredActivityMethod = null; 
Object pm = null; 


    @Override 
public void onCreate() { 
    super.onCreate(); 
     if (pm == null) 
     pm = getPackageManager(); 
    try { 
     if (setPreferredActivityMethod == null) 
      setPreferredActivityMethod = pm.getClass().getMethod(
        "addPreferredActivity", IntentFilter.class, int.class, 
        ComponentName[].class, ComponentName.class); 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
    } 
} 


private final class ServiceHandler extends Handler { 
    private Context context; 

    public ServiceHandler(Looper looper, Context ctx) { 
     super(looper); 
     context = ctx; 
    } 

    @Override 
    public void handleMessage(Message msg) { 
     Intent intent = (Intent) msg.getData().getParcelable(
       UPDATER_SERVICE_ACTION); 
     int request = intent.getIntExtra(
       REQUEST_KEY, 
       REQUEST_UNKNOWN); 
     Bundle bundle = intent.getExtras(); 

     switch (request) { 
     case INSTALL_APPLICATION: { 
      if (bundle != null) { 
       String appPath = bundle 
         .getString(APP_PATH_KEY); 
       if (appPath != null) { 
        LogUtil.e(TAG, "try to install " + appPath); 

        try { 
         am.installPackage(appPath); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 

        LogUtil.e(TAG, "install of " + appPath + " done"); 
       } 
      } 
      break; 
     } 
     case UNISTALL_PACKAGE: { 
      if (bundle != null) { 
       String packagename = bundle 
         .getString(PACKAGE_NAME_KEY); 
       if (packagename != null) { 
        LogUtil.e(TAG, "unistall " + packagename); 

        try { 
         deletePackageMethod 
           .invoke(pm, packagename, null, 0); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
      break; 
     } 
     case SET_PREFERRED_LAUNCHER: { 
      if (bundle != null) { 
       String package_name = bundle 
         .getString(PREFERRED_PACKAGE_KEY); 
       if (package_name == null) { 
        LogUtil.e(TAG, 
          "WARNING: setDefaultActivity cannot continue, package is NULL"); 
        return; 
       } 
       String activity_name = bundle 
         .getString(PREFERRED_ACTIVITY_KEY); 
       if (activity_name == null) { 
        LogUtil.e(TAG, 
          "WARNING: setDefaultActivity cannot continue, activity is NULL"); 
        return; 
       } 

       LogUtil.e(TAG, "setDefaultActivity activity=" 
         + activity_name + " package=" + package_name); 

       IntentFilter filter = new IntentFilter(
         "android.intent.action.MAIN"); 
       filter.addCategory("android.intent.category.HOME"); 
       filter.addCategory("android.intent.category.DEFAULT"); 
       ComponentName[] components = new ComponentName[] { 
         new ComponentName("com.android.launcher", 
           "com.android.launcher2.Launcher"), 
         new ComponentName(package_name, activity_name) }; 
       ComponentName activity = new ComponentName(package_name, 
         activity_name); 
       try { 
        setPreferredActivityMethod.invoke(pm, filter, 
          IntentFilter.MATCH_CATEGORY_EMPTY, components, 
          activity); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     } 

    } 

} 

Ricordate di aggiungere nel file manifest questa autorizzazione:

<uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"/> 

Usage:

public void setPreferredLauncher(String activity_name,String package_name) 
{ 
    Intent intent = new Intent(UPDATER_SERVICE_ACTION); 
    intent.putExtra(REQUEST_KEY, SET_PREFERRED_LAUNCHER); 
    intent.putExtra(PREFERRED_ACTIVITY_KEY, activity_name); 
    intent.putExtra(PREFERRED_PACKAGE_KEY, package_name); 
    context.startService(intent); 
} 

dove:

public static final String _UPDATER_SERVICE_ACTION = "com.android.updaterservice.ACTION"; 
public static final String REQUEST_KEY = "com.android.updaterservice.REQUEST_KEY"; 
public static final String PACKAGE_NAME_KEY = "com.android.updaterservice.PACKAGE_NAME_KEY"; 
public static final String APP_PATH_KEY = "com.android.updaterservice.APP_PATH_KEY"; 
public static final String PREFERRED_ACTIVITY_KEY = "com.android.updaterservice.PREFERRED_ACTIVITY_KEY"; 
public static final String PREFERRED_PACKAGE_KEY = "com.android.updaterservice.PREFERRED_PACKAGE_KEY"; 
public static final String INSTALL_PACKAGE_RESULT = "com.android.updaterservice.INSTALL_PACKAGE_RESULT"; 
public static final String PACKAGE_NAME = "PACKAGE_NAME"; 
public static final String INSTALL_SUCCEEDED = "INSTALL_SUCCEEDED"; 
public static final int REQUEST_UNKNOWN = -1; 
public static final int INSTALL_APPLICATION = 1; 
public static final int UNISTALL_PACKAGE = 2; 
public static final int SET_PREFERRED_LAUNCHER = 3; 
+1

Si noti che solo le app firmate con la stessa chiave di firma firmata il firmware possono contenere l'autorizzazione "SET_PREFERRED_APPLICATIONS'. – CommonsWare

+0

su am.installPackage() .. cosa sono? cosa dichiarare? e non vi è alcun uso di serviceHandler .. si prega di aggiornarlo correttamente –

0
startActivity(new Intent(Settings.ACTION_HOME_SETTINGS)); 
+0

Questo porta alle impostazioni e consente di impostare manualmente Home Launcher, ma non di reimpostarlo al Launcher predefinito a livello di programmazione. – saiyancoder