Android中JavascriptInterface读取SQLite数据库崩溃问题求助
解决Android WebView调用JavascriptInterface读取SQLite崩溃问题
1. 禁止在主线程执行数据库操作
WebView的JavascriptInterface方法默认在主线程触发,直接在此方法内读写SQLite会阻塞UI线程,大概率引发ANR或崩溃。
解决方式:将数据库操作转移到子线程,通过Handler回调将结果返回给JS:
public class MyJavascriptInterface { private Context mContext; private Handler mMainHandler = new Handler(Looper.getMainLooper()); private WebView mWebView; public MyJavascriptInterface(Context context, WebView webView) { mContext = context; mWebView = webView; } @JavascriptInterface public void fetchDbData(final String jsCallback) { new Thread(() -> { DataBaseHelper dbHelper = new DataBaseHelper(mContext); SQLiteDatabase db = dbHelper.getReadableDatabase(); StringBuilder dataResult = new StringBuilder(); try (Cursor cursor = db.rawQuery("SELECT * FROM your_table", null)) { if (cursor.moveToFirst()) { do { String value = cursor.getString(cursor.getColumnIndex("target_column")); dataResult.append(value).append(","); } while (cursor.moveToNext()); } } catch (Exception e) { dataResult.append("Error: ").append(e.getMessage()); e.printStackTrace(); } finally { db.close(); } // 切回主线程调用JS回调 mMainHandler.post(() -> { mWebView.loadUrl("javascript:" + jsCallback + "('" + dataResult.toString() + "')"); }); }).start(); } }
2. 校验JavascriptInterface的核心要求
- 接口方法必须添加
@JavascriptInterface注解(Android 4.2及以上强制要求,否则JS无法调用) - 方法权限必须为public,private/protected方法会直接触发调用失败或崩溃
3. 确认数据库路径与初始化逻辑
检查DataBaseHelper的数据库路径是否正确,避免因找不到数据库文件引发崩溃:
public class DataBaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "app_db.db"; private static final int DB_VERSION = 1; private Context mContext; public DataBaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); mContext = context; copyDefaultDbIfNeeded(); } private void copyDefaultDbIfNeeded() { File dbFile = mContext.getDatabasePath(DB_NAME); if (!dbFile.exists()) { try (InputStream in = mContext.getAssets().open(DB_NAME); OutputStream out = new FileOutputStream(dbFile)) { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } } catch (IOException e) { throw new RuntimeException("Failed to copy default database", e); } } } @Override public void onCreate(SQLiteDatabase db) { // 首次创建数据库的表结构(如果不需要拷贝默认库则实现此方法) } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 数据库版本升级逻辑 } }
4. 确保WebView操作的线程安全
- 所有WebView相关的API调用必须在主线程执行,包括
loadUrl、evaluateJavascript - Android 4.4+推荐使用
evaluateJavascript替代loadUrl,避免URL编码问题:
mMainHandler.post(() -> { mWebView.evaluateJavascript(String.format("%s('%s')", jsCallback, dataResult.toString()), null); });
5. 添加异常捕获定位问题
在数据库操作和JS接口方法中加入try-catch,打印崩溃日志快速定位根因:
@JavascriptInterface public void fetchDbData(final String jsCallback) { new Thread(() -> { try { // 数据库操作逻辑 } catch (Exception e) { e.printStackTrace(); mMainHandler.post(() -> { mWebView.loadUrl("javascript:" + jsCallback + "('Crash: " + e.getMessage() + "')"); }); } }).start(); }
内容的提问来源于stack exchange,提问作者Lo Dennis
相关产品推荐
相关产品推荐

