我正在尝试在基于Android WebView的应用程序中实现离线地图功能:
使用DownloadManager
,我从我们的网络服务器下载 sqlite数据库文件(.mbtiles等结构),其中包含地图图块图像的blob ("离线地图")并将其存储在 android外部存储中
public void downloadMap() {
downloadManager = (DownloadManager) getActivity().getSystemService(Activity.DOWNLOAD_SERVICE);
DownloadManager.Request r = new DownloadManager.Request(Uri.parse("http://sry.youtoknow.idontwant/map.sqlite"));
r.setDestinationInExternalFilesDir(getContext(), "map", "map.sqlite");
downloadManager.enqueue(r);
}
下载似乎运行得非常好。
我注册了一个BroadcastReceiver
来接收DownloadManager.ACTION_DOWNLOAD_COMPLETE
并将路径存储到" map.sqlite"使用SharedPreferences
。
要通过检查URL中的自定义虚拟架构名WebView
,从JavaScript访问数据库以使用customhttp:
中的磁贴图像,我拦截XHRequests :< / p>
webView.setWebViewClient(new WebViewClient() {
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
if (!url.startsWith("customhttp:")) {
return null;
} else {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SQLiteDatabase db = SQLiteDatabase.openDatabase(preferences.getString("map_uri", Environment.getExternalStorageDirectory().getPath() + "berlin.sqlite"), null, SQLiteDatabase.OPEN_READONLY);
}
}
});
我的问题是我似乎以错误的方式实施openDatabase()
,因为我在相应的行中遇到以下不愉快的错误,但无法找出原因:< / p>
E/SQLiteLog(#####): (14) cannot open file at line ##### of [##########]
E/SQLiteLog(#####): (14) os_unix.c:#####: (2) open(//file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite) -
E/SQLiteDatabase(#####): Failed to open database 'file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite'.
E/SQLiteDatabase(#####): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
[...]
文件存在,没有损坏,其路径似乎是正确的。我能够使用SQLite查看应用程序打开文件。
问题:为什么我的代码不起作用;我怎样才能让它发挥作用?
我知道上面的错误信息至少存在三个非常相似的问题,但它们并不具体,详细和/或不完全符合我的需要。阅读本文后,我也无法解决问题:
http://blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
非常感谢你的帮助!
更新
我尝试在外部存储中使用SQLiteDatabase.openOrCreateDatabase()
创建一个新数据库,以便将其与原始数据库进行比较。它没有被创建 - 相反,我出乎意料地面对相同的错误消息(无法打开数据库)。
然后我再次尝试使用 SQLiteDatabase.openOrCreateDatabase(":memory:", null)
在RAM中打开一个新数据库,它没有抛出任何错误。
因此,我开始认为问题是对外部存储的访问限制或在寻址外部存储时的错误,而不是数据库文件本身。
答案 0 :(得分:4)
我终于找到了错误,一个非常发人深省的错误。
我收到DownloadManager.ACTION_DOWNLOAD_COMPLETE
并将 URI 存储到SharedPreferences
中已下载的数据库中,以便稍后在shouldInterceptRequest
方法中引用:
...
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
if (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
editor.putString("map_uri", c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
editor.commit();
}
}
c.close();
在shouldInterceptRequest
我然后打电话给
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SQLiteDatabase db = SQLiteDatabase.openDatabase(preferences.getString("map_uri", Environment.getExternalStorageDirectory().getPath() + "map.sqlite"), null, SQLiteDatabase.OPEN_READONLY);
从而将 URI 传递给openDatabase
,而不是 路径 。
我现在Uri.parse(preferences.getString("map_uri", ...)).getPath()
一切正常。地图加载。
非常感谢你的帮助!