Skip to content

Commit

Permalink
Android q support (#273)
Browse files Browse the repository at this point in the history
* support android Q

* setup api 29

* Handle AndroidQ scoped storage
  • Loading branch information
esafirm authored May 22, 2020
1 parent 749a831 commit 8a96498
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
docker:
# specify the version you desire here
- image: circleci/android:api-28-alpha
- image: circleci/android:api-29

environment:
# Customize the JVM maximum heap limit
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
}
}

ext {
sdk = [
compileSdk: 28,
targetSdk : 28,
compileSdk: 29,
targetSdk : 29,
minSdk : 14
]
}
Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon May 20 03:29:47 EEST 2019
#Wed Mar 04 09:56:13 WIB 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
9 changes: 3 additions & 6 deletions imagepicker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,8 @@ artifacts {

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')

implementation "com.github.bumptech.glide:glide:4.9.0"

implementation "androidx.recyclerview:recyclerview:1.0.0"
implementation "com.github.bumptech.glide:glide:4.11.0"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.appcompat:appcompat:1.1.0"

testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13'
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void onBindViewHolder(final FolderViewHolder holder, int position) {
final Folder folder = folders.get(position);

getImageLoader().loadImage(
folder.getImages().get(0).getPath(),
folder.getImages().get(0),
holder.image,
ImageType.FOLDER
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.esafirm.imagepicker.R;
import com.esafirm.imagepicker.features.imageloader.ImageLoader;
import com.esafirm.imagepicker.features.imageloader.ImageType;
Expand All @@ -18,9 +22,6 @@
import java.util.ArrayList;
import java.util.List;

import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

public class ImagePickerAdapter extends BaseListAdapter<ImagePickerAdapter.ImageViewHolder> {

private List<Image> images = new ArrayList<>();
Expand All @@ -39,8 +40,9 @@ public ImagePickerAdapter(Context context, ImageLoader imageLoader,
}
}

@NonNull
@Override
public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ImageViewHolder(
getInflater().inflate(R.layout.ef_imagepicker_item_image, parent, false)
);
Expand All @@ -53,18 +55,18 @@ public void onBindViewHolder(ImageViewHolder viewHolder, int position) {
final boolean isSelected = isSelected(image);

getImageLoader().loadImage(
image.getPath(),
image,
viewHolder.imageView,
ImageType.GALLERY
);

boolean showFileTypeIndicator = false;
String fileTypeLabel = "";
if(ImagePickerUtils.isGifFormat(image)) {
if (ImagePickerUtils.isGifFormat(image)) {
fileTypeLabel = getContext().getResources().getString(R.string.ef_gif);
showFileTypeIndicator = true;
}
if(ImagePickerUtils.isVideoFormat(image)) {
if (ImagePickerUtils.isVideoFormat(image)) {
fileTypeLabel = getContext().getResources().getString(R.string.ef_video);
showFileTypeIndicator = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;

import com.esafirm.imagepicker.R;
import com.esafirm.imagepicker.features.camera.CameraHelper;
import com.esafirm.imagepicker.features.camera.DefaultCameraModule;
Expand All @@ -38,13 +45,6 @@
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static com.esafirm.imagepicker.helper.ImagePickerPreferences.PREF_WRITE_EXTERNAL_STORAGE_REQUESTED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public Intent getCameraIntent(Context context) {
@Override
public Intent getCameraIntent(Context context, BaseConfig config) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File imageFile = ImagePickerUtils.createImageFile(config.getImageDirectory());
File imageFile = ImagePickerUtils.createImageFile(config.getImageDirectory(), context);
if (imageFile != null) {
Context appContext = context.getApplicationContext();
String providerName = String.format(Locale.ENGLISH, "%s%s", appContext.getPackageName(), ".imagepicker.provider");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;

import androidx.annotation.Nullable;
Expand Down Expand Up @@ -79,7 +80,7 @@ private class ImageLoadRunnable implements Runnable {
private ArrayList<File> exlucedImages;
private ImageLoaderListener listener;

public ImageLoadRunnable(
ImageLoadRunnable(
boolean isFolderMode,
boolean onlyVideo,
boolean includeVideo,
Expand All @@ -95,27 +96,31 @@ public ImageLoadRunnable(
this.listener = listener;
}

@Override
public void run() {
Cursor cursor;
private String getQuerySelection() {
if (onlyVideo) {
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
return MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;

cursor = context.getContentResolver().query(MediaStore.Files.getContentUri("external"), projection,
selection, null, MediaStore.Images.Media.DATE_ADDED);
} else if (includeVideo) {
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
}
if (includeVideo) {
return MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE + " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
}
return null;
}

cursor = context.getContentResolver().query(MediaStore.Files.getContentUri("external"), projection,
selection, null, MediaStore.Images.Media.DATE_ADDED);
} else {
cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
null, null, MediaStore.Images.Media.DATE_ADDED);
private Uri getSourceUri() {
if (onlyVideo || includeVideo) {
return MediaStore.Files.getContentUri("external");
}
return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}

@Override
public void run() {
Cursor cursor = context.getContentResolver().query(getSourceUri(), projection,
getQuerySelection(), null, MediaStore.Images.Media.DATE_ADDED);

if (cursor == null) {
listener.onFailed(new NullPointerException());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.esafirm.imagepicker.features.fileloader;

import android.content.Context;

import com.esafirm.imagepicker.features.common.ImageLoaderListener;

import java.io.File;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package com.esafirm.imagepicker.features.imageloader;

import android.content.ContentUris;
import android.net.Uri;
import android.provider.MediaStore;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.esafirm.imagepicker.R;
import com.esafirm.imagepicker.model.Image;

public class DefaultImageLoader implements ImageLoader {

@Override
public void loadImage(String path, ImageView imageView, ImageType imageType) {
public void loadImage(Image image, ImageView imageView, ImageType imageType) {
Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image.getId());

Glide.with(imageView.getContext())
.load(path)
.load(uri)
.apply(RequestOptions
.placeholderOf(imageType == ImageType.FOLDER
? R.drawable.ef_folder_placeholder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import android.widget.ImageView;

import com.esafirm.imagepicker.model.Image;

public interface ImageLoader {
void loadImage(String path, ImageView imageView, ImageType imageType);
void loadImage(Image image, ImageView imageView, ImageType imageType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;

import androidx.annotation.Nullable;

import com.esafirm.imagepicker.features.ImagePickerSavePath;
import com.esafirm.imagepicker.model.Image;

Expand All @@ -19,20 +22,25 @@
import java.util.List;
import java.util.Locale;

import androidx.annotation.Nullable;

public class ImagePickerUtils {

public static boolean isStringEmpty(@Nullable String str) {
return str == null || str.length() == 0;
}

public static File createImageFile(ImagePickerSavePath savePath) {
private static File createFileInDirectory(ImagePickerSavePath savePath, Context context) {
// External sdcard location
final String path = savePath.getPath();
File mediaStorageDir = savePath.isFullPath()
? new File(path)
: new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), path);

File mediaStorageDir;
if (savePath.isFullPath()) {
mediaStorageDir = new File(path);
} else {
File parent = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
? context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
mediaStorageDir = new File(parent, path);
}

// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
Expand All @@ -42,6 +50,13 @@ public static File createImageFile(ImagePickerSavePath savePath) {
}
}

return mediaStorageDir;
}

public static File createImageFile(ImagePickerSavePath savePath, Context context) {
final File mediaStorageDir = createFileInDirectory(savePath, context);
if (mediaStorageDir == null) return null;

// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.getDefault()).format(new Date());
File result = new File(mediaStorageDir, "IMG_" + timeStamp + ".jpg");
Expand Down
12 changes: 0 additions & 12 deletions imagepicker/src/main/java/com/esafirm/imagepicker/model/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,14 @@ public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
4 changes: 2 additions & 2 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ repositories {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')

implementation "com.github.bumptech.glide:glide:4.9.0"
implementation "androidx.appcompat:appcompat:1.0.2"
implementation "com.github.bumptech.glide:glide:4.10.0"
implementation "androidx.appcompat:appcompat:1.1.0"

/* Development */
implementation project(':rximagepicker')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@
import com.bumptech.glide.request.RequestOptions;
import com.esafirm.imagepicker.features.imageloader.ImageLoader;
import com.esafirm.imagepicker.features.imageloader.ImageType;
import com.esafirm.imagepicker.model.Image;

public class GrayscaleImageLoader implements ImageLoader {

private static final RequestOptions REQUEST_OPTIONS = new RequestOptions().transform(new GrayscaleTransformation());

@Override
public void loadImage(String path, ImageView imageView, ImageType imageType) {
public void loadImage(Image image, ImageView imageView, ImageType imageType) {
Glide.with(imageView)
.asBitmap()
.load(path)
.load(image.getPath())
.transition(BitmapTransitionOptions.withCrossFade())
.apply(REQUEST_OPTIONS)
.into(imageView);
Expand Down

0 comments on commit 8a96498

Please sign in to comment.