2012-01-12 58 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); 
      } 
     } 
    } 

(...) 
}