android 读写sd卡的权限设置

本文探讨了Android中SD卡权限的问题,介绍了如何通过正确配置manifest文件中的uses-permission标签来实现对SD卡的正常读写操作。
Android中,要模拟SD卡,要首先使用adb的mksdcard命令来建立SD卡的镜像,如何建立,大家上网查一下吧,应该很容易找到,这里不说这个问题.

    但是在应用程序执行起来以后,我们可以看到sdcard的执行权限很有问题.懂Linux的人都知道,这样的权限是无法在SD开中写入内容的,也就无法建立目录.Android中对sd卡的读写权限问题

    但是,我们在adb shell命令中,依然可以在sdcard中建立目录,写入文件.这倒是也是见鬼的事情.但是,如果你想把权限更改成777,命令行并不报错,再使用ls -l查看一下,权限依然没有改变过来.我们急中生智,使用su命令将自己变成root用户,在使用chmod 777 sdcard来改变权限,发现结果依然无效.

    网上多有介绍,在Android的manifest.xml文档中加入下面的声名:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>



    试验之后,大多数人发现依然无效.没有人再把问题叙述得更详细些,不知道是什么样的心态?我的一个弟兄终于找到了问题所在.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="byd.eagle"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".EagleBackup"
                  android:label="@string/app_name">
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="8" />
</manifest>

    注意一下uses-permission在manifest.xml中的位置,这是解决问题的关键。

    那么我们再来写个试验程序:

    public class TestMakePath extends Activity {
      
       @Override
        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        try
        {
             Log.v("EagleTag",".......hahhha");
             Log.v("EagleTag",Environment.getExternalStorageState());
             File tPath=new File("/mnt/sdcard/tmp1");
             if(tPath.canRead())
                 Log.v("EagleTag","very bad");
             if(tPath.canWrite())
                 Log.v("EagleTag","very good");
             File tPathSon=new File("/mnt/sdcard/tmp1/good");
         
           tPathSon.mkdirs();
         }
         catch(Exception e)
         {
             Log.v("EagleTag","file create error");
         }      
      }
   }
   这回真的没问题了.
<think> 首先,用户的问题是:“我想查找在Android 14系统中获取读写SD权限的方法 请问Android 14系统获取读写SD权限的方法”。用户指定了Android 14系统。 现在,我需要参考提供的站内引用来回答。这些引用讨论了Android不同版本中的SD读写权限设置。 回顾引用: - 引用[1]:提到了获取SD根目录的方法,但主要涉及基本操作。 - 引用[2]:展示了如何请求SD读写权限,包括处理高版本Android(如Android R及以上)时需要特殊处理。 - 引用[3]:是关于在manifest文件中添加权限的。 - 引用[4]:强调在Android 6.0及以上版本需要动态权限申请。 - 引用[5]:专门讨论了Android 13及以上版本的权限适配,包括Android 14的权限配置。 引用[5]是最相关的,因为它直接提到Android 13及以上版本,包括Android 14。用户的问题是针对Android 14的。 关键点从引用[5]: - 在AndroidManifest.xml中配置权限: - <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> - <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> - <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> 这些权限中,对于Android 14(SDK版本34),READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE在SDK版本大于32时不被推荐使用,而是引入了新的权限如READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO用于特定媒体访问。 在Android 10及以上,引入了Scoped Storage,改变了外部存储的访问方式。Android 13进一步细化,引入了媒体权限分组。Android 14继续这一趋势。 核心步骤: 1. **在AndroidManifest.xml中添加适当的权限。** 根据引用[5],对于Android 14: - 添加READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO权限,取决于应用需要访问的媒体类型。 - READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE在SDK版本<=32时使用,但通过android:maxSdkVersion="32"限制,表示在更高版本不应使用。 2. **动态权限请求。** 类似于Android 6.0及以上版本的需求,需要在运行时请求权限。引用[2]和[4]展示了如何请求权限。 例如,使用ActivityCompat.requestPermissions或新的权限请求API。 对于Android 14,如果是访问特定媒体,可能需要请求READ_MEDIA_*权限。 3. **处理更高版本的特定要求。** 在Android 11及以上,对于所有文件访问,可能需要请求MANAGE_EXTERNAL_STORAGE权限,但这仅适用于特定用例,如文件管理器App。常规App应使用媒体存储API。 从引用[2]中,如果是高版本,需要检查Environment.isExternalStorageManager(),并请求MANAGE_EXTERNAL_STORAGE。 但引用[5]没有提到这个,它专注于媒体权限。 结构化回答: - 解释Android权限系统演变:从静态权限到动态权限,再到Scoped Storage。 - 针对Android 14: - 在manifest中添加所需权限。 - 在代码中动态请求权限。 - 处理权限结果。 使用中文回答,因为系统指令要求中文。 生成相关问题:根据系统指令,需要在回答后生成相关问题。指令说:“生成相关问题”,并在示例中显示了“§§相关问题§§”。 所以,在回答末尾添加相关问题。 确保回答结构清晰,逐步解决问题。 参考用户上一次问题和我的回答:用户的问题是新的,没有之前的上下文,所以基于当前问题。 最终回答框架: 1. **引言**:简述Android 14中权限变更。 2. **步骤1**: 在AndroidManifest.xml中添加权限。 3. **步骤2**: 在运行时动态请求权限。 4. **步骤3**: 处理权限回调。 5. **代码示例**:提供简单代码片段。 6. **相关问题。** 添加引用标识:在引用的地方添加[^n]。 基于引用[5],添加[^5]。 </think> ### Android 14系统中获取读写SD权限的方法 在Android 14(API级别34)系统中,获取SD读写权限的方法比早期版本更严格,主要由于Google引入了Scoped Storage机制和细化的媒体权限分组。从Android 13开始,READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限SDK版本高于32时被废弃,取而代之的是针对特定媒体类型(如图片、视频、音频)的细粒度权限。以下是针对Android 14的完整实现步骤,基于参考站内引用和官方文档[^5]。 #### 步骤1: 在AndroidManifest.xml中添加权限 首先,在应用的 `AndroidManifest.xml` 文件中声明必要的权限Android 14要求使用新的媒体权限分组,而不是传统的存储权限。以下是推荐配置: ```xml <!-- 添加Android 14必需的媒体权限(根据应用需求选择) --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- 读取图片 --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- 读取视频 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- 读取音频 --> <!-- 向后兼容旧版本(SDK <= 32) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> ``` - **关键点**: - 对于Android 14,优先使用 `READ_MEDIA_IMAGES`、`READ_MEDIA_VIDEO` 或 `READ_MEDIA_AUDIO` 权限,具体取决于应用需要访问的媒体类型(如图库应用需包含所有)。 - `android:maxSdkVersion="32"` 确保在Android 12及以下版本仍使用旧权限,但在Android 13+自动失效[^5]。 - 如果应用需要写入文件而不仅仅是读取,上述权限通常足够(写入操作隐含在读取权限中)。但若需管理所有文件(如文件管理器),可能需要额外请求 `MANAGE_EXTERNAL_STORAGE` 权限(需Google Play特殊审核,不推荐常规App使用)。 #### 步骤2: 在运行时动态请求权限 Android 6.0及以上版本均需动态请求权限Android 14也不例外。在代码中,使用 `ActivityCompat.requestPermissions` 或新API请求权限。以下是核心Java/Kotlin代码示例: ```java // 在Activity中请求权限 public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_PERMISSION = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestStoragePermissions(); } private void requestStoragePermissions() { // 检查当前SDK版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13+ // Android 14需请求媒体权限 String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 14 permissions = new String[]{ Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_AUDIO }; } else { // Android 13 permissions = new String[]{Manifest.permission.READ_MEDIA_IMAGES}; // 根据需求调整 } ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_PERMISSION); } else { // Android 12及以下 String[] permissions = new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_PERMISSION); } } // 处理权限请求结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予,执行SD读写操作 Toast.makeText(this, "权限已授予", Toast.LENGTH_SHORT).show(); } else { // 权限被拒绝,提示用户或处理降级逻辑 Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show(); } } } } ``` - **关键点**: - 在Android 14(`Build.VERSION_CODES.UPSIDE_DOWN_CAKE`)中,使用 `READ_MEDIA_*` 权限分组请求[^5]。 - 动态请求权限必须在用户交互的上下文中触发(如按钮点击),否则可能被系统拒绝。 - 如果用户拒绝权限,可使用 `shouldShowRequestPermissionRationale()` 显示解释对话框,引导用户重新授权。 #### 步骤3: 验证SD访问和错误处理 权限授予后,执行SD读写操作时,需检查外部存储状态: ```java // 检查SD是否可用 public boolean isSDCardAvailable() { String state = Environment.getExternalStorageState(); return Environment.MEDIA_MOUNTED.equals(state); } // 获取SD根目录(示例) public File getSDCardRoot() { if (isSDCardAvailable()) { return Environment.getExternalStorageDirectory(); // 返回根目录路径 } return null; } ``` - **关键点**: - 调用 `Environment.getExternalStorageDirectory()` 需确保权限已授予,否则在Android 14会抛出 `SecurityException`。 - 对于写入操作,使用 `Context.getExternalFilesDir()` 或 `MediaStore` API更安全,避免直接路径访问(Scoped Storage限制)。 #### 注意事项 - **兼容性**:此方法向后兼容到Android 6.0。测试时确保目标设备为Android 14(SDK 34)。 - **权限范围**:READ_MEDIA_* 权限仅授予对特定媒体类型的访问,而非整个SD。如果需要全文件访问(如文件管理器),需请求 `MANAGE_EXTERNAL_STORAGE` 权限,但Google Play对此有严格限制[^2][^5]。 - **用户引导**:首次请求权限时,建议在UI中添加简短说明(如“请允许访问媒体文件以保存图片”),提高用户授权率。 通过以上步骤,您的应用可以在Android 14上正确处理SD读写权限。如果权限请求失败,用户可在系统设置中手动启用(设置 > 应用 > 您的应用 > 权限)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值