作者:MK小绿_136 | 来源:互联网 | 2023-09-17 12:52
在安卓的开发中,有时候要用到大文件的存储,这个时候就不能存储在应用内部(data/data),只能借助外部存储。而外部存储又分为手机机身的存储空间(一级sd卡)和外置sd卡存储空间(二级sd卡)。
1.要存储首先是获得读写权限
<uses-permission android:name&#61;"android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />//操作文件<uses-permission android:name&#61;"android.permission.WRITE_EXTERNAL_STORAGE" />//向sd卡写入<uses-permission android:name&#61;"android.permission.READ_EXTERNAL_STORAGE" />//读取sd卡信息
2.接下来是获得外存储路径
我们一般会想到用Environment.getExternalStorageDirectory().getAbsolutePath(),但是由于国内手机系统各种定制&#xff0c;各个厂
商都做过了修改。
Environment.getExternalStorageDirectory().getAbsolutePath()的意思是获得外部存储的路径&#xff0c;各个厂商自己认为的外部存储可
能不一样&#xff0c;所以这个方法能调用到的路劲可能也有所差别。
怎么解决呢&#xff1f;安卓源代码里面有一个类专门管理外部存储&#xff0c;那就是StorageManager。调用storageManager.getStorageVolumes()
就能获得所有外置sd卡的挂载情况。但是这个方法要7.0或者以上才能调用。所以我们考虑使用反射。
public static ArrayList getAvaliableStorages(Context context) {ArrayList storagges &#61; new ArrayList<>();StorageManager storageManager &#61; (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);try {Class>[] paramClasses &#61; {};Method getVolumeList &#61; StorageManager.class.getMethod("getVolumeList", paramClasses);getVolumeList.setAccessible(true);Object[] params &#61; {};Object[] invokes &#61; (Object[]) getVolumeList.invoke(storageManager, params);if (invokes !&#61; null) {StorageInfo info &#61; null;for (int i &#61; 0; i length; i&#43;&#43;) {Object obj &#61; invokes[i];Method getPath &#61; obj.getClass().getMethod("getPath", new Class[0]);String path &#61; (String) getPath.invoke(obj, new Object[0]);info &#61; new StorageInfo(path);File file &#61; new File(info.path);if ((file.exists()) && (file.isDirectory()) && (file.canWrite())) {Method isRemovable &#61; obj.getClass().getMethod("isRemovable", new Class[0]);String state &#61; null;try {Method getVolumeState &#61; StorageManager.class.getMethod("getVolumeState", String.class);state &#61; (String) getVolumeState.invoke(storageManager, info.path);info.state &#61; state;} catch (Exception e) {e.printStackTrace();}if (info.isMounted()) {info.isRemoveable &#61; ((Boolean) isRemovable.invoke(obj, new Object[0])).booleanValue();storagges.add(info);}}}}} catch (NoSuchMethodException e1) {e1.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}storagges.trimToSize();return storagges;
}public class StorageInfo {public String path;public String state;public boolean isRemoveable;public StorageInfo(String path) {this.path &#61; path;}public boolean isMounted() {return "mounted".equals(state);}
}
这样便得到了所有的外置存储卡的信息。我的手机信息是
机身存储 /storage/emulated/0/1
外置sd卡 /storage/sdcard1/
3.文件写入
我们只要调用storageInfo.isRemoveable 可移除的就是二级存储卡&#xff0c;一般就是我们可拔插的sd卡。不可移除的就是机身存储。
调用storageInfo.isMounted()就可知道这个存储位置是否可用。
&#xff08;1&#xff09;机身存储位置的文件写入
这个没什么好讲&#xff0c;只要获得路径便可直接写入
&#xff08;2&#xff09;外置sd卡的文件写入
在4.4以前&#xff0c;外置sd卡也是可以直接写入的&#xff0c;但是在4.4以后Android开始有了多卡存储。于是拓展的sd卡&#xff0c;便没有了写入权限。
据说是为了安卓系统可以在应用卸载之后可以轻松的删掉本地文件。
但是&#xff0c;Android并不是禁止了sd卡所有的写入权限。在特定的目录下&#xff0c;我们还是可以执行写入操作的。那就是在sd卡的
Android/data/"&#43;context.getPackageName()&#43;"/files/ 路径下&#xff0c;允许用户写入文件。这就可以理解了&#xff0c;特定的sd卡目录在
应用卸载之后会被清除文件&#xff0c;而至于机身自带的存储空间要清除残留文件肯定是没问题的。这样就可以在一定程度上缓解安卓机
越用越卡的毛病了&#xff08;残留文件都被系统删除了&#xff09;。
所以&#xff0c;如果我们要在外置sd卡写入文件的话&#xff0c;只要写在这个路径下就可以了&#xff0c;我的是
/storage/sdcard1/Android/data/"&#43;context.getPackageName()&#43;"/files/
需要注意的是&#xff0c;在创建这个路径的时候要先调用context.getExternalFilesDir(null).getAbsolutePath(),一定要先调用这一句
否则文件不能写入&#xff0c;这句话大概就是创建固定路径。
context.getExternalFilesDir(null).getAbsolutePath();//要先执行此方法&#xff0c;创建sd卡目录,否则不能创建目录
String direction &#61; "/storage/sdcard1/Android/data/"&#43;context.getPackageName()&#43;"/files/ ";
File file &#61; new File(direction);
if (!file.exists()){file.mkdirs();}
大功告成&#xff01;