2013-06-30 12 views
7

Używam aktualizacji AlarmManager, aby zaktualizować moje widżety. I chcę to zatrzymać, jeśli na ekranie głównym nie ma widżetu. Ale mam problem z wykryciem, czy na ekranie głównym nie ma widżetu.Sprawdź, czy widżet istnieje na ekranie głównym za pomocą aplikacji appWidgetId

Jako gdy próbuję uzyskać AppWidgetIds korzystając w ten sposób:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 

int[] appWidgetIDs = appWidgetManager 
    .getAppWidgetIds(new ComponentName(context, Widget.class)); 

uzyskać długość appWidgetIDs podczas gdy w rzeczywistości nie ma widget na ekranie głównym. Dlaczego?

Dlatego chciałbym się dowiedzieć, czy istnieje sposób na wykrycie, że identyfikator widżetu istnieje na ekranie głównym.

Dziękuję z góry.

Odpowiedz

16

Gratulacje, napotkali widmowe aplikacje. Wydaje się być udokumentowane na Android issue tracker. Zwykle występują, gdy działanie konfiguracyjne dla aplikacji zostało anulowane, choć wydaje się, że przez niewłaściwe wdrożenie czynności konfiguracyjnej; programiści nie uwzględniają identyfikatora widgetu jako dodatkowego podczas ustawiania wyniku działania na RESULT_CANCELED. (Aplikacja ApiDemos próbka nawet Google za zaniedbuje to zrobić!)

Właściwa realizacja jest tak:

public class AppWidgetConfigActivity extends Activity { 

    private int appWidgetId; 
    private Intent resultValue; 

    protected void onCreate(bundle saved) { 
     super.onCreate(saved); 

     // get the appwidget id from the intent 
     Intent intent = getIntent(); 
     appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 
       AppWidgetManager.INVALID_APPWIDGET_ID); 

     // make the result intent and set the result to canceled 
     resultValue = new Intent(); 
     resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 
     setResult(RESULT_CANCELED, resultValue); 

     // if we weren't started properly, finish here 
     if (appwidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { 
      finish(); 
     } 

     /* ... */ 
    } 

    /* ... */ 

    private void finishConfigure() { 
     /* finish configuring appwidget ... */ 
     setResult(RESULT_OK, resultValue); 
    } 
} 

dotąd nie znam sposób wykryć obecność appwidget phantom nie robiąc własną księgowość . Sugeruję przechowywanie wartości SharedPreferences wskazującej, że działanie konfiguracyjne nie zostało anulowane, a następnie zapytanie o tę wartość w innym kodzie. Możesz również użyć tych informacji, aby "usunąć" widżet fantomu, jeśli go spotkasz. W swojej działalności appwidget konfiguracji:

private void finishConfigure() { 
    /* finish configuring appwidget ... */ 
    setResult(RESULT_OK, resultValue); 

    String key = String.format("appwidget%d_configured", appwidgetId); 
    SharedPreferences prefs = getSharedPreferences("widget_prefs", 0); 
    prefs.edit().putBoolean(key, true).commit; 
} 

Następnie można sprawdzić, że masz co najmniej jeden non-fantom appwidget tak:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 
AppWidgetHost appWidgetHost = new AppWidgetHost(context, 1); // for removing phantoms 
SharedPreferences prefs = getSharedPreferences("widget_prefs", 0); 
boolean hasWidget = false; 

int[] appWidgetIDs = appWidgetManager.getAppWidgetIds(new ComponentName(context, Widget.class)); 
for (int i = 0; i < appWidgetIDs.length; i++) { 
    int id = appWidgetIDs[i]; 
    String key = String.format("appwidget%d_configured", id); 
    if (prefs.getBoolean(key, false)) { 
     hasWidget = true; 
    } else { 
     // delete the phantom appwidget 
     appWidgetHost.deleteAppWidgetId(id); 
    } 
} 

if (hasWidget) { 
    // proceed 
} else { 
    // turn off alarms 
} 
+0

Ta odpowiedź zasługuje na dużo więcej sława! Jestem przekonany, że wiele osób będzie miało ten problem (nawet jeśli go nie znają), ponieważ przykładowy kod aplikacji "Hello world", który otrzymasz z Android Studio, nie działa poprawnie, i to jest dużo ludzie zaczną. Z twoją radą, aby dołączyć identyfikator identyfikatora aplikacji jako dodatkowy podczas ustawiania wyniku działania na 'RESULT_CANCELED', nie wydaje mi się, aby tworzyć widma fantomowe już. Dzięki! – drmrbrewer

+0

Co do kodu do usunięcia widm fantomowych * czy * pojawiają się z jakiegoś powodu, gdzie byś go polecił wstawić? Nie w 'onUpdate()', ponieważ wydaje się, że zostanie wywołana, gdy najpierw uruchomione zostanie działanie konfiguracyjne, czyli przed skonfigurowaniem widżetu - nie chcemy zabijać widżetu przed jego narodzinami! – drmrbrewer

+0

Bardzo pomocna i dobrze napisana odpowiedź. Dzięki. – dazed

Powiązane problemy