6

Android 2.2以降で利用可能な新しいバックアップAPIの使用を検討していますが、下位互換性を維持する必要があります(正確には1.5まで)。

ドキュメントの状態:

バックアップサービスと使用する必要のあるAPIは、APIレベル8(Android 2.2)以降を実行しているデバイスでのみ使用できるため、android:minSdkVersion属性も「8」に設定する必要があります。ただし、アプリケーションに適切な下位互換性を実装すると、APIレベル8以上を実行しているデバイスでこの機能をサポートしながら、古いデバイスとの互換性を維持できます。

targetSdkVersion私は確かにレベル8とレベル3を比較して構築しminSdkVersion、ラッパークラス(リフレクション付き)を使用して、存在しないクラスを拡張するクラスを実装した場合にアプリケーションが実行されないという問題を克服しようとしています。

問題は次のとおりです。クラスを実際に呼び出すことはないためBackupHelper、クラスが実際に存在するかどうかを事前に確認することはできません。(Androidの下位互換性に関するドキュメントでcheckAvailable()メソッドを使用して説明されています。)したがって、クラスはインスタンス化され、にキャストされますBackupAgent。ただし、リフレクションを使用しているため、実際にはBackupAgentをオーバーライドせず、実行時にバックアップが要求されたときに例外が発生します。

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

下位互換性への私のアプローチは次のとおりです。httpBackupAgent://code.google.com/p/transdroid/source/browse/#svn/trunk/src/org/transdroid/serviceここで、BackupAgent.javaは「通常の」BackupAgentHelperです。 -extendingクラスとBackupAgentHelperWrapperは、リフレクションベースのラッパークラスです。

BackupAgent下位互換性を備えた実装に成功した人はいますか?

4

6 に答える 6

10

別の方法として、純粋なリフレクションを使用してBackupManagerと通信することもできます。

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

android:backupAgentをv2.2クラスに直接向けます。v2.2より前のVMにロードされることはないため、リンクの問題は発生しません。

于 2010-12-17T07:34:13.053 に答える
7

なぜこの問題に遭遇したのかわかりません。

同じ問題があります。1.5(API 3)もサポートするアプリでバックアップをサポートしたいです。

クラスが自分のコードから呼び出されることはなく、システム自体BackupAgentHelperから呼び出されるため、クラスの作成に問題はありません。BackupManagerしたがって、私はそれをラップする必要はありません、そしてあなたがそれをするべき理由がわかりません:

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

ただし、バックアップを実行する必要があります。そのためにはBackupManager.dataChanged()、データが変更されるたびに呼び出す必要があり、システムにバックアップするように通知する必要があります(BackupAgentまたはを使用してBackupAgentHelper)。

アプリケーションコードから呼び出すため、そのクラスをラップする必要があります。


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

}

次に、設定を変更したり、データを保存したりするときに、コードから呼び出します。私のアプリからのいくつかのコード:


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

だから、うまくいけば、これはあなたのために働く!

adb shell bmgr run実際のシステムで開始されたバックアッププロセスをエミュレートするたびに呼び出す場合は、アプリを再インストールするときに適切にバックアップおよび復元する必要があります。)

于 2010-10-17T12:54:58.750 に答える
1

minSDKのバージョンを次のように設定する必要があります。

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

ビルドターゲットをsdk8(Eclipse'.default.properties'のプロジェクトプロパティ)に設定します。

# Project target.
target=android-8

SDK 8に追加された新しいものを呼び出すには、リフレクションを使用する必要があります:http: //developer.android.com/resources/articles/backward-compatibility.html

于 2010-06-21T10:30:37.600 に答える
1

私は同じ問題に遭遇しました、そしてこれが私がそれを解決するためにしたことです。

BackupAgentをラッパーで拡張するのではなく、ラップされたクラスで拡張します。したがって、実際のバックアップクラスを作成します。

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

}

さて、それからあなたはアンドロイド開発者の後方互換性の記事のようにラッパーを作ります。このクラスはBackupAgentを拡張しないことに注意してください。

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

}

最後に、マニフェストで、ラッパーをバックアップエージェントとして宣言します。

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

ラッパーには適切なメソッドが定義されているため、バックアップマネージャーがラッパーをBackupAgentにキャストするときに問題が発生することはありません。下位のAPIレベルにはBackupManagerがないため、コードが呼び出されることはなく、そこでもランタイム例外が発生することはありません。

于 2010-06-25T16:03:32.487 に答える
1

どうですか

    if (android.os.Build.VERSION.SDK_INT >= 8) 
    {
        BackupManager bm = new BackupManager(this);
        bm.dataChanged();
    }
于 2013-10-02T09:24:51.927 に答える
0

BackupManager.dataChangedを呼び出すだけでなく、クラスが最初に存在するかどうかを確認します。

   try {
            Class.forName("android.app.backup.BackupManager");
            BackupManager.dataChanged(context.getPackageName());
        } catch (ClassNotFoundException e) {
        }
于 2012-04-13T11:21:25.507 に答える