2013-12-11 7 views
6

Ich habe eine DashClockExtension, die manchmal nicht aktualisiert.Dashclock Widget Erweiterung nicht aktualisiert

Es verwendet einen LocalBroadcastReceiver, um die Erweiterung ähnlich wie http://bit.ly/1e4uMl0 zu aktualisieren. Der Empfänger wird in der onInitialize() Methode registriert:

@Override 
    protected void onInitialize(boolean isReconnect) { 
     super.onInitialize(isReconnect); 

     LocalBroadcastManager broadcastMgr = LocalBroadcastManager.getInstance(this); 
     if (mDashClockReceiver != null) { 
      try { 
       broadcastMgr.unregisterReceiver(mDashClockReceiver); 
      } catch (Exception ignore) {} 
     } 
     mDashClockReceiver = new DashClockUpdateReceiver(); 
     broadcastMgr.registerReceiver(mDashClockReceiver, new IntentFilter(UPDATE_DASHCLOCK)); 
    } 

Das ist, wie ich die Sendung senden:

public static void updateDashClock() { 
    LocalBroadcastManager.getInstance(Application.getContext()).sendBroadcast(new Intent(UPDATE_DASHCLOCK)); 
}   

Das ist mein BroadcastReceiver ist:

private class DashClockUpdateReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     retrieveDataAndUpdateWidget(); 
    } 
} 

Ich bemerkte, dass während der Sendung ausgelöst wird die Empfänger empfängt das Ereignis manchmal nicht.
Ich testete es, indem ich meine App tötete, aber das reproduziert das Problem nicht, also weiß ich nicht, warum das passieren würde.

Jeder?

+0

Können Sie mehr Code posten? Wie genau versuchen Sie, die Daten zu aktualisieren? Wenn publishUpdate fehlschlägt, bleiben die alten Daten erhalten, es sei denn, Sie rufen publishUpdate (null) auf –

+0

Das Problem ist nicht der Aktualisierungscode selbst, sondern die Tatsache, dass die Übertragung nicht vom Broadcast-Empfänger empfangen wird. Normalerweise funktioniert es gut, aber "manchmal" nicht und ich würde gerne wissen, warum und was ich tun kann, um dies zu verhindern. Anfangs dachte ich, wenn die App heruntergefahren wird, würde der Dienst nicht mehr vom DashClock-Widget selbst gebunden werden und der BroadcastReceiver würde nicht registriert werden, aber das ist nicht der Fall. Der Dienst startet und ist an das Widget gebunden. –

Antwort

1

Während meiner ersten Antwort arbeitet, hat es einige unerwünschte Nebenwirkungen. Ich habe daher eine bessere Lösung ohne Nebenwirkungen gefunden.

Instruct DashClockWidget einen gewissen Uri mit addWatchContentUris zu beobachten, und dann, wenn es an der Zeit das Widget einfach anrufen NotifyChange an diesem Uri zu aktualisieren:

public class DashClockService extends DashClockExtension { 
    private static final Uri URI_BASE = Uri.parse("content://com.myauthority"); 
    private static final String URI_PATH_SEGMENT = "dashclock/update"; 

    public static void updateWidget(Context context) { 
     ContentResolver contentResolver = context.getContentResolver(); 
     Uri uri = Uri.withAppendedPath(URI_BASE, URI_PATH_SEGMENT); 
     contentResolver.notifyChange(uri, null); 
    } 

    @Override 
    protected void onInitialize(boolean isReconnect) { 
     super.onInitialize(isReconnect); 

     removeAllWatchContentUris(); 
     Uri uri = Uri.withAppendedPath(URI_BASE, URI_PATH_SEGMENT); 
     addWatchContentUris(new String[] {uri.toString()}); 
    } 

updateWidget kann von überall im Code aufgerufen werden, um das Widget zu aktualisieren. Am wichtigsten ist, dass es aufgerufen werden kann, wenn die App startet, z. nachdem es von Android getötet wurde und neu gestartet wird (ich rufe das Update in Application.onCreate()).

2

Bitte schauen Sie sich an, wie der GCM Broadcast Receiver in Google's GCM Client example implementiert ist.

Es könnte sein, weil Ihre application was killed by the Android OS, weil es mehr Speicher benötigt (oder aus welchem ​​Grund auch immer) und dann werden Sie nicht die Sendungen in Ihrem Rundfunkempfänger empfangen.

Ich hoffe, es hilft, wenn nicht, bitte geben Sie uns einige Protokolle und weitere Informationen.

Viel Glück!

+0

Der BroadcastReceiver muss dynamisch registriert werden, da es sich um eine Mitgliedsklasse handeln muss, oder wir können publishUpdate (ExtensionData) (eine Methode der DashClockExtension, die ein Dienst ist) nicht aufrufen. Siehe auch: http://stackoverflow.com/a/15571547/534471). Wenn ein BroadcastReceiver im Manifest definiert ist, können wir die Broadcast empfangen, aber wir konnten das Widget nicht aktualisieren, da es keine Möglichkeit gibt, publishUpdate (ExtensionData) aufzurufen. –

1

Nach umfangreichen Tests laufen, ich einige Ergebnisse bekam, die auch an andere Entwickler werden interessting könnten:

  • kommt es vor, in der Tat, wenn die Anwendung von Android getötet wird (ich wartete nicht auf Android die App zu töten aber tötete es natürlich manuell)
  • DashClock Widget bindet den Dienst nach einer Weile wieder. Meine Vermutung ist, dass es den Dienst erneut bindet, wenn es das geplante ui-Update ausführt, das ungefähr einmal pro Stunde ist (gemäß dem DashClockExtension-Javadoc). Ich habe das nicht durch das Durchlesen des Quellcodes bestätigt.
  • Die Erweiterung wird daher eventuell aktualisiert, aber erst nachdem der reguläre Aktualisierungszyklus ausgeführt wurde, was möglicherweise nicht bis zu einer Stunde dauern kann.

Hier ist meine Abhilfe:

  • DashClock Widget hört ACTION_PACKAGE_CHANGED Intents (http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_CHANGED) alle DashClockExtensions (Service mit ACTION_EXTENSION Intent-Filter)
  • Durch das Deaktivieren und wieder aktiviert DashClockExtension Service, wenn zu finden meine App startet, kann ich "DashClock Widget" zwingen, den Dienst sofort zu binden.
  • Ich habe das getestet und es dauert ein paar Sekunden, nachdem die App beendet und neu gestartet wurde, bis das DashClock-Widget erneut aktualisiert wird.

Hier ist, wie ich deaktivieren, aktivieren Sie den Dienst:

configureComponent("mypackagename.DashClockService", false); // disable 
configureComponent("mypackagename.DashClockService", true); // enable 

private void configureComponent(Context context, String className, boolean enable) { 
    PackageManager pkMgr = context.getPackageManager(); 
    String packageName = context.getPackageName(); 
    ComponentName component = new ComponentName(packageName, className); 
    int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 
    pkMgr.setComponentEnabledSetting(component, newState, PackageManager.DONT_KILL_APP); 
} 
+0

Während diese Lösung funktioniert, hat das Aktivieren und Deaktivieren des Dienstes unerwünschte Nebenwirkungen auf Samsung-Geräten. Abkürzungen z.B. kann sein benutzerdefiniertes Symbol und/oder seine Beschreibung verlieren (es wird wieder auf das App-Symbol und den Namen zurückgesetzt). Ich habe jedoch einen besseren Weg gefunden, sich nach dem Absturz der App wieder mit DashClockWidget zu verbinden (siehe meine neue Antwort). –

Verwandte Themen