向后兼容BackupAgent
我正在研究使用自Android 2.2以来可用的新备份API,但需要保持向后兼容性(确切为1.5)。向后兼容BackupAgent
的文档状态:
备份服务,你必须使用的API仅适用于运行API等级8(安卓2.2)或更高版本的设备,所以你也应该设置你的安卓的minSdkVersion属性“8”。但是,如果您在应用程序中实现了适当的向后兼容性,则可以为运行API Level 8或更高级别的设备支持此功能,同时保持与旧设备的兼容性。
我确实筑起了8级水平,并尝试使用一个包装类(反射)克服,如果你实现扩展一个不存在的类一类的应用程序将无法运行的问题。
以下是问题所在:由于我们自己并没有实际调用BackupHelper
类,因此我们无法事先检查类是否确实存在。 (正如Android向后兼容性文档中所述,使用checkAvailable()
方法)。因此该类将被实例化并转换为BackupAgent
。但由于我们使用反射,它实际上并没有覆盖BackupAgent并在请求备份在运行时发生异常:
java.lang.RuntimeException: Unable to create BackupAgent org.transdroid.service.BackupAgent: java.lang.ClassCastException: org.transdroid.service.BackupAgent
这里是我的方式,以向后兼容BackupAgent
:http://code.google.com/p/transdroid/source/browse/#svn/trunk/src/org/transdroid/service其中BackupAgent.java是'常规'BackupAgentHelper扩展类和BackupAgentHelperWrapper是基于反射的包装类。
任何成功实施BackupAgent
向后兼容?
我不明白你为什么会遇到这个问题。
我有同样的问题:我想支持也支持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
要模拟实际系统发起backupprocess当您重新安装应用程序应适当的备份和恢复。每次)
看起来很有希望,我会试试看。 – 2010-10-18 14:32:53
你是完全正确的:这个伎俩!备份代理可以是扩展BackupAgentHelper的常规类,它是dataChanged包装的调用。因此,我们围绕BackupManager做了一个包装。我可以在http://code.google.com/p/transdroid/source/browse/trunk/src/org/transdroid/service/BackupManagerWrapper.java找到我的代码 – 2010-11-05 19:54:13
无效链接 - 将链接发布到实时项目的风险code.google.com =( – 2011-12-16 18:32:32
您需要的minSDK版本设置为以下:
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8"/>
和构建目标设定为8 SDK(在Eclipse项目属性” .default.properties'):
# Project target.
target=android-8
现在调用SDK 8中添加的新东西,你必须使用反射:http://developer.android.com/resources/articles/backward-compatibility.html
我可能还不够清楚(我编辑了我的答案以明确说明),但那正是我所尝试的。问题在于包装类无法扩展BackupAgent(这不会对1.5进行编译),而是由Android备份机制转换为BackupAgent。 – 2010-06-22 08:51:24
好吧,我想你将能够在java中使用反射来扩展一个类:http://*.com/questions/1886785/how-do-i-extend-java-classes-by-reflection – Moss 2010-06-22 12:53:17
我遇到了同样的问题,这就是我所做的工作。
您不用包装器扩展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
}
好,然后做个像Android开发者的包装向后兼容性文章说到做到。需要注意的是这个类不延长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,所以代码将永远不会被调用,因此您也不会遇到任何运行时异常。
感谢您的建议。这基本上是我自己做的。我的包装也定义了所需的方法。 由于在仿真程序或真实设备上调试进程似乎无法与bmgr工具一起使用,因此很难确定何时无法工作。 我想我的包装中有一个错误,因为我错过了正确的构造函数。希望它现在可以工作,但我很快会就此回复。 – 2010-06-28 09:09:57
作为替代方案,你可以只使用纯反射交谈备份管理器:
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之前的虚拟机上,所以不会有任何连接问题。
一个很好的例子, Android with reflection。感谢您发布此内容。 – Zulaxia 2011-06-17 16:40:14
Insted只是调用BackupManager.dataChanged,检查该类是否先存在。
try {
Class.forName("android.app.backup.BackupManager");
BackupManager.dataChanged(context.getPackageName());
} catch (ClassNotFoundException e) {
}
如何
if (android.os.Build.VERSION.SDK_INT >= 8)
{
BackupManager bm = new BackupManager(this);
bm.dataChanged();
}
我相信有一说起今年的Barcamp在Droidcon这样做。不记得这个人的名字,但值得有一个搜索。 – 2010-06-22 11:02:40