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

OnActivityResult传递结果失败:空指针异常技术求助

问题原因分析

从错误栈能直接定位核心问题:在new File(filePath)这一行触发了空指针异常,根源是filePath的值为null。

出现这个问题的具体原因有两个:

  • API版本限制:MediaStore.Images.Media.DATA字段在Android 10(API 29)及以上已被废弃,系统不再返回真实的本地文件路径,通过该字段查询得到的结果自然是null。
  • Uri类型问题:你选中图片返回的是content://类型的Uri(比如日志里的content://com.android.providers.media.documents/document/image:28362),这类Uri指向的是系统媒体库的文档条目,而非直接的文件路径,用MediaStore.Images.Media.DATA根本查询不到有效路径。
解决方案

不要再尝试通过MediaStore获取文件路径,而是直接通过ContentResolver打开Uri对应的输入流,将图片内容复制到应用私有目录下的临时文件,再用这个临时文件完成上传操作。

修改后的onActivityResult代码示例:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK && data != null) {
        Uri selectedImage = data.getData();
        if (selectedImage == null) return;

        File tempFile = null;
        try {
            // 获取图片MIME类型,用于设置临时文件后缀
            String mimeType = getContentResolver().getType(selectedImage);
            String fileSuffix = mimeType != null ? mimeType.split("/")[1] : "jpg";
            // 在应用私有缓存目录创建临时文件,无需额外权限
            tempFile = File.createTempFile("upload_temp", "." + fileSuffix, getCacheDir());

            // 将Uri对应的图片内容复制到临时文件
            InputStream inputStream = getContentResolver().openInputStream(selectedImage);
            FileOutputStream outputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[1024];
            int readLength;
            while ((readLength = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, readLength);
            }
            // 关闭流资源
            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        // 基于临时文件创建上传所需的RequestBody和Multipart部件
        RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), tempFile);
        // 获取图片原文件名,提升上传的友好性
        String originalFileName = getOriginalFileName(selectedImage);
        MultipartBody.Part body = MultipartBody.Part.createFormData(
            "banner", 
            originalFileName != null ? originalFileName : tempFile.getName(), 
            reqFile
        );
        RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "banner");

        // 发起上传请求
        retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body, name);
        req.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                // 上传完成后清理临时文件,避免占用存储空间
                if (tempFile != null && tempFile.exists()) {
                    tempFile.delete();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e("FFF", t.getMessage());
                t.printStackTrace();
                // 上传失败也清理临时文件
                if (tempFile != null && tempFile.exists()) {
                    tempFile.delete();
                }
            }
        });
    }
}

// 辅助方法:通过Uri获取图片原文件名
private String getOriginalFileName(Uri uri) {
    String fileName = null;
    if ("content".equals(uri.getScheme())) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {
                fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
    // 如果content类型查询不到,就用Uri的最后一段作为文件名
    if (fileName == null) {
        fileName = uri.getLastPathSegment();
    }
    return fileName;
}

额外注意事项:

  • 若你的应用需要适配Android 10以下版本,需要在Manifest中声明android.permission.READ_EXTERNAL_STORAGE权限,并在运行时申请;Android 10及以上使用Scoped Storage,无需额外权限即可访问媒体库文件。
  • 临时文件创建在应用私有缓存目录,不会暴露给其他应用,安全性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:41:03