web-dev-qa-db-ja.com

デフォルトのホームアプリケーションのクリアと設定

ノヴァはこれを世界でどのように管理していますか?文字通りまったく同じことをしようとしています。ユーザーに新しいデフォルトのランチャーをクリアして選択するために押すボタンを提供します。

デフォルトのアプリ名を取得して表示できます。

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

どこ Intent i

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

次に、システム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);
   }

ピッカーが表示され、正しく機能しますが、実際には値を設定またはクリアしません。それをデバッグしている間、私はいくつかの追加が欠けているようです? makePreferedメソッドを呼び出すと、次のログメッセージが表示されます。

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

Novaの実装を使用すると、これがすべてわかります。

    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. どのようにしてそこに入り、そのバンドルとともに何が送信されているかを確認できますか?
  2. 優先アプリをクリアするにはどうすればよいですか?できないと言わないでください、私はそれらの答えを十分に見ました。 Novaはそれを実行し、私が望んでいるとおりに実行します。
30
r2DoesInc

これを実行するコードは、実際には非常に賢い回避策です。

コンポーネントが

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

が有効になっていると、通常、新しいホームアプリケーションのインストールから、デフォルトのホームアプリケーションがクリアされます。

このようにホームコンポーネントで空のアクティビティを作成してこれを利用するには。

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

新しいデフォルトを設定する場合は、このコンポーネントを有効にし、ホームインテントを呼び出してから、偽のホームコンポーネントを再び無効にします。

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

その結果、システムは新しいホームアプリがインストールされたと見なし、デフォルトがクリアされて、特別な権限なしで自分のアプリを設定できるようになります。

これがどのように行われるかについての情報を提供してくれた、TeslaCoilとNovaLauncherのKevinに感謝します。

51
r2DoesInc

Android 4.1.2で次のコードを使用しています。産業用タブレットのプラットフォーム署名付きキオスクモードアプリケーションを使用しています。非推奨のPackageManager.addPreferredActivity()を使用していますが、利点はユーザーの操作なしで機能し、標準のAndroid=ランチャーが「常に」オプションで選択された後でも機能します。

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

r2DoesIncのソリューションが4.2.2テストデバイスで機能しません。
私の解決策:アプリのHomeActivityを無効にしてから再度有効にします。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);
4
Bruce

(偽のホームアクティビティを使用せずに)@Bruceの回答をさらに取り入れ、PackageManager.setComponentEnabledSettingを使用して最初にコンポーネントを無効にしてから、ホームインテントのresolveActivity(startActivityを使用するのではなく)、次にコンポーネントを有効にして、インテントでstartActivityを実行できます。

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