2012-01-12 31 views
7

Ai đó có thể cho tôi biết cách kiểm tra xem widget của tôi đã được đặt trên màn hình chính chưa?Check Widget được đặt trên màn hình Android

Tôi có một số mã trong ứng dụng của mình sẽ chỉ chạy nếu tiện ích con được đặt trên màn hình chính.

+0

Xin chào, bạn đã có một cái nhìn vào câu trả lời của tôi không? Tôi nghĩ rằng nó có thể giúp .. ;-) –

Trả lời

6

Bạn cần tự lưu trữ thông tin đó. Tôi thường sử dụng các tùy chọn ứng dụng, nhưng bạn có thể sử dụng bất cứ điều gì. Nói chung, các tiện ích sử dụng dịch vụ để giao tiếp, vì vậy mã của bạn thực hiện công việc có thể có trong dịch vụ, nhưng việc sử dụng tùy chọn cho phép bất kỳ phần nào của ứng dụng của bạn truy cập vào dịch vụ này.

Trong lớp tiện ích mở rộng AppWidgetProvider, onEnabled được gọi khi tiện ích được đặt trên màn hình chính và onDeleted (thường) được gọi khi nó bị xóa. onDisabled được gọi khi tất cả các bản sao được xóa.

Vì vậy, trong mã của nhà cung cấp phụ tùng của bạn:

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

Ở những nơi khác trong mã, bạn sẽ kiểm tra để xem nếu widget được kích hoạt bằng cách:

public boolean isWidgetActive(Context context){ 
    Context appContext = context.getApplicationContext(); 
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 
    return prefs.getBoolean(Constants.WIDGET_ACTIVE, false); 
} 
+0

Aargh tốt đẹp! Cảm ơn, đã không nghĩ về onDisabled(), Nó sẽ chỉ chạy khi bạn đã xóa tất cả tiện ích con khỏi màn hình chính của ứng dụng chính xác những gì tôi cần. Tôi đã sử dụng: onDeleted(), phù thủy được chạy mỗi khi bạn xóa một widget. – Jeff

+0

Có một số trường hợp ở trên không bao gồm, và tôi đang tìm kiếm giải pháp: (1) người dùng xóa các tùy chọn được chia sẻ - có tiện ích con, nhưng bạn không biết về nó (2) hối tiếc người dùng giữa "add widget" và nhấn "ok" - nhưng bật được gọi, không có tiện ích nào – auval

+2

Vui lòng xem câu trả lời bên dưới ;-) –

5

Tôi biết đó là một câu hỏi cũ, nhưng nhìn vào điều này hôm nay tôi thấy rằng có một vài vấn đề với câu trả lời được chấp nhận từ @ larsona1:

  1. nếu người dùng xóa anh ấy đã chia sẻ tùy chọn - vẫn có tiện ích nhưng ứng dụng sẽ không biết về nó.
  2. nếu người dùng hối tiếc giữa "thêm tiện ích" và trước khi nhấn "ok" - onEnabled sẽ vẫn được gọi và tiện ích sẽ được đăng ký trên màn hình chính mặc dù không có tiện ích và không có cách nào để xóa tiện ích sau này. (nó có thể là một lỗi trong trình khởi chạy nhà ADT).

Tôi đã tìm ra giải pháp cho vấn đề đầu tiên. Không cần có bất kỳ tùy chọn chia sẻ nào vì nó không đáng tin cậy. Nó phải được kiểm tra trong thời gian chạy.

// in some class you define a static variable, say in S.java 
static boolean sWidgetMayExist = true; 

Trong nhà cung cấp phụ tùng của bạn:

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

Và, trong mã dịch vụ của bạn thêm này:

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

Theo trang này [1] vấn đề 2 có vẻ là lỗi đã được khắc phục bằng Android 2.1 trở lên. Tôi đã thử nghiệm nó với Android 4.1.2 và các phương thức onDelete và onDisabled được gọi chính xác. [1] https://groups.google.com/forum/?fromgroups=#!topic/android-developers/4agiDfaGvDw – friday

+0

Xem câu trả lời của Waza_Be, dường như hoạt động và yêu cầu mã ít hơn nhiều. –

+0

@ WilliamT.Mallard Câu trả lời của tôi lớn hơn Waza 6 tháng. Vì vậy, tôi đã không kiểm tra nó khi trả lời. Nhưng xem lại nó bây giờ, tôi không chắc chắn nó bao gồm các trường hợp cạnh tôi đang đề cập đến. – auval

37

Chỉ cần nói, nhưng ...

int ids[] = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this,MyAppWidgetProvider.class)); 

    Toast.makeText(this, "Number of widgets: "+ids.length, Toast.LENGTH_LONG).show(); 
+5

Đây là câu trả lời đúng: truy vấn AppWidgetManager và gettings các id là cách kiểm tra chính xác xem có bao nhiêu widget được đặt trong màn hình chính hay không. –

+2

Tôi cũng có thể xác nhận rằng đây là câu trả lời đúng. Đừng lãng phí thời gian sau câu trả lời của larsona1 và kết thúc với mã dễ vỡ để duy trì. – Marky

+1

vấn đề duy nhất là đôi khi nó trả về một số id ngay cả khi không có tiện ích nào được hiển thị – Catalina

1

@ Waza_Be đúng khi xem danh sách "AppWidgetIds" để biết số lượng tiện ích đang hoạt động (những tiện ích được cài đặt trên màn hình chính của bạn) là cách chính xác để biết thông tin này.

Tuy nhiên, hãy nhớ rằng bạn KHÔNG phải tự mình xem xét điều này.

Kiểm tra các tài liệu Android chính thức cho thực hành tốt nhất về các widget: https://developer.android.com/guide/topics/appwidgets/index.html#AppWidgetProvider

Cách tiếp cận đúng là để ghi đè chỉ là phương pháp onUpdate() và lặp qua danh sách các vật dụng "hoạt động":

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

Và khi nhà cung cấp tiện ích của riêng bạn ghi đè AppWidgetProvider, bạn sẽ KHÔNG đi vào phương thức onUpdate() nếu bạn không có tiện ích nào hoạt động trên màn hình chính!

Xem mã onReceive() của Android AppWidgetProvider để kiểm tra đã cho bạn biết rằng "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); 
      } 
     } 
    } 

(...) 
} 
Các vấn đề liên quan