Glimpse: Set minimum SDK to 30 (Android 11)

* Oldest supported LineageOS version would be 18.1, which is definitely
  enough for any kind of testing
* While at it fix permissions check for pre-Tiramisu

Change-Id: I9f9ba8fe0c0c8a50436810934b439fd38a2fb445
This commit is contained in:
Sebastiano Barezzi 2023-09-03 17:36:50 +02:00
parent f805d0ce4a
commit b75af064c4
No known key found for this signature in database
GPG Key ID: 763BD3AE91A7A13F
11 changed files with 37 additions and 103 deletions

View File

@ -17,7 +17,7 @@ android {
defaultConfig {
applicationId = "org.lineageos.glimpse"
minSdk = 26
minSdk = 30
targetSdk = 33
versionCode = 1
versionName = "1.0"

View File

@ -27,9 +27,7 @@ class GlimpseApplication : Application(), ImageLoaderFactory {
}
override fun newImageLoader() = ImageLoader.Builder(this).components {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
add(ImageDecoderDecoder.Factory())
}
add(ImageDecoderDecoder.Factory())
add(GifDecoder.Factory())
add(VideoFrameDecoder.Factory())
}.memoryCache {

View File

@ -1,19 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package org.lineageos.glimpse.ext
import android.content.res.Configuration
import android.os.Build
val Configuration.isNightMode
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
isNightModeActive
} else when (uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
Configuration.UI_MODE_NIGHT_UNDEFINED -> null
Configuration.UI_MODE_NIGHT_NO -> false
Configuration.UI_MODE_NIGHT_YES -> true
else -> null
}

View File

@ -20,7 +20,7 @@ var Window.isAppearanceLightStatusBars
fun Window.resetStatusBarAppearance() {
windowInsetsController.isAppearanceLightStatusBars =
context.resources.configuration.isNightMode != true
!context.resources.configuration.isNightModeActive
}
fun Window.setBarsVisibility(

View File

@ -36,9 +36,7 @@ class AlbumsFlow(private val context: Context) : QueryFlow<Album>() {
ContentResolver.QUERY_ARG_SQL_SORT_ORDER to sortOrder,
)
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_INCLUDE)
}
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_INCLUDE)
}
return context.contentResolver.queryFlow(

View File

@ -8,7 +8,6 @@ package org.lineageos.glimpse.flow
import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import androidx.core.os.bundleOf
@ -30,11 +29,8 @@ class MediaFlow(private val context: Context, private val bucketId: Int?) : Quer
when (it) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_FAVORITES.id -> MediaStore.Files.FileColumns.IS_FAVORITE eq 1
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id -> if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id ->
MediaStore.Files.FileColumns.IS_TRASHED eq 1
} else {
null
}
else -> MediaStore.Files.FileColumns.BUCKET_ID eq Query.ARG
}
@ -52,16 +48,15 @@ class MediaFlow(private val context: Context, private val bucketId: Int?) : Quer
ContentResolver.QUERY_ARG_SQL_SORT_ORDER to sortOrder,
)
)
// Exclude trashed media unless we want data for the trashed album
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
putInt(
MediaStore.QUERY_ARG_MATCH_TRASHED, when (bucketId) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id -> MediaStore.MATCH_ONLY
else -> MediaStore.MATCH_EXCLUDE
}
)
}
// Exclude trashed media unless we want data for the trashed album
putInt(
MediaStore.QUERY_ARG_MATCH_TRASHED, when (bucketId) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id -> MediaStore.MATCH_ONLY
else -> MediaStore.MATCH_EXCLUDE
}
)
}
return context.contentResolver.queryFlow(

View File

@ -248,15 +248,11 @@ class MediaViewerFragment : Fragment(R.layout.fragment_media_viewer) {
R.plurals.file_deletion_confirm_message, 1, 1
)
).setPositiveButton(android.R.string.ok) { _, _ ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
deleteUriContract.launch(
requireContext().contentResolver.createDeleteRequest(
it.externalContentUri
)
deleteUriContract.launch(
requireContext().contentResolver.createDeleteRequest(
it.externalContentUri
)
} else {
it.delete(requireContext().contentResolver)
}
)
}
.setNegativeButton(android.R.string.cancel) { _, _ ->
// Do nothing
@ -271,16 +267,11 @@ class MediaViewerFragment : Fragment(R.layout.fragment_media_viewer) {
favoriteButton.setOnClickListener {
mediaViewerAdapter.getItemAtPosition(viewPager.currentItem).let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
favoriteContract.launch(
requireContext().contentResolver.createFavoriteRequest(
!it.isFavorite, it.externalContentUri
)
favoriteContract.launch(
requireContext().contentResolver.createFavoriteRequest(
!it.isFavorite, it.externalContentUri
)
} else {
it.favorite(requireContext().contentResolver, !it.isFavorite)
favoriteButton.isSelected = !it.isFavorite
}
)
}
}
@ -396,19 +387,16 @@ class MediaViewerFragment : Fragment(R.layout.fragment_media_viewer) {
restoreLastTrashedMediaFromTrash = { trashMedia(media, false) }
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val contract = when (trash) {
true -> trashUriContract
false -> restoreUriFromTrashContract
}
contract.launch(
requireContext().contentResolver.createTrashRequest(
trash, media.externalContentUri
)
)
} else {
media.trash(requireContext().contentResolver, trash)
val contract = when (trash) {
true -> trashUriContract
false -> restoreUriFromTrashContract
}
contract.launch(
requireContext().contentResolver.createTrashRequest(
trash, media.externalContentUri
)
)
}
private fun updateSheetsHeight() {

View File

@ -5,12 +5,9 @@
package org.lineageos.glimpse.models
import android.content.ContentResolver
import android.content.ContentUris
import android.content.ContentValues
import android.os.Parcel
import android.os.Parcelable
import android.provider.MediaStore
import java.util.Date
import kotlin.reflect.safeCast
@ -72,22 +69,6 @@ data class Media(
dest.writeLong(dateAdded.time)
}
fun delete(contentResolver: ContentResolver) {
contentResolver.delete(externalContentUri, null, null)
}
fun favorite(contentResolver: ContentResolver, value: Boolean) {
contentResolver.update(externalContentUri, ContentValues().apply {
put(MediaStore.MediaColumns.IS_FAVORITE, value)
}, null, null)
}
fun trash(contentResolver: ContentResolver, value: Boolean) {
contentResolver.update(externalContentUri, ContentValues().apply {
put(MediaStore.MediaColumns.IS_TRASHED, value)
}, null, null)
}
companion object CREATOR : Parcelable.Creator<Media> {
override fun createFromParcel(parcel: Parcel) = Media(parcel)

View File

@ -221,13 +221,9 @@ class MediaInfoBottomSheetDialog(
val contentResolver = fragment.requireContext().contentResolver
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
editDescriptionCallback.launch(
contentResolver.createWriteRequest(media.externalContentUri)
)
} else {
editDescription(media, description)
}
editDescriptionCallback.launch(
contentResolver.createWriteRequest(media.externalContentUri)
)
}
private fun editDescription(media: Media, description: String) {

View File

@ -79,11 +79,10 @@ class PermissionsUtils(private val context: Context) {
add(Manifest.permission.READ_MEDIA_IMAGES)
add(Manifest.permission.READ_MEDIA_VIDEO)
} else {
add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
add(Manifest.permission.ACCESS_MEDIA_LOCATION)
add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
add(Manifest.permission.ACCESS_MEDIA_LOCATION)
}.toTypedArray()
}
}

View File

@ -8,9 +8,7 @@
<style name="Theme.Glimpse" parent="Theme.Material3.DayNight.NoActionBar">
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">
shortEdges
</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
</style>