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

安卓Nougat中点击按钮截图分享遇权限拒绝问题求助

解决Android Nougat(7.0+)截图分享权限拒绝问题

你的问题核心是Android 7.0(API 24)引入的StrictMode安全政策:跨应用传递file://类型的URI会触发权限拒绝——这种方式会直接暴露应用私有文件给其他应用,违反了安卓沙箱机制。你之前申请的WRITE_EXTERNAL_STORAGE权限其实在这里完全没必要,因为你把截图存在了应用的私有缓存目录(getCacheDir()),真正需要调整的是用FileProvider生成安全的content://类型URI来共享文件。

下面是具体的修复步骤:


1. 在AndroidManifest.xml中注册FileProvider

在<application>标签内添加FileProvider的注册信息,注意authorities要使用你的应用包名+.fileprovider格式(避免和其他应用冲突):

<application ...>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.beaconites.gratuitycalculator.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
    ...
</application>

2. 创建文件路径配置文件

在res/xml目录下新建file_paths.xml文件(如果xml目录不存在就手动创建),配置允许共享的缓存目录:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 对应应用的私有缓存目录 -->
    <cache-path name="shared_cache" path="." />
</paths>

3. 修改分享方法中的URI生成逻辑

更新你的Share_result()方法,把Uri.fromFile(file)替换成FileProvider生成的安全URI,同时添加读取权限标记,确保接收方应用能正常访问文件:

public void Share_result() {
    String uniqueId = getTodaysDate() + "_" + getCurrentTime() + "_" + Math.random();
    Bitmap bitmap;
    View v = findViewById(R.id.snapview);
    mAdView.setVisibility(View.INVISIBLE);
    button.setVisibility(View.INVISIBLE);
    v.setDrawingCacheEnabled(true);
    bitmap = v.getDrawingCache();
    try {
        File file = new File(getApplicationContext().getCacheDir(), uniqueId + ".png");
        FileOutputStream fOut = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
        fOut.flush();
        fOut.close();
        file.setReadable(true, false);

        final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
        // 替换为FileProvider生成的content类型URI
        Uri contentUri = FileProvider.getUriForFile(
                this,
                "com.beaconites.gratuitycalculator.fileprovider", // 和Manifest中authorities保持一致
                file
        );
        intent.putExtra(Intent.EXTRA_STREAM, contentUri);
        // 添加权限标记,允许接收方读取该URI指向的文件
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        
        intent.putExtra(Intent.EXTRA_TEXT, "Let me recommend you this application.\n https://play.google.com/store/apps/details?id=com.beaconites.gratuitycalculator ");
        intent.putExtra(Intent.EXTRA_TITLE, "UAE Gratuity Calculator");
        intent.setType("image/*");
        startActivity(Intent.createChooser(intent, "choose one"));
        mAdView.setVisibility(View.VISIBLE);
        button.setVisibility(View.VISIBLE);
    } catch (Exception e) {
        e.printStackTrace();
    }
    v.setDrawingCacheEnabled(false);
}

4. 简化权限请求(可选)

因为你现在把文件存在应用私有缓存目录,完全不需要申请WRITE_EXTERNAL_STORAGE权限,所以可以直接删除checkAndRequestPermissions()相关的代码——这样还能减少用户授权的步骤,提升应用体验。


补充说明

在Android 7.0之前,系统允许跨应用传递file:// URI,但这种方式存在安全风险:其他应用可能通过这个URI随意访问甚至修改你的应用私有文件。Nougat之后的StrictMode强制要求用FileProvider来安全共享文件,通过content:// URI精准控制访问权限,只有你明确授权的应用才能读取对应文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:37:22