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

因非核心功能申请全文件权限,App遭Google Play拒审求助

解决方案:用内部存储+FileProvider实现合规的拍照上传

核心思路

完全放弃外部存储权限(包括MANAGE_EXTERNAL_STORAGE),仅使用应用内部存储保存图片,配合FileProvider给相机授权访问,既满足拍照上传需求,又符合Google Play的权限审核规则。


步骤1:精简权限清单

修改AndroidManifest.xml,只保留必要权限,移除所有外部存储相关权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

<!-- 相机硬件特性,autofocus非必须则设为非强制 -->
<uses-feature
    android:name="android.hardware.camera"
    android:required="true" />
<uses-feature
    android:name="android.hardware.camera.autofocus"
    android:required="false" />

<!-- 保留FileProvider配置 -->
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.test.fileupload.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

file_paths.xml只需配置内部存储路径,示例:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="my_images/" />
</paths>

步骤2:拍照保存到内部存储的正确实现

生成内部存储的图片文件,通过FileProvider给相机授权,避免权限崩溃:

private const val REQUEST_CODE_TAKE_PHOTO = 100

fun takePhoto(context: Context) {
    // 创建内部存储的图片目录
    val storageDir = File(context.filesDir, "my_images")
    if (!storageDir.exists()) {
        storageDir.mkdirs()
    }
    // 生成唯一命名的图片文件
    val photoFile = File(storageDir, "${System.currentTimeMillis()}.jpg")
    // 通过FileProvider生成可共享的Uri
    val photoUri = FileProvider.getUriForFile(
        context,
        "com.test.fileupload.provider", // 与Manifest中authorities一致
        photoFile
    )
    // 启动相机Intent
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
    // 授予相机临时写入权限
    takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    // 适配Android 10+的权限授予方式
    context.packageManager.queryIntentActivities(takePictureIntent, 0).forEach {
        context.grantUriPermission(
            it.activityInfo.packageName,
            photoUri,
            Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        )
    }
    // 启动相机(Activity中用startActivityForResult,Fragment用registerForActivityResult)
    (context as Activity).startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PHOTO)
}

步骤3:直接用内部存储文件上传服务器

图片保存在内部存储,直接通过File对象读取上传,无需Uri转路径:

fun uploadImage(photoFile: File) {
    // 以OkHttp为例构建上传请求
    val requestBody = MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart(
            "image",
            photoFile.name,
            RequestBody.create(MediaType.parse("image/jpeg"), photoFile)
        )
        .build()
    val request = Request.Builder()
        .url("你的服务器上传接口")
        .post(requestBody)
        .build()
    // 执行上传请求(建议在子线程或协程中执行)
    OkHttpClient().newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            // 处理上传失败
        }
        override fun onResponse(call: Call, response: Response) {
            // 处理上传成功
        }
    })
}

关键说明

  • 之前用内部存储崩溃的原因:没有通过FileProvider给相机授权,导致相机无法写入你的App私有内部存储,添加FLAG_GRANT_WRITE_URI_PERMISSION和批量授权后即可解决。
  • 此方案完全符合Google Play的权限最小化要求,不需要任何外部存储权限,审核不会被拒。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:35:20