问题
Can someone tell me how to check that my widget have been placed on the homescreen?
I have some code in my app that should run only if the widget is placed on the homescreen.
回答1:
You need to store that information yourself. I usually use the application preferences, but you could use anything. Generally widgets use services to communicate, so your code that does stuff is likely in a service, but using the preference allows any portion of your app to access this.
In your widget class that extends AppWidgetProvider the onEnabled is called when the widget is put on a homescreen and the onDeleted is (usually) called when it's removed. onDisabled is called when all copies are removed.
So in the code of your widget provider:
@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();
}
Elsewhere in code, you would check to see if the widget is active by:
public boolean isWidgetActive(Context context){
Context appContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(Constants.WIDGET_ACTIVE, false);
}
回答2:
Just saying, but...
int ids[] = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this,MyAppWidgetProvider.class));
Toast.makeText(this, "Number of widgets: "+ids.length, Toast.LENGTH_LONG).show();
回答3:
I know it's an old question, but looking at this today I saw that there are a couple of problems with the accepted answer from @larsona1:
- if the user cleared the shared preferences - there's still widget, but the app won't know about it.
- if the user regret between "add widget" and before pressing "ok" - onEnabled will be called anyway, and a widget will be registered in the home screen even though there is no widget, and no way to remove it later. (it may be a bug in ADT home launcher).
I found a solution to the first problem. No shared preferences are needed at all, since it's unreliable anyway. It has to be checked in runtime.
// in some class you define a static variable, say in S.java
static boolean sWidgetMayExist = true;
In your widget provider:
// 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;
}
And, in your service code add this:
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;
}
回答4:
@Waza_Be is right as looking at the "AppWidgetIds" list to know the number of active widgets (those installed on your homescreen) is the correct way to know this information.
However, keep in mind that you SHOULD don't have to look at this by yourself.
Check the official Android documentation for best practice about widgets : https://developer.android.com/guide/topics/appwidgets/index.html#AppWidgetProvider
The right approach is to override only the onUpdate() method and iterate through the list of "active" widgets :
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);
}
}
}
And as your own widget provider overrides AppWidgetProvider, you will NOT go into the onUpdate() method if you have no widgets active on the home screen!
See the onReceive() code of Android AppWidgetProvider that checks already for you that "appWidgetIds.length > 0":
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);
}
}
}
(...)
}
来源:https://stackoverflow.com/questions/8836724/check-widget-is-placed-on-android-screen