【问题标题】:Clearing and setting the default home application清除和设置默认家庭应用程序
【发布时间】:2012-10-21 11:31:21
【问题描述】:

Nova 到底是如何做到这一点的?我实际上是在尝试做同样的事情:为用户提供一个按钮来清除并选择他们的新默认启动器。

我能够获取默认应用名称并显示它:

       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 做到了,而且完全按照我的意愿去做。

【问题讨论】:

    标签: java android launcher


    【解决方案1】:

    执行此操作的代码实际上只是一个非常聪明的解决方法。

    当一个组件带有

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

    启用,通常从安装新的家庭应用程序开始,默认家庭应用程序会被清除。

    通过像这样使用 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 提供有关如何完成此操作的信息!

    【讨论】:

    • 我已经在 4.2.2 上尝试过,但它不起作用......只有在安装新的 Home Launcher 时,行为才如您所描述的那样。
    • 不错,即使有权限我也不能使用 set_preferred_application()。
    • 此示例需要在某些设备上具有“" 权限。
    • 嗨 r2DoesInc,我也在尝试处理主页按钮,在我的应用程序中我处理主页键,但在按下主页键时我的启动器正在调用应用程序之外。有什么我想念的吗?给我指导线,谢谢。
    • 当已经设置了另一个默认启动器时,这似乎不适用于 4.4.2(有人可以确认吗?)。启用虚假活动似乎没有任何区别,设备不显示任何对话框,并在我达到c.startActivity(selector); 时返回原始默认应用程序。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我在 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; }
      

      【讨论】:

      • 您是如何在 4.1.2 上请求权限 android.permission.SET_PREFERRED_APPLICATIONS 的??我看到它已弃用“此常量在 API 级别 7 中已弃用”。
      • @umesh 我刚刚将 SET_PREFERRED_APPLICATIONS 添加到清单文件中。它已被弃用,但它适用于 API 级别 16 (Android 4.1.2)。
      • 当我的应用程序被签名为系统应用程序时,这适用于我在 Android 4.4.2 上。
      • 我后来在这篇文章中发现了 getPreferredHomeActivity 方法的问题。在用户按下 Home 然后选择启动器“Just Once”的情况下,这里的方法将从 getPreferredHomeActivity 返回该应用程序,而我希望它返回 null。原始问题中提到的 resolveActivity 方法正确处理了这种情况。
      【解决方案4】:

      进一步了解@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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多