Android-FilePicker icon indicating copy to clipboard operation
Android-FilePicker copied to clipboard

Android11

Open marsalmonico opened this issue 3 years ago • 22 comments

Hi, so in Android 11 and above this library won't work? And what do we have to use to make it work? Or do you have any recommendation (library or something) to use also in Android 11?

marsalmonico avatar Nov 13 '20 07:11 marsalmonico

Limitation of Android filepicker has only to do with filepicker part of feature. Images and video picker will work as it is working currently.

It will not work when your targetsdkversion will become 30 (Android 11). It will work as long as your target sdk is 29 and you have added set the value of requestLegacyExternalStorage to true in your app's manifest file.

Google has put restrictions on Android 11 as you need to opt for scoped storage now i.e. you can only access data to your app specific directory or query for media such as images and videos only. More info here: https://developer.android.com/training/data-storage/manage-all-files#all-files-access-google-play

Only way to use default intent picker in the OS itself (https://developer.android.com/training/data-storage/shared/documents-files)

I have still not decided what to do with filepicker, when we have to update targetsdk to 30. But I am open to any ideas: Suggestion: It will open generic default system file picker when calling filepicker

DroidNinja avatar Nov 16 '20 18:11 DroidNinja

I am developing a sample app using a good library.

In ver 2.2.4, it worked successfully in SDK29. I heard that SDK30 failed in ver 2.2.5. However, in ver 2.2.5, SDK29 also had an issue of failure.

DevHyeon0312 avatar Nov 28 '20 10:11 DevHyeon0312

Hello, It's been long since this issue has remained open. You should use the default picker for doc till you find a good option. Thanks!

harshmandan avatar Jan 09 '21 18:01 harshmandan

Hi, Any update?

Geet2312 avatar Feb 22 '21 05:02 Geet2312

Check storage Permissions, In Android 11 storage permission changed add MANAGE_EXTERNAL_STORAGE permission in Manifest

in code check permission of manage storage it will work

Ankita057 avatar Mar 12 '21 08:03 Ankita057

Google will only accept your app if it falls in File Management category otherwise MANAGE_EXTERNAL_STORAGE is of no use.

sidrxd avatar Apr 02 '21 14:04 sidrxd

Limitation of Android filepicker has only to do with filepicker part of feature. Images and video picker will work as it is working currently.

It will not work when your targetsdkversion will become 30 (Android 11). It will work as long as your target sdk is 29 and you have added set the value of requestLegacyExternalStorage to true in your app's manifest file.

Google has put restrictions on Android 11 as you need to opt for scoped storage now i.e. you can only access data to your app specific directory or query for media such as images and videos only. More info here: https://developer.android.com/training/data-storage/manage-all-files#all-files-access-google-play

Only way to use default intent picker in the OS itself (https://developer.android.com/training/data-storage/shared/documents-files)

I have still not decided what to do with filepicker, when we have to update targetsdk to 30. But I am open to any ideas: Suggestion: It will open generic default system file picker when calling filepicker

I found solution for this problem: Step 1: modify AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage"/>
    <application
        android:requestLegacyExternalStorage="true"
        android:allowBackup="true"
        android:supportsRtl="true">

Step 2: modify droidninja.filepicker.FilePickerBuilder.java replace two functions

private void start(Activity context, int requestCode) private void start(Fragment fragment, int requestCode)

private void start(Activity context, int requestCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(context, FilePickerConst.PERMISSIONS_FILE_PICKER)
                    != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(context,
                        context.getResources().getString(R.string.permission_filepicker_rationale),
                        Toast.LENGTH_SHORT).show();
                return;
            }

            //Permission need when you select file
            if(requestCode == FilePickerConst.REQUEST_CODE_DOC) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || Environment.isExternalStorageManager()) {
                    //Toast.makeText(this, "We can access all files on external storage now", Toast.LENGTH_SHORT).show()
                } else {
                    Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                    context.startActivityForResult(intent, requestCode);
                    return;
                }
            }
        }

        PickerManager.getInstance()
                .setProviderAuthorities(
                        context.getApplicationContext().getPackageName() + ".droidninja.filepicker.provider");

        Intent intent = new Intent(context, FilePickerActivity.class);
        intent.putExtras(mPickerOptionsBundle);

        context.startActivityForResult(intent, requestCode);
    }
 private void start(Fragment fragment, int requestCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(fragment.getContext(),
                    FilePickerConst.PERMISSIONS_FILE_PICKER) != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(fragment.getContext(), fragment.getContext()
                        .getResources()
                        .getString(R.string.permission_filepicker_rationale), Toast.LENGTH_SHORT).show();
                return;
            }

            //Permission need when you select file
            if(requestCode == FilePickerConst.REQUEST_CODE_DOC) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || Environment.isExternalStorageManager()) {
                    //Toast.makeText(this, "We can access all files on external storage now", Toast.LENGTH_SHORT).show()
                } else {
                    Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                    fragment.startActivityForResult(intent, requestCode);
                    return;
                }
            }
        }

        PickerManager.getInstance()
                .setProviderAuthorities(fragment.getContext().getApplicationContext().getPackageName()
                        + ".droidninja.filepicker.provider");

        Intent intent = new Intent(fragment.getActivity(), FilePickerActivity.class);
        intent.putExtras(mPickerOptionsBundle);

        fragment.startActivityForResult(intent, requestCode);
    }

Step 3: run your application Thank you for your library, it is very useful for community !!! Mr. Phuong

vsoftphuong avatar Apr 07 '21 07:04 vsoftphuong

@vsoft-phuong https://github.com/DroidNinja/Android-FilePicker/issues/305#issuecomment-814671111 I am trying to implement this solution, Would you kindly explain about the PickerManager.getInstance() method. As of now there is no such method in the library. What is the use of this method? I could add this method manually in my code, but what should be the implementation of the .setProviderAuthorities() method inside the PickerManager. Could you help me with this.

Prashantjagwani avatar Apr 08 '21 08:04 Prashantjagwani

@vsoft-phuong PickerManager.getInstance() .setProviderAuthorities(fragment.getContext().getApplicationContext().getPackageName() + ".droidninja.filepicker.provider");

where is getInstance where to add setProviderAuthorities method

Can you help me in this plz ??

gurjeet734 avatar Apr 16 '21 13:04 gurjeet734

Please see java class below

On Fri, Apr 16, 2021 at 8:02 PM gurjeet734 @.***> wrote:

@vsoft-phuong https://github.com/vsoft-phuong PickerManager.getInstance()

.setProviderAuthorities(fragment.getContext().getApplicationContext().getPackageName()

  • ".droidninja.filepicker.provider");

where is getInstance where to add setProviderAuthorities method

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/DroidNinja/Android-FilePicker/issues/305#issuecomment-821158098, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIYDFDRDF6RI5XFQGJ2DF3TJAYO5ANCNFSM4TUH7D2A .

vsoftphuong avatar Apr 19 '21 06:04 vsoftphuong

PickerManager.java

`package droidninja.filepicker;

import java.util.ArrayList; import java.util.LinkedHashSet;

import droidninja.filepicker.models.BaseFile; import droidninja.filepicker.models.FileType; import droidninja.filepicker.models.sort.SortingTypes; import droidninja.filepicker.utils.Orientation;

/**

  • Created by droidNinja on 29/07/16. */ public class PickerManager { private static PickerManager ourInstance = new PickerManager(); private int maxCount = FilePickerConst.DEFAULT_MAX_COUNT; private boolean showImages = true; private int cameraDrawable = R.drawable.ic_camera; private SortingTypes sortingType = SortingTypes.none;

    public static PickerManager getInstance() { return ourInstance; }

    private ArrayList<String> mediaFiles; private ArrayList<String> docFiles;

    private LinkedHashSet<FileType> fileTypes;

    private int theme = R.style.LibAppTheme;

    private String title = null;

    private boolean showVideos;

    private boolean showGif;

    private boolean showSelectAll = false;

    private boolean docSupport = true;

    private boolean enableCamera = true;

    private Orientation orientation = Orientation.UNSPECIFIED;

    private boolean showFolderView = true;

    private String providerAuthorities;

    private PickerManager() { mediaFiles = new ArrayList<>(); docFiles = new ArrayList<>(); fileTypes = new LinkedHashSet<>(); }

    public void setMaxCount(int count) { reset(); this.maxCount = count; }

    public int getMaxCount() { return maxCount; }

    public int getCurrentCount() { return mediaFiles.size() + docFiles.size(); }

    public void add(String path, int type) { if (path != null && shouldAdd()) { if (!mediaFiles.contains(path) && type == FilePickerConst.FILE_TYPE_MEDIA) { mediaFiles.add(path); } else if (!docFiles.contains(path) && type == FilePickerConst.FILE_TYPE_DOCUMENT) { docFiles.add(path); } else { return; } } }

    public void add(ArrayList<String> paths, int type) { for (int index = 0; index < paths.size(); index++) { add(paths.get(index), type); } }

    public void remove(String path, int type) { if ((type == FilePickerConst.FILE_TYPE_MEDIA) && mediaFiles.contains(path)) { mediaFiles.remove(path); } else if (type == FilePickerConst.FILE_TYPE_DOCUMENT) { docFiles.remove(path); } }

    public boolean shouldAdd() { if (maxCount == -1) return true; return getCurrentCount() < maxCount; }

    public ArrayList<String> getSelectedPhotos() { return mediaFiles; }

    public ArrayList<String> getSelectedFiles() { return docFiles; }

    public ArrayList<String> getSelectedFilePaths(ArrayList<BaseFile> files) { ArrayList<String> paths = new ArrayList<>(); for (int index = 0; index < files.size(); index++) { paths.add(files.get(index).getPath()); } return paths; }

    public void reset() { docFiles.clear(); mediaFiles.clear(); fileTypes.clear(); maxCount = -1; }

    public void clearSelections() { mediaFiles.clear(); docFiles.clear(); }

    public void deleteMedia(ArrayList<String> paths) { mediaFiles.removeAll(paths); }

    public int getTheme() { return theme; }

    public void setTheme(int theme) { this.theme = theme; }

    public String getTitle() { return title; }

    public void setTitle(String title) { this.title = title; }

    public boolean showVideo() { return showVideos; }

    public void setShowVideos(boolean showVideos) { this.showVideos = showVideos; }

    public boolean showImages() { return showImages; }

    public void setShowImages(boolean showImages) { this.showImages = showImages; }

    public boolean isShowGif() { return showGif; }

    public void setShowGif(boolean showGif) { this.showGif = showGif; }

    public boolean isShowFolderView() { return showFolderView; }

    public void setShowFolderView(boolean showFolderView) { this.showFolderView = showFolderView; }

    public void addFileType(FileType fileType) { fileTypes.add(fileType); }

    public void addDocTypes() { String[] pdfs = {"pdf"}; fileTypes.add(new FileType(FilePickerConst.PDF, pdfs, R.drawable.icon_file_pdf));

     String[] docs = {"doc", "docx", "dot", "dotx"};
     fileTypes.add(new FileType(FilePickerConst.DOC, docs, R.drawable.icon_file_doc));
    
     String[] ppts = {"ppt", "pptx"};
     fileTypes.add(new FileType(FilePickerConst.PPT, ppts, R.drawable.icon_file_ppt));
    
     String[] xlss = {"xls", "xlsx"};
     fileTypes.add(new FileType(FilePickerConst.XLS, xlss, R.drawable.icon_file_xls));
    
     String[] txts = {"txt"};
     fileTypes.add(new FileType(FilePickerConst.TXT, txts, R.drawable.icon_file_unknown));
    

    }

    public ArrayList<FileType> getFileTypes() { return new ArrayList<>(fileTypes); }

    public boolean isDocSupport() { return docSupport; }

    public void setDocSupport(boolean docSupport) { this.docSupport = docSupport; }

    public boolean isEnableCamera() { return enableCamera; }

    public void setEnableCamera(boolean enableCamera) { this.enableCamera = enableCamera; }

    public Orientation getOrientation() { return orientation; }

    public void setOrientation(Orientation orientation) { this.orientation = orientation; }

    public String getProviderAuthorities() { return providerAuthorities; }

    public void setProviderAuthorities(String providerAuthorities) { this.providerAuthorities = providerAuthorities; }

    public void setCameraDrawable(int drawable) { this.cameraDrawable = drawable; }

    public int getCameraDrawable() { return cameraDrawable; }

    public boolean hasSelectAll() { return maxCount == -1 && showSelectAll; }

    public void enableSelectAll(boolean showSelectAll) { this.showSelectAll = showSelectAll; }

    public SortingTypes getSortingType() { return sortingType; }

    public void setSortingType(SortingTypes sortingType) { this.sortingType = sortingType; } } `

mrsinhloi avatar Apr 19 '21 06:04 mrsinhloi

hi all, I got the same issue on mine. I downloaded source code version 2.2.5 & run on Android 11, pickup photo, image, video, file worked fine, but take photo didn't. It showed "No Application exists for camera!". Please help me fix this issue as soon as possible. Thanks

vtuan070978 avatar Apr 29 '21 10:04 vtuan070978

please help me this issue https://github.com/DroidNinja/Android-FilePicker/issues/324

RageshAntony avatar Apr 29 '21 11:04 RageshAntony

Hello,

If we enable this permission (PACKAGE_NAME MANAGE_EXTERNAL_STORAGE) then app gets rejected on play store so is there any solution for this?

Thanks!

Aastha-dev avatar Jul 22 '21 07:07 Aastha-dev

Hello,

If we enable this permission (PACKAGE_NAME MANAGE_EXTERNAL_STORAGE) then app gets rejected on play store so is there any solution for this?

Thanks!

Yes, I download the source code & update very simple in that and it works well. Here is my update: I updated the function dispatchTakePictureIntent like this public Intent dispatchTakePictureIntent(Context context) throws IOException { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Ensure that there's a camera activity to handle the intent if (Build.VERSION.SDK_INT >= 29) { File newFile = createImageFile(); takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri photoURI = FileProvider.getUriForFile(context, PickerManager.getInstance().getProviderAuthorities(), newFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); return takePictureIntent; } else { if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) { // Create the File where the photo should go if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { File newFile = createImageFile(); takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri photoURI = FileProvider.getUriForFile(context, PickerManager.getInstance().getProviderAuthorities(), newFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); } else { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(createImageFile())); } return takePictureIntent; } } return null; }

Then build lib to .arr file

vtuan070978 avatar Jul 22 '21 10:07 vtuan070978

Hello, If we enable this permission (PACKAGE_NAME MANAGE_EXTERNAL_STORAGE) then app gets rejected on play store so is there any solution for this? Thanks!

Yes, I download the source code & update very simple in that and it works well. Here is my update: I updated the function dispatchTakePictureIntent like this public Intent dispatchTakePictureIntent(Context context) throws IOException { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Ensure that there's a camera activity to handle the intent if (Build.VERSION.SDK_INT >= 29) { File newFile = createImageFile(); takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri photoURI = FileProvider.getUriForFile(context, PickerManager.getInstance().getProviderAuthorities(), newFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); return takePictureIntent; } else { if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) { // Create the File where the photo should go if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { File newFile = createImageFile(); takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri photoURI = FileProvider.getUriForFile(context, PickerManager.getInstance().getProviderAuthorities(), newFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); } else { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(createImageFile())); } return takePictureIntent; } } return null; }

Then build lib to .arr file

but This possible for only media files but what about non media files like pdfs and text what i should do to access the non media files from internal storage

natvar97 avatar Aug 17 '21 06:08 natvar97

You need to use MANAGE_EXTERNAL_STORAGE permission for version 11 or later.

Add in Manifest: " <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> "

Please follow below code:

private String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; private String[] cameraPermissions = new String[]{Manifest.permission.CAMERA};

//region FOR CHECK PERMISSION private void checkPermission() { if (SDK_INT >= Build.VERSION_CODES.R) { if (Environment.isExternalStorageManager()) { //FOR CAMERA PERMISSION if (!hasPermissions(this, cameraPermissions)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { for (int a = 0; a < cameraPermissions.length; a++) { if (checkSelfPermission(cameraPermissions[a]) != PackageManager.PERMISSION_GRANTED) {

                        }
                    }
                    requestPermissions(cameraPermissions, Constant.orprREQUEST_PERMISSION);
                }
            } else {
                fetchMyCreation();
            }
        } else {
            try {
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                intent.addCategory("android.intent.category.DEFAULT");
                intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName())));
                startActivityForResult(intent, Constant.oarREQ_CODE_MANUAL_STORE_PERMISSION);
            } catch (Exception e) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                startActivityForResult(intent, Constant.oarREQ_CODE_MANUAL_STORE_PERMISSION);
            }
        }
    } else {
        if (!hasPermissions(this, permissions)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                for (int a = 0; a < permissions.length; a++) {
                    if (checkSelfPermission(permissions[a]) != PackageManager.PERMISSION_GRANTED) {

                    }
                }
                requestPermissions(permissions, Constant.orprREQUEST_PERMISSION);
            }
        } else {
            fetchMyCreation();
        }
    }
}
//endregion

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    boolean isPermissionGranted = true;
    if (requestCode == Constant.orprREQUEST_PERMISSION) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            for (int a = 0; a < permissions.length; a++) {
                if (checkSelfPermission(permissions[a]) != PackageManager.PERMISSION_GRANTED) {
                    isPermissionGranted = false;
                }
            }
            if (!isPermissionGranted) {
                requestPermissions(permissions, Constant.orprREQUEST_PERMISSION);
            } else {
                fetchMyCreation();
            }
        }
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == Constant.oarREQ_CODE_MANUAL_STORE_PERMISSION) {
        checkPermission();
    }
}

ajaysolwin avatar Aug 23 '21 12:08 ajaysolwin

Hi,

I want access of non media files only in Android Version 11 like pdf , doc, txt etc. Is there any solution found for this without using MANAGE_EXTERNAL_STORAGE permission where targetSdkVersion is 30.

Can anyone help me out with this?

Aastha-dev avatar Nov 17 '21 05:11 Aastha-dev

+1

gdoudeng avatar Jan 06 '22 01:01 gdoudeng

In Android 13, we might be getting much better looking photo picker with material UI soon. https://developer.android.com/about/versions/13/features/photopicker

DroidNinja avatar Feb 17 '22 08:02 DroidNinja

Check my repository, that may solve your issues

https://github.com/braver-tool/Android11FilePicker

braver-tool avatar Mar 23 '22 05:03 braver-tool

Storage access framework

JamzApps avatar Mar 23 '22 07:03 JamzApps