5

Mam AppWidget, który zawiera StackView w nim. Wraz z AppWidget, mam usługę, która jest uruchamiana, gdy użytkownik dodaje mój AppWidget do ich ekranu głównego, który sonduje nowe dane co dwie godziny. Kiedy usługa znajdzie nowe dane, potrzebuję go zaalarmować mój AppWidget, a także przekazać te dane do RemoteViewsService (która ma mój RemoteViewsFactory), aby mógł utworzyć niezbędne widoki dla nowych danych.Przekazywanie tablicy liczb całkowitych z AppWidget do istniejącej usługi RemoteViewsService do renderowania przez RemoteViewsFactory

Obecnie, gdy usługa znajduje nowe dane, wysyłam ją do mojego AppWidget, że znaleziono nowe dane, przekazując te dane jako tablicę liczb całkowitych w ramach intencji.

Moja metoda onReceive w mojej aplikacji AppWidgetProvider wyciąga te dane, a następnie przechodzę przez proces konfigurowania nowego zamiaru, który jest przekazywany do moich RemoteViews dla AppWidget. Przykładowy kod poniżej:

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

To działa po raz pierwszy. Dane są wyświetlane przez RemoteViewsService/RemoteViewsFactory. Kolejne nowe dane nie trafiają do konstruktora RemoteViewsFactory, ponieważ usługa dla tej fabryki już działa.

Jak mogę zaktualizować dane? Czuję, że powinienem używać DataSetChanged, ale w jaki sposób uzyskać dostęp do zamiaru, który przekazałem z OnReceive AppWidget?

Byłbym wdzięczny za wszelkie informacje na temat tego, jak poprawnie to zrobić. Dzięki.

+0

Jeśli mogę dostać onGetViewFactory w RemoteViewsService uruchomić ponownie, chciałbym być w stanie uzyskać nowe dane z zamiarem przekazywane do dane. Lub jeśli mogę jakoś powiedzieć usłudze, aby odświeżyć jego dane ... – Steven

Odpowiedz

3

Moje rozwiązanie do tablicy całkowitej przekazywanej do RemoteViewsFactory rozwiązano za pomocą BroadcastReceiver. Rozszerzyłem mój RemoteViewsFactory o implementację BroadcastReceiver (konkretnie onReceive) i zarejestrowałem go z moją aplikacją w konstruktorze dla fabryki (to oznacza również, że wyrejestrowałem ją w onDestroy). Dzięki temu mogłem transmitować intencję z tablicą całkowitą, którą miałem w komórce onReceive mojego AppWidgetProvider i odebrać ją w ramach RemoteViewsFactory.

Należy również wywołać metodę notifyAppWidgetViewDataChanged obiektu AppWidgetManager, aby obiekt RemoteViewsFactory wiedział, że dane, które były używane wcześniej, zostały unieważnione, a nowa tablica liczb całkowitych została przedstawiona w celu utworzenia nowych widoków zdalnych.

+0

Czy mógłbyś wysłać szczegółowy kod o tym, jak zaimplementowałeś to? Mam kłopoty z ustaleniem tego. Dzięki za porady! –

3

by dopracowała rozwiązanie Steve'a powyżej na rzecz arne.jans i innych, I wdrożone rozwiązanie Stevena przez:

  • Wyodrębnianie StackRemoteViewsFactory do pliku klasy własnej
  • rozprowadzanie go BroadcastReceiver
  • realizacji sposobu onReceive(), aby zapisać nowe dane do zmiennej statycznej, w którym klasa StackRemoteViewsFactory mogą również uzyskać dostęp podczas jego getViewAt wymagane dane
  • Przekazywanie wszystkich identyfikatorów widżetów za pośrednictwem Intent, aby można było wywoływać notifyAndUpdate WSZYSTKIE widżety w metodzie onReceive().
  • W końcu dodałem standardową definicję odbiornika do AndroidManifest.xml
1

nie rozciągają RemoteViewFactory z BroadcastReceiver, ale wdrożyć dynamiczną BroadcastReceiver na to, aby przekazać ciąg z AppWidgetProvider do RemoteViewFactory.

tak:

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

Inną alternatywą jest użycie systemu albo SQLite bazy danych, np

W AppWidgetProvider:

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

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