这段时间公司项目,涉及到数据缓存,由于需要缓冲的数据太多、太大,通过网络请求,再缓存到本地sqlite数据库,太费时间,消耗流量。所以准备先在本地保存一个标准版sqlite数据库(包含数据),打包到apk文件里,以后需要的操作就是更新数据,这样一来,请求和操作的数据就很小了。

  那么问题来了,如何把标准版的sqlite数据库文件(db格式)从内部存储空间里面导出,然后放到项目中assets文件夹下?

  想从内部存储空间里拷贝东西,首先要root,手机要root,APP也要获得root权限。这篇博客不讲如何通过root拷贝内容,因为这种办法真的很蠢,root手机会给手机带来不可逆的改变,如果手机很贵的话,尽量不要root;即便手机root后,app也好获得root权限,很麻烦,而且国内手机厂商rom不同,很多手机即便按照步骤一步步root了,也不能查看和赋值内部存储空间里的文件。

  那么怎么实现呢?一个简单到可笑的办法(获取这是android系统安全性上的漏洞),在代码中,我们可以访问、读取内部存储空间里的东西,也可以读写SD卡等外部存储空间(要添加相应权限),那么我们就可以通过IO的方法,将内部存储空间中的文件,拷贝到外部存储空间,然后再从外部存储空间里拷贝我们需要的东西就OK了。

  实现方式:

1、添加系统权限:

在AndroidManifest.xml中添加读写SD卡等操作权限:

    <!-- 写入扩展存储,向扩展卡写入数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2、从内部存储空间通过IO的方式拷贝到SD卡和外部存储空间:

这个时候,已经通过网络请求,将拿到的JSON数据写入到sqlite数据库中了。直接拷贝就好:

/**
* 拷贝内部存储空间的数据库到外部
*
* @throws FileNotFoundException
*/
public void copyDBFile() throws FileNotFoundException {
File toDir = new File(Field.DB_PATH_SD); //外部存储文件夹
if (!toDir.exists()) {
toDir.mkdirs();
} File toDb = new File(Field.DB_PATH_SD + App.BaseDB.dbName); //外部存储数据库
File fromDir = new File(Field.DB_PATH + App.BaseDB.dbName); //内部存储数据库 InputStream is;
OutputStream os;
is = new FileInputStream(fromDir);
os = new FileOutputStream(toDb);
byte[] buffer = new byte[1024];
int length;
try {
/**
* 拷贝过程
*/
while ((length = is.read(buffer, 0, buffer.length)) > 0) {
os.write(buffer, 0, length);
} os.flush();
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}

相关常量:

/**
* 内部数据库路径
*/
public static final String DB_PATH = File.separator + "data"
+ Environment.getDataDirectory().getAbsolutePath() + File.separator
+ MyApplication.getInstance().getPackageName() + File.separator + "databases" + File.separator; /**
* 外部数据库路径
*/
public static final String DB_PATH_SD = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "tdr" + File.separator; public static class BaseDB{
public static final int version=1;
public static final String dbName="base.db";
}

3、在需要的地方,调用copyDBFile()

            try {
//拷贝工具类通过单例获取
BaseDBHelper.getInstance().copyDBFile();
} catch (FileNotFoundException e) {
Log.e(TAG, "fileNotFount");
Log.e(TAG, e.getMessage());
Log.e(TAG, e.toString());
e.printStackTrace();
}

执行完成以后,就可以直接在手机文件夹里看到需要的db文件了:

如此,就可以在非root的前提下,拷贝出内部存储空间里的文件了。不得不说,这也许是android无意的一个安全漏洞吧!因为这个真的很蠢,就好比:一家人有一个保险柜,里面放着家里的财产,贼要是想从保险柜里直接拿走财物是不可以的,但是如果贼先把钱从保险柜里拿到客厅,再从客厅拿走,就完全可以,这样拿走,不仅没有约束,家里主人还会主动把保险柜密码告诉你,把家里的大门为你敞开。。。。。。

4、后记

我之前介绍公司项目的时候,提到:我会把db文件通过离线的方式拷贝到项目的assets文件夹下,然后需要操作数据库的时候,就操作assets文件夹里的数据库。但是这样做会有一个很大的性能上的问题:

sqlite数据库的读写,只能读写/data/...中的数据库文件,如此一来,每次读写或修改assets中的数据库的时候,就要先把assets的数据库拷贝到data对应文件夹下,然后再进行读取,这样一来,效率极低,并且对数据库做完改动后,改动也没有办法同步到源数据库中(也就是数据库会自动还原)。那么这个问题该输入解决呢?以后有时间,再整理一篇博客,说一些这个问题。

如何导出android内部存储的文件(不用root)的更多相关文章

  1. Android用路径api在内部存储读写文件

    复制并修改原有项目 复制之前创建的项目CC+CV操作 需要改动的地方: * 项目名字 * 应用包名 * R文件重新导包 接着修改件/AndroidManifest.xml中的包名:package=&q ...

  2. Android 在内部存储读写文件

    文件读写操作* Ram内存:运行内存,相当于电脑的内存* Rom内存:内部存储空间,相当于电脑的硬盘* sd卡:外部存储空间,相当于电脑的移动硬盘在内部存储空间中读写文件>小案例:用户输入账号密 ...

  3. Android 数据存储之 文件存储

    -------------------------------------------文件存储----------------------------------------------- 文件存储是 ...

  4. Android 内部存储相关的函数(getCacheDir,getDir, getFileStreamPath,getFilesDir,openFileInput, ...)

    为了保证应用程序存储数据的安全性,开发人员在开发应用程序的过程中须要注意使用Android 应用程序的内部存储空间. 依据不同的要求.将相应的数据文件.缓存文件.暂时文件等分别存储在相应的位置. 注意 ...

  5. android 内部存储 安装apk

    在做应用自动更新模块下载apk时遇到了内部存储和sd卡存储两种情况,存在sk卡中存储apk可以正常安装,可是在内部存储中安装apk时出现了parse error的问题. 在网上搜了搜,大致分为两种方案 ...

  6. Android 内部存储读写介绍

    内部存储读写 内容介绍 Android系统允许应用程序创建仅能够自身访问的私有文件,文件保存在设备的内部存储器上,在Linux系统下的/data/data//files目录中 Android系统不仅支 ...

  7. Android 内部存储和外部存储

    应用程序的一些配置文件需要存储在手机上.一般分为内部存储和SD卡存储. 一. 内部存储 ,以 FileOutputStream File file = new File(getFilesDir(),& ...

  8. Android 内部存储安装apk文件实现

    目前国内市场的山寨机横行,安卓手机升级也是一天一个样,对于原来老手机可能没有SDCARD,导致我们的APP不能下载资源,无法更新APP,针对这种情况有以下解决方案.通过以下函数判断是否有SD卡再判断下 ...

  9. android 内部存储相关知识点: getfilestreampath getDir 子文件夹

    文件系统的API的命名方式和常规的不一样: 都是get命名,但是功能就是能创建文件夹...   这种方式的API 命名习惯和常规的不一样...  createXXX ----方便查找 http://i ...

随机推荐

  1. Privacy-Enhanced Mail (PEM) Privacy Enhancement for Internet Electronic Mail

    小结 1. 加密基本流程 本地格式标准格式认证(填充与完整性检查)与加密可打印编码 Privacy-Enhanced Mail (PEM) RFC 2313 - PKCS #1: RSA Encryp ...

  2. springboot项目-声明式事务失效

    1.项目背景 集成了shiro配置 2. 项目分析 由于ShiroFilterFactoryBean实现了FactoryBean接口,所以它会提前被初始化.又因为SecurityManager,Sec ...

  3. 【Android初级】教你用两行代码实现“显示/隐藏密码”的效果

    Android里面要使用密码的场景是非常多的,支付宝.微信.淘宝以及各大银行APP,都跟用户的密码有关.用户的密码是极为隐私的,用户在输入时不希望密码被别人看到,所以几乎所有需要输入密码的场景下都会把 ...

  4. SpringMVC听课笔记(九:数据转换 & 数据格式化 & 数据校验)

    1.数据绑定流程 --1). Spring MVC主框架将ServletRequest对象及目标方法入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象. - ...

  5. vue3.0初尝试

  6. (25)Vim 1

    1.安装Vim CentOS 系统中,使用如下命令即可安装 Vim: yum install vim 需要注意的是,此命令运行时,有时需要手动确认 [y/n] 遇到此情况,选择 "y&quo ...

  7. HarmonyOS三方件开发指南(8)——RoundedImage

    [小年答谢,新春送礼]免费抽取1000元京东卡+更多新春好礼~查看详情>>> 目录: 1. RoundedImage组件功能介绍 2. RoundedImage使用方法 3. Rou ...

  8. linux(9)find命令详解

    find命令格式: find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数: path:要查找的目录路径. ~ 表示$HO ...

  9. Python3.9.1中如何使用split()方法?

    本文出自:lunvey,半路出家学编程之Python.split()方法定义于str类中,str类大家都知道是python内置定义的一个字符串类. split()默认两个参数,分别是分隔符和分隔数量, ...

  10. Luogu4168 蒲公英 (分块)

    题目传送门 题意 长度为n的序列,有m次询问,每次询问求\([l,r]\) 间的众数,如果有多个,输出最小的那个 \(n\le 4\times 10^4,m\le 5\times 10^5,a_i\l ...