From 9e5d1d560e7831e3452b626b9326efa180fde76f Mon Sep 17 00:00:00 2001 From: Jaisel Rahman Date: Mon, 18 May 2020 23:18:28 +0530 Subject: [PATCH] feat: paging support for dirs --- .../activity/DirSelectActivity.java | 46 ++++--- .../activity/FilePickerActivity.java | 3 +- .../filepicker/adapter/DirListAdapter.java | 24 ++-- .../loader/dir/DirResultCallback.java | 30 ----- .../DirDataSource.java} | 118 +++++++++++------- .../DirLoader.java} | 66 ++++------ .../filepicker/model/DirViewModel.java | 69 ++++++++++ .../{loader => model}/FileLoader.java | 32 +++-- .../filepicker/model/MediaFileDataSource.java | 26 +--- 9 files changed, 216 insertions(+), 198 deletions(-) delete mode 100644 filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirResultCallback.java rename filepicker/src/main/java/com/jaiselrahman/filepicker/{loader/dir/DirLoader.java => model/DirDataSource.java} (58%) rename filepicker/src/main/java/com/jaiselrahman/filepicker/{loader/dir/DirLoaderCallback.java => model/DirLoader.java} (75%) create mode 100644 filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirViewModel.java rename filepicker/src/main/java/com/jaiselrahman/filepicker/{loader => model}/FileLoader.java (93%) diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/DirSelectActivity.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/DirSelectActivity.java index 74b29f3..6c7bf68 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/DirSelectActivity.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/DirSelectActivity.java @@ -37,50 +37,38 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.PagedList; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.jaiselrahman.filepicker.R; import com.jaiselrahman.filepicker.adapter.DirListAdapter; import com.jaiselrahman.filepicker.config.Configurations; -import com.jaiselrahman.filepicker.loader.FileLoader; -import com.jaiselrahman.filepicker.loader.dir.DirLoader; -import com.jaiselrahman.filepicker.loader.dir.DirResultCallback; +import com.jaiselrahman.filepicker.model.FileLoader; import com.jaiselrahman.filepicker.model.Dir; +import com.jaiselrahman.filepicker.model.DirViewModel; import com.jaiselrahman.filepicker.model.MediaFile; import com.jaiselrahman.filepicker.view.DividerItemDecoration; import java.io.File; import java.util.ArrayList; -import java.util.List; public class DirSelectActivity extends AppCompatActivity implements DirListAdapter.OnCameraClickListener { public static final String MEDIA_FILES = "MEDIA_FILES"; public static final String CONFIGS = "CONFIGS"; + private static final int REQUEST_WRITE_PERMISSION = 1; private static final int REQUEST_CAMERA_PERMISSION_FOR_CAMERA = 2; private static final int REQUEST_CAMERA_PERMISSION_FOR_VIDEO = 3; private static final int REQUEST_DOCUMENT = 4; private static final int REQUEST_FILE = 5; - private static final int INIT_SIZE = 6; + private Configurations configs; - private ArrayList dirs = new ArrayList<>(); private DirListAdapter dirAdapter; - - private DirResultCallback dirResultCallback = new DirResultCallback() { - @Override - public void onResult(final List dirsResult) { - if (dirs != null) { - if (dirsResult.size() <= INIT_SIZE) { - dirAdapter.submitList(dirsResult); - } else { - dirAdapter.submitList(dirsResult.subList(0, INIT_SIZE)); - dirAdapter.submitList(dirsResult); - } - } - } - }; + private DirViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { @@ -162,7 +150,7 @@ public boolean isAutoMeasureEnabled() { recyclerView.setItemViewCacheSize(20); if (requestPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION)) { - loadDirs(false); + loadDirs(); } } @@ -172,15 +160,23 @@ private boolean useDocumentUi() { && !(configs.isShowImages() || configs.isShowVideos() || configs.isShowAudios()); } - private void loadDirs(boolean restart) { - DirLoader.loadDirs(this, dirResultCallback, configs, restart); + private void loadDirs() { + viewModel = new ViewModelProvider(this, new DirViewModel.Factory(getContentResolver(), configs)) + .get(DirViewModel.class); + + viewModel.dirs.observe(this, new Observer>() { + @Override + public void onChanged(PagedList dirs) { + dirAdapter.submitList(dirs); + } + }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_WRITE_PERMISSION) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - loadDirs(false); + loadDirs(); } else { Toast.makeText(this, R.string.permission_not_given, Toast.LENGTH_SHORT).show(); finish(); @@ -210,7 +206,7 @@ public void onScanCompleted(String path, final Uri uri) { runOnUiThread(new Runnable() { @Override public void run() { - loadDirs(true); + viewModel.refresh(); } }); } diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/FilePickerActivity.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/FilePickerActivity.java index d71c413..ea074e5 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/FilePickerActivity.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/activity/FilePickerActivity.java @@ -28,7 +28,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.webkit.MimeTypeMap; @@ -49,7 +48,7 @@ import com.jaiselrahman.filepicker.adapter.FileGalleryAdapter.OnCameraClickListener; import com.jaiselrahman.filepicker.adapter.MultiSelectionAdapter.OnSelectionListener; import com.jaiselrahman.filepicker.config.Configurations; -import com.jaiselrahman.filepicker.loader.FileLoader; +import com.jaiselrahman.filepicker.model.FileLoader; import com.jaiselrahman.filepicker.model.MediaFile; import com.jaiselrahman.filepicker.model.MediaFileViewModel; import com.jaiselrahman.filepicker.view.DividerItemDecoration; diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/adapter/DirListAdapter.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/adapter/DirListAdapter.java index dc19beb..5ca7f9c 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/adapter/DirListAdapter.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/adapter/DirListAdapter.java @@ -29,8 +29,9 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.paging.AsyncPagedListDiffer; +import androidx.paging.PagedList; import androidx.recyclerview.widget.AsyncDifferConfig; -import androidx.recyclerview.widget.AsyncListDiffer; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; @@ -46,7 +47,6 @@ import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; import java.util.Locale; import static android.os.Environment.DIRECTORY_MOVIES; @@ -67,7 +67,7 @@ public class DirListAdapter extends RecyclerView.Adapter differ = new AsyncListDiffer<>(this, new AsyncDifferConfig.Builder<>(DIR_ITEM_CALLBACK).build()); + private AsyncPagedListDiffer differ = new AsyncPagedListDiffer<>(this, new AsyncDifferConfig.Builder<>(DIR_ITEM_CALLBACK).build()); public DirListAdapter(Activity activity, int imageSize, boolean showCamera, boolean showVideoCamera) { this.activity = activity; @@ -208,19 +208,19 @@ public void setOnCameraClickListener(OnCameraClickListener onCameraClickListener } private Dir getItem(int position) { - return differ.getCurrentList().get(position); + return differ.getItem(position); } @Override public int getItemCount() { if (showCamera) { if (showVideoCamera) - return differ.getCurrentList().size() + 2; - return differ.getCurrentList().size() + 1; + return differ.getItemCount() + 2; + return differ.getItemCount() + 1; } else if (showVideoCamera) { - return differ.getCurrentList().size() + 1; + return differ.getItemCount() + 1; } - return differ.getCurrentList().size(); + return differ.getItemCount(); } @Override @@ -243,7 +243,7 @@ public void onChanged(int position, int count, Object payload) { notifyItemRangeChanged(itemStartPosition + position, count, payload); } - public void submitList(List dirs) { + public void submitList(PagedList dirs) { differ.submitList(dirs); } @@ -287,10 +287,10 @@ public boolean areItemsTheSame(@NonNull Dir oldItem, @NonNull Dir newItem) { @Override public boolean areContentsTheSame(@NonNull Dir oldItem, @NonNull Dir newItem) { - return oldItem.getName() != null && oldItem.getName().equals(newItem.getName()) + return (oldItem.getName() != null && oldItem.getName().equals(newItem.getName())) && oldItem.getCount() == newItem.getCount() - && (oldItem.getPreview() == null && newItem.getPreview() == null) - || oldItem.getPreview().equals(newItem.getPreview()); + && ((oldItem.getPreview() == null && newItem.getPreview() == null) + || (oldItem.getPreview() !=null && oldItem.getPreview().equals(newItem.getPreview()))); } }; } diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirResultCallback.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirResultCallback.java deleted file mode 100644 index 1ea463e..0000000 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirResultCallback.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2020, Jaisel Rahman . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.jaiselrahman.filepicker.loader.dir; - -import androidx.annotation.Nullable; - -import com.jaiselrahman.filepicker.model.Dir; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public interface DirResultCallback { - void onResult(@Nullable List dirs); -} diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoader.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirDataSource.java similarity index 58% rename from filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoader.java rename to filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirDataSource.java index 34c3aa8..a6d2745 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoader.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirDataSource.java @@ -14,16 +14,18 @@ * limitations under the License. */ -package com.jaiselrahman.filepicker.loader.dir; +package com.jaiselrahman.filepicker.model; -import android.content.Context; +import android.content.ContentResolver; +import android.database.Cursor; +import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; -import androidx.loader.app.LoaderManager; -import androidx.loader.content.CursorLoader; +import androidx.core.content.ContentResolverCompat; +import androidx.paging.DataSource; +import androidx.paging.PositionalDataSource; import com.jaiselrahman.filepicker.config.Configurations; @@ -40,29 +42,23 @@ import static android.provider.MediaStore.MediaColumns.DATA; import static android.provider.MediaStore.MediaColumns.DATE_ADDED; import static android.provider.MediaStore.MediaColumns.SIZE; -import static com.jaiselrahman.filepicker.loader.FileLoader.appendDefaultFileSelection; -import static com.jaiselrahman.filepicker.loader.FileLoader.appendFileSelection; - -public class DirLoader extends CursorLoader { - static final String COUNT = "count"; - - private static final String[] DIR_PROJECTION = new String[]{ - MediaStore.Files.FileColumns._ID, - MediaStore.Files.FileColumns.DATA, - MediaStore.Files.FileColumns.BUCKET_ID, - MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME, - MEDIA_TYPE, - }; - - static final int COLUMN_ID = 0; - static final int COLUMN_DATA = 1; - static final int COLUMN_BUCKET_ID = 2; - static final int COLUMN_BUCKET_DISPLAY_NAME = 3; - static final int COLUMN_MEDIA_TYPE = 4; - static final int COLUMN_COUNT = 5; - - DirLoader(Context context, @NonNull Configurations configs) { - super(context); +import static com.jaiselrahman.filepicker.model.MediaFileDataSource.appendDefaultFileSelection; +import static com.jaiselrahman.filepicker.model.MediaFileDataSource.appendFileSelection; + +public class DirDataSource extends PositionalDataSource { + private Configurations configs; + private ContentResolver contentResolver; + + private String[] projection; + private String sortOrder; + private String selection; + private String[] selectionArgs; + private Uri uri; + + private DirDataSource(ContentResolver contentResolver, Uri uri, @NonNull Configurations configs) { + this.contentResolver = contentResolver; + this.configs = configs; + this.uri = uri; ArrayList selectionArgs = new ArrayList<>(); StringBuilder selectionBuilder = new StringBuilder(200); @@ -118,37 +114,63 @@ public class DirLoader extends CursorLoader { selectionBuilder.append(BUCKET_ID).append(" IS NOT NULL"); } - if (selectionBuilder.length() != 0) { - setProjection(getDirProjection()); - setUri(MediaStore.Files.getContentUri("external")); - setSortOrder(DATE_ADDED + " DESC"); - setSelection(selectionBuilder.toString()); - setSelectionArgs(selectionArgs.toArray(new String[0])); - } + this.projection = getDirProjection(); + this.sortOrder = DATE_ADDED + " DESC"; + this.selection = selectionBuilder.toString(); + this.selectionArgs = selectionArgs.toArray(new String[0]); + } + + @Override + public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback callback) { + callback.onResult(getDirs(params.requestedStartPosition, params.requestedLoadSize), 0); + } + + @Override + public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback callback) { + callback.onResult(getDirs(params.startPosition, params.loadSize)); + } + + private List getDirs(int offset, int limit) { + Cursor data = ContentResolverCompat.query(contentResolver, uri, projection, + selection, selectionArgs, + sortOrder + " LIMIT " + limit + " OFFSET " + offset, null); + + return DirLoader.getDirs(data, configs); } private static String[] getDirProjection() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - return DIR_PROJECTION; + return DirLoader.DIR_PROJECTION; } List projection = new ArrayList<>(); - Collections.addAll(projection, DIR_PROJECTION); - projection.add("COUNT(*) as " + COUNT); + Collections.addAll(projection, DirLoader.DIR_PROJECTION); + projection.add("COUNT(*) as " + DirLoader.COUNT); return projection.toArray(new String[0]); } - public static void loadDirs(FragmentActivity activity, DirResultCallback dirResultCallback, Configurations configs, boolean restart) { - if (configs.isShowFiles() || configs.isShowVideos() || configs.isShowAudios() || configs.isShowImages()) { - DirLoaderCallback dirLoaderCallBack = new DirLoaderCallback(activity, dirResultCallback, configs); - if (!restart) { - LoaderManager.getInstance(activity).initLoader(0, null, dirLoaderCallBack); - } else { - LoaderManager.getInstance(activity).restartLoader(0, null, dirLoaderCallBack); - } - } else { - dirResultCallback.onResult(null); + public static class Factory extends DataSource.Factory { + private ContentResolver contentResolver; + private Configurations configs; + + private Uri uri; + + Factory(ContentResolver contentResolver, Configurations configs) { + this.contentResolver = contentResolver; + this.configs = configs; + + uri = MediaStore.Files.getContentUri("external"); + } + + public Uri getUri() { + return uri; + } + + @NonNull + @Override + public DataSource create() { + return new DirDataSource(contentResolver, uri, configs); } } } diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoaderCallback.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirLoader.java similarity index 75% rename from filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoaderCallback.java rename to filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirLoader.java index a2b9a90..323fb22 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/dir/DirLoaderCallback.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirLoader.java @@ -14,64 +14,49 @@ * limitations under the License. */ -package com.jaiselrahman.filepicker.loader.dir; +package com.jaiselrahman.filepicker.model; import android.content.ContentUris; -import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Build; -import android.os.Bundle; import android.provider.MediaStore; -import androidx.annotation.NonNull; -import androidx.loader.app.LoaderManager; -import androidx.loader.content.Loader; - import com.jaiselrahman.filepicker.config.Configurations; -import com.jaiselrahman.filepicker.model.Dir; import com.jaiselrahman.filepicker.utils.FileUtils; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.HashMap; import java.util.List; +import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE; import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO; import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE; import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO; -class DirLoaderCallback implements LoaderManager.LoaderCallbacks { - private Context context; - private DirResultCallback dirResultCallback; - private Configurations configs; - - DirLoaderCallback(@NonNull Context context, - @NonNull DirResultCallback dirResultCallback, - @NonNull Configurations configs) { - this.context = context; - this.dirResultCallback = dirResultCallback; - this.configs = configs; - } - - @NonNull - @Override - public Loader onCreateLoader(int id, Bundle args) { - return new DirLoader(context, configs); - } - - @Override - public void onLoadFinished(@NonNull Loader loader, Cursor data) { - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - dirResultCallback.onResult(getDirs(data, configs)); - } else { - dirResultCallback.onResult(getDirsQ(data, configs)); +class DirLoader { + static final String COUNT = "count"; + + static final String[] DIR_PROJECTION = new String[]{ + MediaStore.Files.FileColumns._ID, + MediaStore.Files.FileColumns.DATA, + MediaStore.Files.FileColumns.BUCKET_ID, + MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME, + MEDIA_TYPE, + }; + + private static final int COLUMN_ID = 0; + private static final int COLUMN_DATA = 1; + private static final int COLUMN_BUCKET_ID = 2; + private static final int COLUMN_BUCKET_DISPLAY_NAME = 3; + private static final int COLUMN_MEDIA_TYPE = 4; + private static final int COLUMN_COUNT = 5; + + static List getDirs(Cursor data, Configurations configs) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return getDirsQ(data, configs); } - } - private static List getDirs(Cursor data, Configurations configs) { List dirs = new ArrayList<>(); List ignoredPaths = new ArrayList<>(); @@ -128,10 +113,6 @@ private static List getDirsQ(Cursor data, Configurations configs) { return new ArrayList<>(dirs.values()); } - @Override - public void onLoaderReset(@NonNull Loader loader) { - } - private static Uri getPreview(Cursor cursor) { long id = cursor.getLong(DirLoader.COLUMN_ID); int mediaType = cursor.getInt(DirLoader.COLUMN_MEDIA_TYPE); @@ -153,6 +134,7 @@ private static Uri getPreview(Cursor cursor) { return ContentUris.withAppendedId(contentUri, id); } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private static boolean isExcluded(String path, List ignoredPaths) { for (String p : ignoredPaths) { if (path.startsWith(p)) return true; diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirViewModel.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirViewModel.java new file mode 100644 index 0000000..488ef24 --- /dev/null +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/DirViewModel.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, Jaisel Rahman . + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.jaiselrahman.filepicker.model; + +import android.content.ContentResolver; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PagedList; + +import com.jaiselrahman.filepicker.config.Configurations; + +public class DirViewModel extends ViewModel { + public LiveData> dirs; + + private DirViewModel(ContentResolver contentResolver, Configurations configs) { + DirDataSource.Factory dirDataSourceFactory = new DirDataSource.Factory(contentResolver, configs); + + dirs = new LivePagedListBuilder<>( + dirDataSourceFactory, + new PagedList.Config.Builder() + .setPageSize(Configurations.PAGE_SIZE) + .setInitialLoadSizeHint(15) + .setMaxSize(Configurations.PAGE_SIZE * 3) + .setPrefetchDistance(Configurations.PREFETCH_DISTANCE) + .setEnablePlaceholders(false) + .build() + ).build(); + } + + public void refresh() { + if (dirs.getValue() != null) + dirs.getValue().getDataSource().invalidate(); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + private ContentResolver contentResolver; + private Configurations configs; + + public Factory(ContentResolver contentResolver, Configurations configs) { + this.contentResolver = contentResolver; + this.configs = configs; + } + + @NonNull + @Override + @SuppressWarnings("unchecked") + public T create(@NonNull Class modelClass) { + return (T) new DirViewModel(contentResolver, configs); + } + } +} diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/FileLoader.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/FileLoader.java similarity index 93% rename from filepicker/src/main/java/com/jaiselrahman/filepicker/loader/FileLoader.java rename to filepicker/src/main/java/com/jaiselrahman/filepicker/model/FileLoader.java index a96f1cf..5d9af5f 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/loader/FileLoader.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/FileLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Jaisel Rahman . + * Copyright (c) 2020, Jaisel Rahman . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.jaiselrahman.filepicker.loader; +package com.jaiselrahman.filepicker.model; import android.content.ContentResolver; import android.content.ContentUris; @@ -27,9 +27,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; - import com.jaiselrahman.filepicker.config.Configurations; -import com.jaiselrahman.filepicker.model.MediaFile; import java.util.ArrayList; import java.util.Arrays; @@ -50,7 +48,7 @@ import static android.provider.MediaStore.MediaColumns.WIDTH; public class FileLoader { - private static final List FILE_PROJECTION = Arrays.asList( + static final List FILE_PROJECTION = Arrays.asList( MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.DATA, @@ -64,7 +62,16 @@ public class FileLoader { MediaStore.Video.Media.DURATION ); - public static Uri getContentUri(Configurations configs) { + @Nullable + public static MediaFile asMediaFile(ContentResolver contentResolver, Uri uri, Configurations configs) { + Cursor data = contentResolver.query(uri, FILE_PROJECTION.toArray(new String[0]), null, null, null); + if (data != null && data.moveToFirst()) { + return asMediaFile(data, configs, uri); + } + return null; + } + + static Uri getContentUri(Configurations configs) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && (configs.isShowAudios() && !(configs.isShowFiles() || configs.isShowImages() || configs.isShowVideos()))) { return MediaStore.Audio.Media.getContentUri("external"); @@ -73,7 +80,7 @@ public static Uri getContentUri(Configurations configs) { } } - public static List asMediaFiles(Cursor data, Configurations configs) { + static List asMediaFiles(Cursor data, Configurations configs) { ArrayList mediaFiles = new ArrayList<>(data.getCount()); if (data.moveToFirst()) do { @@ -85,7 +92,7 @@ public static List asMediaFiles(Cursor data, Configurations configs) return mediaFiles; } - public static MediaFile asMediaFile(@NonNull Cursor data, Configurations configs, @Nullable Uri uri) { + private static MediaFile asMediaFile(@NonNull Cursor data, Configurations configs, @Nullable Uri uri) { MediaFile mediaFile = new MediaFile(); mediaFile.setPath(data.getString(data.getColumnIndex(DATA))); @@ -143,15 +150,6 @@ public static MediaFile asMediaFile(@NonNull Cursor data, Configurations configs return mediaFile; } - @Nullable - public static MediaFile asMediaFile(ContentResolver contentResolver, Uri uri, Configurations configs) { - Cursor data = contentResolver.query(uri, FILE_PROJECTION.toArray(new String[0]), null, null, null); - if (data != null && data.moveToFirst()) { - return asMediaFile(data, configs, uri); - } - return null; - } - private static @MediaFile.Type int getMediaType(String mime) { if (mime.startsWith("image/")) { diff --git a/filepicker/src/main/java/com/jaiselrahman/filepicker/model/MediaFileDataSource.java b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/MediaFileDataSource.java index 68ffb8f..81c3358 100644 --- a/filepicker/src/main/java/com/jaiselrahman/filepicker/model/MediaFileDataSource.java +++ b/filepicker/src/main/java/com/jaiselrahman/filepicker/model/MediaFileDataSource.java @@ -21,21 +21,17 @@ import android.net.Uri; import android.os.Build; import android.provider.MediaStore; -import android.util.Log; import androidx.annotation.NonNull; import androidx.core.content.ContentResolverCompat; import androidx.paging.DataSource; import androidx.paging.PositionalDataSource; -import com.jaiselrahman.filepicker.activity.FilePickerActivity; import com.jaiselrahman.filepicker.config.Configurations; -import com.jaiselrahman.filepicker.loader.FileLoader; import com.jaiselrahman.filepicker.utils.FileUtils; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE; @@ -51,20 +47,6 @@ public class MediaFileDataSource extends PositionalDataSource { - private static final List FILE_PROJECTION = Arrays.asList( - MediaStore.Files.FileColumns._ID, - MediaStore.Files.FileColumns.DISPLAY_NAME, - MediaStore.Files.FileColumns.DATA, - MediaStore.Files.FileColumns.SIZE, - MediaStore.Files.FileColumns.DATE_ADDED, - MediaStore.Files.FileColumns.MIME_TYPE, - MediaStore.Images.Media.BUCKET_ID, - MediaStore.Images.Media.BUCKET_DISPLAY_NAME, - MediaStore.Files.FileColumns.HEIGHT, - MediaStore.Files.FileColumns.WIDTH, - MediaStore.Video.Media.DURATION - ); - private Configurations configs; private ContentResolver contentResolver; @@ -136,7 +118,7 @@ private MediaFileDataSource(ContentResolver contentResolver, Uri uri, @NonNull C selectionBuilder.append(SIZE).append(" > 0 "); } - List projection = new ArrayList<>(FILE_PROJECTION); + List projection = new ArrayList<>(FileLoader.FILE_PROJECTION); if (canUseMediaType(configs)) { projection.add(MediaStore.Files.FileColumns.MEDIA_TYPE); @@ -236,7 +218,7 @@ private static List getFoldersToIgnore(ContentResolver contentResolver, return folders; } - private static void appendDefaultFileSelection(StringBuilder selection) { + static void appendDefaultFileSelection(StringBuilder selection) { selection.append("(") .append("(") .append(MEDIA_TYPE).append(" = ").append(MEDIA_TYPE_NONE) @@ -253,7 +235,7 @@ private static void appendDefaultFileSelection(StringBuilder selection) { .append(")"); } - private static void appendFileSelection(StringBuilder selectionBuilder, List selectionArgs, String[] suffixes) { + static void appendFileSelection(StringBuilder selectionBuilder, List selectionArgs, String[] suffixes) { selectionBuilder.append("(").append(DISPLAY_NAME).append(" LIKE ?"); selectionArgs.add("%." + suffixes[0].replace(".", "")); @@ -281,7 +263,7 @@ public static class Factory extends DataSource.Factory { private Uri uri; - public Factory(ContentResolver contentResolver, Configurations configs, Long dirId) { + Factory(ContentResolver contentResolver, Configurations configs, Long dirId) { this.contentResolver = contentResolver; this.configs = configs; this.dirId = dirId;