工程下载:https://download.csdn.net/download/LinZhonglong/14040361 AndoridStudio工程
https://download.csdn.net/download/LinZhonglong/14040316 Unity2018.4.0工程
说明:存储分外置和内置。内置存储指机身内存,如手机,平板内存等。当没有外置内存卡时,根路径为/storage/emulated/0 。比如我想读取Download目录里的文件,则/storage/emulated/0/Download/a.txt
不同品牌的SD卡存储路径也不同。比如三星Samsung SD卡里根路径是 /storage/0000-E33A
AndroidManifest.xml权限
//主要权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
//挂载SD卡(可不用)
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" />
Eclips代码示例
package com.pico.Integration;
import com.unity3d.player.UnityPlayer;
import android.R.string;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.support.v4.content.FileProvider;
import android.view.WindowManager;
import android.app.Service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class ThirdActivity {
public static String getStoragePath(boolean is_removale) {
StorageManager mStorageManager = (StorageManager) (UnityPlayer.currentActivity.getApplicationContext()).getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
Object result = getVolumeList.invoke(mStorageManager);
final int length = Array.getLength(result);
for (int i = 0; i < length; i++) {
Object storageVolumeElement = Array.get(result, i);
String path = (String) getPath.invoke(storageVolumeElement);
boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
if (is_removale == removable) {
return path;
}
}
} catch (Exception e) {
return e.getMessage();
}
return null;
}
}
UnityPlayer.currentActivity.getApplicationContext()是导入Unity版本对应的class.jar后可以调用的函数,等价于Context。也就是应用窗口。class.jar一般在你安装目录的D:\ProgramFile\Unity里
在Unity里调用
public void Test()
{
try
{
//我的包名是com.pico.Integration
//类是ThirdActivity.java 用来调用
AndroidJavaClass jc = new AndroidJavaClass("com.pico.Integration.ThirdActivity");
string s2 = jc.CallStatic<string>("getStoragePath",true);
//UI text打印输出路径
}
catch (System.Exception e)
{
}
}
测试:
在Samsung SD卡三星卡里打印出的结果是 /storage/0000-E33A
在其他SD卡(未知牌子)打印结果 /storage/B68B-66E5
工程目录
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pico.Integration"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="27" />
<!-- 增加权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ThirdActivity"
android:label="@string/app_name" >
</activity>
</application>
</manifest>
附带 Unity工程2018.1.9
链接:https://pan.baidu.com/s/140q68Fbwn8p3May3QSYpuQ
提取码:lfm1
根据安卓版本或设备机型可能无法获取SD卡路径,推荐使用反射的方式获取
/**
* 通过反射调用获取内置存储和外置sd卡根路径(通用)
*
* @param mContext 上下文
* @param is_removale 是否可移除,false返回内部存储路径,true返回外置SD卡路径
* @return
*/
public static String getStoragePath(Context mContext, boolean is_removale) {
String path = "";
//使用getSystemService(String)检索一个StorageManager用于访问系统存储功能。
StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
Object result = getVolumeList.invoke(mStorageManager);
for (int i = 0; i < Array.getLength(result); i++) {
Object storageVolumeElement = Array.get(result, i);
path = (String) getPath.invoke(storageVolumeElement);
boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
if (is_removale == removable) {
return path;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return path;
}