动态启用或禁用窗口小部件不起作用

时间:2010-02-06 13:13:18

标签: android widget

我们希望通过代码启用或禁用小部件。当我们说 “禁用”我们指的是在应用程序中注册的小部件 不应该出现在用户可用的小部件列表中 他们尝试将小部件添加到主屏幕。 不幸的是,这个问题已被多次提出 回答。

Dianne Hackborn对另一个人做出了回应 小部件问题,表明可以使用 包管理器禁用小部件:

PackageManager pm = context.getPackageManager(); 
pm.setComponentEnabledSetting(new ComponentName("com.example.android.apis", ".appwidget.ExampleBroadcastReceiver"), 
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, // or DISABLED 
    PackageManager.DONT_KILL_APP); 

然而,这不起作用。小部件组件仍将出现 在小部件列表中。它可能是AppWidgetService(位于 在Android源代码的Base.git中\ src \ base \ services \ java \ com \ android \ server),它加载可用小部件列表,缓存此列表 可用的小部件。如果是这样的话,那么就是上面的话 启用或禁用窗口小部件组件的代码将在a之后工作 设备重置,因为没有缓存;它不是。

我也尝试过重写一些方法 AppWidgetProvider,例如过滤掉任何事件。我不认为 这将去任何地方,因为AppWidgetService填充 列表,使用包管理器查找捕获的所有组件 启动时和包的时间的ACTION_APPWIDGET_UPDATE操作 添加(即安装了新的应用程序)。提供者唯一的时间 从此列表中删除的是ACTION_PACKAGE_REMOVED广播。 因此,无论如何,提供商将始终在那里 启用/禁用组件的状态,我已经调查了实际 列出当用户长时从Launcher应用程序显示的活动 单击桌面并添加一个小部件:AppWidgetPickActivity in Settings.GIT in com.android.settings。不幸的是,这填补了这个清单 直接来自AppWidgetService,没有任何过滤 组件的启用状态:     void putInstalledAppWidgets(List items){         列表安装= mAppWidgetManager.getInstalledProviders();         putAppWidgetItems(安装,null,items);     }

我很想知道是否有人克服了这个障碍。也许我是 走错了路。我想要的是能够删除一个 用户在尝试时可用的小部件列表中的小部件 将小部件添加到其主屏幕。

4 个答案:

答案 0 :(得分:4)

  

可能是AppWidgetService   (位于Android源代码中   Base.git at   \ SRC \基地\服务\ java中的\ com \机器人   \ server),它加载列表   可用的小部件,缓存此列表   可用的小部件。

它确实如此,我可以说。它将列表存储在mInstalledProviders;此列表将添加到via readStateFromFileLocked(),它似乎是从系统启动逻辑调用的。

  

如果是这样的话,那么   以上代码启用或   禁用小部件组件   设备重置后工作,因为   没有缓存;它没有。

您假设是RAM缓存。缓存是一个XML文件。

  

不幸的是,这填补了这一点   从中直接列出   AppWidgetService,没有任何   过滤组件已启用   状态

这似乎是Android中的一个错误。更一般地说,我认为整个缓存的问题是错误 - 如果缓存不同步,我认为无法恢复。

如果你还没有这样做,我建议你将你的写作作为一个问题发布在public Android issue tracker上。

答案 1 :(得分:3)

它对我有用!我不得不使用DONT_KILL_APP,否则会立即杀死我的应用程序。此外,我必须评论条件,以检查它是否已经处于相同的状态。

这是我创建的辅助方法:

public void setMyCustomWidgetEnabled( boolean bEnable )
    {
        Log.d( LOG_TAG_NAME, "Entering setMyCustomWidgetEnabled( " + bEnable + " )..." );

        PackageManager rPackageManager = getPackageManager();
        if( rPackageManager != null )
        {
            ComponentName rComponentName = new ComponentName( getBaseContext(), MyCustomWidget.class );

            int nComponentEnabledState = rPackageManager.getComponentEnabledSetting( rComponentName );

            if( bEnable )
            {
                //if( nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED )
                {
                    // Change the State to Enabled
                    rPackageManager.setComponentEnabledSetting( rComponentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP );

                    Log.d( LOG_TAG_NAME, "-> Changed My Custom Widget' to ENABLED!" );
                }
            }
            else
            {
                //if( nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED )
                {
                    // Change the State to Disabled
                    rPackageManager.setComponentEnabledSetting( rComponentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP );

                    Log.d( LOG_TAG_NAME, "-> Changed 'My Custom Widget' to DISABLED!" );
                }
            }
        }

        Log.d( LOG_TAG_NAME, "Leaving setMyCustomWidgetEnabled( " + bEnable + " )..." );
}

答案 2 :(得分:0)

功能

pm.setComponentEnabledSetting()

在ICS工作。当窗口小部件被禁用时,它将从可用窗口小部件列表中删除。暂时的小安慰,但它至少得到了纠正。

答案 3 :(得分:0)

platform code 中有一个错误,导致系统忽略清单中禁用的小部件。 此问题已针对 Android 12 修复,但仍会影响以前的版本。

您的小部件提供商的接收器必须在清单中启用,否则它将永远不会显示给用户。

<!-- DO NOT set android:enabled="false" on this receiver! -->
<receiver android:name="ExampleAppWidgetProvider" >
<intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
           android:resource="@xml/example_appwidget_info" />

只要默认启用小部件,PackageManager.setComponentEnabledSetting 就会在以后禁用和重新启用它。

您可以为 MY_PACKAGE_REPLACED 注册接收器,以便在更新您的应用时立即为用户禁用此功能。要处理全新安装,您需要在应用的其他位置添加代码,以便在应用首次运行时禁用小部件。