diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-11-05 10:18:27 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-11-05 10:18:27 +0300 |
commit | 9f442181a8f1b405283b55df128ed4fa9dc6b42e (patch) | |
tree | 1facd03f9f8c08c98b64ae481db6fa0a37c9abb6 /app/src/main/java/it/niedermann/nextcloud/deck | |
parent | 92a96a57c36b69939dc860b74c9f9a84cdaa0372 (diff) |
Check for closed cursors to prevent crashes when switchting quickly between adapter types
Signed-off-by: Stefan Niedermann <info@niedermann.it>
Diffstat (limited to 'app/src/main/java/it/niedermann/nextcloud/deck')
-rw-r--r-- | app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java | 17 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/AbstractCursorPickerAdapter.java | 2 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapter.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapterAbstract.java) | 42 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/FileAdapter.java | 18 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapter.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapterAbstract.java) | 4 |
5 files changed, 45 insertions, 38 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java index eb7822679..b137b1b7f 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java @@ -4,6 +4,7 @@ import android.animation.ValueAnimator; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -50,10 +51,10 @@ import it.niedermann.nextcloud.deck.ui.branding.BrandedFragment; import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar; import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel; import it.niedermann.nextcloud.deck.ui.card.attachments.picker.AbstractPickerAdapter; -import it.niedermann.nextcloud.deck.ui.card.attachments.picker.ContactAdapterAbstract; +import it.niedermann.nextcloud.deck.ui.card.attachments.picker.ContactAdapter; import it.niedermann.nextcloud.deck.ui.card.attachments.picker.FileAdapter; import it.niedermann.nextcloud.deck.ui.card.attachments.picker.FileAdapterLegacy; -import it.niedermann.nextcloud.deck.ui.card.attachments.picker.GalleryAdapterAbstract; +import it.niedermann.nextcloud.deck.ui.card.attachments.picker.GalleryAdapter; import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment; import it.niedermann.nextcloud.deck.ui.takephoto.TakePhotoActivity; import it.niedermann.nextcloud.deck.util.VCardUtil; @@ -264,7 +265,7 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme pickerAnimationInProgress = true; binding.pickerBackdrop.setVisibility(VISIBLE); binding.bottomNavigation.animate().translationY(0).setDuration(250).start(); - final ValueAnimator backdropAnimation = ValueAnimator.ofObject(ArgbEvaluatorCompat.getInstance(), getResources().getColor(android.R.color.transparent), getResources().getColor(R.color.mdtp_transparent_black)); + final ValueAnimator backdropAnimation = ValueAnimator.ofObject(ArgbEvaluatorCompat.getInstance(), ((ColorDrawable) binding.pickerBackdrop.getBackground()).getColor(), getResources().getColor(R.color.mdtp_transparent_black)); backdropAnimation.setDuration(250); backdropAnimation.addUpdateListener(animator -> binding.pickerBackdrop.setBackgroundColor((int) animator.getAnimatedValue())); backdropAnimation.start(); @@ -274,7 +275,7 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme private void hidePickerSheet() { pickerAnimationInProgress = true; - final ValueAnimator backdropAnimation = ValueAnimator.ofObject(ArgbEvaluatorCompat.getInstance(), getResources().getColor(R.color.mdtp_transparent_black), getResources().getColor(android.R.color.transparent)); + final ValueAnimator backdropAnimation = ValueAnimator.ofObject(ArgbEvaluatorCompat.getInstance(), ((ColorDrawable) binding.pickerBackdrop.getBackground()).getColor(), getResources().getColor(android.R.color.transparent)); backdropAnimation.setDuration(250); backdropAnimation.addUpdateListener(animator -> binding.pickerBackdrop.setBackgroundColor((int) animator.getAnimatedValue())); backdropAnimation.start(); @@ -287,12 +288,12 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme } private void showGalleryPicker() { - if (!(pickerAdapter instanceof GalleryAdapterAbstract)) { + if (!(pickerAdapter instanceof GalleryAdapter)) { if (isPermissionRequestNeeded(READ_EXTERNAL_STORAGE) || isPermissionRequestNeeded(CAMERA)) { requestPermissions(new String[]{READ_EXTERNAL_STORAGE, CAMERA}, REQUEST_CODE_PICK_GALLERY_PERMISSION); } else { unbindPickerAdapter(); - pickerAdapter = new GalleryAdapterAbstract(requireContext(), uri -> onActivityResult(REQUEST_CODE_PICK_FILE, RESULT_OK, new Intent().setData(uri)), this::openNativeCameraPicker, getViewLifecycleOwner()); + pickerAdapter = new GalleryAdapter(requireContext(), uri -> onActivityResult(REQUEST_CODE_PICK_FILE, RESULT_OK, new Intent().setData(uri)), this::openNativeCameraPicker, getViewLifecycleOwner()); binding.pickerRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 3)); binding.pickerRecyclerView.setAdapter(pickerAdapter); } @@ -300,12 +301,12 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme } private void showContactPicker() { - if (!(pickerAdapter instanceof ContactAdapterAbstract)) { + if (!(pickerAdapter instanceof ContactAdapter)) { if (isPermissionRequestNeeded(READ_CONTACTS)) { requestPermissions(new String[]{READ_CONTACTS}, REQUEST_CODE_PICK_CONTACT_PICKER_PERMISSION); } else { unbindPickerAdapter(); - pickerAdapter = new ContactAdapterAbstract(requireContext(), uri -> onActivityResult(REQUEST_CODE_PICK_CONTACT, RESULT_OK, new Intent().setData(uri)), this::openNativeContactPicker); + pickerAdapter = new ContactAdapter(requireContext(), uri -> onActivityResult(REQUEST_CODE_PICK_CONTACT, RESULT_OK, new Intent().setData(uri)), this::openNativeContactPicker); binding.pickerRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); binding.pickerRecyclerView.setAdapter(pickerAdapter); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/AbstractCursorPickerAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/AbstractCursorPickerAdapter.java index 1890f5111..73058c757 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/AbstractCursorPickerAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/AbstractCursorPickerAdapter.java @@ -69,7 +69,7 @@ public abstract class AbstractCursorPickerAdapter<T extends RecyclerView.ViewHol */ @Override public long getItemId(int position) { - if (cursor.moveToPosition(position - 1)) { + if (!cursor.isClosed() && cursor.moveToPosition(position - 1)) { //noinspection SwitchStatementWithTooFewBranches switch (columnIndexType) { case FIELD_TYPE_INTEGER: diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapterAbstract.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapter.java index b7b35dae5..874127103 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapterAbstract.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/ContactAdapter.java @@ -31,13 +31,13 @@ import static android.provider.ContactsContract.Contacts.DISPLAY_NAME; import static android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY; import static android.provider.ContactsContract.Contacts._ID; -public class ContactAdapterAbstract extends AbstractCursorPickerAdapter<RecyclerView.ViewHolder> { +public class ContactAdapter extends AbstractCursorPickerAdapter<RecyclerView.ViewHolder> { private final int lookupKeyColumnIndex; private final int displayNameColumnIndex; - public ContactAdapterAbstract(@NonNull Context context, @NonNull Consumer<Uri> onSelect, @NonNull Runnable onSelectPicker) { + public ContactAdapter(@NonNull Context context, @NonNull Consumer<Uri> onSelect, @NonNull Runnable onSelectPicker) { super(context, onSelect, onSelectPicker, CONTENT_URI, _ID, new String[]{_ID, LOOKUP_KEY, DISPLAY_NAME}, SORT_KEY_PRIMARY); lookupKeyColumnIndex = cursor.getColumnIndex(LOOKUP_KEY); displayNameColumnIndex = cursor.getColumnIndex(DISPLAY_NAME); @@ -67,27 +67,31 @@ public class ContactAdapterAbstract extends AbstractCursorPickerAdapter<Recycler case VIEW_TYPE_ITEM: { bindExecutor.execute(() -> { final ContactItemViewHolder viewHolder = (ContactItemViewHolder) holder; - cursor.moveToPosition(position - 1); - final String displayName = cursor.getString(displayNameColumnIndex); - final String lookupKey = cursor.getString(lookupKeyColumnIndex); - try (InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, Uri.withAppendedPath(CONTENT_LOOKUP_URI, lookupKey))) { - final Bitmap thumbnail = BitmapFactory.decodeStream(inputStream); - String contactInformation = ""; - try (final Cursor phoneCursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{NUMBER}, LOOKUP_KEY + " = ?", new String[]{lookupKey}, null)) { - if (phoneCursor != null && phoneCursor.moveToFirst()) { - contactInformation = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER)); + if (!cursor.isClosed()) { + cursor.moveToPosition(position - 1); + final String displayName = cursor.getString(displayNameColumnIndex); + final String lookupKey = cursor.getString(lookupKeyColumnIndex); + try (InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, Uri.withAppendedPath(CONTENT_LOOKUP_URI, lookupKey))) { + final Bitmap thumbnail = BitmapFactory.decodeStream(inputStream); + String contactInformation = ""; + try (final Cursor phoneCursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{NUMBER}, LOOKUP_KEY + " = ?", new String[]{lookupKey}, null)) { + if (phoneCursor != null && phoneCursor.moveToFirst()) { + contactInformation = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER)); + } } - } - if (TextUtils.isEmpty(contactInformation)) { - try (final Cursor emailCursor = contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{DATA}, LOOKUP_KEY + " = ?", new String[]{lookupKey}, null)) { - if (emailCursor != null && emailCursor.moveToFirst()) { - contactInformation = emailCursor.getString(emailCursor.getColumnIndex(DATA)); + if (TextUtils.isEmpty(contactInformation)) { + try (final Cursor emailCursor = contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{DATA}, LOOKUP_KEY + " = ?", new String[]{lookupKey}, null)) { + if (emailCursor != null && emailCursor.moveToFirst()) { + contactInformation = emailCursor.getString(emailCursor.getColumnIndex(DATA)); + } } } + final String finalContactInformation = contactInformation; + new Handler(Looper.getMainLooper()).post(() -> viewHolder.bind(Uri.withAppendedPath(CONTENT_LOOKUP_URI, lookupKey), thumbnail, displayName, finalContactInformation, onSelect)); + } catch (IOException ignored) { + new Handler(Looper.getMainLooper()).post(viewHolder::bindError); } - final String finalContactInformation = contactInformation; - new Handler(Looper.getMainLooper()).post(() -> viewHolder.bind(Uri.withAppendedPath(CONTENT_LOOKUP_URI, lookupKey), thumbnail, displayName, finalContactInformation, onSelect)); - } catch (IOException ignored) { + } else { new Handler(Looper.getMainLooper()).post(viewHolder::bindError); } }); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/FileAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/FileAdapter.java index 46e00fc95..47dd3f7a3 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/FileAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/FileAdapter.java @@ -65,14 +65,16 @@ public class FileAdapter extends AbstractCursorPickerAdapter<RecyclerView.ViewHo break; } case VIEW_TYPE_ITEM: { - bindExecutor.execute(() -> { - final long id = getItemId(position); - final String name = cursor.getString(displayNameColumnIndex); - final String mimeType = cursor.getString(mimeTypeColumnIndex); - final long size = cursor.getLong(sizeColumnIndex); - final long modified = cursor.getLong(modifiedColumnIndex); - new Handler(Looper.getMainLooper()).post(() -> ((FileItemViewHolder) holder).bind(ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), id), name, mimeType, size, modified, onSelect)); - }); + if (!cursor.isClosed()) { + bindExecutor.execute(() -> { + final long id = getItemId(position); + final String name = cursor.getString(displayNameColumnIndex); + final String mimeType = cursor.getString(mimeTypeColumnIndex); + final long size = cursor.getLong(sizeColumnIndex); + final long modified = cursor.getLong(modifiedColumnIndex); + new Handler(Looper.getMainLooper()).post(() -> ((FileItemViewHolder) holder).bind(ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), id), name, mimeType, size, modified, onSelect)); + }); + } break; } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapterAbstract.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapter.java index d47187cd0..0be85d9e5 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapterAbstract.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/picker/GalleryAdapter.java @@ -27,7 +27,7 @@ import static android.os.Build.VERSION_CODES.Q; import static android.provider.BaseColumns._ID; import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; -public class GalleryAdapterAbstract extends AbstractCursorPickerAdapter<RecyclerView.ViewHolder> { +public class GalleryAdapter extends AbstractCursorPickerAdapter<RecyclerView.ViewHolder> { @NonNull private final LifecycleOwner lifecycleOwner; @@ -37,7 +37,7 @@ public class GalleryAdapterAbstract extends AbstractCursorPickerAdapter<Recycler ? MediaStore.Images.Media.DATE_TAKEN : MediaStore.Images.Media.DATE_ADDED; - public GalleryAdapterAbstract(@NonNull Context context, @NonNull Consumer<Uri> onSelect, @NonNull Runnable openNativePicker, @NonNull LifecycleOwner lifecycleOwner) { + public GalleryAdapter(@NonNull Context context, @NonNull Consumer<Uri> onSelect, @NonNull Runnable openNativePicker, @NonNull LifecycleOwner lifecycleOwner) { super(context, onSelect, openNativePicker, EXTERNAL_CONTENT_URI, _ID, sortOrder + " DESC"); this.lifecycleOwner = lifecycleOwner; notifyItemRangeInserted(0, getItemCount()); |