2012-01-12 16 views
7

有人能告诉我如何检查我的小工具是否已放置在主屏幕上?检查小工具放在Android屏幕上

我在我的应用程序中有一些代码,只有在小部件放在主屏幕上时才能运行。

+0

你好,做了你看看我的答案吗?我认为这可能会有所帮助.. ;-) – 2013-06-19 10:29:31

回答

6

您需要自行存储该信息。我通常使用应用程序首选项,但可以使用任何东西。通常,小部件使用服务进行通信,因此您的代码可能在服务中执行,但使用首选项可以让应用程序的任何部分都可以访问它。

在扩展AppWidgetProvider的widget类中,当widget被放在主屏幕上时,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); 
} 
+0

Aargh很好!谢谢,没想到onDisabled(), 当你删除了所有窗口小部件从您的应用程序的主屏幕正是我需要的也只会是运行的。我正在使用:onDeleted(),女巫每次删除一个小部件时都会运行。 – Jeff 2012-01-12 22:31:26

+0

有一些情况下,上述不包括的,我正在寻找解决方案:(1)用户清除共享偏好 - 有小部件,但你不知道它(2)用户之间遗憾“添加小工具”和按“OK” - 但是要允许被称为无插件 – auval 2012-08-05 08:51:01

+2

请看看下面的答案;-) – 2013-04-26 18:48:15

5

我知道这是个老问题,但今天看到这个,我看到@ larsona1接受的答案有几个问题:

  1. 如果用户清除了t他分享了偏好 - 还有小部件,但应用程序不知道它。
  2. 如果用户后悔在“添加小部件”和按“ok”之前 - onEnabled将被调用,并且即使没有小部件也将在主屏幕中注册小部件,并且以后无法将其删除。 (这可能是ADT主页启动器中的一个错误)。

我找到了第一个问题的解决方案。 根本不需要共享首选项,因为它无论如何都不可靠。它必须在运行时检查。

// 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; 
} 
+1

根据此页[1] 2的问题似乎是,固定与Android 2.1及更高版本的bug。我使用Android 4.1.2测试了它,并正确调用了onDelete和onDisabled方法。 [1] https://groups.google.com/forum/?fromgroups=#!topic/android-developers/4agiDfaGvDw – friday 2013-01-18 11:41:15

+0

见Waza_Be的回答,似乎工作,并需要更少的代码。 – 2014-09-26 16:13:07

+0

@ WilliamT.Mallard我的回答比Waza年纪大6个月。所以我在回答时没有检查它。但现在回顾一下,我不确定它是否涵盖了我所指的边缘案例。 – auval 2014-09-26 19:46:31

37

只是说,但...

int ids[] = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this,MyAppWidgetProvider.class)); 

    Toast.makeText(this, "Number of widgets: "+ids.length, Toast.LENGTH_LONG).show(); 
+5

这是正确的答案:查询AppWidgetManager和gettings的ID是正确的方法检查,如果和多少小部件放在主屏幕。 – 2013-06-19 10:17:32

+2

我也可以确认这是正确的答案。不要浪费时间跟随larsona1的回答,并以脆弱的代码来维护。 – Marky 2014-01-08 10:51:00

+1

唯一的问题是,即使没有显示小部件,有时它也会返回多个ID – Catalina 2015-10-13 11:17:57

1

@ Waza_Be是正确的,正在查看“AppWidgetIds”列表来了解t他的活动窗口小部件(安装在主屏幕上)的数量是了解此信息的正确方法。

但是,请记住,你应该不必自己看这个。

检查小部件的最佳实践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()方法,如果你没有在主屏幕上活动控件!

见的Android的AppWidgetProvider的的onReceive()代码检查已经为你 “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); 
      } 
     } 
    } 

(...) 
}