Frage

Ich suche den neuen Backup-API, dass verfügbar seit Android in mit 2.2, aber Notwendigkeit, die Abwärtskompatibilität zu erhalten (bis 1,5 um genau zu sein).

Der docs Zustand:

  

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

Ich baue in die Tat gegen die Stufe 8 targetSdkVersion mit Level 3 minSdkVersion und versuche, eine Wrapper-Klasse zu verwenden (mit Reflexion), um das Problem zu überwinden, dass die Anwendung nicht ausgeführt, wenn Sie eine Klasse implementieren, die eine nicht vorhandene Klasse erweitert.

Hier ist das Problem: da wir uns nicht die tatsächlichen Anrufe an die BackupHelper Klasse machen, können wir nicht überprüfen im Voraus, wenn die Klasse tatsächlich 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 überschreibt Backupagenten 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 ist mein Ansatz zu einem rückwärtskompatibel BackupAgent: http://code.google.com/p/transdroid/source/browse/#svn/trunk/src/org/transdroid/service wo die BackupAgent.java ist die 'normale' BackupAgentHelper erstreckender Klasse und BackupAgentHelperWrapper ist die Reflexion basierenden Wrapper-Klasse.

Wer erfolgreich eine BackupAgent mit Rückwärtskompatibilität bei der Umsetzung?

War es hilfreich?

Lösung

Ich sehe nicht, warum Sie in dieses Problem.

Ich habe das gleiche Problem. Ich mag Unterstützung Backup mit einer App, dass Träger auch 1,5 (API 3)

Es gibt kein Problem meine BackupAgentHelper Klasse schaffen, da diese Klasse nie aus meinem eigenen Code aufgerufen wird, sondern aus dem BackupManager das heißt das System selbst. 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
 }

Aber Sie wollen eine Sicherung zum Laufen zu bringen, zu tun, dass Sie auf BackupManager.dataChanged() aufrufen müssen, wenn Sie Ihre Daten ändern und Sie wollen das System-Backup informieren es (mit Ihrem BackupAgent oder BackupAgentHelper).

Sie müssen diese Klasse wickeln, da Sie es von Ihnen 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 nennen es dann aus dem Code, wenn Sie eine Präferenz oder speichern einige Daten verändern. 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 rufen jedes Mal, wenn das eigentliche System backupprocess es richtig Backup initiiert emulieren möchten sollten und wiederherstellen, wenn Sie die App neu installieren.)

Andere Tipps

Als Alternative können Sie nur reine Reflexion zu reden verwenden, um das 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 der android: Backup gerade bei einer v2.2-Klasse; es wird nie auf einem bereits v2.2 geladen werden VM, so wird es keine Verknüpfung Probleme.

Sie müssen die minSDK Version der folgenden festlegen:

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

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

# Project target.
target=android-8

Jetzt neue Sachen in der SDK 8 hinzugefügt aufrufen müssen Sie Reflektion verwenden: http://developer.android.com/resources/articles/backward-compatibility.html

Ich lief in das gleiche Problem und hier ist, was ich tat, ihn auszuführen.

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

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 Kompatibilität Artikel zurück Android Entwickler sagte zu tun. Beachten Sie, dass diese Klasse nicht erweitern Backup:

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, erklären Sie den Wrapper als Sicherungsmittel:

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

Da Ihr Wrapper die richtigen Methoden hat definiert Sie nicht auf ein Problem stoßen, wenn der Backup-Manager an einen Backup wirft. Da niedrigere API-Ebene werden keinen Backup den Code haben wird nie aufgerufen, so werden Sie dort auch nicht in irgendwelche Laufzeit Ausnahmen führen.

Insted von nur BackupManager.dataChanged rufen, überprüfen Sie, ob die Klasse zuerst vorhanden ist.

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

Wie wäre es

    if (android.os.Build.VERSION.SDK_INT >= 8) 
    {
        BackupManager bm = new BackupManager(this);
        bm.dataChanged();
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top