Android清单文件详解(四) ---- backupAgent的用法(一)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Android清单文件详解(四) ---- backupAgent的用法(一)

在<application>节点中有一个非常重要的属性,那就是backupAgent。这里我们将它单独列出来,从基本含义,用法及其相关属性等方面来详细介绍一下。


1.backupAgent简介


android:backupAgent用来设置备份代理。对于大部分应用程序来说,都或多或少保存着一些持久性的数据,比如数据库和共享文件,或者有自己的配置信息。为了保证这些数据和配置信息的安全性以及完整性,Android提供了这样一个机制。


我们可以通过这个备份机制来保存配置信息和数据以便为应用程序提供恢复点。如果用户将设备恢复出厂设置或者转换到一个新的Android设备上,系统就会在应用程序重新安装时自动恢复备份数据。这样,用户就不需要重新产生它们以前的数据或者设置了。这个进程对于用户是完全透明的,并且不影响其自身的功能或者应用程序的用户体验。


在备份操作的过程中,Android备份管理器查询应用程序需要备份的数据,接着将这些数据发送到备份传输点上,由备份传输点发送到云存储器上。


在恢复操作中,备份管理器从备份传输点中检索到备份数据并且将它返回到应用程序上,这样该程序就能将数据恢复到设备上了。恢复操作也可以由应用程序主动发起,在应用程序被安装并且存在与用户相关的备份数据时,Android能自动恢复操作。恢复备份数据主要发生在两个场景,一是在用户重置设备或者升级到新设备后,二是以前装过的应用程序再次被安装的时候。


另外,我们需要注意,备份服务不能将数据传输到另一个客户端上,不能用于保存应用程序生命周期中需要访问的数据,不能任意读写,且只能通过备份服务来访问。


备份传输点是Android备份框架的客户端组件,它是由设备制造商以及服务提供商定制的。备份传输点对于不同的设备或许不同,并且对于应用程序是透明的。备份管理器API使得应用程序独立于实际的备份传输,也就是说,应用程序通过一套固定的API与备份管理器进行通信,不管底层传输如何处理。但不是所有设备都支持备份,不过这不会对应用程序的运行产生任何负面影响。


2.如何使用backupAgent来实现备份


为了实现应用程序数据的备份,就必须实现一个备份代理。实现的备份代理是由备份管理器调用的,它用来提供需要备份的数据。当重新安装应用程序时,它也可以被调用以便于恢复备份数据。


要实现备份代理,就必须做两件事,一是实现BackupAgent或者BackupAgentHelper的子类,二是在Manifest文件内用android:backupAgent属性声明备份代理。


首先,我们来看看BackupAgent类提供的方法,如下表所示:


方法描述 说明

public final void fullBackupFile(File file,FullBackupDataOutput output)

写入作为备份操作一部分的一个完整文件,该方法中的参数如下所示:
file:需要备份的文件。这个文件必须存在并且可以被调用者读取。
output:需要备份的文件中的数据将要保存的目的地

public abstract void onBackup(ParcelFileDescriptor oldState,BackupDataOutput data,ParcelFileDescriptor newState)

请求应用程序写入所有上次执行的备份操作后有变动的数据。之前备份的状态通过oldState文件描述,如果oldState是null,则说明没有有效的旧状态并且此时应用程序应该执行一次完全备份。该方法中的参数如下所示:

oldState:应用程序提供的打开的只读ParcelFileDescriptor,它指向最后备份的状态。它可以是null。

data:它是一个结构化封装的,打开的,可读写的文件描述,指向备份数据的目的地。

newState:打开的,可读写的ParcelFileDescriptor,指向一个空文件,应用程序应该在这里记录需要备份的状态。

注意:这个函数可能抛出IOException异常

public void onCreate()

在真正执行备份或者操作之前执行一次初始化操作的地方
public void onDestroy() 销毁此代理时被调用
public abstract void onRestore(BackupDataInput data,int appVersionCode,ParcelFileDescriptor newState)

应用程序正在从备份文件中恢复并且应该使用备份的内容替换掉所有已经存在的数据。该方法的参数如下所示。

data:结构化封装了一个打开的,只读的文件描述,指向应用程序数据的快照。

appVersionCode:由AndroidManifest.xml文件中的android:versionCode属性提供的应用程序版本信息。

newState:打开的,可读写的ParcelFileDescriptor,指向一个空文件,应用程序应该在恢复它的数据之后记录它的最终备份状态。


然后,我们通过一个简单的实例来说明上表中一些重要方法的调用时间点,包括onBackup(),onCreate()和onRestore()。在这个实例中,仅仅在里面添加一些日志来说明问题,具体步骤如下:


①还是以前面的HelloWorld为例,创建一个HelloWorld,或者删除掉前面的实验代码,恢复刚创建时候的样子。


②在应用程序项目中添加一个继承自BackupAgent的类,名叫MyBackupAgent


③添加完MyBackupAgent类后,这个类中已经默认添加了onBackup()和onRestore()两个回调方法。这里我们还需要添加onCreate()回调方法。


④在各个回调方法中添加打印日志的代码,完成后的代码如下所示:

public class MyBackupAgent extends BackupAgent {
    private static final String TAG="MyBackupAgent";
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
        Log.e(TAG,"onBackup running");
    }
    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException {
        Log.e(TAG,"onRestore running");
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate running");
    }


⑤将MyBackupAgent类配置到AndroidManifest.xml中,代码如下所示:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:backupAgent=".MyBackupAgent">


⑥此时我们就已经完成基本配置。通过上面的描述可知,执行备份有两种方法,一种是通过BackupManager.dataChanged()方法执行备份,另一种则是通过bmgr工具执行备份。这里我们首先演示第一种方法。在创建项目时,默认生成的MainActivity.java文件和AndroidManifest.xml文件使其具有备份的功能。此外,还要添加一个按钮,这个按钮的作用是当你单击它后执行备份动作。修改后的代码如下:

public class MainActivity extends Activity {
    private Button myBackup;
    private BackupManager backupManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.myBackup=(Button)findViewById(R.id.myBackup);
        this.backupManager=new BackupManager(this);
        this.myBackup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                backupManager.dataChanged();//此处执行备份
            }
        });
    }}


⑦完成了这些工作,就可以开始执行一次备份。需要说明是,我们的测试可能在真机或者模拟器上巡行的时候要确保备份功能处于打开状态,因此,我们执行如下命令:

adb shell bmgr enabled


如果得到提示是“Backup Manager currently disable”,则说明备份管理器处于禁用状态,此时就需要执行步骤8启用备份管理器,否则,可以跳过这个步骤。


⑧使用以下命令启用备份管理器:

adb shell bmgr enable true


值得注意的是,这个时候单击按钮,代码就强制执行了backupManager.dataChanged(),但此时Android系统只是简单地将这次备份请求加入了备份消息队列中,并没有执行MyBackupAgent的onBackup()方法。要执行备份与还原,还需要继续完成下面的步骤。


⑨使用bmgr工执行一次备份操作,相关命令如下所示:

adb shell bmgr run


所有的命令步骤如下图:


61.png


此时我们会得到如下所示的执行结果:


62.png


现在来解读一下这个日志。


第一,通过日志的1-4行可以看到,此时备份管理器(BackupManagerService)已经做好了备份的准备。


第二,通过日志的第5行到最后一行可以看到,这时的Android正在执行一个备份任务,这个任务做了很多重要的工作,具体如下:


㈠初始化实现的备份代理类,并调用类的onCreate()方法。


㈡执行备份并调用实现的备份代理类的onBackup()方法。


㈢完成以后会形成一个LocalTransport:。


此时值得注意的是,当执行 adb shell bmgr run命令后,它会通知ActivityThread我们需要一个备份代理,然后由ActivityThread按照输入到ActivityThread中的参数找到需要初始化的备份代理MyBackAgent,接着它会回调onCreate()方法做一次初始化操作,最后备份服务会回调onBackup()方法,开始执行真正的备份。


还有另一种方法,如下所示:


没有执行第9步的时候,通过在按钮的单击事件中添加dataChanged()方法来对备份队列进行操作。不过,bmgr工具提供了另一个手段来完成dataChanged()所做的事情:


adb shell bmgr backup you.package.name


对于应用程序来说,这个命令应该是adb shell bmgr backup com.example.liyuanjing.helloworld。执行此命令后,在执行adb shell bmgr run 命令,将会有相同的结果。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
6月前
|
Android开发 开发者
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
本文详细介绍了如何通过自定义 `attrs.xml` 文件实现 Android 自定义 View 的属性配置。以一个包含 TextView 和 ImageView 的 DemoView 为例,讲解了如何使用自定义属性动态改变文字内容和控制图片显示隐藏。同时,通过设置布尔值和点击事件,实现了图片状态的切换功能。代码中展示了如何在构造函数中解析自定义属性,并通过方法 `setSetting0n` 和 `setbackeguang` 实现功能逻辑的优化与封装。此示例帮助开发者更好地理解自定义 View 的开发流程与 attrs.xml 的实际应用。
173 2
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
|
6月前
|
Java Android开发
Android studio中build.gradle文件简单介绍
本文解析了Android项目中build.gradle文件的作用,包括jcenter仓库配置、模块类型定义、包名设置及依赖管理,涵盖本地、库和远程依赖的区别。
610 19
|
9月前
|
移动开发 安全 Java
Android历史版本与APK文件结构
通过以上内容,您可以全面了解Android的历史版本及其主要特性,同时掌握APK文件的结构和各部分的作用。这些知识对于理解Android应用的开发和发布过程非常重要,也有助于在实际开发中进行高效的应用管理和优化。希望这些内容对您的学习和工作有所帮助。
946 83
|
6月前
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
1747 2
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
1023 1
|
编解码 前端开发 Android开发
Android经典实战之TextureView原理和高级用法
本文介绍了 `TextureView` 的原理和特点,包括其硬件加速渲染的优势及与其他视图叠加使用的灵活性,并提供了视频播放和自定义绘制的示例代码。通过合理管理生命周期和资源,`TextureView` 可实现高效流畅的图形和视频渲染。
881 12
|
存储 监控 数据库
Android经典实战之OkDownload的文件分段下载及合成原理
本文介绍了 OkDownload,一个高效的 Android 下载引擎,支持多线程下载、断点续传等功能。文章详细描述了文件分段下载及合成原理,包括任务创建、断点续传、并行下载等步骤,并展示了如何通过多种机制保证下载的稳定性和完整性。
575 1
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
571 1
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
803 0

热门文章

最新文章