3

So I am trying to store a PDF file on the user's android device by creating a Folder and then storing it. I am using getExternalStorageDir() but this has been deprecated under API29. The problem is Andriod guidelines say to opt-out out of scoped storage I have to put this in Manifest File

<manifest xmlns:android="http://schemas.android.com/apk/res/android
....
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
<application  
    android:requestLegacyExternalStorage="true"
....
</application>

This is not working anymore. I can download on Devices with andriod M but Not able to in recent 9/10 devices.

public class FinalActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {

    private static final int WRITE_REQUEST_CODE = 300;
    private static final String TAG = MainActivity.class.getSimpleName();
    private String url;
    SessionManagement sessionManagement;
    String userID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_final);

        sessionManagement = new SessionManagement(this);
        HashMap<String, String> user = sessionManagement.getUserDetail();
        userID = user.get(sessionManagement.ID);

        TextView submit = findViewById(R.id.download);

        submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (EasyPermissions.hasPermissions(FinalActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    //Get the URL entered
                    url = F.url1 + userID + "/FPO.pdf";
                    new DownloadFile().execute(url.replaceAll(" ", "%20"));

                } else {
                    //If permission is not present request for the same.
                    EasyPermissions.requestPermissions(FinalActivity.this, "This app needs access to your file storage so that it can write files.", WRITE_REQUEST_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, FinalActivity.this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        //Download the file once permission is granted
        url = F.url1 + userID + "/FPO.pdf";
        new DownloadFile().execute(url.replaceAll(" ", "%20"));
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        Log.d(TAG, "Permission has been denied");
    }

    private class DownloadFile extends AsyncTask<String, String, String> {
        private ProgressDialog progressDialog;
        private String fileName;
        private String folder;
        private boolean isDownloaded;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            this.progressDialog = new ProgressDialog(FinalActivity.this);
            this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            this.progressDialog.setCancelable(false);
            this.progressDialog.show();
        }

        @Override
        protected String doInBackground(String... f_url) {
            int count;
            try {
                URL url = new URL(f_url[0]);
                URLConnection connection = url.openConnection();
                connection.connect();
                // getting file length
                int lengthOfFile = connection.getContentLength();


                // input stream to read file - with 8k buffer
                InputStream input = new BufferedInputStream(url.openStream(), 8192);

                String timestamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());

                //Extract file name from URL
                fileName = f_url[0].substring(f_url[0].lastIndexOf('/') + 1, f_url[0].length());

                //External directory path to save fileb n
                folder = Environment.getExternalStorageDirectory() + File.separator + "FPO/";

                //Create LSK folder if it does not exist
                File directory = new File(folder);

                if (!directory.exists()) {
                    directory.mkdirs();
                }

                // Output stream to write file
                OutputStream output = new FileOutputStream(folder + fileName.replaceAll("%20", " "));

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    // publishing the progress....
                    // After this onProgressUpdate will be called
                    publishProgress("" + (int) ((total * 100) / lengthOfFile));
                    Log.d(TAG, "Progress: " + (int) ((total * 100) / lengthOfFile));

                    // writing data to file
                    output.write(data, 0, count);
                }

                // flushing output
                output.flush();

                // closing streams
                output.close();
                input.close();
                return "Downloaded at: " + folder + fileName.replaceAll("%20", " ");

            } catch (Exception e) {
                Log.e("Error: ", e.getMessage());
                Log.i("error123", e.getMessage());
                return e.getMessage();

            }
            
            //           return "Something went wrong";
        }

        protected void onProgressUpdate(String... progress) {
            // setting progress percentage
            progressDialog.setProgress(Integer.parseInt(progress[0]));
        }

        @Override
        protected void onPostExecute(String message) {
            // dismiss the dialog after the file was downloaded
            this.progressDialog.dismiss();
            Intent intent = new Intent(FinalActivity.this, Welcome_screen1.class);
            startActivity(intent);
            // Display File path after downloading
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
        }
    }
}
Leo
  • 2,097
  • 21
  • 35
Neel Patel
  • 35
  • 2
  • 8

2 Answers2

0

"Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory()."

Check this;

https://stackoverflow.com/a/57116787/5924743

  • I Tried getExternalFilesDir() but it stores inside the app's internal folder. I wanted the file to be downloaded in the Downloads Folder of the User Device or Open the document as soon as the file is downloaded irrespective of location. – Neel Patel Jan 08 '21 at 09:28
  • did you try this; Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); – Recep_dagli Jan 08 '21 at 09:51
  • and dont forget add this in AndroidManifest.xml; – Recep_dagli Jan 08 '21 at 09:52
  • https://stackoverflow.com/a/61560931/5924743 and you can check this. – Recep_dagli Jan 08 '21 at 09:54
  • Didn't work I have both user permission in my manifest file and Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS): the problem is Android straight away gives me a Permission denied Access even though Permission is already granted by User. – Neel Patel Jan 08 '21 at 10:31
0

After a bit of analysis. Here is my suggestion

        //External directory path to save fileb n
        folder = Environment.getExternalStoragePublicDirectory("FPO")+File.separator;// Deprecated I know but it works 


        //Create LSK folder if it does not exist
        File file = new File(folder + fileName.replaceAll("%20"," "));// create file in particular path with name and extension

        if (!file.exists()) {
            file.createNewFile(); //creates file for writing
        }



        // Output stream to write file
        OutputStream output = new FileOutputStream(file);

First create a File before starting to write using OutputStream. Don't just create directory.

Hope helpful!

Udhaya
  • 335
  • 3
  • 12
  • Didn't Worked since getExternalStoragePublicDirectory is Deprecated. – Neel Patel Jan 08 '21 at 10:16
  • @NeelPatel Have you really tried it mate? Does it give any error? I'm using this method to download videos to the downloads folder by `Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/"+videoName+".mp4"` and it works fine in Samsung M21(API 29) . By the way, have you specified the file type? – Udhaya Jan 08 '21 at 10:30
  • Yes, I am able to download the file on devices running Andriod M but it gives me an EONOET or EACCESS (Permission denied or Folder doesn't exist) on Devices running android Q and P – Neel Patel Jan 08 '21 at 10:34
  • @NeelPatel As it says File doesn't exist, Once again I'm Quoting have you used `file.createNewFile()` while the file object is Created with path+filename+fileExtention? – Udhaya Jan 08 '21 at 10:47
  • Tried your edited answer. This was the response "E/Error:: No such file or directory" – Neel Patel Jan 11 '21 at 05:32
  • @NeelPatel Hey, mate sorry! I used `folder` two times in the edited answer as `new File(folder +folder + fileName.replaceAll("%20"," "));`.Have you changed before executing? If not check it now I have debugged it. Try it mate once again with the proper directory. Also Log `folder + fileName.replaceAll("%20"," ")` this and please post it in comment. – Udhaya Jan 11 '21 at 06:13