Android 5.1.1在外置SD卡中创建文件夹
Android 4.4之后WRITE_MEDIA_STORAGE 权限仅提供给系统应用,不再授予第三方App,WRITE_EXTERNAL_STORAGE 权限,仅仅用于授权用户写 primary external storage,除了与自己包名相关的文件夹之外,应用程序不允许写secondary external storage devices;
举例来说,如果应用的包名是com.travis.example,那么外部存储上的Android/data/com.travis.example/文件夹就可随意访问,其他任何地方都不允许写,并且,存储在自己包名相关的文件夹的文件,当该应用被卸载时候也会随之被清除。
分以下三种情况:
只有外部存储的设备,这种设备一般是android4.0之前的,只有一个存储,不受这个规则限制,还是可以随便读写,但如果高于4.4系统,那么就只能写自己包名相关(上述规则)的文件夹了。
只有内部存储的设备,不受这个规则限制,但是建议在自己的包名相关的文件夹写数据。
既有内部存储又有外部存储需要遵守这个规定,不可以在外部存储乱写了,需要在自己的包名相关的文件夹写数据。
Google官网原话如此:
The WRITE_EXTERNAL_STORAGE permission must only grant write access to the primary external storage on a device. Apps must not be allowed to write to secondary external storage devices, except in their package-specific directories as allowed by synthesized permissions.Restricting writes in this way ensures the system can clean up fileswhen applications are uninstalled.
先给出创建后的效果日志:

具体的Log日志如下:
08-15 14:00:53.005 8458-8458/com.flash E/Logger: [ (SdCardUtil.java:98)#main ] 路径:/storage/emulated/0
08-15 14:00:53.006 8458-8458/com.flash E/Logger: [ (SdCardUtil.java:98)#main ] 路径:/storage/uicc0
08-15 14:00:53.006 8458-8458/com.flash E/Logger: [ (SdCardUtil.java:98)#main ] 路径:/storage/sdcard1
08-15 14:00:53.010 8458-8458/com.flash E/Logger: [ (MyApplication.java:39)#main ] 文件路径:/storage/sdcard1/Android/data/com.flash/cache/
08-15 14:00:53.524 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/photos/q
08-15 14:00:53.799 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/photos/u
08-15 14:00:53.956 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/photos/w
08-15 14:00:54.118 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/videos
08-15 14:00:54.230 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/apk
08-15 14:00:54.318 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/shanghai/w
08-15 14:00:54.577 8458-8577/com.flash E/Logger: [ (MainActivity.java:234)#Thread-2256 ] /storage/sdcard1/Android/data/com.flash/cache/images
很明显,属于第三种情况,存在外部存储,也存在内部存储的情况,因此在外置SD卡中创建文件夹的时候,需要按照Google官方给出的规则来创建,即为:外部路径 + Android + data + 包名 + cache / file + 需要创建的文件夹名称;
具体代码如下:
/**
* 获取外置SD卡路径
*/
public static List<String> getExtSDCardPathList() {
List<String> paths = new ArrayList<String>();
String extFileStatus = Environment.getExternalStorageState();
File extFile = Environment.getExternalStorageDirectory();
//首先判断一下外置SD卡的状态,处于挂载状态才能获取的到
if (extFileStatus.equals(Environment.MEDIA_MOUNTED) && extFile.exists() && extFile.isDirectory() && extFile.canWrite()) {
//外置SD卡的路径
paths.add(extFile.getAbsolutePath());
}
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("mount");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
int mountPathIndex = 1;
while ((line = br.readLine()) != null) {
// format of sdcard file system: vfat/fuse
if ((!line.contains("fat") && !line.contains("fuse") && !line
.contains("storage"))
|| line.contains("secure")
|| line.contains("asec")
|| line.contains("firmware")
|| line.contains("shell")
|| line.contains("obb")
|| line.contains("legacy") || line.contains("data")) {
continue;
}
String[] parts = line.split(" ");
int length = parts.length;
if (mountPathIndex >= length) {
continue;
}
String mountPath = parts[mountPathIndex];
if (!mountPath.contains("/") || mountPath.contains("data")
|| mountPath.contains("Data")) {
continue;
}
File mountRoot = new File(mountPath);
if (!mountRoot.exists() || !mountRoot.isDirectory()
|| !mountRoot.canWrite()) {
continue;
}
boolean equalsToPrimarySD = mountPath.equals(extFile
.getAbsolutePath());
if (equalsToPrimarySD) {
continue;
}
//扩展存储卡即TF卡或者SD卡路径
paths.add(mountPath);
}
} catch (IOException e) {
e.printStackTrace();
}
return paths;
} public static String getTFSDCardPath() {
List<String> list;
list = getExtSDCardPathList();
return list.get(list.size() - 1);
} /**
* 获取外置SD卡存储文件的绝对路径
* Android 4.4以后
* @param context
*/
public static String getExternalFileDir(Context context) {
StringBuilder sb = new StringBuilder();
File file = context.getExternalCacheDir(); //此句代码一定要,在内部存储空间创建对应的data目录,但不存储文件
if (file.exists()) {
sb.append(SdCardUtil.getTFSDCardPath().toString()).append("/Android/data/").append(context.getPackageName())
.append("/cache").append(File.separator).toString();
} else {
sb.append(SdCardUtil.getTFSDCardPath().toString()).append("/Android/data/").append(context.getPackageName())
.append("/cache").append(File.separator).toString();
}
return sb.toString();
}
友情提示:转载请注明出处,谢谢!
Android 5.1.1在外置SD卡中创建文件夹的更多相关文章
- 转-Android 之 使用File类在SD卡中读取数据文件
如果需要在程序中使用sdcard进行数据的存储,那么需要在AndroidMainfset.xml文件中 进行权限的配置: Java代码: <!-- 在sd中创建和删除文件的权限 --> ...
- 【记录】尝试用android-logging-log4j去实现log输出内容到sd卡中的文件的功能
[背景] 折腾: [记录]给Android中添加log日志输出到文件 期间,已经试了: [记录]尝试用android中microlog4android实现log输出到文件的功能 但是不好用. 然后就是 ...
- 与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件
[源码下载] 与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件 作者:w ...
- android获取内置和外置SD卡路径 - z
本文将介绍Android真机环境下如何获取内置和外置SD卡路径. 测试环境:三星Note3,其他手机待测试... 所需权限(AndroidManifest.xml文件里) <uses-permi ...
- android 往sd卡中写入文件
在调用前需要判断是否有写入权限 Environment类提供了比较丰富的方法 static File getDataDirectory() 获得android data的目录. static File ...
- Android扫描SD卡中的文件
当android的系统启动的时候,系统会自动扫描sdcard内的多媒体文件,并把获得的信息保存在一个系统数据库中,以后在其他程序中如果想要访问多媒体文件的信息,其实就是在这个数据库中进行的,而不是直接 ...
- Android加载SD卡目录,文件夹遍历,图片设置,设置文件对应打开方式等
此案例主要说的是Android使用GridView加载SD卡下所有目录,文件夹多层遍历,文件图标修改,设置文件对应打开方式等功能. 如图: 代码: public class GridViewFile ...
- Android从raw、assets、SD卡中获取资源文件内容
先顺带提一下,raw文件夹中的文件会和project一起经过编译,而assets里面的文件不会~~~ 另外,SD卡获取文件需要权限哦! //从res文件夹中的raw 文件夹中获取文件并读取数据 p ...
- 往SD卡中写文件的方法。
package com.lixu.writetosd; import java.io.File; import java.io.FileOutputStream; import java.io.IOE ...
随机推荐
- Perl初试
通过接口发送短信的socket小样: #!/usr/bin/perl -w # auth:lichmama@cnblogs.com # what:send message to phone # usa ...
- React 实践项目 (二)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一 ...
- IT小天博客APP版本
今天弄了一个博客的APP版本,感觉还不错,欢迎下载体验. 共 1 张图片 APP名称:[IT小天博客APP] APP版本:1.3 APP上线时间:2017-06-29 下载地址:点击下载
- Asp.net MVC-3-执行过程
本篇主要讲述MVC处理请求时创建Controller和执行Action的完整过程. 创建Controller 先查看MvcHandler中处理请求的方法BeginProcessRequest: pro ...
- Unreal Engine 4 Radiant UI 插件入门教程(二)
本篇章前提要求:在UE4上安装了Radiant UI插件.如果没有安装,请找其它教程(或者是笔者的其它的教程,目前正在写). 本教程的目的:探讨如何从网页元素中调用蓝图中的内容: 第一步: 写一个网页 ...
- 设备常用框架framework
framework名称 framework说明 framework文档 Accelerate.framework 包含加速数学和DSP函数 http://developer.apple.com/iph ...
- Servlet中 End event threw exception,错误404 的解决方法
End event threw exception SEVERE: End event threw exceptionjava.lang.reflect.InvocationTargetExce ...
- docker~通过vs2017的Dockerfile来生成镜像
回到目录 Dockerfile这个东西我们之前是介绍过,它方便,快捷,易用,而在vs2017中也对docker进行了支持,而生成docker image的方式就是有用Dockerfile为基础的,在添 ...
- 玲珑杯 Round #11 (1001 1004 1007)
比赛链接 直接贴代码.. #include<bits/stdc++.h> using namespace std; typedef long long LL; int main() { L ...
- 一些重要 Docker 命令的简单介绍
1. 拉取 Docker 镜像 由于容器是由 Docker 镜像构建的,首先我们需要拉取一个 docker 镜像来开始.我们可以从 Docker Registry Hub 获取所需的 docker 镜 ...