2010-10-01 16 views
23

jakiegoś konkretnego wymogu jestem zobowiązany do zmiany Android domyślnej aplikacji Home z mojego dostosowanych aplikacji Home (ustawienie wewnątrz mojej aplikacji, która przełącza domyślny główna = mój wniosek lub poprzedniego domu)Android: zmiana domyślnego Home Zastosowanie

Nie chcę, aby użytkownik poruszał się po ustawieniach Androida, które są bardzo skomplikowane.

Może ktoś mi pomóc jak gdzie rejestruje launcher.apk dla domyślnego zastosowania w domu lub jak to zmienić

Jedyne co udało mi się znaleźć to, że stare pytanie: How to change default Android's Desktop application?

ale żadnych odpowiedzi w ogóle.

Widziałem HomeSwitcher na rynku, który robi lewę, ale brak odpowiedzi dla programisty, który z pewnością byłby zajęty.

EDIT

Znalazłem w internecie http://www.mail-archive.com/[email protected]/msg74167.html

Ale mam ten sam problem:

To jest mój kod:

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

Mam zestaw android.permission.SET_PREFERRED_APPLICATIONS w manifeście . Po wykonaniu powyższego kodu dzienniki zgłaszają, że rzeczy zostały dodane zgodnie z oczekiwaniami (takie same dzienniki, jak w przypadku odznaczenia opcji "Ustaw jako domyślną" z listy IntentResolver). Jednak, kiedy przystąpić klikając domu, lista nadal pokazuje się i loguje powiedzieć:

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 

Więc wydaje się, że rezolwer usuwa pozycję domyślną. Czy robię coś złego, czy to jest środek bezpieczeństwa? Jakie są za tym pomysły ?

+1

Jestem całkiem pewien, że nie może zmusić użytkownika do korzystania z intencję jako domyślny dla niczego - powinien być zawsze ich wybór. Zarejestrowanie go jako zamiaru Home powinno wystarczyć, aby użytkownik otrzymał okno dialogowe z zapytaniem, którą aplikację domową chce uruchomić. –

+0

To nie jest możliwe, O ile nie pracujesz z podstawową kompilacją dla telefonu, a nawet wtedy jest to nadal ryzykowne. Zastanów się, czy powiedzieć swojemu requesterowi NIE. Ponieważ nie jest to oczekiwane zachowanie z perspektywy aplikacji. – JoxTraex

Odpowiedz

8

Zrobiłem obszerne badania na ten temat i począwszy od 2.2 nie ma sposobu, aby to zrobić. Jedynym sposobem jest użycie hakowania, który ma aplikacja blokady malucha, ale ta aplikacja umieszcza ostatnio telefony Samsung w nieskończonej pętli, więc jest to ryzykowne podejście.

jeśli spojrzeć na kod źródłowy Froyo here klasy packagemanager, widać ten mały warunek w sposób addPreferredActivity:

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

HomeSwitcher nie działa poprawnie na 2.2, ponieważ wykorzystuje tę samą metodę i deweloper wykonane komentarz na stronie aplikacji „Froyo (2.2) nie jest obsługiwana ze względu na zmianę API

+0

PO nie uderza w to. Jego błąd to "upuszczanie preferowanej aktywności ...", która jest generowana w dalszej części kodu. Wszystko to sprawi, że nie zadzwonisz do addPreferredActivity z aplikacji, która nie została zbudowana przeciwko Froyo. –

7

„zestaw Wynik zmienił się” oznacza, że ​​zestaw pakietów pasujących tego zamiaru nie zmieniło od zestawu został podany podczas do przywrócono domyślną - - więc domyślna wartość nie jest już ważna. Twoja lista komponentów (która obecnie ma wartość NULL) musi zawierać wszystkie aplikacje ekranu głównego obecne na urządzeniu, a nie tylko twoje.

Oto przykładowy kod, który przetestowałem (przy użyciu powłoki adb am start http://www.google.co.uk/) i używany do ustawienia domyślnej przeglądarki.XXX reprezentuje nazwę klienta, którą musiałam wyłączyć.

Pamiętaj, że aby zadzwonić do addPreferredActivity, musisz skompilować program w wersji minimum-sdk 8 (2.2) i musisz mieć uprawnienie SET_PREFERRED_APPLICATIONS. To uprawnienie to poziom ochrony 2, więc musisz być podpisany przy użyciu tego samego certyfikatu co Menedżer pakietów.

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 - jeśli zaznaczyłeś tę odpowiedź w dół, możesz dać mi znać dlaczego. Kod, który napisałem powyżej jest testowany i działa ...

+6

jak podpisać to z tym samym certyfikatem? – hoffmanc

+0

Chcę go również zaimplementować, chcę zmienić domyślny program uruchamiający po pierwszym uruchomieniu. Umieściłem kod w konstruktorze PackageManagerService, ale zawsze zawodził. Czy możesz mi powiedzieć Jeśli chcę to zrobić, na jakiej pozycji powinienem umieścić kod? Dziękuję bardzo! – alexunder

+0

@ hoffmanc potrzebujesz kluczy platformy, na których zbudowano system operacyjny. Jeśli nie budujesz i nie podpisujesz własnego ROM-a, nie będziesz miał do nich dostępu. – amitav13

0

Ten kod działa na moim urządzeniu ICS: korzystam z usługi, która jest sensowna dla niektórych połączeń, jedna z nich nazywa się SET_PREFERRED_LAUNCHER, należy umieścić w pakiecie nowe ustawienie domyślne pakiet Launcher (PREFERRED_PACKAGE_KEY) i jest to aktywność (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(); 
       } 
      } 
     } 
     } 

    } 

} 

Pamiętaj, aby dodać w pliku manifestu to uprawnienie:

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

Zastosowanie:

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

gdzie:

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

Należy pamiętać, że tylko aplikacje podpisane tym samym kluczem podpisu, co podpisane oprogramowanie, mogą posiadać uprawnienie "SET_PREFERRED_APPLICATIONS". – CommonsWare

+0

At am.installPackage() .. czym jest? co zadeklarować? i nie ma potrzeby korzystania z serviceHandler ... proszę go odpowiednio zaktualizować –

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

To przenosi się do ustawień i umożliwia ręczne ustawienie Home Launchera, ale nie ustawia programowo z powrotem do domyślnego Launchera. – saiyancoder