android 14
This commit is contained in:
parent
bd55ff2971
commit
55acf408d0
16 changed files with 38 additions and 64 deletions
|
@ -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
|
||||
|
|
|
@ -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"] ?: "<NONE>",
|
||||
|
|
|
@ -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
|
||||
-->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<uses-permission
|
||||
|
|
|
@ -96,12 +96,7 @@ class SvgRegionFetcher internal constructor(
|
|||
svg.renderToCanvas(canvas, renderOptions)
|
||||
|
||||
bitmap = Bitmap.createBitmap(bitmap, bleedX, bleedY, targetBitmapWidth, targetBitmapHeight)
|
||||
|
||||
if (bitmap != null) {
|
||||
result.success(bitmap.getBytes(canHaveAlpha = true, recycle = true))
|
||||
} else {
|
||||
result.error("fetch-null", "failed to decode region for uri=$uri regionRect=$regionRect", null)
|
||||
}
|
||||
result.success(bitmap.getBytes(canHaveAlpha = true, recycle = true))
|
||||
} catch (e: Exception) {
|
||||
result.error("fetch-read-exception", "failed to initialize region decoder for uri=$uri regionRect=$regionRect", e.message)
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): Ap
|
|||
return if (Build.VERSION.SDK_INT >= 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<out Service>): 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)) {
|
||||
|
|
|
@ -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<Boolean> { cont ->
|
||||
suspendCoroutine { cont: Continuation<Boolean> ->
|
||||
Handler(mainLooper).post {
|
||||
r.run()
|
||||
cont.resume(true)
|
||||
|
|
|
@ -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+
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class AppReference extends StatefulWidget {
|
|||
static List<Widget> 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,
|
||||
),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ class _TagEditorPageState extends State<TagEditorPage> {
|
|||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(AIcons.tagUntagged, color: untaggedColor),
|
||||
Icon(AIcons.tagUntagged, color: untaggedColor),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
l10n.filterNoTagLabel,
|
||||
|
|
|
@ -61,11 +61,11 @@ class _SettingsMobilePageState extends State<SettingsMobilePage> 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)),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
|
|
@ -77,7 +77,7 @@ class _WelcomePageState extends State<WelcomePage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: LinkChip(
|
||||
leading: const Icon(
|
||||
leading: Icon(
|
||||
AIcons.privacy,
|
||||
size: 22,
|
||||
),
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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/
|
||||
|
|
Loading…
Reference in a new issue