platform upgrades

This commit is contained in:
2026-09-02 20:17:17 +02:00
parent 71839d0848
commit f19f212fb4
12 changed files with 51 additions and 56 deletions
+1
View File
@@ -11,3 +11,4 @@ GeneratedPluginRegistrant.java
key.properties key.properties
**/*.keystore **/*.keystore
**/*.jks **/*.jks
.kotlin/
+6 -6
View File
@@ -33,10 +33,6 @@ android {
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled true
} }
kotlinOptions {
jvmTarget = '17'
}
sourceSets { sourceSets {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
} }
@@ -47,7 +43,6 @@ android {
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
multiDexEnabled true
} }
buildTypes { buildTypes {
@@ -59,12 +54,17 @@ android {
} }
} }
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
flutter { flutter {
source '../..' source '../..'
} }
dependencies { dependencies {
implementation 'com.android.support:multidex:2.0.1'
// Same version as workmanager_android pins — needed to enqueue its // Same version as workmanager_android pins — needed to enqueue its
// BackgroundWorker from native widget code (the plugin uses // BackgroundWorker from native widget code (the plugin uses
// `implementation`, so androidx.work is not exposed transitively). // `implementation`, so androidx.work is not exposed transitively).
@@ -1,25 +0,0 @@
// Generated file.
//
// If you wish to remove Flutter's multidex support, delete this entire file.
//
// Modifications to this file should be done in a copy under a different name
// as this file may be regenerated.
package io.flutter.app;
import android.app.Application;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;
/**
* Extension of {@link android.app.Application}, adding multidex support.
*/
public class FlutterMultiDexApplication extends Application {
@Override
@CallSuper
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
+18 -3
View File
@@ -5,10 +5,25 @@ allprojects {
} }
} }
rootProject.buildDir = '../build' rootProject.layout.buildDirectory = file('../build')
subprojects { subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}" project.layout.buildDirectory = rootProject.layout.buildDirectory.dir(project.name)
} }
// AGP 9 enables built-in Kotlin, but Flutter's migrator pins
// android.builtInKotlin=false while the plugin ecosystem catches up. Most
// plugins honour that flag and fall back to KGP themselves; file_picker and
// background_downloader only check the AGP major version and silently skip
// applying KGP, which leaves their Kotlin sources uncompiled (missing
// FilePickerPlugin/BackgroundDownloaderPlugin at link time). Apply KGP for
// them as soon as AGP is on the project, i.e. before their android {} block
// runs. Drop this once both plugins ship a builtInKotlin-aware build script.
gradle.beforeProject { sub ->
if (!(sub.name in ['file_picker', 'background_downloader'])) return
sub.plugins.withId('com.android.library') {
sub.pluginManager.apply('org.jetbrains.kotlin.android')
}
}
// Pin every Android subproject to JVM 17 so plugins that ship Kotlin sources // Pin every Android subproject to JVM 17 so plugins that ship Kotlin sources
// compiled with a higher target (e.g. receive_sharing_intent at 21) or stale // compiled with a higher target (e.g. receive_sharing_intent at 21) or stale
// Java compatibility (e.g. home_widget at 1.8) don't break the build under // Java compatibility (e.g. home_widget at 1.8) don't break the build under
@@ -42,5 +57,5 @@ subprojects {
} }
tasks.register("clean", Delete) { tasks.register("clean", Delete) {
delete rootProject.buildDir delete rootProject.layout.buildDirectory
} }
+2 -6
View File
@@ -1,10 +1,6 @@
org.gradle.jvmargs=-Xmx4G org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
# This builtInKotlin flag was added automatically by Flutter migrator
android.builtInKotlin=false
# This newDsl flag was added automatically by Flutter migrator # This newDsl flag was added automatically by Flutter migrator
android.newDsl=false android.newDsl=false
# This builtInKotlin flag was added automatically by Flutter migrator
android.builtInKotlin=false
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
+3 -3
View File
@@ -19,9 +19,9 @@ pluginManagement {
plugins { plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '8.13.2' apply false id "com.android.application" version '9.1.0' apply false
id "com.android.library" version '8.13.2' apply false id "com.android.library" version '9.1.0' apply false
id "org.jetbrains.kotlin.android" version "2.2.20" apply false id "org.jetbrains.kotlin.android" version "2.4.0" apply false
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0' id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0'
} }
+3 -2
View File
@@ -343,7 +343,8 @@ class PushRegistration {
/// transient plugin/platform hiccup never silently disables push (the OS /// transient plugin/platform hiccup never silently disables push (the OS
/// simply won't show notifications until the user decides). /// simply won't show notifications until the user decides).
static bool isPermissionUsable(AuthorizationStatus status) => static bool isPermissionUsable(AuthorizationStatus status) =>
status != AuthorizationStatus.denied; status != AuthorizationStatus.denied &&
status != AuthorizationStatus.deniedPermanently;
/// Requests the OS notification permission (covers iOS + Android 13) and /// Requests the OS notification permission (covers iOS + Android 13) and
/// returns whether registration should proceed. Errors from the plugin are /// returns whether registration should proceed. Errors from the plugin are
@@ -365,7 +366,7 @@ class PushRegistration {
try { try {
final settings = await FirebaseMessaging.instance final settings = await FirebaseMessaging.instance
.getNotificationSettings(); .getNotificationSettings();
return settings.authorizationStatus == AuthorizationStatus.denied; return !isPermissionUsable(settings.authorizationStatus);
} on Object { } on Object {
return false; return false;
} }
+1
View File
@@ -148,6 +148,7 @@ Future<PushCheck> _osPermission() async {
case AuthorizationStatus.provisional: case AuthorizationStatus.provisional:
return PushCheck.ok; return PushCheck.ok;
case AuthorizationStatus.denied: case AuthorizationStatus.denied:
case AuthorizationStatus.deniedPermanently:
return PushCheck.fail; return PushCheck.fail;
case AuthorizationStatus.notDetermined: case AuthorizationStatus.notDetermined:
return PushCheck.unknown; return PushCheck.unknown;
+1 -1
View File
@@ -203,7 +203,7 @@ class AppModule {
var moveIndex = 0; var moveIndex = 0;
return [ return [
for (final m in effective) for (final m in effective)
displayedSet.contains(m) ? moved[moveIndex++] : m, if (displayedSet.contains(m)) moved[moveIndex++] else m,
]; ];
} }
+4 -4
View File
@@ -20,7 +20,7 @@ dependencies:
async: ^2.11.0 async: ^2.11.0
badges: ^3.1.2 badges: ^3.1.2
cached_network_image: ^3.4.1 cached_network_image: ^4.0.0
# Grapheme-cluster iteration for emoji-only message detection # Grapheme-cluster iteration for emoji-only message detection
# (lib/utils/emoji_detection.dart). Already present transitively via flutter. # (lib/utils/emoji_detection.dart). Already present transitively via flutter.
characters: ^1.4.0 characters: ^1.4.0
@@ -44,7 +44,7 @@ dependencies:
flutter_bloc: ^9.0.0 flutter_bloc: ^9.0.0
flutter_secure_storage: ^10.0.0 flutter_secure_storage: ^10.0.0
home_widget: ^0.9.3 home_widget: ^0.9.3
workmanager: ^0.9.0+3 workmanager: ^0.10.9
intl: ^0.20.2 intl: ^0.20.2
flutter_linkify: ^6.0.0 flutter_linkify: ^6.0.0
linkify: ^5.0.0 linkify: ^5.0.0
@@ -96,7 +96,7 @@ dependencies:
background_downloader: ^9.5.5 background_downloader: ^9.5.5
# Opens the OS notification settings for this app (iOS + Android) when the # Opens the OS notification settings for this app (iOS + Android) when the
# user declined the permission and wants to enable it later. # user declined the permission and wants to enable it later.
app_settings: ^7.0.0 app_settings: ^9.0.0
flutter_layout_grid: ^2.0.8 flutter_layout_grid: ^2.0.8
flutter_markdown_plus: ^1.0.12 flutter_markdown_plus: ^1.0.12
# Underlying parser for flutter_markdown_plus; imported directly to build the # Underlying parser for flutter_markdown_plus; imported directly to build the
@@ -114,7 +114,7 @@ dev_dependencies:
flutter_launcher_icons: ^0.14.3 flutter_launcher_icons: ^0.14.3
build_runner: ^2.10.5 build_runner: ^2.10.5
freezed: ^3.2.4 freezed: ^4.0.0
json_serializable: ^6.11.4 json_serializable: ^6.11.4
flutter_lints: ^6.0.0 flutter_lints: ^6.0.0
+11 -5
View File
@@ -5,10 +5,16 @@ import 'package:marianum_mobile/push/push_registration.dart';
void main() { void main() {
group('PushRegistration.isPermissionUsable', () { group('PushRegistration.isPermissionUsable', () {
test('explicit denial blocks registration', () { test('explicit denial blocks registration', () {
expect( for (final status in [
PushRegistration.isPermissionUsable(AuthorizationStatus.denied), AuthorizationStatus.denied,
isFalse, AuthorizationStatus.deniedPermanently,
); ]) {
expect(
PushRegistration.isPermissionUsable(status),
isFalse,
reason: '$status should block registration',
);
}
}); });
test('all other statuses allow registration', () { test('all other statuses allow registration', () {
@@ -28,7 +34,7 @@ void main() {
test('covers every AuthorizationStatus value', () { test('covers every AuthorizationStatus value', () {
// Guard: if firebase_messaging ever adds a status, revisit the gate. // Guard: if firebase_messaging ever adds a status, revisit the gate.
expect(AuthorizationStatus.values, hasLength(4)); expect(AuthorizationStatus.values, hasLength(5));
}); });
}); });
} }