我们希望通过代码启用或禁用小部件。当我们说 “禁用”我们指的是在应用程序中注册的小部件 不应该出现在用户可用的小部件列表中 他们尝试将小部件添加到主屏幕。 不幸的是,这个问题已被多次提出 回答。
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); }
我很想知道是否有人克服了这个障碍。也许我是 走错了路。我想要的是能够删除一个 用户在尝试时可用的小部件列表中的小部件 将小部件添加到其主屏幕。
答案 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 注册接收器,以便在更新您的应用时立即为用户禁用此功能。要处理全新安装,您需要在应用的其他位置添加代码,以便在应用首次运行时禁用小部件。