0

I have an issue in my application that I am not able to copy file to SD card in a particular folder. There is a error occurs in the process shown as "permission denied" even after setting the user permission in AndroidManifest.xml file

Button Click

copyBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    try{
                       String pp = dataModels.get(getAdapterPosition()).getName();
                    File sdCardRoot1 = Environment.getExternalStorageDirectory();
                    File src = new File(sdCardRoot1, "/.MoreData/closed/" +pp);
                    String[] ff = StorageUtil.getStorageDirectories(context);
                    File filess = new File(ff[1]);
                    File dir = new File(filess, "/" + "new folder/"+pp+".jpg");
                    Log.e("videoAdapter3", String.valueOf(dir));
                    new USBCopyFileTask(context).execute(src, dir);
                     }catch (Exception e){
                        Log.e("videoAdapter", e.getMessage());
                    }
                }
            });

StorageUtil.class

package com.example.xpertech_android.more_movies_app.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class StorageUtil {
    // Primary physical SD-CARD (not emulated)
    private static final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");

    // All Secondary SD-CARDs (all exclude primary) separated by File.pathSeparator, i.e: ":", ";"
    private static final String SECONDARY_STORAGES = System.getenv("SECONDARY_STORAGE");

    // Primary emulated SD-CARD
    private static final String EMULATED_STORAGE_TARGET = System.getenv("EMULATED_STORAGE_TARGET");

    // PhysicalPaths based on phone model
    @SuppressLint("SdCardPath")
    @SuppressWarnings("SpellCheckingInspection")
    private static final String[] KNOWN_PHYSICAL_PATHS = new String[]{
            "/storage/sdcard0",
            "/storage/sdcard1",                 //Motorola Xoom
            "/storage/extsdcard",               //Samsung SGS3
            "/storage/sdcard0/external_sdcard", //User request
            "/mnt/extsdcard",
            "/mnt/sdcard/external_sd",          //Samsung galaxy family
            "/mnt/sdcard/ext_sd",
            "/mnt/external_sd",

            "/mnt/media_rw/sdcard1",            //4.4.2 on CyanogenMod S3
            "/removable/microsd",               //Asus transformer prime
            "/mnt/emmc",
            "/storage/external_SD",             //LG
            "/storage/ext_sd",                  //HTC One Max
            "/storage/removable/sdcard1",       //Sony Xperia Z1
            "/data/sdext",
            "/data/sdext2",
            "/data/sdext3",
            "/data/sdext4",
            "/sdcard1",                         //Sony Xperia Z
            "/sdcard2",                         //HTC One M8s
            "/storage/microsd"                  //ASUS ZenFone 2
    };

    /**
     * Returns all available storages in the system (include emulated)
     * <p/>
     * Warning: Hack! Based on Android source code of version 4.3 (API 18)
     * Because there is no standard way to get it.
     *
     * @return paths to all available storages in the system (include emulated)
     */
    public static String[] getStorageDirectories(Context context) {
        // Final set of paths
        final Set<String> availableDirectoriesSet = new HashSet<>();

        if (!TextUtils.isEmpty(EMULATED_STORAGE_TARGET)) {
            // Device has an emulated storage
            availableDirectoriesSet.add(getEmulatedStorageTarget());
        } else {
            // Device doesn't have an emulated storage
            availableDirectoriesSet.addAll(getExternalStorage(context));
        }

        // Add all secondary storages
        Collections.addAll(availableDirectoriesSet, getAllSecondaryStorages());

        String[] storagesArray = new String[availableDirectoriesSet.size()];
        return availableDirectoriesSet.toArray(storagesArray);
    }

    private static Set<String> getExternalStorage(Context context) {
        final Set<String> availableDirectoriesSet = new HashSet<>();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // Solution of empty raw emulated storage for android version >= marshmallow
            // because the EXTERNAL_STORAGE become something like: "/Storage/A5F9-15F4",
            // so we can't access it directly
            File[] files = getExternalFilesDirs(context, null);
            for (File file : files) {
                if (file != null) {
                    String applicationSpecificAbsolutePath = file.getAbsolutePath();
                    String rootPath = applicationSpecificAbsolutePath.substring(
                            0,
                            applicationSpecificAbsolutePath.indexOf("Android/data")
                    );
                    availableDirectoriesSet.add(rootPath);
                }
            }
        } else {
            if (TextUtils.isEmpty(EXTERNAL_STORAGE)) {
                availableDirectoriesSet.addAll(getAvailablePhysicalPaths());
            } else {
                // Device has physical external storage; use plain paths.
                availableDirectoriesSet.add(EXTERNAL_STORAGE);
            }
        }
        return availableDirectoriesSet;
    }

    private static String getEmulatedStorageTarget() {
        String rawStorageId = "";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // External storage paths should have storageId in the last segment
            // i.e: "/storage/emulated/storageId" where storageId is 0, 1, 2, ...
            final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
            final String[] folders = path.split(File.separator);
            final String lastSegment = folders[folders.length - 1];
            if (!TextUtils.isEmpty(lastSegment) && TextUtils.isDigitsOnly(lastSegment)) {
                rawStorageId = lastSegment;
            }
        }

        if (TextUtils.isEmpty(rawStorageId)) {
            return EMULATED_STORAGE_TARGET;
        } else {
            return EMULATED_STORAGE_TARGET + File.separator + rawStorageId;
        }
    }

    private static String[] getAllSecondaryStorages() {
        if (!TextUtils.isEmpty(SECONDARY_STORAGES)) {
            // All Secondary SD-CARDs split into array
            return SECONDARY_STORAGES.split(File.pathSeparator);
        }
        return new String[0];
    }

    /**
     * Filter available physical paths from known physical paths
     *
     * @return List of available physical paths from current device
     */
    private static List<String> getAvailablePhysicalPaths() {
        List<String> availablePhysicalPaths = new ArrayList<>();
        for (String physicalPath : KNOWN_PHYSICAL_PATHS) {
            File file = new File(physicalPath);
            if (file.exists()) {
                availablePhysicalPaths.add(physicalPath);
            }
        }
        return availablePhysicalPaths;
    }
    
    private static File[] getExternalFilesDirs(Context context, String type) {
        if (Build.VERSION.SDK_INT >= 19) {
            return context.getExternalFilesDirs(type);
        } else {
            return new File[]{context.getExternalFilesDir(type)};
        }
    }

}

USBCopyFileTask

package com.example.xpertech_android.more_movies_app.util;

import android.app.Dialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ProgressBar;

import com.example.xpertech_android.more_movies_app.R;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import androidx.appcompat.widget.AppCompatTextView;
import androidx.constraintlayout.widget.ConstraintLayout;

public class USBCopyFileTask  extends AsyncTask<File, Integer, File> {

    Context context;
    Dialog dialog;
    AppCompatTextView textView;
    ProgressBar progressBar;
    ConstraintLayout layout;

    public USBCopyFileTask(Context context) {
        this.context = context;
    }

    @Override
    protected File doInBackground(File... files) {
        File source, destination;
        source = files[0];
        destination = files[1];
        publishProgress(50);    // update progress to 50%
        Log.e("videoAdapter", String.valueOf(files[1]));
        try {
            Log.e("videoAdapterUSB", "try");
            int progress;

            InputStream in = new FileInputStream(source);
            OutputStream out = new FileOutputStream(destination);
            // Transfer bytes from in to out
            final long expectedBytes = source.length(); // This is the number of bytes we expected to copy..
            long totalBytesCopied = 0; // This will track the total number of bytes we've copied
            byte[] buf = new byte[1024];
            int len = 0;

            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
                totalBytesCopied += len;
                progress = (int) Math.round(((double) totalBytesCopied / (double) expectedBytes) * 100);
                publishProgress(progress);
            }
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("videoAdapter", e.getMessage());
        }
        return null;
    }


    @Override
    protected void onPreExecute() {
       dialog = new Dialog(context);
       dialog.setContentView(R.layout.progresslayout);
       textView = dialog.findViewById(R.id.txtDownloadingMusic);
       progressBar = dialog.findViewById(R.id.progressBarMovie);
       layout = dialog.findViewById(R.id.progressLayoutnew);
       textView.setText("Coping");
       dialog.setCancelable(false);
       progressBar.setIndeterminate(false);
       progressBar.setMax(100);
       layout.setVisibility(View.VISIBLE);
       dialog.show();
        Window window = dialog.getWindow();
        window.setLayout(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);
        dialog.dismiss();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        progressBar.setProgress(values[0]);
    }
}

Logcat

2021-01-15 17:27:44.399 6833-7342/luck.materialdesign.tabsnavigator E/videoAdapter: /storage/0C69-1809/CAREER WOMAN PART TWO.@iQlSXRgI2JykcsBWtFMTJvkinR5fV_JdU6iQ--HVNCI=
    !1&204.jpg (Permission denied)

can anyone help me to resolve this issue ??

Mukesh Kumar
  • 133
  • 1
  • 2
  • 8
  • 1
    Does this answer your question? [Android M write to SD Card - Permission Denied](https://stackoverflow.com/questions/43066117/android-m-write-to-sd-card-permission-denied) – Riyaz Parasara Jan 15 '21 at 12:07
  • Yes. A removable micro sd card is not writable already since Kitkat. – blackapps Jan 15 '21 at 13:05

0 Answers0