Android文件目录及文件访问权限等详解

说明

android 中获取目录的API有两种,一种是通过Environment获取,另一种就是通过Context获取。两者获取到的目录区别还是很大的。
通过Environment API获取的目录,不会包含应用的内部目录,也就是带应用包名的目录。
通过Context API获取的目录,绝对路径都会带有改应用的包名,app访问自己包名下的该类文件,不需要额外申请权限

在Android10及以上设备上,即便申请了存储权限,也会报permission Denied . 在manifest文件中,添加: android:requestLegacyExternalStorage= “true”

应用访问权限及范围

这里可以将文件归纳为三种:App共享文件、App独立文件、App专属文件
在这里插入图片描述

在app内创建文件演示

package com.shoneworn.dirmake;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class MainActivity extends AppCompatActivity {

    private TextView tvDir;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvDir = findViewById(R.id.tv_dir);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onResume() {
        super.onResume();
//        initDir();
        if (Utils.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && Utils.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            initDir();
            return;
        }
        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults == null || grantResults.length == 0) {
            return;
        }
        if (requestCode != 1000) {
            return;
        }
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
            initDir();
            return;
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void initDir() {
        StringBuffer sb = new StringBuffer();

        File externalStorageDirectory = Environment.getExternalStorageDirectory();
        sb.append("Environment externalStorageDirectory>>" + externalStorageDirectory.getAbsolutePath() + "\n");
        Log.e("cxx", "Environment externalStorageDirectory>>" + externalStorageDirectory.getAbsolutePath());
        makeFile(externalStorageDirectory, "env externalStorageDirectory");

        File dataDirectory = Environment.getDataDirectory();
        sb.append("Environment dataDirectory>>" + dataDirectory.getAbsolutePath() + "\n");
        Log.e("cxx", "Environment dataDirectory>>" + dataDirectory.getAbsolutePath());
        makeFile(dataDirectory, "env dataDirectory");

        File downloadCacheDirectory = Environment.getDownloadCacheDirectory();
        sb.append("Environment downloadCacheDirectory>>" + downloadCacheDirectory.getAbsolutePath() + "\n");
        Log.e("cxx", "Environment downloadCacheDirectory>>" + downloadCacheDirectory.getAbsolutePath());
        makeFile(downloadCacheDirectory, "env downloadCacheDirectory");

        File rootDirectory = Environment.getRootDirectory();
        sb.append("Environment rootDirectory>>" + rootDirectory.getAbsolutePath() + "\n");
        Log.e("cxx", "Environment rootDirectory>>" + rootDirectory.getAbsolutePath());
        makeFile(rootDirectory, "env rootDirectory");

        File externalStoragePublicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
        sb.append("Environment externalStoragePublicDirectory>>" + externalStoragePublicDirectory.getAbsolutePath() + "\n");
        Log.e("cxx", "Environment externalStoragePublicDirectory>>" + externalStoragePublicDirectory.getAbsolutePath());
        makeFile(externalStoragePublicDirectory, "env externalStoragePublicDirectory");

        Context context = this;
        File externalFilesDir = context.getExternalFilesDir(null);
        sb.append("Context externalFilesDir>>" + externalFilesDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context externalFilesDir>>" + externalFilesDir.getAbsolutePath());
        makeFile(externalFilesDir, "externalFilesDir");


        File externalCacheDir = context.getExternalCacheDir();
        sb.append("Context externalCacheDir>>" + externalCacheDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context externalCacheDir>>" + externalCacheDir.getAbsolutePath());
        makeFile(externalCacheDir, "externalCacheDir");

        File[] externalCacheDirs = context.getExternalCacheDirs();
        sb.append("Context externalCacheDirs>>");
        for (File file : externalCacheDirs) {
            sb.append(file.getAbsolutePath() + "  ");
            Log.e("cxx", "Context externalCacheDirs>>" + file.getAbsolutePath());
        }
        sb.append("\n");

        File filesDir = context.getFilesDir();
        sb.append("Context filesDir>>" + filesDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context filesDir>>" + filesDir.getAbsolutePath());
        makeFile(filesDir, "filesDir");


        File cacheDir = context.getCacheDir();
        sb.append("Context cacheDir>>" + cacheDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context cacheDir>>" + cacheDir.getAbsolutePath());
        makeFile(cacheDir, "cacheDir");

        File codeCacheDir = context.getCodeCacheDir();
        sb.append("Context codeCacheDir>>" + codeCacheDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context codeCacheDir>>" + codeCacheDir.getAbsolutePath());
        makeFile(codeCacheDir, "codeCacheDir");

        File noBackupFilesDir = context.getNoBackupFilesDir();
        sb.append("Context noBackupFilesDir>>" + noBackupFilesDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context noBackupFilesDir>>" + noBackupFilesDir.getAbsolutePath());
        makeFile(noBackupFilesDir, "noBackupFilesDir");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            File dataDir = context.getDataDir();
            sb.append("Context dataDir>>" + dataDir.getAbsolutePath() + "\n");
            Log.e("cxx", "Context dataDir>>" + dataDir.getAbsolutePath());
            makeFile(dataDir, "dataDir");
        }



        File[] externalMediaDirs = context.getExternalMediaDirs();
        sb.append("Context externalMediaDirs>>");
        for (File file : externalMediaDirs) {
            sb.append(file.getAbsolutePath() + "  ");
            Log.e("cxx", "Context externalMediaDirs>>" + file.getAbsolutePath());
        }
        sb.append("\n");

        File obbDir = context.getObbDir();
        sb.append("Context obbDir>>" + obbDir.getAbsolutePath() + "\n");
        Log.e("cxx", "Context obbDir>>" + obbDir.getAbsolutePath());
        makeFile(obbDir, "obbDir");

        String s = sb.toString();
        tvDir.setText(s);
    }

	//向各个目录下写入文件
    private void makeFile(File dir, String name) {
        if (dir == null || !dir.exists()) {
            return;
        }
        try {
            File file = new File(dir, "cxx.txt");
            if (!file.exists()) {
                file.createNewFile();
            }
            OutputStreamWriter out = new OutputStreamWriter(
                    new FileOutputStream(file, false), // true to append
                    "UTF-8"
            );
            out.write(getPackageName() + "  name:" + name + "  dir>>" + dir.getAbsolutePath());
            out.close();
        } catch (Exception e) {
            Log.e("cxx", e.getMessage());
        }
    }

}

看下输出:

E/cxx: Environment externalStorageDirectory>>/storage/emulated/0
E/cxx: Environment dataDirectory>>/data
E/cxx: Permission denied
E/cxx: Environment downloadCacheDirectory>>/data/cache
E/cxx: Permission denied
E/cxx: Environment rootDirectory>>/system
E/cxx: Read-only file system
E/cxx: Environment externalStoragePublicDirectory>>/storage/emulated/0/DCIM

//从这里开始,均由context获取的目录,访问不需要申请应用权限,随app卸载而删除
//系统分区下的app私有目录
E/cxx: Context externalFilesDir>>/storage/emulated/0/Android/data/com.shoneworn.dirmake/files
E/cxx: Context externalCacheDir>>/storage/emulated/0/Android/data/com.shoneworn.dirmake/cache
E/cxx: Context externalCacheDirs>>/storage/emulated/0/Android/data/com.shoneworn.dirmake/cache
E/cxx: Context externalMediaDirs>>/storage/emulated/0/Android/media/com.shoneworn.dirmake
E/cxx: Context obbDir>>/storage/emulated/0/Android/obb/com.shoneworn.dirmake

//sdcard下应用独有目录 
E/cxx: Context filesDir>>/data/user/0/com.shoneworn.dirmake/files
E/cxx: Context cacheDir>>/data/user/0/com.shoneworn.dirmake/cache
E/cxx: Context codeCacheDir>>/data/user/0/com.shoneworn.dirmake/code_cache
E/cxx: Context noBackupFilesDir>>/data/user/0/com.shoneworn.dirmake/no_backup
E/cxx: Context dataDir>>/data/user/0/com.shoneworn.dirmake

可以看到有两个目录下创建文件被拒了。应用想要向这两个目录下创建文件,需要root权限。

在其他app内访问上面的app创建的文件

package com.shoneworn.readfile;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.Buffer;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_ext_cache).setOnClickListener(this);
        findViewById(R.id.btn_ext_file).setOnClickListener(this);
        findViewById(R.id.btn_file_dir).setOnClickListener(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onResume() {
        super.onResume();
        if (Utils.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) && Utils.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            return;
        }
        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults == null || grantResults.length == 0) {
            return;
        }
        if (requestCode != 1000) {
            return;
        }
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
            return;
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_ext_file:
                readFile("/storage/emulated/0/Android/data/com.shoneworn.dirmake/files");
                break;
            case R.id.btn_file_dir:
                readFile("/data/user/0/com.shoneworn.dirmake/files");
                break;
            case R.id.btn_ext_cache:
                readFile("/storage/emulated/0/Android/data/com.shoneworn.dirmake/cache");
                break;
        }
    }

    private void readFile(String path) {
        File file = new File(path + File.separator + "cxx.txt");
        if (!file.exists()) {
            Log.e("cxx", "read " + file.getAbsolutePath() + " not exists");
            return;
        }
        try {
            StringBuilder sb = new StringBuilder();
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len = fileInputStream.read(buffer);
            while (len > 0) {
                sb.append(new String(buffer, 0, len));
                len = fileInputStream.read(buffer);
            }
            fileInputStream.close();
            String s = sb.toString();
            Log.e("cxx", path + " content:" + s);
        } catch (Exception e) {
            Log.e("cxx", e.getMessage());
        }
    }
}

看看日志:

 E/cxx: /storage/emulated/0/Android/data/com.shoneworn.dirmake/files content:com.shoneworn.dirmake  name:externalFilesDir  dir>>/storage/emulated/0/Android/data/com.shoneworn.dirmake/files
 E/cxx: read /data/user/0/com.shoneworn.dirmake/files/cxx.txt not exists
 E/cxx: /storage/emulated/0/Android/data/com.shoneworn.dirmake/cache content:com.shoneworn.dirmake  name:externalCacheDir  dir>>/storage/emulated/0/Android/data/com.shoneworn.dirmake/cache

这里只演示了访问其他应用app独立文件和其他应用app专属文件的情况。
访问其他应用app专属文件时直接文件不存在。

Demo下载地址
https://download.csdn.net/download/shoneworn/14046663

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值