0

I am getting an error of No permission to write on external storage. Neither User nor android has permission to write on extenral storage. Please help. Below is my code.

    package com.saidev.instagramquotes;

import android.Manifest;
import android.app.DownloadManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import androidx.annotation.NonNull;
import androidx.core.content.PermissionChecker;
import androidx.recyclerview.widget.RecyclerView;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;

import java.io.File;
import java.util.List;

import static androidx.core.content.PermissionChecker.checkSelfPermission;
import static com.saidev.instagramquotes.MainActivity.loadingDialog;

public class VideosAdapter extends FirebaseRecyclerAdapter<VideoItem , VideosAdapter.myViewHolder> {

    ImageButton download;
    ImageButton share;

    /**
     * Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
     * {@link FirebaseRecyclerOptions} for configuration options.
     *
     * @param options
     */
    public VideosAdapter(@NonNull FirebaseRecyclerOptions<VideoItem> options) {
        super(options);
    }

    @Override
    protected void onBindViewHolder(@NonNull myViewHolder holder, int position, @NonNull VideoItem model) {
            holder.setdata(model);

            download.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                

File dir = new File("/storage/9016-4EF8/Photo Memory");
                if ( !(dir.exists())) if ( ! (dir.mkdirs())) {
                    Toast.makeText(v.getContext(), "Sorry, could not create directory:\n\n" + dir.getAbsolutePath(),Toast.LENGTH_SHORT).show();
                  return;

                }

                File file = new File( dir, model.videoTitle);

                    Toast.makeText(v.getContext(), "Downloading", Toast.LENGTH_SHORT).show();
                    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(model.videoUrl))
                            .setTitle(model.videoTitle)
                            .setDescription("Downloading")
                            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                            .setDestinationUri(Uri.fromFile(file))
                            .setAllowedOverMetered(true)
                            .setAllowedOverRoaming(true);

                    DownloadManager downloadManager = (DownloadManager) v.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
                    long downloadID = downloadManager.enqueue(request);
                }

   

                }
            });


    }

    @NonNull
    @Override
    public myViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_container_video, parent, false);

        download = view.findViewById(R.id.download);
        share = view.findViewById(R.id.vidshare);
        return new myViewHolder(view);
    }

    class myViewHolder extends RecyclerView.ViewHolder{

        VideoView videoView;
        TextView videoTitle;


        public myViewHolder(@NonNull View itemView) {
            super(itemView);
            videoView = itemView.findViewById(R.id.videoview);
            videoTitle = itemView.findViewById(R.id.textVideoTitle);


        }

        void setdata(VideoItem obj){
            videoView.setVideoPath(obj.videoUrl);
            videoTitle.setText(obj.videoTitle);
            videoView.setOnPreparedListener(mp -> {
                mp.start();

            });

            videoView.setOnCompletionListener(MediaPlayer::start);

        }
    }



}

I am trying to download video from url. And I am showing the videos through video view in recycler view. Please help me. I have used download Manager to download the video from url. And i want to save the downloaded video in the user's download folder

  • You should use File.exists() on the folder where you wanna download to before you start the download. Please add that code so we can check. – blackapps Sep 02 '20 at 15:03
  • File dir = new File("/storage/9016-4EF8/Photo Memory); if ( !(dir.exists()) if ( ! (dir.mkdirs()) { Toast.makeText(v.getContext(), "Sorry, could not create directory:\n\n" + dir.getAbsolutePath(), Toast.LENGTH_SHORT).show() return; } File file = new File( dir, model.videoTitle); – blackapps Sep 02 '20 at 16:23
  • Which exception told that message? Further you did not tell if the directory existed and or that it could not be created. Inform me. Your app can not write to that directory on a removable micro sd card. So how could your app? How could you? – blackapps Sep 02 '20 at 16:58
  • @blackapps I told you that i am getting the same problem of No permission to write to file:///storage/9016-4EF8. Directory is existing in my external storage. – Shivani Dixit Sep 02 '20 at 17:05
  • @blackapps can i download my video in internal storage?? – Shivani Dixit Sep 02 '20 at 17:05
  • `And i want to save the downloaded video in the user's download folder` ? Your path does not very much look like a path to a download folder is it? – blackapps Sep 02 '20 at 17:15
  • Facing this on android 10 only or lower versions too? I think this is specific to android 10. If yes, You need to use the FileProvider instead of Uris. This can be helpful https://stackoverflow.com/questions/60332565/android-10-file-provider-permission-denial-reading-android-support-v4-conte – Jaswant Singh Sep 02 '20 at 23:49
  • @JaswantSingh I am facing this problem in android 9. The phone which i use for testing has android 9 OS – Shivani Dixit Sep 03 '20 at 07:58

2 Answers2

1

I believe you are trying to access files in SD Card without URI permissions. Granting read and write permissions in runtime is not enough. Managing files in SD Card requires URI permission. SimpleStorage could help you solving the crash.

Accessing files with SimpleStorage is pretty straightforward:

DocumentFile folder = DocumentFileCompat.fromPath(context, "9016-4EF8", "Photo Memory");
if (folder != null) {
    // folder exists
}

You can create directory like this:

DocumentFile folder = DocumentFileCompat.mkdirs(context, "9016-4EF8", "Photo Memory");
if (file != null) {
    // folder exists or has been created previously
}

Please note that above methods wont work unless you have URI permissions. To grant it, just call SimpleStorage.requestStorageAccess().

Anggrayudi H
  • 14,977
  • 11
  • 54
  • 87
0

After some experimenting it was clear that DownloadManager will not download to root of external storage or removable micro sd card.

Not even to apps private directory on micro sd card.

But to Download folder on external root or sd card root is ok.

Change

/storage/9016-4EF8/Photo Memory

To

/storage/9016-4EF8/Download/PhotoMemory

and you will have success with:

request.setDestinationUri(Uri.fromFile(file));

And... you do not have to create the directory yourself.

Hmmm.. this very much offers the same as

request.setDestinationInExternalPublicDir(choice, fileName);

So why doing it with a file uri?

blackapps
  • 8,011
  • 2
  • 11
  • 25
  • Please adapt your code. You can remove the code i first proposed checking if the dir exists and creating it. Use a Download folder. – blackapps Sep 03 '20 at 08:54
  • My error has still not resolved. I am thinking that instead of downloading videos in internal storage, can we download the video on EXTERNAL STORAGE? If Yes, then what is the procedure of doing that?? – Shivani Dixit Sep 04 '20 at 12:27
  • All the paths i mentioned here are on external storage.On removable external storage. DownloadManager will not download to internal storage to begin with. – blackapps Sep 04 '20 at 12:34