diff --git a/CHANGELOG.md b/CHANGELOG.md index b461cb8e1..acbbac6b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. ### Changed +- target Android 14 (API 34) - upgraded Flutter to stable v3.10.4 ### Fixed diff --git a/android/app/build.gradle b/android/app/build.gradle index b48594695..fb9110b6e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -48,7 +48,7 @@ if (keystorePropertiesFile.exists()) { android { namespace 'deckers.thibault.aves' - compileSdk 33 + compileSdk 34 ndkVersion flutter.ndkVersion compileOptions { @@ -75,7 +75,7 @@ android { // which implementation `DocumentBuilderImpl` is provided by the OS and is not customizable on Android, // but the implementation on API <19 is not robust enough and fails to build XMP documents minSdkVersion 19 - targetSdkVersion 33 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName manifestPlaceholders = [googleApiKey: keystoreProperties["googleApiKey"] ?: "", diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a8084c988..df714353e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ TODO TLAD [Android 14 (API 34)] request/handle READ_MEDIA_VISUAL_USER_SELECTED permission cf https://developer.android.com/about/versions/14/changes/partial-photo-video-access --> + = Build.VERSION_CODES.TIRAMISU) { getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong())) } else { - @Suppress("deprecation") getApplicationInfo(packageName, flags) } } @@ -45,7 +44,6 @@ fun PackageManager.queryIntentActivitiesCompat(intent: Intent, flags: Int): List return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { queryIntentActivities(intent, PackageManager.ResolveInfoFlags.of(flags.toLong())) } else { - @Suppress("deprecation") queryIntentActivities(intent, flags) } } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt index df443830d..30d79ebd3 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt @@ -1,13 +1,10 @@ package deckers.thibault.aves.utils -import android.app.ActivityManager -import android.app.Service import android.content.ContentResolver import android.content.ContentUris import android.content.Context import android.database.Cursor import android.net.Uri -import android.provider.DocumentsContract import android.provider.MediaStore import android.util.Log import deckers.thibault.aves.utils.UriUtils.tryParseId @@ -24,19 +21,6 @@ object ContextUtils { .build() } - fun Context.isMyServiceRunning(serviceClass: Class): Boolean { - val am = this.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager - am ?: return false - @Suppress("deprecation") - return am.getRunningServices(Integer.MAX_VALUE).any { it.service.className == serviceClass.name } - } - - // `flag`: `DocumentsContract.Document.FLAG_SUPPORTS_COPY`, etc. - fun Context.queryDocumentProviderFlag(docUri: Uri, flag: Int): Boolean { - val flags = queryContentPropValue(docUri, "", DocumentsContract.Document.COLUMN_FLAGS) as Long? - return if (flags != null) (flags.toInt() and flag) == flag else false - } - fun Context.queryContentPropValue(uri: Uri, mimeType: String, column: String): Any? { var contentUri: Uri = uri if (StorageUtils.isMediaStoreContentUri(uri)) { diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/FlutterUtils.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/FlutterUtils.kt index 5275e0ed3..d3c56d23c 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/FlutterUtils.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/FlutterUtils.kt @@ -11,6 +11,7 @@ import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.embedding.engine.loader.FlutterLoader import io.flutter.view.FlutterCallbackInformation +import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -60,7 +61,7 @@ object FlutterUtils { suspend fun runOnUiThread(r: Runnable) { val mainLooper = Looper.getMainLooper() if (Looper.myLooper() != mainLooper) { - suspendCoroutine { cont -> + suspendCoroutine { cont: Continuation -> Handler(mainLooper).post { r.run() cont.resume(true) diff --git a/android/build.gradle b/android/build.gradle index c173b9fdb..2362dbadb 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.8.21' - agp_version = '8.0.1' + agp_version = '8.0.2' glide_version = '4.15.1' // AppGallery Connect plugin versions: https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-sdk-changenotes-0000001058732550 // TODO TLAD AppGallery Connect plugin v1.9.0.300 does not support Gradle 8+ diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 8f46027fa..876e6420d 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -17,7 +17,7 @@ class AIcons { static const brightnessMin = Icons.brightness_low_outlined; static const brightnessMax = Icons.brightness_high_outlined; static const checked = Icons.done_outlined; - static const count = MdiIcons.counter; + static final count = MdiIcons.counter; static const counter = Icons.plus_one_outlined; static const date = Icons.calendar_today_outlined; static const dateByDay = Icons.today_outlined; @@ -42,11 +42,11 @@ class AIcons { static const mainStorage = Icons.smartphone_outlined; static const mimeType = Icons.code_outlined; static const opacity = Icons.opacity; - static const privacy = MdiIcons.shieldAccountOutline; + static final privacy = MdiIcons.shieldAccountOutline; static const rating = Icons.star_border_outlined; static const ratingFull = Icons.star; - static const ratingRejected = MdiIcons.starMinusOutline; - static const ratingUnrated = MdiIcons.starOffOutline; + static final ratingRejected = MdiIcons.starMinusOutline; + static final ratingUnrated = MdiIcons.starOffOutline; static const raw = Icons.raw_on_outlined; static const shooting = Icons.camera_outlined; static const removableStorage = Icons.sd_storage_outlined; @@ -56,7 +56,7 @@ class AIcons { static const size = Icons.data_usage_outlined; static const text = Icons.format_quote_outlined; static const tag = Icons.local_offer_outlined; - static const tagUntagged = MdiIcons.tagOffOutline; + static final tagUntagged = MdiIcons.tagOffOutline; static const volumeMin = Icons.volume_mute_outlined; static const volumeMax = Icons.volume_up_outlined; @@ -79,35 +79,35 @@ class AIcons { static const clear = Icons.clear_outlined; static const clipboard = Icons.content_copy_outlined; static const convert = Icons.transform_outlined; - static const convertToStillImage = MdiIcons.movieRemoveOutline; + static final convertToStillImage = MdiIcons.movieRemoveOutline; static const copy = Icons.file_copy_outlined; static const debug = Icons.whatshot_outlined; static const delete = Icons.delete_outlined; static const edit = Icons.edit_outlined; static const emptyBin = Icons.delete_sweep_outlined; static const export = Icons.open_with_outlined; - static const fileExport = MdiIcons.fileExportOutline; - static const fileImport = MdiIcons.fileImportOutline; + static final fileExport = MdiIcons.fileExportOutline; + static final fileImport = MdiIcons.fileImportOutline; static const flip = Icons.flip_outlined; static const favourite = Icons.favorite_border; static const favouriteActive = Icons.favorite; - static const filter = MdiIcons.filterOutline; - static const filterOff = MdiIcons.filterOffOutline; + static final filter = MdiIcons.filterOutline; + static final filterOff = MdiIcons.filterOffOutline; static const geoBounds = Icons.public_outlined; static const goUp = Icons.arrow_upward_outlined; static const hide = Icons.visibility_off_outlined; static const info = Icons.info_outlined; static const layers = Icons.layers_outlined; static const map = Icons.map_outlined; - static const move = MdiIcons.fileMoveOutline; + static final move = MdiIcons.fileMoveOutline; static const mute = Icons.volume_off_outlined; static const unmute = Icons.volume_up_outlined; static const name = Icons.abc_outlined; static const newTier = Icons.fiber_new_outlined; static const openOutside = Icons.open_in_new_outlined; - static const openVideo = MdiIcons.moviePlayOutline; + static final openVideo = MdiIcons.moviePlayOutline; static const pin = Icons.push_pin_outlined; - static const unpin = MdiIcons.pinOffOutline; + static final unpin = MdiIcons.pinOffOutline; static const play = Icons.play_arrow; static const pause = Icons.pause; static const print = Icons.print_outlined; @@ -123,10 +123,10 @@ class AIcons { static const search = Icons.search_outlined; static const select = Icons.select_all_outlined; static const setAs = Icons.wallpaper_outlined; - static const setCover = MdiIcons.imageEditOutline; + static final setCover = MdiIcons.imageEditOutline; static const share = Icons.share_outlined; static const show = Icons.visibility_outlined; - static const showFullscreen = MdiIcons.arrowExpand; + static final showFullscreen = MdiIcons.arrowExpand; static const slideshow = Icons.slideshow_outlined; static const speed = Icons.speed_outlined; static const stats = Icons.donut_small_outlined; @@ -136,7 +136,7 @@ class AIcons { static const streamText = Icons.closed_caption_outlined; static const vaultLock = Icons.lock_outline; static const vaultAdd = Icons.enhanced_encryption_outlined; - static const vaultConfigure = MdiIcons.shieldLockOutline; + static final vaultConfigure = MdiIcons.shieldLockOutline; static const videoSettings = Icons.video_settings_outlined; static const view = Icons.grid_view_outlined; static const viewerLock = Icons.lock_outline; @@ -176,6 +176,6 @@ class AIcons { static const selected = Icons.check_circle_outline; static const unselected = Icons.radio_button_unchecked; - static const github = MdiIcons.github; - static const legal = MdiIcons.scaleBalance; + static final github = MdiIcons.github; + static final legal = MdiIcons.scaleBalance; } diff --git a/lib/widgets/about/app_ref.dart b/lib/widgets/about/app_ref.dart index af20e6d55..99d814f00 100644 --- a/lib/widgets/about/app_ref.dart +++ b/lib/widgets/about/app_ref.dart @@ -19,7 +19,7 @@ class AppReference extends StatefulWidget { static List buildLinks(BuildContext context) { final l10n = context.l10n; return [ - const LinkChip( + LinkChip( leading: Icon( AIcons.github, size: 24, @@ -28,7 +28,7 @@ class AppReference extends StatefulWidget { urlString: AppReference.avesGithub, ), LinkChip( - leading: const Icon( + leading: Icon( AIcons.legal, size: 22, ), @@ -36,7 +36,7 @@ class AppReference extends StatefulWidget { urlString: '${AppReference.avesGithub}/blob/main/LICENSE', ), LinkChip( - leading: const Icon( + leading: Icon( AIcons.privacy, size: 22, ), diff --git a/lib/widgets/common/identity/aves_icons.dart b/lib/widgets/common/identity/aves_icons.dart index 022389b7d..f108ca0fe 100644 --- a/lib/widgets/common/identity/aves_icons.dart +++ b/lib/widgets/common/identity/aves_icons.dart @@ -100,7 +100,7 @@ class TagIcon extends StatelessWidget { factory TagIcon.tagged() => const TagIcon._private(icon: AIcons.tag); - factory TagIcon.untagged() => const TagIcon._private(icon: AIcons.tagUntagged); + factory TagIcon.untagged() => TagIcon._private(icon: AIcons.tagUntagged); static const scale = .9; diff --git a/lib/widgets/dialogs/entry_editors/tag_editor_page.dart b/lib/widgets/dialogs/entry_editors/tag_editor_page.dart index 18a8ed91a..246fd4d7b 100644 --- a/lib/widgets/dialogs/entry_editors/tag_editor_page.dart +++ b/lib/widgets/dialogs/entry_editors/tag_editor_page.dart @@ -171,7 +171,7 @@ class _TagEditorPageState extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(AIcons.tagUntagged, color: untaggedColor), + Icon(AIcons.tagUntagged, color: untaggedColor), const SizedBox(width: 8), Text( l10n.filterNoTagLabel, diff --git a/lib/widgets/settings/settings_mobile_page.dart b/lib/widgets/settings/settings_mobile_page.dart index 354e613f0..1ae0c5f9a 100644 --- a/lib/widgets/settings/settings_mobile_page.dart +++ b/lib/widgets/settings/settings_mobile_page.dart @@ -61,11 +61,11 @@ class _SettingsMobilePageState extends State with FeedbackMi return [ PopupMenuItem( value: SettingsAction.export, - child: MenuRow(text: context.l10n.settingsActionExport, icon: const Icon(AIcons.fileExport)), + child: MenuRow(text: context.l10n.settingsActionExport, icon: Icon(AIcons.fileExport)), ), PopupMenuItem( value: SettingsAction.import, - child: MenuRow(text: context.l10n.settingsActionImport, icon: const Icon(AIcons.fileImport)), + child: MenuRow(text: context.l10n.settingsActionImport, icon: Icon(AIcons.fileImport)), ), ]; }, diff --git a/lib/widgets/welcome_page.dart b/lib/widgets/welcome_page.dart index 9a03e5a52..1bde23fa2 100644 --- a/lib/widgets/welcome_page.dart +++ b/lib/widgets/welcome_page.dart @@ -77,7 +77,7 @@ class _WelcomePageState extends State { Padding( padding: const EdgeInsets.all(16), child: LinkChip( - leading: const Icon( + leading: Icon( AIcons.privacy, size: 22, ), diff --git a/pubspec.lock b/pubspec.lock index a0ffa0f13..ce8fe4f26 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -798,18 +798,18 @@ packages: dependency: "direct main" description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" material_design_icons_flutter: dependency: "direct main" description: name: material_design_icons_flutter - sha256: "8ef8562d16e747b2d93e5da5c2508931588939c5c00ebc8e2768e803db7dfd3c" + sha256: "6f986b7a51f3ad4c00e33c5c84e8de1bdd140489bbcdc8b66fc1283dad4dea5a" url: "https://pub.dev" source: hosted - version: "6.0.7096" + version: "7.0.7296" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9725cbffa..07f1d1dba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -128,12 +128,6 @@ dev_dependencies: shared_preferences_platform_interface: test: -dependency_overrides: - # as of Flutter beta v3.10.0-1.5.pre, `flutter_driver` - # constrains `material_color_utilities` to v0.2.0, which - # constrains `dynamic_color` to v1.6.4, which is incompatible with AGP8 - material_color_utilities: ^0.5.0 - flutter: assets: - assets/