Tebrikler, phantom appwidgets ile karşılaştınız. Android issue tracker'da belgelenmiş gibi görünüyor. Genellikle, bir appwidget yapılandırma faaliyeti iptal edildiğinde gerçekleşir, ancak yapılandırma etkinliğinin hatalı bir şekilde uygulanmasıyla olduğu anlaşılmaktadır; Geliştiriciler, etkinlik sonucunu RESULT_CANCELED
olarak ayarlarken, appwidget kimliğini ek olarak eklemeyi ihmal eder.
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);
}
}
Şimdiye kadar ben kendi muhasebe yapmadan bir fantom appwidget varlığını tespit için hiçbir yol biliyorum:
doğru bir şekilde çalışmak böyledir (! Hatta Google'ın ApiDemos örnek uygulama bunu ihmal) . Yapılandırma etkinliğinin iptal edilmediğini ve ardından bu değeri diğer kodunuzda sorguladığını belirten bir SharedPreferences değeri depolamanızı öneririm. Ayrıca, bu bilgiyi, birine rastlarsanız bir hayali parçacığı "silmek" için de kullanabilirsiniz. senin appwidget yapılandırma etkinliği:
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;
}
O zaman en azından bir sigara fantom şöyle appwidget sahip olduğunu kontrol edebilirsiniz:
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
}
Bu cevap çok daha fazla övgü hak ediyor! Ben Android Studio'dan aldığınız örnek "merhaba dünya" appwidget kodu düzgün yapmaz çünkü bu kadar çok insanın bu sorunu yaşıyor olacağına inanıyorum (ve burası çok) insanlar başlayacak. Etkinlik sonucunu "RESULT_CANCELED" olarak ayarlarken ek olarak appwidget kimliğini eklemeye ilişkin tavsiyenizle artık herhangi bir fantom öğesi oluşturmuyorum. Teşekkürler! – drmrbrewer
Phantom widget'larını silme koduna gelince * bunlar * her ne sebeple olursa olsun, nereye koymanızı önerirsiniz? OnUpdate() 'de değil çünkü bu, bir yapılandırma etkinliğinin ilk açıldığında, yani pencere öğesi yapılandırılmadan önce çağrılmış gibi görünüyor - doğmadan önce widget'ı öldürmek istemiyorum! – drmrbrewer
Çok yardımcı ve iyi yazılmış bir cevap. Teşekkürler. – dazed