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

Android WebView实现图片视频分享报主线程调用错误问题求解

问题原因

你遇到的Method call should not happen from the main thread报错本质是线程调用违规,核心触发点有两个:

  • 所有被@JavascriptInterface注解标记的方法,默认运行在WebView专属的JS后台线程,并非Android主线程,直接在这个线程里调用涉及UI、系统组件的操作本身就违反Android单线程模型规则
  • 你在Picasso的加载回调里直接调用了MediaStore.Images.Media.insertImage和startActivity,这两个API强制要求在主线程调用,后台线程触发就会直接抛出你看到的异常
  • 补充说明:navigator.shareAPI确实不支持Android系统WebView环境,你通过JavascriptInterface桥接原生分享能力的思路是可行的,只是线程处理逻辑存在问题。

另外你的代码还存在一个隐藏bug:Picasso对Target是弱引用持有,你把Target定义为方法内局部变量,很容易被GC回收,导致分享回调不触发。

修复方案

核心调整点

  • 所有涉及UI操作、MediaStore写入、Activity启动的逻辑,必须切到主线程执行
  • 将Target改为全局强引用持有,避免被GC回收导致回调失效
  • 给分享Intent添加临时读权限标记,避免第三方应用无法读取待分享文件
  • 适配Android版本权限差异:Android 10及以上版本不需要读写外置存储权限即可写入MediaStore,无需在高版本申请冗余权限

修正后的核心代码

public class Principal extends AppCompatActivity {

    private WebView mBibouView;
    // 全局持有Target,避免被GC回收
    private Target shareTarget;

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

        mBibouView=findViewById(R.id.bibouview);
        WebSettings webSettings = mBibouView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        
        mBibouView.setWebViewClient(new WebViewClient());
        mBibouView.addJavascriptInterface(new JavascriptShareInterface(), "AndroidShareHandler");
        mBibouView.loadUrl("https://www.myadress.fr");
    }


    public class JavascriptShareInterface {
        @JavascriptInterface
        public void share(String url){
            // JS接口运行在后台线程,切主线程执行后续操作
            runOnUiThread(() -> {
                shareTarget = new Target() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                        // Picasso主线程回调,可直接调用系统API
                        String path = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "ShareImage", null);
                        if (path == null) {
                            Log.e("Share", "Write image to MediaStore failed");
                            return;
                        }
                        Uri shareUri = Uri.parse(path);
                        Intent shareIntent = new Intent(Intent.ACTION_SEND);
                        shareIntent.setType("image/*");
                        shareIntent.putExtra(Intent.EXTRA_TEXT, "Hey view/download this image");
                        shareIntent.putExtra(Intent.EXTRA_STREAM, shareUri);
                        // 给第三方应用授予临时文件读权限
                        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        startActivity(Intent.createChooser(shareIntent, "Share image via..."));
                    }

                    @Override
                    public void onBitmapFailed(Drawable errorDrawable) {
                        Log.e("Share", "Load image from url failed");
                    }

                    @Override
                    public void onPrepareLoad(Drawable placeHolderDrawable) {
                        // 可在此处添加加载中提示
                    }
                };
                Picasso.with(Principal.this)
                        .load(url)
                        .into(shareTarget);
            });
        }
    }

    @Override
    public void onBackPressed(){
        mBibouView.evaluateJavascript("document.getElementById('div_form').style.display='none';",null);
        mBibouView.evaluateJavascript("document.getElementById('div_menu').style.display='none';",null);
    }
}

额外优化建议

  • 你当前使用的是旧版Picasso(Picasso.with()初始化),建议升级到最新版本使用Picasso.get()初始化,避免老版本存在的线程调度bug
  • 视频分享逻辑和图片基本一致,只需要将MIME类型替换为video/*,对应加载视频资源写入MediaStore即可
  • 清单文件中的读写外置存储权限,可以添加android:maxSdkVersion="28"配置,在Android 10及以上版本自动跳过该权限申请,减少权限弹窗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:57:20