【发布时间】:2011-08-17 22:46:31
【问题描述】:
是否可以获得对位于 apk 的 sqlite 数据库的只读访问权限?如果可以从 apk 中出于只读目的访问它,我不想复制数据库。
【问题讨论】:
是否可以获得对位于 apk 的 sqlite 数据库的只读访问权限?如果可以从 apk 中出于只读目的访问它,我不想复制数据库。
【问题讨论】:
我刚刚开始为 Android 开发,并惊讶地发现捆绑静态数据库不容易。所以我做了唯一合理的事情:创建了一个库来做到这一点。
android-staticdb 是一个 Android 库,允许对包含在应用程序的 .apk 文件中的 SQLite 数据库进行只读访问。这非常适合需要附带大量静态数据的应用程序(例如离线维基百科阅读器)。
它通过从本地 C 代码向 SQLite 库注册一个新的“虚拟文件系统”层来工作,该库能够拦截 SQLite 进行的文件系统调用。因为每个 VM 进程只有一个 SQLite 库副本,所以我们实际上最终会拦截 any 应用程序在与我们相同的进程中进行的任何 SQLite 调用!
在正常操作中,我们的 VFS 层只是将所有调用代理到“默认”
VFS,它只使用 open() 和 read() 来访问常规数据库文件。但
当遇到与*.apk!filename 模式匹配的特殊文件名时,
我们的 VFS 获得了控制权。使用 zlib 和 minizip,它会打开 .apk 文件并
在里面查找数据库文件;然后它将读取此文件的块
满足来自 SQLite 的任何 read() 请求。
通过这种方式,应用程序可以继续使用标准 Android 数据库 API。
示例用法:
import android.database.sqlite.SQLiteDatabase;
import kiwidrew.staticdb.StaticDatabase;
public class BlahBlah extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SQLiteDatabase db = StaticDatabase.openDatabase(this, "assets/foobar.db");
// Do normal database stuff with 'db'...
}
}
你得到一个标准的 SQLiteDatabase 对象,唯一的限制是它不支持写入。 (显然!)
请注意,除非数据库未经压缩存储在您的.apk 中,否则这将失败。使用aapt -0 命令添加SQLite 数据库或修改build.xml 以将<nocompress extension="db" /> 标志传递给<aapt> 标记...
我刚刚写完这篇文章,到目前为止只进行了非常基本的测试。错误报告将不胜感激。
【讨论】:
正如这个答案中提到的Load files bigger than 1M from assets folder
如果资产未压缩,系统可以对文件数据进行内存映射 并使用Linux虚拟内存分页系统拉入或丢弃 4K 块(视情况而定)。
如果这是真的,可以将未压缩的数据库存储到 APK(使用 mp3 等一些扩展来保持文件未压缩)并直接从 APK 中读取。这只是我的猜测,不过我不确定具体的实现方式。
对于 Android 2.3 及更高版本,您可以通过 NDK http://groups.google.com/group/android-ndk/browse_thread/thread/30b9f5abf48347a0/ef62db9a18646b1d 使用 Native Access。
【讨论】:
不,apk 必须有一个接口供您提取数据 - 可以通过 Android 服务公开。
据我所知,Android 是一个 Linux 发行版,其中每个 .apk 都作为/由单独的用户帐户安装,这些帐户都不是 root。因此,应用空间得到了有效的划分。
【讨论】: