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

Android 动态启用或禁用小部件不起作用,android,widget,Android,Widget,我们希望通过代码启用或禁用小部件。当我们说 “禁用”是指在应用程序中注册的小部件 不应显示在用户可用的小部件列表中 他们试图在主屏幕上添加一个小部件。 不幸的是,这个问题已经被问了很多次,但都没有回答 回答 Dianne Hackborn对另一个 小部件问题,这表明可以使用 要禁用小部件的程序包管理器: PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(new ComponentName

我们希望通过代码启用或禁用小部件。当我们说 “禁用”是指在应用程序中注册的小部件 不应显示在用户可用的小部件列表中 他们试图在主屏幕上添加一个小部件。 不幸的是,这个问题已经被问了很多次,但都没有回答 回答

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 \服务器),加载可用小部件列表,缓存此列表 可用小部件的数量。如果是这样的话,那么上述 启用或禁用小部件组件的代码将在 设备重置,因为没有缓存;事实并非如此

我还尝试过重写 AppWidgetProvider,例如筛选出任何事件。我不这么认为 这将发生在任何地方,因为AppWidgetService 列表使用包管理器查找捕获的所有组件 启动时和启动包时的操作\u APPWIDGET\u更新操作 添加(即安装了新的应用程序)。提供程序的唯一时间是 从该列表中删除的是一个动作\u程序包\u删除的广播。 因此,考虑到提供者将始终在那里,无论 组件的启用/禁用状态,我已经查看了实际的 列出当用户长时间执行以下操作时从Launcher应用程序显示的活动- 单击桌面并在中添加一个小部件:AppWidgetPickActivity 中的Settings.GIT com.android.settings。不幸的是,这会填充列表 直接从AppWidgetService,无需对 组件的启用状态: void putInstalledAppWidgets(列表项){ 已安装列表= mAppWidgetManager.getInstalledProviders(); putAppWidgetItems(已安装,空,items); }

我很想看看是否有人克服了这个障碍。也许我是 走错了路。我想要的只是能够移除一个 当用户尝试使用时,可从窗口小部件列表中选择窗口小部件 将小部件添加到他们的主屏幕

可能是AppWidgetService (位于Android源代码的 Base.git位于 \src\base\services\java\com\android \服务器),它加载 可用小部件,缓存此列表中的 可用的小部件

是的,就我所知。它将列表存储在
minInstalledProviders
中;此列表是通过
readStateFromFileLocked()
添加到的,它似乎是从系统启动逻辑调用的

如果是这样的话,那么 上述代码可启用或 禁用窗口小部件组件 在设备重置后工作,因为 没有缓存;事实并非如此

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

不幸的是,这种情况充斥着整个世界 直接从 AppWidgetService,不带任何 已启用组件的筛选 地位

这似乎是安卓系统的一个缺陷。更一般地说,我认为整个缓存都是bug——如果缓存不同步,我看不到恢复的方法

如果您还没有这样做,我建议您将您的writeup作为问题发布在上。

该功能

pm.setComponentEnabledSetting()

在ICS工作。当小部件被禁用时,它将从可用小部件列表中删除。这只是暂时的小小安慰,但至少已经纠正了。

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

以下是我创建的帮助器方法:

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 + " )..." );
}
中存在一个错误,导致系统忽略清单中禁用的小部件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" />


若要在用户更新应用程序时立即禁用此功能,请执行以下操作。要处理新安装,您需要在应用程序的其他位置添加代码,以便在应用程序第一次运行时禁用该小部件。

3年后是否有此问题的更新?看起来只有当清单中的接收器最初启用时,启用/禁用才起作用。如果它被清单禁用,则以编程方式启用/禁用不起作用。请您确认一下这个行为好吗?@peter.bartos是的,它只有在清单中最初启用时才起作用。此外,对于要禁用小部件的应用程序,用户需要强制退出应用程序,以便“更新”小部件列表(如果它没有以编程方式将其杀死)。只要默认情况下未禁用小部件提供程序接收器,此操作就可以工作