Skip to content

Commit

Permalink
Added support for Android 13
Browse files Browse the repository at this point in the history
  • Loading branch information
TutorialsAndroid committed Sep 5, 2023
1 parent 5002b8a commit f7acf91
Show file tree
Hide file tree
Showing 10 changed files with 292 additions and 68 deletions.
20 changes: 18 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Add it in your root build.gradle at the end of repositories:
Step 2. Add the dependency

dependencies {
implementation 'com.github.TutorialsAndroid:FilePicker:v8.0.19'
implementation 'com.github.TutorialsAndroid:FilePicker:v9.0.0'
}

### Usage
Expand Down Expand Up @@ -84,7 +84,7 @@ Step 2. Add the dependency
3. Next create an instance of `FilePickerDialog`, and pass `Context` and `DialogProperties` references as parameters. Optional: You can change the title of dialog. Default is current directory name. Set the positive button string. Default is Select. Set the negative button string. Defalut is Cancel.

```java
FilePickerDialog dialog = new FilePickerDialog(MainActivity.this,properties);
FilePickerDialog dialog = new FilePickerDialog(MainActivity.this, MainActivity.this,properties);
dialog.setTitle("Select a File");
```

Expand Down Expand Up @@ -125,6 +125,22 @@ Marshmallow and above requests for the permission on runtime. You should overrid
}
```

### Android13 and Above Instructions:
If your app targets Android 13 or higher and needs to access media files that other apps have created, you must request one or more of the following granular media permissions instead of the ```READ_EXTERNAL_STORAGE permission```:
As of Android 13 and above you can only browse and select Images,Videos and Audio files only. This library is still in development and I'm looking for contributors to make this library more better
```
Type of media | Permission to request
Images and photos | READ_MEDIA_IMAGES
Videos | READ_MEDIA_VIDEO
Audio files | READ_MEDIA_AUDIO
```
Before you access another app's media files, verify that the user has granted the appropriate granular media permissions to your app.

If you request both the ```READ_MEDIA_IMAGES``` permission and the ```READ_MEDIA_VIDEO``` permission at the same time, only one system permission dialog appears.

If your app was previously granted the ```READ_EXTERNAL_STORAGE``` permission, then any requested ```READ_MEDIA_*``` permissions are granted automatically when upgrading.

That's It. You are good to proceed further.


Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath 'com.android.tools.build:gradle:8.1.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'

// NOTE: Do not place your application dependencies here; they belong
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
9 changes: 4 additions & 5 deletions library/build.gradle
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
apply plugin: 'com.android.library'

//apply plugin: 'com.github.dcendents.android-maven'
group='com.github.TutorialsAndroid'

android {
compileSdkVersion 31
compileSdk 34

defaultConfig {
minSdkVersion 19
targetSdkVersion 31
targetSdkVersion 34
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
namespace 'com.developer.filepicker'
lint {
abortOnError false
}
}
13 changes: 9 additions & 4 deletions library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.developer.filepicker">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<!-- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>-->
</manifest>
22 changes: 22 additions & 0 deletions library/src/main/java/com/developer/filepicker/utils/Utility.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.developer.filepicker.utils;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;

import com.developer.filepicker.model.FileListItem;

Expand All @@ -15,6 +18,8 @@
*/
public class Utility {

private static final int REQUEST_MEDIA_PERMISSIONS = 456;

public static boolean checkStorageAccessPermissions(Context context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
String permission = "android.permission.READ_EXTERNAL_STORAGE";
Expand All @@ -26,6 +31,23 @@ public static boolean checkStorageAccessPermissions(Context context) {
}
}

@android.annotation.TargetApi(Build.VERSION_CODES.TIRAMISU)
public static boolean checkMediaAccessPermissions(Context context) {//, Activity activity) {
String audioPermission = Manifest.permission.READ_MEDIA_AUDIO;
String imagesPermission = Manifest.permission.READ_MEDIA_IMAGES;
String videoPermission = Manifest.permission.READ_MEDIA_VIDEO;
// Check for permissions and request them if needed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// You have the permissions, you can proceed with your media file operations.
// You don't have the permissions. Request them.
// activity.requestPermissions(new String[]{audioPermission, imagesPermission, videoPermission}, REQUEST_MEDIA_PERMISSIONS);
return context.checkSelfPermission(audioPermission) == PackageManager.PERMISSION_GRANTED &&
context.checkSelfPermission(imagesPermission) == PackageManager.PERMISSION_GRANTED &&
context.checkSelfPermission(videoPermission) == PackageManager.PERMISSION_GRANTED;
}
return false;
}

public static ArrayList<FileListItem>
prepareFileListEntries(ArrayList<FileListItem> internalList, File inter,
ExtensionFilter filter, boolean show_hidden_files) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
Expand Down Expand Up @@ -38,7 +39,10 @@
@SuppressWarnings("unused")
public class FilePickerDialog extends Dialog implements AdapterView.OnItemClickListener {

private static final String TAG = FilePickerDialog.class.getSimpleName();

private final Context context;
private Activity activity;
private ListView listView;
private TextView dname, dir_path, title;
private DialogProperties properties;
Expand All @@ -53,6 +57,7 @@ public class FilePickerDialog extends Dialog implements AdapterView.OnItemClickL

public static final int EXTERNAL_READ_PERMISSION_GRANT = 112;

@Deprecated
public FilePickerDialog(Context context) {
super(context);
this.context = context;
Expand All @@ -61,6 +66,16 @@ public FilePickerDialog(Context context) {
internalList = new ArrayList<>();
}

public FilePickerDialog(Activity activity, Context context) {
super(context);
this.activity = activity;
this.context = context;
properties = new DialogProperties();
filter = new ExtensionFilter(properties);
internalList = new ArrayList<>();
}

@Deprecated
public FilePickerDialog(Context context, DialogProperties properties, int themeResId) {
super(context, themeResId);
this.context = context;
Expand All @@ -69,6 +84,16 @@ public FilePickerDialog(Context context, DialogProperties properties, int themeR
internalList = new ArrayList<>();
}

public FilePickerDialog(Activity activity, Context context, DialogProperties properties, int themeResId) {
super(context, themeResId);
this.activity = activity;
this.context = context;
this.properties = properties;
filter = new ExtensionFilter(properties);
internalList = new ArrayList<>();
}

@Deprecated
public FilePickerDialog(Context context, DialogProperties properties) {
super(context);
this.context = context;
Expand All @@ -77,6 +102,15 @@ public FilePickerDialog(Context context, DialogProperties properties) {
internalList = new ArrayList<>();
}

public FilePickerDialog(Activity activity, Context context, DialogProperties properties) {
super(context);
this.activity = activity;
this.context = context;
this.properties = properties;
filter = new ExtensionFilter(properties);
internalList = new ArrayList<>();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -197,33 +231,50 @@ protected void onStart() {
positiveBtnNameStr
);
select.setText(positiveBtnNameStr);
if (Utility.checkStorageAccessPermissions(context)) {
File currLoc;
internalList.clear();
if (properties.offset.isDirectory() && validateOffsetPath()) {
currLoc = new File(properties.offset.getAbsolutePath());
FileListItem parent = new FileListItem();
parent.setFilename(context.getString(R.string.label_parent_dir));
parent.setDirectory(true);
parent.setLocation(Objects.requireNonNull(currLoc.getParentFile())
.getAbsolutePath());
parent.setTime(currLoc.lastModified());
internalList.add(parent);
} else if (properties.root.exists() && properties.root.isDirectory()) {
currLoc = new File(properties.root.getAbsolutePath());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (Utility.checkMediaAccessPermissions(context)) {
//Permission granted...
dir();
} else {
currLoc = new File(properties.error_dir.getAbsolutePath());
//Permissions are not granted...
Log.d(TAG, "Permissions are not granted");
}
} else {
if (Utility.checkStorageAccessPermissions(context)) {
Log.d(TAG, "Permission granted");
dir();
} else {
Log.d(TAG, "Permission not granted");
}
dname.setText(currLoc.getName());
dir_path.setText(currLoc.getAbsolutePath());
setTitle();
internalList = Utility.prepareFileListEntries(internalList, currLoc, filter,
properties.show_hidden_files);
mFileListAdapter.notifyDataSetChanged();
listView.setOnItemClickListener(this);
}
}

private void dir() {
File currLoc;
internalList.clear();
if (properties.offset.isDirectory() && validateOffsetPath()) {
currLoc = new File(properties.offset.getAbsolutePath());
FileListItem parent = new FileListItem();
parent.setFilename(context.getString(R.string.label_parent_dir));
parent.setDirectory(true);
parent.setLocation(Objects.requireNonNull(currLoc.getParentFile())
.getAbsolutePath());
parent.setTime(currLoc.lastModified());
internalList.add(parent);
} else if (properties.root.exists() && properties.root.isDirectory()) {
currLoc = new File(properties.root.getAbsolutePath());
} else {
currLoc = new File(properties.error_dir.getAbsolutePath());
}
dname.setText(currLoc.getName());
dir_path.setText(currLoc.getAbsolutePath());
setTitle();
internalList = Utility.prepareFileListEntries(internalList, currLoc, filter,
properties.show_hidden_files);
mFileListAdapter.notifyDataSetChanged();
listView.setOnItemClickListener(this);
}

private boolean validateOffsetPath() {
String offset_path = properties.offset.getAbsolutePath();
String root_path = properties.root.getAbsolutePath();
Expand Down Expand Up @@ -393,24 +444,49 @@ public void markFiles(List<String> paths) {

@Override
public void show() {
if (!Utility.checkStorageAccessPermissions(context)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
((Activity) context).requestPermissions(new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE}, EXTERNAL_READ_PERMISSION_GRANT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (Utility.checkMediaAccessPermissions(context)) {
//Permission granted...
super.show();
positiveBtnNameStr = positiveBtnNameStr == null ?
context.getResources().getString(R.string.choose_button_label) : positiveBtnNameStr;
select.setText(positiveBtnNameStr);
int size = MarkedItemList.getFileCount();
if (size == 0) {
select.setText(positiveBtnNameStr);
} else {
String button_label = positiveBtnNameStr + " (" + size + ") ";
select.setText(button_label);
}
} else {
//Permissions are not granted...
Log.d(TAG, "Permissions are not granted");
}
} else {
super.show();
positiveBtnNameStr = positiveBtnNameStr == null ?
context.getResources().getString(R.string.choose_button_label) : positiveBtnNameStr;
select.setText(positiveBtnNameStr);
int size = MarkedItemList.getFileCount();
if (size == 0) {
select.setText(positiveBtnNameStr);
if (!Utility.checkStorageAccessPermissions(context)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
((Activity) context).requestPermissions(new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE}, EXTERNAL_READ_PERMISSION_GRANT);
}
} else {
String button_label = positiveBtnNameStr + " (" + size + ") ";
select.setText(button_label);
super.show();
positiveBtnNameStr = positiveBtnNameStr == null ?
context.getResources().getString(R.string.choose_button_label) : positiveBtnNameStr;
select.setText(positiveBtnNameStr);
int size = MarkedItemList.getFileCount();
if (size == 0) {
select.setText(positiveBtnNameStr);
} else {
String button_label = positiveBtnNameStr + " (" + size + ") ";
select.setText(button_label);
}
}
}
if (!Utility.checkStorageAccessPermissions(context)) {

} else {

}
}

@Override
Expand Down
13 changes: 7 additions & 6 deletions sample/build.gradle
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 31
compileSdk 34

defaultConfig {
applicationId "com.developer.filepicker.file"
minSdkVersion 19
targetSdkVersion 31
versionCode 7
versionName "8.0.20"
targetSdkVersion 34
versionCode 8
versionName "9.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
namespace 'com.developer.filepicker.file'
}

dependencies {
Expand All @@ -25,6 +26,6 @@ dependencies {
implementation project(':library')

//AndroidX Libraries
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.recyclerview:recyclerview:1.3.1'
}
Loading

0 comments on commit f7acf91

Please sign in to comment.