Android11
marsalmonico opened this issue · 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?
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 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.
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!
Hi,
Any update?
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
Google will only accept your app if it falls in File Management category otherwise MANAGE_EXTERNAL_STORAGE is of no use.
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
requestLegacyExternalStoragetotruein 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-playOnly 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
@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.
@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 ??
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;
}
}
`
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
please help me this issue #324
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!
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
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
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();
}
}
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?
+1
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
Check my repository, that may solve your issues
Storage access framework