2013-06-30 29 views
7

Tôi đang sử dụng AlarmManager để cập nhật tiện ích của mình. Và tôi muốn dừng nó nếu không có widget trên màn hình chính. Nhưng tôi đang phải đối mặt với một vấn đề với phát hiện nếu không có widget trên màn hình chủ.Kiểm tra xem tiện ích có tồn tại trên màn hình chính không bằng cách sử dụng appWidgetId

Như bất cứ khi nào tôi cố gắng để có được những AppWidgetIds sử dụng theo cách này:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 

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

tôi nhận được một chiều dài của appWidgetIDs trong khi thực sự không có widget trên màn hình chính. Tại sao?

Vì vậy, tôi muốn biết liệu có cách nào phát hiện thấy id tiện ích có tồn tại trên màn hình chính hay không.

Cảm ơn bạn đã trả trước.

Trả lời

16

Xin chúc mừng, bạn đã gặp phải appwidgets ảo. Dường như nó được ghi lại trên Android issue tracker. Chúng thường xảy ra khi hoạt động cấu hình cho appwidget bị hủy, mặc dù nó có vẻ là thông qua việc triển khai không đúng hoạt động cấu hình; các nhà phát triển bỏ bê bao gồm ID appwidget như một phần bổ sung khi đặt kết quả hoạt động thành RESULT_CANCELED. (Ứng dụng ApiDemos mẫu thậm chí của Google bỏ qua để làm điều này!)

Việc thực hiện đúng là như thế này:

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); 
    } 
} 

Như vậy đến nay tôi biết có cách nào để phát hiện sự hiện diện của một appwidget phantom mà không làm sổ sách kế toán của riêng bạn . Tôi khuyên bạn nên lưu trữ giá trị SharedPreferences cho biết hoạt động cấu hình không bị hủy và sau đó truy vấn giá trị này trong mã khác của bạn. Bạn cũng có thể sử dụng thông tin này để "xóa" một tiện ích con ảo nếu bạn gặp phải. Trong hoạt động cấu hình appwidget của bạn:

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; 
} 

Sau đó, bạn có thể kiểm tra xem bạn có ít nhất một phi phantom appwidget như vậy:

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

Câu trả lời này xứng đáng hơn rất nhiều tiếng tăm! Tôi tin rằng rất nhiều người sẽ gặp phải vấn đề này (ngay cả khi họ không biết điều đó) vì mã appwidget "hello world" mẫu mà bạn nhận được từ Android Studio không thực hiện đúng cách và đó là nơi rất nhiều của mọi người sẽ bắt đầu. Với lời khuyên của bạn để bao gồm ID appwidget như một phần bổ sung khi đặt kết quả hoạt động thành 'RESULT_CANCELED', tôi dường như không tạo bất kỳ tiện ích ảo nào nữa. Cảm ơn! – drmrbrewer

+0

Đối với mã để xóa các vật dụng ảo * nên * chúng xuất hiện vì bất kỳ lý do gì, bạn muốn giới thiệu nó ở đâu? Không có trong 'onUpdate()' bởi vì dường như nó được gọi khi một hoạt động config được mở lần đầu tiên, trước khi widget được cấu hình - không muốn giết tiện ích trước khi nó được sinh ra! – drmrbrewer

+0

Câu trả lời rất hữu ích và được viết tốt. Cảm ơn. – dazed