How to copy image to an existing directory on sd card?

隐身守侯 提交于 2019-12-10 22:18:11

问题


I'm trying to copy an image file with this code:

InputStream fileInputStream = null;
OutputStream fileOutputStream = null;
String inPath = "/storage/emulated/0/Pictures/MyImage.jpg"; 
String outPath = "/storage/extSdCard/MyFolder/MyImage.jpg";
    try {
    verifyStoragePermissions(this);
    fileInputStream = new FileInputStream(new File(inPath));
    File outputFile = new File(outPath);
        if (!outputFile.exists()) {
            try {
                outPutFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    fileOutputStream = new FileOutputStream(outputFile);

    byte[] buffer = new byte[1024];
    int read;
    while ((read = fileInputStream.read(buffer)) != -1) {
        fileOutputStream.write(buffer, 0, read);
    }
    fileInputStream.close();
    fileInputStream = null;
    fileOutputStream.flush();
    fileOutputStream.close();
    fileOutputStream = null;

    } catch (Exception e) {
    Log.e("tag", e.getMessage());
    }

And this is the method for verifying storage permissions on sdk>=23

// 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
        );
    }
}

And result is this error which occurs before reaching the buffer line.

Unable to decode stream: java.io.FileNotFoundException: /storage/extSdCard/MyFolder/MyImage.jpg: open failed: ENOENT (No such file or directory)

I have MyFolder on sd card and gallery apps on my device copy images to this directory without any problem.

NOTE: permissions are granted in the manifest (in the correct place before application tag) and inside activity(for skd >=23) .

EDITS:

  1. Implemented suggestion of creating file before fileOutputStream (didn't help).

  2. Lowered the targetSdkVersion to overpass any possible problems related to permissions and still no success.

targetSdkVersion 22

  1. Creating File in this way:

    File outFile = new File("/storage/extSdCard", "MyFolder/MyImage.jpg");

    also made no result.

I'm testing it on android version 22.

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

回答1:


You need to create the file first, FileOutputStream will throw that exception if the file does not exist FileNotFoundException

File outputFile = new File(outPath);
file.createNewFile();
fileOutputStream = new FileOutputStream(outputFile);



回答2:


if you are using targetSdkVersion 23 (or higher) in your app gradle file, you need to explicitly request the permission (could be into the onCreate method of the Activity or a button listener method), like this...

private static final int CODE_WRITE_EXTERNAL = 10;
    if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    Log.d(TAG, "onCreate: " + "Show explanation");
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_WRITE_EXTERNAL );
                } else {
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_WRITE_EXTERNAL );
                }
            } else {
                Log.d(TAG, "onCreate: " + "Permission already granted!");
                //Call your method to save the file
            }

Then you need to implement the next callback method

@Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case CODE_WRITE_EXTERNAL : {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "onRequestPermissionsResult: Good to go!");
                    //Call your mehotd here
                } else {
                    Log.d(TAG, "onRequestPermissionsResult: Bad user");
                }
            }
        }
    }



回答3:


This is the way I used SAF to get the job done.

private void newcopyFile(File fileInput, String outputParentPath,
                    String mimeType, String newFileName) {

DocumentFile documentFileGoal = DocumentFile.fromTreeUri(this, treeUri);

String[] parts = outputParentPath.split("\\/");
for (int i = 3; i < parts.length; i++) { //ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "MyFolder"}
    if (documentFileGoal != null) {
        documentFileGoal = documentFileGoal.findFile(parts[i]);
    }
}
if (documentFileGoal == null) {
    Toast.makeText(MainActivity.this, "Directory not found", Toast.LENGTH_SHORT).show();
    return;
}

DocumentFile documentFileNewFile = documentFileGoal.createFile(mimeType, newFileName);

InputStream inputStream = null;
OutputStream outputStream = null;
try {
    outputStream = getContentResolver().openOutputStream(documentFileNewFile.getUri());
    inputStream = new FileInputStream(fileInput);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
try {
    if (outputStream != null) {
        byte[] buffer = new byte[1024];
        int read;
        if (inputStream != null) {
            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
        }
        if (inputStream != null) {
            inputStream.close();
        }
        inputStream = null;
        outputStream.flush();
        outputStream.close();
        outputStream = null;
    }
} catch (IOException e) {
    e.printStackTrace();
}
}


来源:https://stackoverflow.com/questions/38445467/how-to-copy-image-to-an-existing-directory-on-sd-card

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!