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
}
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
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
Bardzo pomocna i dobrze napisana odpowiedź. Dzięki. – dazed