You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android与JS通信异常:后台被杀重启后操作数据库崩溃

问题描述

我正在开发一款集成WebView的App,将HTML、CSS和JS文件嵌入WebView中,并搭建多个SQLite数据库存储数据,通过JS完成数据的增删改操作。App后台驻留被系统杀死后,数据库用于重建HTML恢复运行。

初次运行时WebView与数据库均正常工作,但App被杀死重启后,虽能通过数据库重建HTML,但执行数据增删改操作时崩溃,报错:

[INFO:CONSOLE(5841)] "Uncaught Error: Java exception was raised during method invocation", source: file:///android_asset/index.html (5841)

崩溃时执行的JS代码:

app.delete_duty(String(myVar[4 * a]));

对应的Java代码:

@JavascriptInterface
public void delete_duty(String id)
{
        myDB2.deleteData(id); // myDB2是存储数据的数据库实例之一
}

MainActivity核心代码:

public class MainActivity extends AppCompatActivity
{
    HTMLDataBase myDB1;
    ContentTableDataBase myDB2;
    CloudTableDataBase myDB3;
    InterviewDataBase myDB4;
    Context context;
    boolean check;

    private WebView view;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myDB1 = new HTMLDataBase(this);
        myDB2 = new ContentTableDataBase(this);
        myDB3 = new CloudTableDataBase(this); 
        myDB4 = new InterviewDataBase(this); 

        display_html();
        Javascript_Android_Communication();
    }

    public void display_html()
    {
        WebView view = (WebView) findViewById(R.id.WebView);
        view.getSettings().setJavaScriptEnabled(true);
        view.getSettings().setDomStorageEnabled(true);
        view.loadUrl("file:///android_asset/index.html");
    }

    public void Javascript_Android_Communication()
    {
        WebView view = (WebView) findViewById(R.id.WebView);
        view.setWebChromeClient(new WebChromeClient() {});
        WebSettings settings = view.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);

        view.addJavascriptInterface(new JavaScriptInterface(this), "Android");
        view.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
    }
}

怀疑问题出在Java与JavaScript的通信环节,因为App未被杀死时JS操作完全正常,仅重启后执行相同脚本出错。


可能的原因

  1. 数据库实例引用失效:WebViewJavaScriptInterface类大概率直接持有了MainActivity中myDB2的旧引用,App被杀死重启后,原有数据库连接已失效,但接口仍在使用旧实例,调用deleteData时抛出异常。
  2. WebView重复初始化:display_html和Javascript_Android_Communication方法中重复通过findViewById获取WebView实例,可能导致JavascriptInterface绑定出现状态冲突,尤其在重启后的WebView恢复阶段。
  3. 上下文引用无效:如果WebViewJavaScriptInterface保存的Context不是MainActivity的有效实例,会导致数据库操作时上下文失效,引发异常。

解决方案

1. 让WebViewJavaScriptInterface动态获取最新数据库实例

修改WebViewJavaScriptInterface类,通过传入的MainActivity实例动态获取当前的数据库对象,避免持有旧引用:

public class WebViewJavaScriptInterface {
    private WeakReference<MainActivity> mActivityRef;

    public WebViewJavaScriptInterface(MainActivity activity) {
        mActivityRef = new WeakReference<>(activity);
    }

    @JavascriptInterface
    public void delete_duty(String id) {
        MainActivity activity = mActivityRef.get();
        if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
            activity.myDB2.deleteData(id);
        }
    }
}

注:需将MainActivity中的myDB2设为public,或提供getMyDB2()这类getter方法。

2. 统一WebView初始化逻辑

将WebView的配置、接口绑定和HTML加载统一到一个方法中,避免重复操作:

private WebView view;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 初始化数据库
    myDB1 = new HTMLDataBase(this);
    myDB2 = new ContentTableDataBase(this);
    myDB3 = new CloudTableDataBase(this); 
    myDB4 = new InterviewDataBase(this); 

    // 统一初始化WebView
    initWebView();
}

private void initWebView() {
    view = findViewById(R.id.WebView);
    WebSettings settings = view.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
    view.setWebChromeClient(new WebChromeClient() {});
    
    // 绑定JavascriptInterface
    view.addJavascriptInterface(new JavaScriptInterface(this), "Android");
    view.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
    
    // 加载HTML
    view.loadUrl("file:///android_asset/index.html");
}

3. 给数据库操作添加异常捕获

在deleteData方法中添加异常处理,明确错误原因:

public void deleteData(String id) {
    SQLiteDatabase db = null;
    try {
        db = this.getWritableDatabase();
        db.delete("your_table_name", "id=?", new String[]{id});
    } catch (Exception e) {
        e.printStackTrace();
        // 记录错误日志,方便排查
    } finally {
        if (db != null && db.isOpen()) {
            db.close();
        }
    }
}

内容的提问来源于stack exchange,提问作者Lo Dennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:40:57