Android 6.0写入外部SD卡

Android 6.0写入外部SD卡,android,android-6.0-marshmallow,android-permissions,Android,Android 6.0 Marshmallow,Android Permissions,我试着在Android 6.0上的外部SD卡上写东西,但我不能在上面写 我对stackoverflow进行了研究,发现了很多东西,但都不管用。这是我的密码 String extPath = System.getenv("SECONDARY_STORAGE") + "/Android/data/com.gvm.externalstorage.externalstoragetest/"; File file = new File(extPath,"myFiles"); if

我试着在Android 6.0上的外部SD卡上写东西,但我不能在上面写

我对stackoverflow进行了研究,发现了很多东西,但都不管用。这是我的密码

String extPath = System.getenv("SECONDARY_STORAGE") + "/Android/data/com.gvm.externalstorage.externalstoragetest/";
File file = new File(extPath,"myFiles");

            if (!file.exists()) {
                boolean dirResult = file.mkdirs();
                Log.e("Directory Exist", dirResult + " Directory created");
            } else {
                Log.e("Directory Exist", "Exist");
                Log.e("Direcotry Path",file.getAbsolutePath());
            }
            //String displayname = fileName.replace("%20", " ");
            File outputFile = new File(file, "mytest5.txt");
            outputFile.createNewFile();
此代码适用于Android 5.0,但不适用于Android 6.0

然后我也尝试了这个路径,这给了我权限错误,我已经为运行时权限设置了所有权限和托管代码

/mnt/media_rw/6AC9-083B

File write failed: java.io.IOException: open failed: EACCES (Permission denied)
如果有人能帮助我,这将是伟大的,因为我正在尝试这一点,因为过去3天

谢谢, Anvesh

从API 23+(6.0)您需要请求读/写权限,即使它们已经在您的清单(称为)中

来自文档

从Android 6.0(API级别23)开始,用户向 应用程序运行时,而不是安装应用程序时。这 这种方法简化了应用程序安装过程,因为用户不需要 安装或更新应用程序时需要授予权限。它也 让用户能够更好地控制应用程序的功能;例如 用户可以选择让摄像头应用程序访问摄像头,但不允许 到设备位置。用户可以随时撤销权限 时间,转到应用程序的设置屏幕

java

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}
AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

从API 23+(6.0)中,您需要请求读/写权限,即使这些权限已经存在于您的清单(称为)中

来自文档

从Android 6.0(API级别23)开始,用户向 应用程序运行时,而不是安装应用程序时。这 这种方法简化了应用程序安装过程,因为用户不需要 安装或更新应用程序时需要授予权限。它也 让用户能够更好地控制应用程序的功能;例如 用户可以选择让摄像头应用程序访问摄像头,但不允许 到设备位置。用户可以随时撤销权限 时间,转到应用程序的设置屏幕

java

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}
AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

我认为你应该首先检查你的应用程序权限,以确保你的存储权限已打开

如果没有存储权限: 请检查您是否在AndroidManifest中使用此权限

<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

致以最良好的祝愿。我希望这能帮助你

我认为你应该首先检查你的应用程序权限,以确保你的存储权限已打开

如果没有存储权限: 请检查您是否在AndroidManifest中使用此权限

<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

致以最良好的祝愿。我希望这能对你有所帮助。经过长期的努力,我找到了一个解决办法。在Android 6.0中,它不会始终使用以下命令为您提供SD卡路径:

System.getenv("SECONDARY_STORAGE") 
还是这个

Environment.getExternalStorageDirectory()
所以我用这个来检索外部SD卡路径

File[] fs = context.getExternalFilesDirs(null);
            String extPath = "";
            // at index 0 you have the internal storage and at index 1 the real external...
            if (fs != null && fs.length >= 2)
            {
                extPath = fs[1].getAbsolutePath();
                Log.e("SD Path",fs[1].getAbsolutePath());
            }
其余的一切将保持不变,以供许可和所有


感谢那些帮助我的人

经过长时间的努力,我想出了一个解决办法。在Android 6.0中,它不会始终使用以下命令为您提供SD卡路径:

System.getenv("SECONDARY_STORAGE") 
还是这个

Environment.getExternalStorageDirectory()
所以我用这个来检索外部SD卡路径

File[] fs = context.getExternalFilesDirs(null);
            String extPath = "";
            // at index 0 you have the internal storage and at index 1 the real external...
            if (fs != null && fs.length >= 2)
            {
                extPath = fs[1].getAbsolutePath();
                Log.e("SD Path",fs[1].getAbsolutePath());
            }
其余的一切将保持不变,以供许可和所有


感谢那些帮助我的人

@Anvesh我正在使用的另一种可靠方法:

/**
 * Get external storage path use reflect on android 6.0 device.
 * Source code:
 * https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/storage/StorageVolume.java
 *
 * @param removable the sdcard can remove or not, true means external sdcard, false means
 *                  internal sdcard.
 * @return path of sdcard we want
 */
public static String getStoragePath(boolean removable) {
    WinZipApplication application = WinZipApplication.getInstance();
    Context mContext = application.getApplicationContext();
    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);
        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 mRemovable = (Boolean) isRemovable.invoke(storageVolumeElement);
            if (removable == mRemovable) {
                return path;
            }
        }
    } catch (Exception e) {
        return null;
    }
    return null;
}
/**
*获取外部存储路径使用android 6.0设备上的反射。
*源代码:
* https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/storage/StorageVolume.java
*
*@param removable SD卡是否可以移除,true表示外部SD卡,false表示外部SD卡
*内部SD卡。
*@我们想要的SD卡的返回路径
*/
公共静态字符串getStoragePath(布尔可移动){
WinZipApplication application=WinZipApplication.getInstance();
Context mContext=application.getApplicationContext();
StorageManager mStorageManager=(StorageManager)mContext.getSystemService(Context.STORAGE\u服务);
类storageVolumeClazz=null;
试一试{
storageVolumeClazz=Class.forName(“android.os.storage.StorageVolume”);
方法getVolumeList=mStorageManager.getClass().getMethod(“getVolumeList”);
方法getPath=storageVolumeClazz.getMethod(“getPath”);
方法isRemovable=storageVolumeClazz.getMethod(“isRemovable”);
对象结果=getVolumeList.invoke(MSTorAgerManager);
最终整数长度=Array.getLength(结果);
for(int i=0;i
@Anvesh我正在使用的另一种可靠方法:

/**
 * Get external storage path use reflect on android 6.0 device.
 * Source code:
 * https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/storage/StorageVolume.java
 *
 * @param removable the sdcard can remove or not, true means external sdcard, false means
 *                  internal sdcard.
 * @return path of sdcard we want
 */
public static String getStoragePath(boolean removable) {
    WinZipApplication application = WinZipApplication.getInstance();
    Context mContext = application.getApplicationContext();
    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);
        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 mRemovable = (Boolean) isRemovable.invoke(storageVolumeElement);
            if (removable == mRemovable) {
                return path;
            }
        }
    } catch (Exception e) {
        return null;
    }
    return null;
}
/**
*获取外部存储路径使用android 6.0设备上的反射。
*源代码:
* https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/storage/StorageVolume.java
*
*@param removable SD卡是否可以移除,true表示外部SD卡,false表示外部SD卡
*内部SD卡。
*@我们想要的SD卡的返回路径
*/
公共静态字符串getStoragePath(布尔可移动){
WinZipApplication application=WinZipApplication.getInstance();
Context mContext=application.getApplicationContext();
StorageManager mStorageManager=(StorageManager)mContext.getSystemService(Context.STORAGE\u服务);
类storageVolumeClazz=null;
试一试{
storageVolumeClazz=Class.forName(“android.os.storage.StorageVolume”);
方法getVolumeList=mStorageManager.getClass().getMethod(“getVolumeList”);
方法getPath=storageVolumeClazz.getMethod(“getPath”);
方法isRemovable=storageVolumeClazz.getMethod(“isRemovable”);
对象结果=GetVolume