【发布时间】:2012-01-12 14:31:14
【问题描述】:
谁能告诉我如何检查我的小部件是否已放置在主屏幕上?
我的应用中有一些代码只有在小部件放在主屏幕上时才应该运行。
【问题讨论】:
-
您好,您看我的回答了吗?我认为这可能会有所帮助.. ;-)
标签: android widget homescreen
谁能告诉我如何检查我的小部件是否已放置在主屏幕上?
我的应用中有一些代码只有在小部件放在主屏幕上时才应该运行。
【问题讨论】:
标签: android widget homescreen
只是说,但是...
int ids[] = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this,MyAppWidgetProvider.class));
Toast.makeText(this, "Number of widgets: "+ids.length, Toast.LENGTH_LONG).show();
【讨论】:
getAppWidgetIds() 仍然返回值
AppWidgetProvider 中调用onUpdate。
您需要自己存储这些信息。我通常使用应用程序首选项,但你可以使用任何东西。通常小部件使用服务进行通信,因此您的代码可能在服务中,但使用首选项允许您的应用程序的任何部分访问它。
在扩展 AppWidgetProvider 的小部件类中,当小部件放在主屏幕上时会调用 onEnabled,而(通常)在移除时调用 onDeleted。删除所有副本时调用 onDisabled。
所以在你的小部件提供者的代码中:
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
setWidgetActive(true);
context.startService(new Intent(appContext, WidgetUpdateService.class));
}
@Override
public void onDisabled(Context context) {
Context appContext = context.getApplicationContext();
setWidgetActive(false);
context.stopService(new Intent(appContext, WidgetUpdateService.class));
super.onDisabled(context);
}
private void setWidgetActive(boolean active){
Context appContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(Constants.WIDGET_ACTIVE, active);
edit.commit();
}
在代码的其他地方,您可以通过以下方式检查小部件是否处于活动状态:
public boolean isWidgetActive(Context context){
Context appContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(Constants.WIDGET_ACTIVE, false);
}
【讨论】:
我知道这是一个老问题,但今天看到这个问题,我发现@larsona1 接受的答案存在一些问题:
我找到了第一个问题的解决方案。 根本不需要共享偏好,因为无论如何它都是不可靠的。必须在运行时检查。
// in some class you define a static variable, say in S.java
static boolean sWidgetMayExist = true;
在您的小部件提供程序中:
// MyAppWidgetProvider.java
// to respond to runtime changes, when widgets are added and removed
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
S.sWidgetMayExist = true;
}
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
S.sWidgetMayExist = true;
}
并且,在您的服务代码中添加:
AppWidgetManager manager = null;
RemoteViews views = null;
ComponentName widgetComponent = null;
// ..and in your update thread
if (!S.sWidgetMayExist) { return; }
if (manager == null || widgetComponent == null) {
widgetComponent = new ComponentName(c,
MyAppWidgetProvider.class);
manager = AppWidgetManager.getInstance(c);
}
if (manager.getAppWidgetIds(widgetComponent) == null) {
S.sWidgetMayExist = false;
}
【讨论】:
@Waza_Be 是正确的,因为查看“AppWidgetIds”列表以了解活动小部件(安装在主屏幕上的小部件)的数量是了解此信息的正确方法。
但是,请记住,您不必自己看这个。
查看官方 Android 文档以了解有关小部件的最佳实践: https://developer.android.com/guide/topics/appwidgets/index.html#AppWidgetProvider
正确的方法是仅覆盖 onUpdate() 方法并遍历“活动”小部件列表:
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
由于您自己的小部件提供程序会覆盖 AppWidgetProvider,因此如果您在主屏幕上没有活动小部件,您将不会进入 onUpdate() 方法!
查看已经为您检查“appWidgetIds.length > 0”的 Android AppWidgetProvider 的 onReceive() 代码:
public void onReceive(Context context, Intent intent) {
// Protect against rogue update broadcasts (not really a security issue,
// just filter bad broacasts out so subclasses are less likely to crash).
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null) {
int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds != null && appWidgetIds.length > 0) {
this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
}
}
}
(...)
}
【讨论】:
下面的呢:
boolean widgetExists(Context context, int appWidgetId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
AppWidgetProviderInfo info = appWidgetManager.getAppWidgetInfo(appWidgetId);
return (info != null);
}
来自the docs 为appWidgetManager.getAppWidgetInfo():
如果 appWidgetId 尚未绑定到提供程序,或者您无权访问该 appWidgetId,则返回 null。
【讨论】: