Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android11 #305

Open
marsalmonico opened this issue Nov 13, 2020 · 22 comments
Open

Android11 #305

marsalmonico opened this issue Nov 13, 2020 · 22 comments

Comments

@marsalmonico
Copy link

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?

@DroidNinja
Copy link
Owner

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

@DevHyeon0312
Copy link

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.

@harshmandan
Copy link

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!

@Geet2312
Copy link

Hi,
Any update?

@Ankita057
Copy link

Ankita057 commented Mar 12, 2021

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

@sidrxd
Copy link

sidrxd commented Apr 2, 2021

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

@vsoftphuong
Copy link

vsoftphuong commented Apr 7, 2021

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

@Prashantjagwani
Copy link

@vsoft-phuong
#305 (comment)
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.

@gurjeet734
Copy link

gurjeet734 commented Apr 16, 2021

@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 ??

@vsoftphuong
Copy link

vsoftphuong commented Apr 19, 2021 via email

@mrsinhloi
Copy link

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 mediaFiles;
    private ArrayList docFiles;

    private LinkedHashSet 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 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 getSelectedPhotos() {
    return mediaFiles;
    }

    public ArrayList getSelectedFiles() {
    return docFiles;
    }

    public ArrayList getSelectedFilePaths(ArrayList files) {
    ArrayList 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 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 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;
    }
    }
    `

@vtuan070978
Copy link

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

@RageshAntony
Copy link

please help me this issue #324

@Aastha-dev
Copy link

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!

@vtuan070978
Copy link

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

@natvar97
Copy link

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

@ajaysolwin
Copy link

ajaysolwin commented Aug 23, 2021

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

Add in Manifest:
"

"

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();
    }
}

@Aastha-dev
Copy link

Aastha-dev commented Nov 17, 2021

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?

@gdoudeng
Copy link

gdoudeng commented Jan 6, 2022

+1

@DroidNinja
Copy link
Owner

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

@braver-tool
Copy link

Check my repository, that may solve your issues

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

@JamzApps
Copy link

Storage access framework

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests