这段时间公司项目,涉及到数据缓存,由于需要缓冲的数据太多、太大,通过网络请求,再缓存到本地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. Redis-第六章节-事务

    目录 简介 执行过程 特点 案例 watch 简介 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 执行 ...

  2. bzoj 2038(莫队算法)

    2038: [2009国家集训队]小Z的袜子(hose) 时间限制: 20 Sec  内存限制: 259 MB 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来 ...

  3. Prometheus 监控之 Blackbox_exporter黑盒监测

    Prometheus 监控之 Blackbox_exporter黑盒监测 1.blackbox_exporter概述 1.1 Blackbox_exporter 应用场景 2.blackbox_exp ...

  4. Linux 输入输出重定向, &>file, 2>&1, 1>&2

    Linux 输入输出重定向, &>file, 2>&1, 1>&2 一.1和2在Linux中代表什么 1.1 输出重定向 1.2 输入重定向 1.3 绑定重定 ...

  5. Java——Number类

    在平时学习中,当我们需要使用数字的时候,通常使用内置数据类型,如byte,int,long,double等. int i =12; float a = 12.3; 在实际开发中,经常会遇到需要使用对象 ...

  6. JavaWeb——Cookie,Session学习汇总

    什么是Cookie Cookie的作用 安全性能 Cookie的语法 Cookie注意细节 Cookie实例练习 什么是会话Session Session语法 Session与浏览器窗口的关系 ses ...

  7. Linux环境Hadoop安装配置

    Linux环境Hadoop安装配置 1. 准备工作 (1)linux配置IP(NAT模式) (2)linux关闭防火墙 (3)设置主机名 (4)设置映射 (5)设置免密登录 2. 安装jdk (1)上 ...

  8. Hbase 表的设计原则 ————总结

    1.列族的数量及列族的势 建议将HBase列族的数量设置的越少越好.当强,对于两个或两个以上的列族HBase并不能处理的很好.这是由于HBase的Flushing和压缩是基于Region的.当一个列族 ...

  9. telnet | ping

    ping通常是用来检查网络是否通畅或者网络连接速度的命令.  ping www.baidu.com 而telnet是用来探测指定ip是否开放指定端口的. telnet xxx 443 查看443开放没 ...

  10. css按钮样式

    style='height:22px;padding:1 17px;font-size: 8px;font-weight: 100;line-height: 25px;'http://www.boot ...