Android 6.0写入外部SD卡

时间:2016-08-17 05:58:00

标签: 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 (!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

5 个答案:

答案 0 :(得分:8)

经过长时间的努力,我找到了解决方案。在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());
            }

休息一切都将保持一致以获得许可和所有。

感谢那些帮助过我的人。

答案 1 :(得分:4)

从API 23+(6.0)开始,您需要申请读/写权限,即使它们已经在您的清单Requesting Permissions at Run Time中。

来自文档的

  

从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" />

答案 2 :(得分:0)

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

如果没有存储权限: 请检查您是否在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"/>

如果已关闭存储权限: 请检查您的运行时权限,也许您可​​以参考此代码

private void checkPermissions() {
    if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        return;
    }

    final List<String> permissionsList = new ArrayList<String>();
    permissionsList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    permissionsList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    permissionsList.add(Manifest.permission.WRITE_CALENDAR);
    permissionsList.add(Manifest.permission.READ_PHONE_STATE);

    int permissionCheckLocation = ContextCompat.checkSelfPermission(IntroductionActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION);
    int permissionCheckStorage = ContextCompat.checkSelfPermission(IntroductionActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int permissionCheckCalendar = ContextCompat.checkSelfPermission(IntroductionActivity.this, Manifest.permission.WRITE_CALENDAR);
    int permissionCheckPhoneState = ContextCompat.checkSelfPermission(IntroductionActivity.this, Manifest.permission.READ_PHONE_STATE);

    boolean locationPermission=permissionCheckLocation == PackageManager.PERMISSION_GRANTED?true:false;
    boolean storagePermission=permissionCheckStorage == PackageManager.PERMISSION_GRANTED?true:false;
    boolean calendarPermission=permissionCheckCalendar == PackageManager.PERMISSION_GRANTED?true:false;
    boolean phoneStatePermission=permissionCheckPhoneState == PackageManager.PERMISSION_GRANTED?true:false;


    boolean shouldShowLocationPermission=ActivityCompat.shouldShowRequestPermissionRationale(IntroductionActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION);
    boolean shouldShowStoragePermission=ActivityCompat.shouldShowRequestPermissionRationale(IntroductionActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    boolean shouldShowCalendarPermission=ActivityCompat.shouldShowRequestPermissionRationale(IntroductionActivity.this, Manifest.permission.WRITE_CALENDAR);
    boolean shouldShowPhoneStatePermission=ActivityCompat.shouldShowRequestPermissionRationale(IntroductionActivity.this, Manifest.permission.READ_PHONE_STATE);

    if (permissionCheckLocation == PackageManager.PERMISSION_GRANTED && permissionCheckStorage == PackageManager.PERMISSION_GRANTED
            && permissionCheckCalendar == PackageManager.PERMISSION_GRANTED && permissionCheckPhoneState == PackageManager.PERMISSION_GRANTED){
        return;
    }else if(((!locationPermission&&!shouldShowLocationPermission)||(!storagePermission&&!shouldShowStoragePermission)
            ||(!calendarPermission&&!shouldShowCalendarPermission)||(!phoneStatePermission&&!shouldShowPhoneStatePermission))&&appContext.localCheckPermission){
        showMessageOKCancel("You need to allow access these permissions",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
                        startActivityForResult(intent, 1);
                    }
                });
    }else{
        ActivityCompat.requestPermissions(IntroductionActivity.this, permissionsList.toArray(new String[permissionsList.size()]), 0);

    }
}

如果仍有问题,请尝试更改文件路径:

String fileName="mytest5.txt";
 File folder = new File(Environment.getExternalStorageDirectory().getPath() + "/com.gvm.externalstorage.externalstoragetest/");

    if (!folder.exists()) {
        try {
            folder.mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Default Save Path Creation Error:" + folder);
        }
    }

    File logFile = new File(folder, fileName);
    if (!logFile.exists()) {
        try {
            logFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Default Save Path Creation Error:" + logFile);

        }
    }

祝你好运。我希望这可以帮助你

答案 3 :(得分:0)

@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;
}

答案 4 :(得分:0)

经过大量研究后,我找到了ABSOLUTE SOLUTION。它工作。

public boolean checkStorage() {
    File[] fs = con.getExternalFilesDirs(null);
    if (fs.length == 2)
        return true;
    else
        return false;
}