5

Tôi có một AppWidget có một StackView chứa trong nó. Cùng với AppWidget, tôi có một dịch vụ được bắt đầu khi người dùng thêm AppWidget của tôi vào màn hình chính để thăm dò dữ liệu mới cứ hai giờ một lần. Khi dịch vụ tìm thấy dữ liệu mới, tôi cần cho nó cảnh báo AppWidget của tôi, và cũng chuyển dữ liệu đó đến RemoteViewsService (có RemoteViewsFactory của tôi) để nó có thể tạo các khung nhìn cần thiết cho dữ liệu mới.Chuyển một mảng các số nguyên từ một AppWidget đến một RemoteViewsService từ trước được kết xuất bởi RemoteViewsFactory

Hiện tại, khi dịch vụ tìm thấy dữ liệu mới, tôi đã phát sóng dữ liệu mới cho AppWidget của mình rằng dữ liệu mới đã được tìm thấy, chuyển dữ liệu đó dưới dạng một dãy số nguyên trong một mục đích.

Phương thức onReceive của tôi trong AppWidgetProvider của tôi kéo dữ liệu đó ra, và sau đó tôi đi qua quá trình thiết lập một mục đích mới được chuyển đến RemoteViews của tôi cho AppWidget. Mã mẫu bên dưới:

public void onReceive(Context context, Intent intent) 
{ 
    int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, SampleAppWidgetProvider.class)); 

    int[] sampleData = intent.getIntArrayExtra(Intent.EXTRA_TITLE); 
    for (int i = 0; i < appWidgetIds.length; i++) 
    { 
     // RemoteViewsFactory service intent 
     Intent remoteViewsFactoryIntent = new Intent(context, SampleAppWidgetService.class); 
     remoteViewsFactoryIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); 
     remoteViewsFactoryIntent.setData(Uri.parse(remoteViewsFactoryIntent.toUri(Intent.URI_INTENT_SCHEME))); 
     remoteViewsFactoryIntent.putExtra(Intent.EXTRA_TITLE, sampleData); 

     RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 

     // Sync up the remoteviews factory 
     rv.setRemoteAdapter(appWidgetIds[i], R.id.sample_widget, remoteViewsFactoryIntent);   
     rv.setEmptyView(R.id.sample_widget, R.id.empty_view); 

     appWidgetManager.updateAppWidget(appWidgetIds[i], rv); 
    } 

    super.onUpdate(context, appWidgetManager, appWidgetIds); 
} 

Đây là lần đầu tiên hoạt động. Dữ liệu được hiển thị bởi RemoteViewsService/RemoteViewsFactory. Dữ liệu mới tiếp theo không nhấn vào hàm tạo của RemoteViewsFactory vì dịch vụ cho nhà máy đó đang chạy.

Tôi làm cách nào để cập nhật dữ liệu? Tôi cảm thấy như tôi nên được sử dụng onDataSetChanged, nhưng làm thế nào tôi sẽ truy cập vào ý định mà tôi đã vượt qua từ onWeceive của AppWidget?

Tôi đánh giá cao bất kỳ thông tin chi tiết nào về cách thực hiện điều này đúng cách. Cảm ơn.

+0

Nếu tôi có thể nhận onGetViewFactory trong RemoteViewsService để chạy một lần nữa, tôi sẽ có thể để có được các dữ liệu mới từ mục đích truyền cho dữ liệu. Hoặc nếu tôi bằng cách nào đó có thể nói với dịch vụ để làm mới dữ liệu của nó ... – Steven

Trả lời

3

Giải pháp của tôi cho một mảng số nguyên được chuyển đến RemoteViewsFactory đã được giải quyết bằng cách sử dụng BroadcastReceiver. Tôi đã mở rộng RemoteViewsFactory của mình để triển khai BroadcastReceiver (cụ thể là onReceive) và đăng ký nó với ứng dụng của tôi trong hàm tạo cho nhà máy (điều này cũng có nghĩa là tôi chưa đăng ký nó trong onDestroy). Với điều đó, tôi đã có thể phát sóng ý định với mảng số nguyên mà tôi đã có trong onReceive của AppWidgetProvider và nhận nó trong RemoteViewsFactory.

Đảm bảo cũng gọi cho AppWidgetManager notificationAppWidgetViewDataChanged để RemoteViewsFactory biết rằng dữ liệu mà nó đã sử dụng trước đây đã bị vô hiệu và một mảng số nguyên mới được trình bày để tạo ra RemoteViews mới.

+0

Bạn có thể vui lòng đăng mã chi tiết về cách bạn thực hiện điều này? Tôi có một số rắc rối trong việc tìm ra nó. Cảm ơn vì những lời khuyên! –

3

Để xây dựng thêm về giải pháp của Steve trên vì lợi ích của arne.jans và những người khác, tôi thực hiện giải pháp của Steven bởi:

  • Trích xuất các StackRemoteViewsFactory vào một tập tin lớp học của riêng nó
  • Mở rộng nó với một BroadcastReceiver
  • Thực hiện phương pháp onReceive() để lưu dữ liệu mới cho một biến tĩnh trong đó lớp StackRemoteViewsFactory cũng có thể truy cập khi getViewAt nó đòi hỏi dữ liệu
  • Truyền vào tất cả các id tiện ích qua số Intent để tôi có thể gọi notifyAndUpdate của TẤT CẢ các tiện ích trong phương thức onReceive().
  • Cuối cùng tôi đã thêm các nét tiêu chuẩn cho một máy thu vào AndroidManifest.xml
1

tôi không mở rộng RemoteViewFactory với một BroadcastReceiver, nhưng thực hiện BroadcastReceiver động vào nó để vượt qua một chuỗi từ AppWidgetProvider để RemoteViewFactory.

như thế này:

public class MyWidgetProvider extends AppWidgetProvider { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     super.onReceive(context, intent); 

     String action = intent.getAction(); 
     if (action.equals("android.appwidget.action.APPWIDGET_UPDATE")) { 
      ..... 
     } else if (action.equals("some.string.you.want.ACTION_TODO")) { 
      String url = intent.getStringExtra("some.string.you.want.EXTRA_URL"); 

      // Send broadcast intent to pass mUrl variable to the MyContentFactory. 
      Intent broadcastIntent = new Intent("some.string.you.want.ACTION_UPDATE_URL"); 
      broadcastIntent.putExtra("some.string.you.want.EXTRA_URL", url); 
      context.sendBroadcast(broadcastIntent); 
     } 
     ..... 
    } 
} 

public class MyContentFactory implements RemoteViewsService.RemoteViewsFactory { 
    private Context mContext; 
    private String mUrl; // target to update 
    private BroadcastReceiver mIntentListener; 

    public MyContentFactory(Context context, Intent intent) { 
     mContext = context; 
     setupIntentListener(); 
    } 

    @Override 
    public void onDestroy() { 
     teardownIntentListener(); 
    } 

    private void setupIntentListener() { 
     if (mIntentListener == null) { 
      mIntentListener = new BroadcastReceiver() { 
       @Override 
       public void onReceive(Context context, Intent intent) { 
        // Update mUrl through BroadCast Intent 
        mUrl = intent.getStringExtra("some.string.you.want.EXTRA_URL"); 
       } 
      }; 
      IntentFilter filter = new IntentFilter(); 
      filter.addAction("some.string.you.want.ACTION_UPDATE_URL"); 
      mContext.registerReceiver(mIntentListener, filter); 
     } 
    } 

    private void teardownIntentListener() { 
     if (mIntentListener != null) { 
      mContext.unregisterReceiver(mIntentListener); 
      mIntentListener = null; 
     } 
    } 
} 
1

Một lựa chọn khác là sử dụng hệ thống tập tin hoặc một cơ sở dữ liệu SQLite, ví dụ

Trong AppWidgetProvider:

File file = new File(context.getCacheDir(), "filename that service also knows"); 
writeFile(file, "my content"); // impl. not shown; uses BufferedWriter.java 

Trong RemoteViewsService:

File file = new File(context.getCacheDir(), "filename that service also knows"); 
if (file.exists()) { 
    // handle params contained within file 
    file.delete(); // clear for next run 
} 
Các vấn đề liên quan