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

迁移到AndroidX后文件上传模块startActivityForResult报错解决方案求助

改造代码实现(替换startActivityForResult为registerForActivityResult)

1. 新增成员变量声明

在WebviewActivity类中保留原有变量,新增Activity结果启动器:

// 原有成员变量保留
private ValueCallback<Uri[]> mUMA;
private String mCM;
private static final String TAG = "WebviewActivity";
// 新增Activity Result启动器,完全替代废弃的startActivityForResult
private ActivityResultLauncher<Intent> fileChooserLauncher;

2. 初始化启动器(在onCreate方法中实现)

registerForActivityResult必须在Activity生命周期的onStart之前调用,直接放在onCreate原有逻辑之后即可:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 保留原有onCreate逻辑,比如setContentView、WebView初始化等

    // 初始化文件选择/拍照启动器,处理返回结果
    fileChooserLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
        if (result.getResultCode() != RESULT_OK || mUMA == null) {
            // 用户取消操作,返回空值
            mUMA.onReceiveValue(null);
            mUMA = null;
            return;
        }
        Intent data = result.getData();
        Uri[] resultUris = null;
        // 处理拍照返回场景:data为空说明拍照成功,使用预先存储的文件路径
        if (data == null || data.getData() == null) {
            if (mCM != null) {
                resultUris = new Uri[]{Uri.parse(mCM)};
            }
        } else {
            // 处理文件选择返回场景
            String dataStr = data.getDataString();
            if (dataStr != null) {
                resultUris = new Uri[]{Uri.parse(dataStr)};
            }
            // 兼容多选场景(如果需要开启多选,可在文件选择Intent中加EXTRA_ALLOW_MULTIPLE参数)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                if (data.getClipData() != null) {
                    int count = data.getClipData().getItemCount();
                    resultUris = new Uri[count];
                    for (int i = 0; i < count; i++) {
                        resultUris[i] = data.getClipData().getItemAt(i).getUri();
                    }
                }
            }
        }
        mUMA.onReceiveValue(resultUris);
        mUMA = null;
    });
}

3. 修改原有onShowFileChooser方法

仅需要替换最后启动Activity的代码,同时补充高版本Uri适配逻辑:

//File manager
public boolean onShowFileChooser(
        WebView webView, ValueCallback<Uri[]> filePathCallback,
        FileChooserParams fileChooserParams) {
    if (mUMA != null) {
        mUMA.onReceiveValue(null);
    }
    mUMA = filePathCallback;
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(WebviewActivity.this.getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile();
            takePictureIntent.putExtra("PhotoPath", mCM);
        } catch (IOException ex) {
            Log.e(TAG, "Image file creation failed", ex);
        }
        if (photoFile != null) {
            mCM = "file:" + photoFile.getAbsolutePath();
            // 适配Android7.0+的Uri暴露限制,必须用FileProvider生成Uri
            Uri photoUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
                takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            } else {
                photoUri = Uri.fromFile(photoFile);
            }
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
        } else {
            takePictureIntent = null;
        }
    }
    Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
    contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
    contentSelectionIntent.setType("*/*");
    // 如需开启多选可放开下面注释
    // contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    Intent[] intentArray;
    if (takePictureIntent != null) {
        intentArray = new Intent[]{takePictureIntent};
    } else {
        intentArray = new Intent[0];
    }
    Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
    chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
    chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
    // 替换原有的startActivityForResult调用
    fileChooserLauncher.launch(chooserIntent);
    return true;
}

高版本兼容说明

  1. API24及以上适配:必须配置FileProvider否则会触发FileUriExposedException崩溃,需要在AndroidManifest.xml中添加如下配置:
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

同时在res/xml目录下新建file_paths.xml,路径和你createImageFile方法中存储图片的路径对应即可,示例:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="images" path="Pictures" />
</paths>
  1. API29及以上适配:当前逻辑已经适配分区存储规则,不需要额外申请存储权限即可正常运行。
  2. API30、31兼容性:完成上述改造后,文件选择、拍照上传功能在这两个版本系统上均可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:18:00