Search code examples
androidandroid-sdcardfileoutputstreamfile-copying

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


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

Solution

  • 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();
    }
    }