0

On /storage/emulated/0/Download directory, I'm not able to get read access of PDF file. How can I enable read access on it?

I'm using Android 13 Device, and android development in Kotlin.

Granted Read URI permission, but didn't get any luck.

M.Omer
  • 11
  • 4
  • Use `ACTION_OPEN_DOCUMENT` / `ActivityResultContracts.OpenDocument` and let the user choose the PDF to open. The user will have access to `Download/`. You can then use `ContentResolver` to work with the resulting `Uri`, such as using `openInputStream()`to get an `InputStream` on the content. – CommonsWare Aug 07 '23 at 10:57
  • I'm using ACTION_OPEN_DOCUMENT this, but not getting luck. The file is picked from download directory, but not able to get read access on it. I try to upload my pdf file through Retrofit post require, but due to read access permission, I'm not able to upload it! Can you share the example, how are you dealing Uri with ContentResolver? Thanks – M.Omer Aug 07 '23 at 11:28
  • "I try to upload my pdf file through Retrofit post require, but due to read access permission, I'm not able to upload it!" -- my guess is that you think that you are getting a `File`, and you are not. You do not need a `File` to upload via Retrofit. See [this SO answer](https://stackoverflow.com/a/56308643/115145), [this blog post](https://commonsware.com/blog/2020/07/05/multipart-upload-okttp-uri.html), and [this blog post](https://cketti.de/2020/05/23/content-uris-and-okhttp/) for more. – CommonsWare Aug 07 '23 at 12:39

1 Answers1

0

In this way you can get the URI of PDF

ActivityResultLauncher<String[]> filePickerLauncher= registerForActivityResult(new ActivityResultContracts.OpenDocument(),
                    result -> {
                        if (result != null) {
                           //DO SOMETHING WITH THE RESULT
                        }
                    });
Intent filePickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
filePickerIntent.addCategory(Intent.CATEGORY_OPENABLE);
filePickerLauncher.launch(new String[] {"application/pdf"});

Update 1 If you want to upload file through retrofit you can use MultipartBody.Part which is available in Retrofit

You can do it as follows:

private MultipartBody.Part createMultipartBody(File file) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        return MultipartBody.Part.createFormData(<Your key>, file.getName(), requestBody);

    }

API interface

   @Multipart
    @POST(<Your endpoint here>)
    Call<ResponseBody> yourMethod(@Part MultipartBody.Part file);

API calling:

Call<ResponseBody> apiCall = Client.getConverterClient().yourMethod(createMultipartBody(fileData));
        apiCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                try {
                    if (response.code() == 200){
                          //HANDLE YOUR REST OF THE CODE HERE
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                //HANDLE ERROR HERE
            }
        });

Update 2 To get file path by using URI you can use following snippet:

 public static String getFilePath(Uri uri, Context context) {
        Cursor returnCursor = context.getContentResolver().query(uri, null, null, null, null);

        if (returnCursor == null) {
            return null;
        }

        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        returnCursor.moveToFirst();
        String name = returnCursor.getString(nameIndex);
        File file = new File(context.getFilesDir(), name);

        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            FileOutputStream outputStream = new FileOutputStream(file);
            int read;
            int maxBufferSize = 1024 * 1024;
            int bytesAvailable = inputStream.available();

            int bufferSize = Math.min(bytesAvailable, maxBufferSize);
            byte[] buffers = new byte[bufferSize];
            while ((read = inputStream.read(buffers)) != -1) {
                outputStream.write(buffers, 0, read);
            }
            inputStream.close();
            outputStream.close();
            returnCursor.close();
        } catch (Exception e) {
            e.getLocalizedMessage();
        }
        return file.getPath();
    }