app备份与恢复研究

最近打算搞一个app备份与恢复的小应用,顾名思义,必然包括app的备份和app的恢复两部分。备份部分由可以分为apk的备份与data的备份两部分。需要注意的是备份与恢复都需要一堆的权限,尤其是恢复的时候。

app的备份

首先看看下面几个目录:

system/app 系统自带的应用程序apk目录,无法删除。

data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录。

data/data 存放应用程序的数据。

data/dalvik-cache 将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)。

app的备份原理就是把system/app、data/app、data/data中的apk和数据存起来,可以存到sd卡也可以上传到网络。既然如此我们就可写代码了,下面代码只是我自己写来测试用的,不严谨,拷贝可能有问题。

apk的备份

public String backupAppPackage(String packageInPath, String packageName)

{

FileInputStream fis = null;

FileOutputStream fos = null;

try

{

File in = new File(packageInPath);

File out = new File(backupPath + packageName + ".apk");

out.createNewFile();

fis = new FileInputStream(in);

fos = new FileOutputStream(out);

int count;

byte[] buffer = new byte[256 * 1024];

while ((count = fis.read(buffer)) > 0)

{

fos.write(buffer, 0, count);

}

}

catch (IOException e)

{

e.printStackTrace();

return "IOException";

}

finally

{

if (fis != null)

{

try

{

fis.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

if (fos != null)

{

try

{

fos.flush();

fos.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

return "OK";

}

data的备份

public String backupAppData(String dataInPath, String packageName)

{

FileInputStream fis = null;

FileOutputStream fos = null;

try

{

File in = new File(dataInPath);

File out = new File(backupPath + packageName);

out.createNewFile();

fis = new FileInputStream(in);

fos = new FileOutputStream(out);

int count;

byte[] buffer = new byte[256 * 1024];

while ((count = fis.read(buffer)) > 0)

{

fos.write(buffer, 0, count);

}

}

catch (IOException e)

{

e.printStackTrace();

return "IOException";

}

finally

{

if (fis != null)

{

try

{

fis.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

if (fos != null)

{

try

{

fos.flush();

fos.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

return "OK";

}

app恢复

app恢复的时候就稍微有点纠结了,因为这就牵扯到apk的安装,而apk的安装的方法很多,需要根据自己的情况选择。

情况一

如果你搞的是一个系统级应用,可以考虑使用反射机制,但是最好是直接使用系统API,由于PackageManager的installPackage函数是隐藏的,所以在用eclipse开发编译的时候需要引入classes.jar。代码如下:

public void installPackage(Uri apkFileUri) throws Exception

{

if (apkFileUri != null)

{

//使用放射机制得到PackageManager类的隐藏函数installPackage

PackageManager pm = context.getPackageManager(); //得到pm对象

try

{

//通过反射机制获得该隐藏函数

//                Method installPackage = pm.getClass()

//                        .getDeclaredMethod("installPackage",

//                                Uri.class,

//                                IPackageInstallObserver.class,

//                                int.class,

//                                String.class);

//                //调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数

//                installPackage.invoke(pm,

//                        apkFileUri,

//                        new PkgInstallObserver(),

//                        INSTALL_REPLACE_EXISTING,

//                        null);

//直接通过API

pm.installPackage(apkFileUri,

new PkgInstallObserver(),

INSTALL_REPLACE_EXISTING,

null);

//W/System.err(24923): Caused by: java.lang.SecurityException: Neither user 10053 nor current process has android.permission.INSTALL_PACKAGES.

System.out.println("invoke-->>>");

}

catch (Exception ex)

{

System.out.println("Exception-->>>");

ex.printStackTrace();

//Neither user 10053 nor current process has android.permission.GET_PACKAGE_SIZE.

throw ex; // 抛出异常

}

}

}

IPackageInstallObserver是安装结果的回调,通过它监听安装的结果。

class PkgInstallObserver extends IPackageInstallObserver.Stub

{

public void packageInstalled(String packageName, int returnCode)

throws RemoteException

{

System.out.println("packageInstalled-->>" + packageName);

}

}

情况二

如果搞的是一个普通应用则还有两种选择方案。

第一种是通过获取系统权限,执行命令静默安装,如下:

public void installApp()

{

File dir = new File(backupPath);

File file = dir.listFiles()[2];

String apkPath = file.getAbsolutePath();

String result = execRootCmd("pm install -r " + apkPath);

}

// 执行命令并且输出结果

public static String execRootCmd(String cmd)

{

String result = "";

DataOutputStream dos = null;

DataInputStream dis = null;

try

{

// 经过Root处理的android系统即有su命令

Process p = Runtime.getRuntime().exec("su");

dos = new DataOutputStream(p.getOutputStream());

dis = new DataInputStream(p.getInputStream());

Log.i(TAG, cmd);

dos.writeBytes(cmd + "\n");

dos.flush();

dos.writeBytes("exit\n");

dos.flush();

String line = null;

while ((line = dis.readLine()) != null)

{

Log.d("result", line);

result += line;

}

p.waitFor();

}

catch (Exception e)

{

e.printStackTrace();

}

finally

{

if (dos != null)

{

try

{

dos.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

if (dis != null)

{

try

{

dis.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

return result;

}

第二种最普通的安装是把安装的任务交给系统应用去做,如下:

public static void install(Context context, String filePath) {

Intent i = new Intent(Intent.ACTION_VIEW);

i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");

i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startActivity(i);

}

需要滴权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.INSTALL_PACKAGES" />

app备份与恢复研究

时间: 2024-10-27 19:38:30

app备份与恢复研究的相关文章

搜狗市场高速下载以及网页端调起APP页面研究与实现

Github博文地址,此处更新可能不是很及时. 好久没写博客了,好大一个坑.正好,最近刚做完搜狗市场的高速下载功能,便拿来填了这个坑. 话说产品为了增加用户量,提升用户活跃度以及配合推广,更坑爹的是看到其他市场也有这些功能,等等,要求做一个捆绑下载的功能.WTF. 当然吐槽归吐槽,任务还是要完成的. 具体要求是: 用户在手机浏览WAP站点的时候,1.进入应用详情页时打开本应用(搜狗市场)里面的详情页面 2.点击WAP端高速下载时,如果本应用已安装,则调用本应用进行下载,否则下载本应用的捆绑包,安

app安全研究

国内Android App在线漏洞检测平台 腾讯金刚审计系统 http://service.security.tencent.com/kingkong 免费 无限制 腾讯御安全 http://yaq.qq.com/ 免费 查看漏洞详情需认证 阿里聚安全 http://jaq.alibaba.com/ 免费 查看漏洞详情需认证 360显微镜 http://appscan.360.cn/ 免费 无限制 360APP漏洞扫描 http://dev.360.cn/html/vulscan/scannin

点击APP外部链接唤醒APP的研究

在微信里面打开app的指定页面,考虑到使用Url Scheme,可是微信已经禁止了,但是通过浏览器可以实现,最终是在微信里面让用户通过打开浏览器,使用安卓或者IOS开发者提供的协议短链,如贴吧APP,协议为:com.baidu.tieba:// ,微信的:weixin://实现在浏览器中打开app指定页面,通过传递不同的参数实现跳转不同的页面 而对于点击链接后,能否直接打开,可以通过下面的代码来实现. js代码 document.querySelector("#linkApp").on

iOS-最全的App上架教程

分类:App Store研究 来源:随梦而飞飞 简书 应用商店iOSApp上架 授权转载,作者:随梦而飞飞 准备 开发者账号 完工的项目 上架步骤 一.创建App ID 二.创建证书请求文件 (CSR文件) 三.创建发布证书 (CER) 四.创建Provisioning Profiles配置文件 (PP文件) 五.在App Store创建应用 六.打包上架 一.创建App ID 1.打开苹果开发者官网,点击"Account"登录会员中心. 2.填写信息创建app ID 点击+创建ID

【iOS秘籍】-下载历史版本App超详细教程

有些时候我们需要下载旧版本的 App 进行研究或者其他用途,然而在 iOS 下,苹果的 App Store 里面默认只能下载最新版本的 App,对滴,就是这么任性,不服不行.然而在 Android 里面任意一个应用商店都可以下载任意版本的 App,就是这么开放.重点来啦,今天我要教大家的就是利用 iTunes 下载任意历史版本的 App,任意哟,下面开始教程??.(为方便大家理解操作,图片较多,流量党慎入0-0) 题外话(强迫症排版.拼写): 文章排版:个人强迫症比较喜欢关注一些细节,比如博客或

Android开机自动运行APP——BroadcastReceiver

前言: 有些时候,应用需要在开机时就自动运行,例如某个自动从网上更新内容的后台service.怎样实现开机自动运行的应用?在撰写本文时,联想到高焕堂先生以"Don't call me, I'll call you back!"总结Android框架,真是说到点子上了.理解这句话的含义,许多有关Android平台上实现某种功能的问题,都能迎刃而解. 使用场景: 手机开机后,自动运行程序. {只是最近本人在做万达大歌星点餐系统,需要用到系统启动直接启动App避免服务员玩别的app才研究的,

App工程结构

在经过千辛万苦各种填坑终于安装好了Android Studio之后,在其自带的模拟器上成功运行了第一个APP(hello world),通过这个APP首先研究了一下APP基本的工程结构,从而使后面的开发更加得心应手. 先上HelloWorld工程的目录结构图 从结构图我们可以看到,该工程下面有两个目录:一个是app,另一个是Gradle Scripts. 其中,app又分下面三个子目录 (1)manifests,下面只有一个AndroidManifest.xml文件,它是APP运行的配置文件 (

解决小米/红米手机无法进行jdwp调试的问题

问题描述:在逆向一个app,研究环境是一台红米2,需要使用jdwp接口,也就是ddms下面这个界面: 但神奇的是,同一台主机上,模拟器的进程可以显示在ddms界面上,红米2确一个进程都没有显示出来.cmd里使用 adb jdwp 命令,也没有显示任何接口. 通过简单搜索发现,一个app进程要能被jdwp客户端调试,要不就是编译的时候主配置文件需要开启  android:debuggable="true" ,要不就是系统 boot.img 里的一个文件  default.pro 里的 r

半糖iOS版首页实现与基本原理揭秘

很久以前,一个学弟的曾问过我如何实现半糖iOS版本首页效果,我当时一看觉得这个效果挺酷炫,然后去github上搜了一下,很多自称是仿半糖首页的,我下载之后发现其实很多代码都没有实现主要的代码.有些代码也做了一些简单的尝试,但是最后都放弃了,所以说这个效果还是没有很好的实现.我于是打算研究一下这个有趣的效果,经过工作之余一段时间的研究.有时候路上也会想一想,做了很多的尝试,一点一点的把遇到的问题解决了.于是写下这篇文章,把自己的一些尝试和想法与大家分享. 有的开发者可能会觉得这么简单的东西别拿来忽