6

Ich suche den neuen Backup-API, die verfügbar seit Android 2.2, in Verwendung, sondern müssen, um die Rückwärtskompatibilität (bis 1,5 um genau zu sein).rückwärts-kompatible Backupagent

Der docs Zustand:

Der Backup-Service und die APIs, die Sie nur auf Geräte verfügbar verwenden müssen laufen API Stufe 8 (Android 2.2) oder mehr, so dass Sie auch Ihr Android setzen sollen minSdkVersion Attribut "8". Wenn Sie jedoch implementieren richtige Abwärtskompatibilität in Ihrer Anwendung, können Sie diese Funktion für Geräte mit API Stufe 8 oder höher unterstützen, während kompatibel bleiben mit älteren Geräten.

ich in der Tat gegen die Ebene bauen 8 targetSdkVersion mit Level 3 minSdkVersion und versuchen, eine Wrapper-Klasse zu verwenden (mit Reflexion), um das Problem zu überwinden, die die Anwendung nicht ausgeführt werden, wenn Sie eine Klasse implementieren, die eine nicht vorhandene Klasse erweitert.

Hier ist das Problem: Da wir selbst keine Aufrufe an die BackupHelper Klasse machen, können wir nicht vorab überprüfen, ob die Klasse wirklich existiert. (Wie in der Android Rückwärtskompatibilität Dokumentation mit einem checkAvailable() Verfahren erläutert.) Die Klasse wird daher instanziiert und zu einem BackupAgent gegossen werden. Aber da wir Reflexion verwenden, ist es nicht wirklich Backupagent außer Kraft setzen und eine Ausnahme auftritt, während der Laufzeit, wenn die Sicherung angefordert wird:

java.lang.RuntimeException: Unable to create BackupAgent org.transdroid.service.BackupAgent: java.lang.ClassCastException: org.transdroid.service.BackupAgent 

Hier mein Ansatz ist auf eine rückwärtskompatibel BackupAgent: http://code.google.com/p/transdroid/source/browse/#svn/trunk/src/org/transdroid/service wo die BackupAgent.java das ist ‚normaler‘ BackupAgentHelper erstreckender Klasse und BackupAgentHelperWrapper ist die Reflexion basierende Hüllklasse.

Jeder erfolgreich ein BackupAgent mit Rückwärtskompatibilität bei der Umsetzung?

+0

Ich glaube, ein Gespräch über das tun dies auf der diesjährigen Barcamp bei Droidcon da war. Kann mich nicht an den Namen des Kerls erinnern, aber es lohnt sich, danach zu suchen. –

Antwort

7

Ich sehe nicht, warum Sie auf dieses Problem stoßen.

Ich habe das gleiche Problem: Ich möchte das Backup mit einer App unterstützen, die auch 1.5 (API 3) unterstützt.

Es gibt kein Problem bei der Erstellung meiner BackupAgentHelper Klasse, da diese Klasse nie von meinem eigenen Code, sondern von der BackupManager, also das System selbst aufgerufen wird. Deshalb brauche ich nicht, es zu wickeln, und ich sehe nicht, warum Sie das tun sollten:

public class MyBackupAgentHelper extends BackupAgentHelper { 
@override onCreate() 
{ 
     \\do something usefull 
} 

jedoch eine Sicherung zum Laufen bringen wollen, zu tun, dass Sie auf BackupManager.dataChanged() anrufen müssen wann immer sich Ihre Daten ändern und Sie das System informieren möchten, um es zu sichern (unter Verwendung Ihrer BackupAgent oder BackupAgentHelper).

Sie müssen diese Klasse umbrechen, da Sie sie über Ihren Anwendungscode aufrufen.


public class WrapBackupManager { 
private BackupManager wrappedInstance; 

static 
{ 
    try 
    { 
     Class.forName("android.app.backup.BackupManager"); 
    } 
    catch (Exception e) 
    { 
     throw new RuntimeException(e); 
    } 
} 
public static void checkAvailable() {} 

public void dataChanged() 
{ 
    wrappedInstance.dataChanged(); 
} 

public WrapBackupManager(Context context) 
{ 
    wrappedInstance = new BackupManager(context); 
} 

} 

Sie rufen es dann aus Ihrem Code, wenn Sie eine Einstellung ändern oder einige Daten speichern. Einige Code aus meiner App:


private static Boolean backupManagerAvailable = null; 

    private static void postCommitAction() { 


     if (backupManagerAvailable == null) { 
      try { 
       WrapBackupManager.checkAvailable(); 
       backupManagerAvailable = true; 
      } catch (Throwable t) { 
       backupManagerAvailable = false; 
      } 
     } 

     if (backupManagerAvailable == true) { 
      Log.d("Fretter", "Backup Manager available, using it now."); 
      WrapBackupManager wrapBackupManager = new WrapBackupManager(
        FretterApplication.getApplication()); 
      wrapBackupManager.dataChanged(); 
     } else { 
      Log.d("Fretter", "Backup Manager not available, not using it now."); 
     } 

Also, hoffentlich funktioniert dies für Sie!

(Wenn Sie adb shell bmgr run jedes Mal, wenn das eigentliche System initiiert emulieren möchten rufen backupprocess es richtig Sicherung sollte und wiederherstellen, wenn Sie die App neu installieren.)

+0

Sieht vielversprechend aus und ich werde es versuchen. –

+0

Sie haben völlig Recht: Das hat den Trick gemacht! Der Backup-Agent kann eine reguläre Klasse sein, die BackupAgentHelper erweitert, und es ist der Aufruf von dataChanged, ihn zu umbrechen. Daher machen wir einen Wrapper um BackupManager. Meine finden Sie unter http://code.google.com/p/transdroid/source/browse/trunk/src/org/transdroid/service/BackupManagerWrapper.java –

+0

Dead Link - die Risiken der Veröffentlichung von Links zu Live-Projekten auf code.google.com = ( –

1

Sie benötigen die minSDK Version auf die folgenden Einstellungen:

<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8"/> 

und Einstellen des Build-Ziel zu sdk 8 (Projekteigenschaften in Eclipse‘.default.properties'):

# Project target. 
target=android-8 

Jetzt, um neue Sachen zu nennen, die in SDK 8 hinzugefügt wurden, musst du reflection verwenden: http://developer.android.com/resources/articles/backward-compatibility.html

+0

Ich war möglicherweise nicht klar genug (ich redigierte meine Antwort, um es ausdrücklich zu sagen), aber das ist genau, was ich versuchte. Das Problem besteht darin, dass die Wrapper-Klasse den BackupAgent nicht erweitern kann (dies wird nicht mit 1.5 kompiliert), sondern vom Android-Backup-Mechanismus auf einen BackupAgent übertragen. –

+0

Ok, ich denke, dass Sie in der Lage sein werden, eine Klasse mit Reflektion in Java zu erweitern: http://stackoverflow.com/questions/1886785/how-do-i-e-tend-java-classes-by-reflection – Moss

1

Ich lief auf das gleiche Problem und hier ist, was ich getan habe, um es auszuarbeiten.

Sie erstrecken sich nicht Backupagent mit dem Wrapper, Sie es mit dem umwickelten Klasse erweitern. So machen Sie Ihre echte Backup-Klasse:

public class MyBackup extends BackupAgent { 

@Override 
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 
     ParcelFileDescriptor newState) throws IOException { 
    // TODO Auto-generated method stub 

} 

@Override 
public void onRestore(BackupDataInput data, int appVersionCode, 
     ParcelFileDescriptor newState) throws IOException { 
    // TODO Auto-generated method stub 

} 

Okay, und dann machen Sie einen Wrapper wie die Android-Entwickler Abwärtskompatibilität Artikel sagte zu tun.Beachten Sie, dass diese Klasse nicht Backupagent erweitern:

public class WrapMyBackup { 
private MyBackup wb; 

static { 
    try { 
     Class.forName("MyBackup"); 
    } 
    catch (Exception ex) { 
     throw new RuntimeException(ex); 
    } 
} 

/** call this wrapped in a try/catch to see if we can instantiate **/ 
public static void checkAvailable() {} 

public WrapMyBackup() { 
    wb = new MyBackup(); 
} 

public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 
     ParcelFileDescriptor newState) throws IOException { 
    wb.onBackup(oldState, data, newState); 

} 

public void onRestore(BackupDataInput data, int appVersionCode, 
     ParcelFileDescriptor newState) throws IOException { 
    wb.onRestore(data, appVersionCode, newState); 

} 

public void onCreate() { 
    wb.onCreate(); 
} 

public void onDestroy() { 
    wb.onDestroy(); 
} 

}

schließlich in Ihrem Manifest, Sie den Wrapper als Backup-Agent erklären:

<application 
    android:label="@string/app_name" 
    android:icon="@drawable/ic_launch_scale" 
    android:backupAgent="WrapMyBackup" 
    > 

Da Ihr Wrapper das hat Nachdem Sie die richtigen Methoden definiert haben, wird kein Problem mehr auftreten, wenn der Backup Manager sie auf einen BackupAgent überträgt. Da niedrigere API-Ebenen keinen BackupManager haben, wird der Code niemals aufgerufen, so dass Sie dort auch keine Laufzeitausnahmen finden werden.

+0

Danke für Ihren Vorschlag . Es ist im Wesentlichen was ich selbst getan habe. Mein Wrapper hat die benötigten Methoden ebenfalls definiert. Da das Debuggen des Prozesses auf einem Emulator oder einem echten Gerät nicht mit dem bmgr-Tool zu funktionieren scheint, ist es schwierig festzustellen, was/wann es nicht funktioniert. Ich denke, ich hatte einen Fehler in meinem Wrapper, da ich den richtigen Konstruktor fehlte. Hoffentlich klappt es jetzt, aber ich werde bald darüber berichten. –

10

Als Alternative können Sie verwenden nur reine Reflexion zu reden die Backup:

public void scheduleBackup() { 
    Log.d(TAG, "Scheduling backup"); 
    try { 
     Class managerClass = Class.forName("android.app.backup.BackupManager"); 
     Constructor managerConstructor = managerClass.getConstructor(Context.class); 
     Object manager = managerConstructor.newInstance(context); 
     Method m = managerClass.getMethod("dataChanged"); 
     m.invoke(manager); 
     Log.d(TAG, "Backup requested"); 
    } catch(ClassNotFoundException e) { 
     Log.d(TAG, "No backup manager found"); 
    } catch(Throwable t) { 
     Log.d(TAG, "Scheduling backup failed " + t); 
     t.printStackTrace(); 
    } 
} 

Punkt des androide: Backup gerade bei einer v2.2-Klasse; Es wird niemals auf einer VM vor Version 2.2 geladen, so dass es keine Verbindungsprobleme gibt.

+0

Ein großartiges Beispiel für Rückwärtskompatibilität in Android mit Reflektion Danke für das Posten. – Zulaxia

0

Anstatt nur BackupManager.dataChanged aufzurufen, überprüfen Sie, ob die Klasse zuerst existiert.

try { 
      Class.forName("android.app.backup.BackupManager"); 
      BackupManager.dataChanged(context.getPackageName()); 
     } catch (ClassNotFoundException e) { 
     } 
0

Wie wäre es

if (android.os.Build.VERSION.SDK_INT >= 8) 
    { 
     BackupManager bm = new BackupManager(this); 
     bm.dataChanged(); 
    }