diff --git a/.gitignore b/.gitignore
index 4d651efb..7c439c7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
.buildlog/
.history
.svn/
+.last_build_id
# IntelliJ related
*.iml
@@ -39,3 +40,6 @@ lib/generated_plugin_registrant.dart
# Firebase
android/app/google-services.json
ios/Runner/GoogleService-Info.plist
+
+# release build
+*.symbols
\ No newline at end of file
diff --git a/README.md b/README.md
index 215a518d..ecaeb720 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@
## 貢獻者
- [morris13579](https://github.com/morris13579)
- [yaoandy107](https://github.com/yaoandy107)
+- [Xanonymous](https://github.com/Xanonymous-GitHub)
- [DevilTea](https://github.com/DevilTea)
## 授權
diff --git a/android/.gitignore b/android/.gitignore
index bc2100d8..eee13a6c 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -5,3 +5,4 @@ gradle-wrapper.jar
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
+*.jks
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index ef30434e..a37171d0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
-apply plugin: 'io.fabric'
+apply plugin: 'com.google.firebase.crashlytics'
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
@@ -35,7 +35,7 @@ if (keystorePropertiesFile.exists()) {
}
android {
- compileSdkVersion 29
+ compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -50,11 +50,12 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "club.ntut.npc.tat"
- minSdkVersion 16
- targetSdkVersion 29
+ minSdkVersion 23
+ targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
signingConfigs {
@@ -71,10 +72,11 @@ android {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.release
- shrinkResources true // To enable code shrinking with ProGuard
- minifyEnabled true // 移除未使用的code, 簡化apk
- proguardFiles getDefaultProguardFile('proguard-android.txt'),
- 'proguard-rules.pro'
+ shrinkResources false // To enable code shrinking with ProGuard
+ minifyEnabled false // remove unused code
+ proguardFiles getDefaultProguardFile(
+ 'proguard-android.txt'
+ ), 'proguard-rules.pro'
}
}
}
@@ -86,11 +88,13 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test:runner:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
-
- implementation 'com.google.firebase:firebase-analytics:17.2.3'
- implementation 'com.llew:reflect:1.0.1'
+ androidTestImplementation 'androidx.test:runner:1.3.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.code.gson:gson:2.8.6'
- implementation "androidx.media:media:1.1.0"
+ implementation "androidx.media:media:1.2.1"
+ implementation 'com.google.firebase:firebase-analytics:18.0.1'
+ implementation 'com.google.firebase:firebase-crashlytics:17.3.0'
+ implementation 'com.google.firebase:firebase-messaging:21.0.1'
+ implementation "androidx.multidex:multidex:2.0.1"
}
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
index ad4751d8..ba9bb15d 100644
--- a/android/app/proguard-rules.pro
+++ b/android/app/proguard-rules.pro
@@ -5,7 +5,6 @@
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
--keep class tv.danmaku.ijk.media.player.** {*;}
-dontwarn io.flutter.embedding.**
@@ -34,4 +33,6 @@
}
## flutter_local_notification plugin rules
--keep class com.dexterous.** { *; }
\ No newline at end of file
+-keep class com.dexterous.** { *; }
+
+-keep class com.google.firebase.provider.FirebaseInitProvider
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 26bc657a..34173ef4 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -13,11 +13,14 @@
+
+ android:usesCleartextTraffic="true"
+ android:label="TAT"
+ tools:targetApi="m">
+
+
+
+
@@ -38,16 +45,18 @@
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/splash" />
+
+
+ -->
+
@@ -64,7 +73,7 @@
-
+
+
+
+
diff --git a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterLogger.java b/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterLogger.java
deleted file mode 100644
index e285b72d..00000000
--- a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterLogger.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.flutter.embedding.engine.hotfix;
-
-import android.util.Log;
-
-public class FlutterLogger {
-
- public static boolean logEnabled = true;
-
- public static String logTag = FlutterLogger.class.getSimpleName();
-
-
- public static void setLogEnabled(boolean enabled) {
- logEnabled = enabled;
- }
-
- public static void i(String msg) {
- i(logTag, msg);
- }
-
- public static void i(String tag, String msg) {
- if (logEnabled) {
- Log.i(tag, msg);
- }
- }
-
- public static void w(String msg) {
- w(logTag, msg);
- }
-
- public static void w(String tag, String msg) {
- if (logEnabled) {
- Log.w(tag, msg);
- }
- }
-
- public static void e(String msg) {
- e(logTag, msg);
- }
-
- public static void e(String tag, String msg) {
- if (logEnabled) {
- Log.e(tag, msg);
- }
- }
-}
diff --git a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterManager.java b/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterManager.java
deleted file mode 100644
index c36b81c5..00000000
--- a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterManager.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.flutter.embedding.engine.hotfix;
-
-import android.content.Context;
-import android.os.Looper;
-
-import java.io.File;
-
-import io.flutter.embedding.engine.loader.FlutterLoader;
-import io.flutter.embedding.engine.loader.FlutterLoaderV012000;
-import io.flutter.view.FlutterMain;
-
-public class FlutterManager {
-
- private static final String TAG = "FlutterManager";
-
- public static void startInitialization(Context context) {
- startInitialization(context, null);
- }
-
- public static void startInitialization(Context context, File aotFile) {
- startInitialization(context, aotFile, FlutterVersion.VERSION_012000);
- }
-
- public static void startInitialization(Context context, File aotFile, FlutterVersion version) {
- startInitialization(context, aotFile, version, new FlutterMain.Settings());
- }
-
- public static void startInitialization(Context context, File aotFile, FlutterVersion version, FlutterMain.Settings settings) {
- ensureInitializeOnMainThread();
- FlutterCallback flutterCallback = generateFlutterCallback(version);
- if (null != flutterCallback) {
- flutterCallback.startInitialization(context, aotFile, getFlutterLoaderSettings(settings));
- } else {
- FlutterLogger.w(TAG, "Flutter Version not supported: " + version);
- FlutterMain.startInitialization(context);
- }
- }
-
- private static void ensureInitializeOnMainThread() {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new IllegalStateException("startInitialization must be called on the main thread");
- }
- }
-
- private static FlutterLoader.Settings getFlutterLoaderSettings(FlutterMain.Settings settings) {
- FlutterLoader.Settings setting = new FlutterLoader.Settings();
- if (null != settings) {
- setting.setLogTag(settings.getLogTag());
- }
- return setting;
- }
-
- private static FlutterCallback generateFlutterCallback(FlutterVersion version) {
- if (FlutterVersion.VERSION_012000 == version) {
- return FlutterLoaderV012000.getInstance();
- }
- return null;
- }
-
- public interface FlutterCallback {
- void startInitialization(Context context, File aotFile, FlutterLoader.Settings settings);
- }
-}
diff --git a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterVersion.java b/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterVersion.java
deleted file mode 100644
index 0fbceb8f..00000000
--- a/android/app/src/main/java/io/flutter/embedding/engine/hotfix/FlutterVersion.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.flutter.embedding.engine.hotfix;
-
-public enum FlutterVersion {
- /**
- * Flutter Version: 1.14.0
- */
- VERSION_012000
-}
diff --git a/android/app/src/main/java/io/flutter/embedding/engine/loader/FlutterLoaderV012000.java b/android/app/src/main/java/io/flutter/embedding/engine/loader/FlutterLoaderV012000.java
deleted file mode 100644
index c3b18ba7..00000000
--- a/android/app/src/main/java/io/flutter/embedding/engine/loader/FlutterLoaderV012000.java
+++ /dev/null
@@ -1,488 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.embedding.engine.loader;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.llew.reflect.FieldUtils;
-
-import io.flutter.BuildConfig;
-import io.flutter.embedding.engine.FlutterJNI;
-import io.flutter.embedding.engine.hotfix.FlutterLogger;
-import io.flutter.embedding.engine.hotfix.FlutterManager;
-import io.flutter.util.PathUtils;
-import io.flutter.view.VsyncWaiter;
-
-import java.io.File;
-import java.util.*;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-/**
- * Finds Flutter resources in an application APK and also loads Flutter's native library.
- */
-public class FlutterLoaderV012000 extends FlutterLoader implements FlutterManager.FlutterCallback {
- private static final String TAG = "FlutterLoader";
-
- // Must match values in flutter::switches
- private static final String AOT_SHARED_LIBRARY_NAME = "aot-shared-library-name";
- private static final String SNAPSHOT_ASSET_PATH_KEY = "snapshot-asset-path";
- private static final String VM_SNAPSHOT_DATA_KEY = "vm-snapshot-data";
- private static final String ISOLATE_SNAPSHOT_DATA_KEY = "isolate-snapshot-data";
- private static final String FLUTTER_ASSETS_DIR_KEY = "flutter-assets-dir";
-
- // XML Attribute keys supported in AndroidManifest.xml
- private static final String PUBLIC_AOT_SHARED_LIBRARY_NAME =
- FlutterLoader.class.getName() + '.' + AOT_SHARED_LIBRARY_NAME;
- private static final String PUBLIC_VM_SNAPSHOT_DATA_KEY =
- FlutterLoader.class.getName() + '.' + VM_SNAPSHOT_DATA_KEY;
- private static final String PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY =
- FlutterLoader.class.getName() + '.' + ISOLATE_SNAPSHOT_DATA_KEY;
- private static final String PUBLIC_FLUTTER_ASSETS_DIR_KEY =
- FlutterLoader.class.getName() + '.' + FLUTTER_ASSETS_DIR_KEY;
-
- // Resource names used for components of the precompiled snapshot.
- private static final String DEFAULT_AOT_SHARED_LIBRARY_NAME = "libapp.so";
- private static final String DEFAULT_VM_SNAPSHOT_DATA = "vm_snapshot_data";
- private static final String DEFAULT_ISOLATE_SNAPSHOT_DATA = "isolate_snapshot_data";
- private static final String DEFAULT_LIBRARY = "libflutter.so";
- private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin";
- private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";
-
- // Mutable because default values can be overridden via config properties
- private String aotSharedLibraryName = DEFAULT_AOT_SHARED_LIBRARY_NAME;
- private String vmSnapshotData = DEFAULT_VM_SNAPSHOT_DATA;
- private String isolateSnapshotData = DEFAULT_ISOLATE_SNAPSHOT_DATA;
- private String flutterAssetsDir = DEFAULT_FLUTTER_ASSETS_DIR;
-
- private static FlutterLoaderV012000 instance;
-
- /**
- * Returns a singleton {@code FlutterLoader} instance.
- *
- *
The returned instance loads Flutter native libraries in the standard way. A singleton object
- * is used instead of static methods to facilitate testing without actually running native library
- * linking.
- */
- @NonNull
- public static FlutterLoaderV012000 getInstance() {
- if (instance == null) {
- instance = new FlutterLoaderV012000();
- }
- return instance;
- }
-
- private boolean initialized = false;
- @Nullable
- private Settings settings;
- private long initStartTimestampMillis;
-
- private static class InitResult {
- final String appStoragePath;
- final String engineCachesPath;
- final String dataDirPath;
-
- private InitResult(String appStoragePath, String engineCachesPath, String dataDirPath) {
- this.appStoragePath = appStoragePath;
- this.engineCachesPath = engineCachesPath;
- this.dataDirPath = dataDirPath;
- }
- }
-
- @Nullable
- Future initResultFuture;
-
- /**
- * Starts initialization of the native system.
- *
- * @param applicationContext The Android application context.
- */
- public void startInitialization(@NonNull Context applicationContext) {
- startInitialization(applicationContext, new Settings());
- }
-
- /**
- * Starts initialization of the native system.
- *
- * This loads the Flutter engine's native library to enable subsequent JNI calls. This also
- * starts locating and unpacking Dart resources packaged in the app's APK.
- *
- *
Calling this method multiple times has no effect.
- *
- * @param applicationContext The Android application context.
- * @param settings Configuration settings.
- */
- public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
- // Do not run startInitialization more than once.
- if (this.settings != null) {
- return;
- }
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new IllegalStateException("startInitialization must be called on the main thread");
- }
-
- // Ensure that the context is actually the application context.
- final Context appContext = applicationContext.getApplicationContext();
-
- this.settings = settings;
-
- initStartTimestampMillis = SystemClock.uptimeMillis();
- initConfig(appContext);
- VsyncWaiter.getInstance((WindowManager) appContext.getSystemService(Context.WINDOW_SERVICE))
- .init();
-
- // Use a background thread for initialization tasks that require disk access.
- Callable initTask =
- new Callable() {
- @Override
- public InitResult call() {
- ResourceExtractor resourceExtractor = initResources(appContext);
-
- System.loadLibrary("flutter");
-
- // Prefetch the default font manager as soon as possible on a background thread.
- // It helps to reduce time cost of engine setup that blocks the platform thread.
- Executors.newSingleThreadExecutor()
- .execute(
- new Runnable() {
- @Override
- public void run() {
- FlutterJNI.nativePrefetchDefaultFontManager();
- }
- });
-
- if (resourceExtractor != null) {
- resourceExtractor.waitForCompletion();
- }
-
- return new InitResult(
- PathUtils.getFilesDir(appContext),
- PathUtils.getCacheDirectory(appContext),
- PathUtils.getDataDirectory(appContext));
- }
- };
- initResultFuture = Executors.newSingleThreadExecutor().submit(initTask);
- }
-
- // *************************************************** hot fix code start ***************************************************//
- private static final String FIELD_NAME = "instance";
-
- private File aotSharedLibraryFile;
-
- @Override
- public void startInitialization(Context context, File aotFile, FlutterLoader.Settings settings) {
- aotSharedLibraryFile = aotFile;
- hookFlutterLoaderIfNecessary();
- FlutterLoader.getInstance().startInitialization(context, settings);
- }
-
- private void hookFlutterLoaderIfNecessary() {
- try {
- if (!flutterLoaderHookedSuccess()) {
- FlutterLogger.i(TAG, "FlutterLoader hook start.");
- FlutterLoaderV012000 instance = FlutterLoaderV012000.getInstance();
- FieldUtils.writeStaticField(FlutterLoader.class, FIELD_NAME, instance);
- FlutterLogger.i(TAG, "FlutterLoader hook finish.");
-
- if (flutterLoaderHookedSuccess()) {
- FlutterLogger.i(TAG, "FlutterLoader hook success.");
- } else {
- FlutterLogger.i(TAG, "FlutterLoader hook failure.");
- }
- } else {
- FlutterLogger.i(TAG, "FlutterLoader already hooked.");
- }
- } catch (Throwable error) {
- FlutterLogger.w(TAG, "FlutterLoader hook " + (flutterLoaderHookedSuccess() ? "success" : "failure") + " and error occured: " + error);
- }
- }
-
- private boolean flutterLoaderHookedSuccess() {
- return FlutterLoader.getInstance() instanceof FlutterLoaderV012000;
- }
-
- /**
- * Blocks until initialization of the native system has completed.
- *
- * Calling this method multiple times has no effect.
- *
- * @param applicationContext The Android application context.
- * @param args Flags sent to the Flutter runtime.
- */
- public void ensureInitializationComplete(
- @NonNull Context applicationContext, @Nullable String[] args) {
- if (initialized) {
- return;
- }
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new IllegalStateException(
- "ensureInitializationComplete must be called on the main thread");
- }
- if (settings == null) {
- throw new IllegalStateException(
- "ensureInitializationComplete must be called after startInitialization");
- }
- try {
- InitResult result = initResultFuture.get();
-
- List shellArgs = new ArrayList<>();
- shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
-
- ApplicationInfo applicationInfo = getApplicationInfo(applicationContext);
- shellArgs.add(
- "--icu-native-lib-path="
- + applicationInfo.nativeLibraryDir
- + File.separator
- + DEFAULT_LIBRARY);
- if (args != null) {
- Collections.addAll(shellArgs, args);
- }
-
- String kernelPath = null;
- if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
- String snapshotAssetPath = result.dataDirPath + File.separator + flutterAssetsDir;
- kernelPath = snapshotAssetPath + File.separator + DEFAULT_KERNEL_BLOB;
- shellArgs.add("--" + SNAPSHOT_ASSET_PATH_KEY + "=" + snapshotAssetPath);
- shellArgs.add("--" + VM_SNAPSHOT_DATA_KEY + "=" + vmSnapshotData);
- shellArgs.add("--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + isolateSnapshotData);
- } else {
- // replace libapp.so fie here if aotSharedLibraryFile is valid
- if (null != aotSharedLibraryFile
- && aotSharedLibraryFile.exists()
- && aotSharedLibraryFile.isFile()
- && aotSharedLibraryFile.canRead()
- && aotSharedLibraryFile.length() > 0) {
- shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryFile.getName());
-
- // Most devices can load the AOT shared library based on the library name
- // with no directory path. Provide a fully qualified path to the library
- // as a workaround for devices where that fails.
- shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryFile.getAbsolutePath());
-
- FlutterLogger.i(TAG, "initialize with fixed file: " + aotSharedLibraryFile.getAbsolutePath());
- } else {
- // aotSharedLibraryFile is not valid, and use origin file here
- shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
-
- // Most devices can load the AOT shared library based on the library name
- // with no directory path. Provide a fully qualified path to the library
- // as a workaround for devices where that fails.
- shellArgs.add(
- "--"
- + AOT_SHARED_LIBRARY_NAME
- + "="
- + applicationInfo.nativeLibraryDir
- + File.separator
- + aotSharedLibraryName);
- FlutterLogger.i(TAG, "initialize with origin file: " + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
- }
-
- }
-
- shellArgs.add("--cache-dir-path=" + result.engineCachesPath);
- if (settings.getLogTag() != null) {
- shellArgs.add("--log-tag=" + settings.getLogTag());
- }
-
- long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
-
- // TODO(cyanlaz): Remove this when dynamic thread merging is done.
- // https://github.com/flutter/flutter/issues/59930
- Bundle bundle = applicationInfo.metaData;
- if (bundle != null) {
- boolean use_embedded_view = bundle.getBoolean("io.flutter.embedded_views_preview");
- if (use_embedded_view) {
- shellArgs.add("--use-embedded-view");
- }
- }
-
- FlutterJNI.nativeInit(
- applicationContext,
- shellArgs.toArray(new String[0]),
- kernelPath,
- result.appStoragePath,
- result.engineCachesPath,
- initTimeMillis);
-
- initialized = true;
- } catch (Exception e) {
- Log.e(TAG, "Flutter initialization failed.", e);
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Same as {@link #ensureInitializationComplete(Context, String[])} but waiting on a background
- * thread, then invoking {@code callback} on the {@code callbackHandler}.
- */
- public void ensureInitializationCompleteAsync(
- @NonNull Context applicationContext,
- @Nullable String[] args,
- @NonNull Handler callbackHandler,
- @NonNull Runnable callback) {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new IllegalStateException(
- "ensureInitializationComplete must be called on the main thread");
- }
- if (settings == null) {
- throw new IllegalStateException(
- "ensureInitializationComplete must be called after startInitialization");
- }
- if (initialized) {
- callbackHandler.post(callback);
- return;
- }
- Executors.newSingleThreadExecutor()
- .execute(
- new Runnable() {
- @Override
- public void run() {
- InitResult result;
- try {
- result = initResultFuture.get();
- } catch (Exception e) {
- Log.e(TAG, "Flutter initialization failed.", e);
- throw new RuntimeException(e);
- }
- new Handler(Looper.getMainLooper())
- .post(
- new Runnable() {
- @Override
- public void run() {
- ensureInitializationComplete(
- applicationContext.getApplicationContext(), args);
- callbackHandler.post(callback);
- }
- });
- }
- });
- }
-
- @NonNull
- private ApplicationInfo getApplicationInfo(@NonNull Context applicationContext) {
- try {
- return applicationContext
- .getPackageManager()
- .getApplicationInfo(applicationContext.getPackageName(), PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Initialize our Flutter config values by obtaining them from the manifest XML file, falling back
- * to default values.
- */
- private void initConfig(@NonNull Context applicationContext) {
- Bundle metadata = getApplicationInfo(applicationContext).metaData;
-
- // There isn't a `` tag as a direct child of `` in
- // `AndroidManifest.xml`.
- if (metadata == null) {
- return;
- }
-
- aotSharedLibraryName =
- metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME);
- flutterAssetsDir =
- metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);
-
- vmSnapshotData = metadata.getString(PUBLIC_VM_SNAPSHOT_DATA_KEY, DEFAULT_VM_SNAPSHOT_DATA);
- isolateSnapshotData =
- metadata.getString(PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_ISOLATE_SNAPSHOT_DATA);
- }
-
- /**
- * Extract assets out of the APK that need to be cached as uncompressed files on disk.
- */
- private ResourceExtractor initResources(@NonNull Context applicationContext) {
- ResourceExtractor resourceExtractor = null;
- if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
- final String dataDirPath = PathUtils.getDataDirectory(applicationContext);
- final String packageName = applicationContext.getPackageName();
- final PackageManager packageManager = applicationContext.getPackageManager();
- final AssetManager assetManager = applicationContext.getResources().getAssets();
- resourceExtractor =
- new ResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
-
- // In debug/JIT mode these assets will be written to disk and then
- // mapped into memory so they can be provided to the Dart VM.
- resourceExtractor
- .addResource(fullAssetPathFrom(vmSnapshotData))
- .addResource(fullAssetPathFrom(isolateSnapshotData))
- .addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
-
- resourceExtractor.start();
- }
- return resourceExtractor;
- }
-
- @NonNull
- public String findAppBundlePath() {
- return flutterAssetsDir;
- }
-
- /**
- * Returns the file name for the given asset. The returned file name can be used to access the
- * asset in the APK through the {@link android.content.res.AssetManager} API.
- *
- * @param asset the name of the asset. The name can be hierarchical
- * @return the filename to be used with {@link android.content.res.AssetManager}
- */
- @NonNull
- public String getLookupKeyForAsset(@NonNull String asset) {
- return fullAssetPathFrom(asset);
- }
-
- /**
- * Returns the file name for the given asset which originates from the specified packageName. The
- * returned file name can be used to access the asset in the APK through the {@link
- * android.content.res.AssetManager} API.
- *
- * @param asset the name of the asset. The name can be hierarchical
- * @param packageName the name of the package from which the asset originates
- * @return the file name to be used with {@link android.content.res.AssetManager}
- */
- @NonNull
- public String getLookupKeyForAsset(@NonNull String asset, @NonNull String packageName) {
- return getLookupKeyForAsset("packages" + File.separator + packageName + File.separator + asset);
- }
-
- @NonNull
- private String fullAssetPathFrom(@NonNull String filePath) {
- return flutterAssetsDir + File.separator + filePath;
- }
-
- public static class Settings {
- private String logTag;
-
- @Nullable
- public String getLogTag() {
- return logTag;
- }
-
- /**
- * Set the tag associated with Flutter app log messages.
- *
- * @param tag Log tag.
- */
- public void setLogTag(String tag) {
- logTag = tag;
- }
- }
-}
diff --git a/android/app/src/main/java/widget/CourseWidgetProvider.java b/android/app/src/main/java/widget/CourseWidgetProvider.java
index 6c6226c0..cb710374 100644
--- a/android/app/src/main/java/widget/CourseWidgetProvider.java
+++ b/android/app/src/main/java/widget/CourseWidgetProvider.java
@@ -14,7 +14,7 @@
import java.util.Arrays;
-import club.ntut.npc.tat.BootLoaderActivity;
+import club.ntut.npc.tat.MainActivity;
import club.ntut.npc.tat.R;
import io.flutter.Log;
@@ -50,7 +50,8 @@ public void onReceive(Context context, Intent intent) {
if (ACTION_ONCLICK.equals(intent.getAction())) {
//Toast.makeText(context, "開啟app", Toast.LENGTH_LONG).show();
- Intent actIntent = new Intent(context, BootLoaderActivity.class);
+ //Intent actIntent = new Intent(context, BootLoaderActivity.class);
+ Intent actIntent = new Intent(context, MainActivity.class);
actIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
context.startActivity(actIntent);
}
diff --git a/android/app/src/main/kotlin/club/ntut/npc/tat/Application.java b/android/app/src/main/kotlin/club/ntut/npc/tat/Application.java
new file mode 100644
index 00000000..f140c942
--- /dev/null
+++ b/android/app/src/main/kotlin/club/ntut/npc/tat/Application.java
@@ -0,0 +1,20 @@
+package club.ntut.npc.tat;
+
+import io.flutter.app.FlutterApplication;
+import io.flutter.plugin.common.PluginRegistry;
+import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundService;
+import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin;
+
+public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ FlutterFirebaseMessagingBackgroundService.setPluginRegistrant(this);
+ }
+
+ @Override
+ public void registerWith(PluginRegistry registry) {
+
+ //FlutterFirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin"));
+ }
+}
diff --git a/android/app/src/main/kotlin/club/ntut/npc/tat/BootLoaderActivity.java b/android/app/src/main/kotlin/club/ntut/npc/tat/BootLoaderActivity.java
deleted file mode 100644
index 99241624..00000000
--- a/android/app/src/main/kotlin/club/ntut/npc/tat/BootLoaderActivity.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package club.ntut.npc.tat;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import androidx.annotation.Nullable;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.nio.channels.FileChannel;
-
-import io.flutter.embedding.engine.hotfix.FlutterLogger;
-import io.flutter.embedding.engine.hotfix.FlutterManager;
-import io.flutter.embedding.engine.hotfix.FlutterVersion;
-
-public class BootLoaderActivity extends Activity {
- //final String Tag = "BootLoaderActivity";
-
- final String flutter_state_key = "flutter.flutter_state"; //會刪除由flutter app寫入如果檢查到沒寫入代表app crash,會清除補丁
- final String app_version_key = "flutter.version"; //取得之前執行APP版本
- final String app_patch_version = "flutter.patch_version";
- final String hotfixFileName = "hotfix.so";
-
- SharedPreferences pref;
- File dir;
-
- public String getVersionName(Context context) {
- PackageManager packageManager = context.getPackageManager();
- PackageInfo packageInfo;
- String versionName = "";
- try {
- packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
- versionName = packageInfo.versionName;
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- return versionName;
- }
-
- void checkPatchDir() {
- if (!dir.exists()) {
- if (dir.mkdirs()) {
- FlutterLogger.i("mkdirs success: " + dir.getAbsolutePath());
- } else {
- FlutterLogger.i("mkdirs failure: " + dir.getAbsolutePath());
- }
- } else {
- FlutterLogger.i("dirs exists: " + dir.getAbsolutePath());
- }
- }
-
- void handleAppVersionUpdate() {
- String appVersionNow = getVersionName(getApplicationContext());
- String appVersionName = pref.getString(app_version_key, appVersionNow);
- boolean app_version_update = !appVersionName.contains(appVersionNow); //版本號不同刪除補丁
- if (app_version_update) { //app版本更新
- File dest = new File(dir, hotfixFileName);
- try {
- if (dest.exists() && !dest.delete()) { //刪除舊的補釘
- FileWriter writer = new FileWriter(dest, false);
- writer.write("");
- writer.flush();
- writer.close();
- }
- pref.edit().remove(app_patch_version).apply();
- } catch (Exception e) {
- FlutterLogger.i("delete fail");
- }
- }
- }
-
- void handleAppCrash() {
- boolean launch_success = pref.contains(flutter_state_key); //如果flutter沒有正常啟動就不會寫入
- if (!launch_success) { //載入失敗刪除補丁
- File dest = new File(dir, hotfixFileName);
- try {
- if (dest.exists() && !dest.delete()) { //刪除舊的補釘
- FileWriter writer = new FileWriter(dest, false);
- writer.write("");
- writer.flush();
- writer.close();
- }
- } catch (Exception e) {
- FlutterLogger.i("delete fail");
- }
- }
- pref.edit().remove(flutter_state_key).apply(); //每次啟動會刪除由flutter重新寫入
- }
-
-
- void handlePatchUpdate() {
- try {
- File downloadDir = getApplicationContext().getExternalFilesDir(null);
- File source = new File(downloadDir, hotfixFileName);
- File dest = new File(dir, hotfixFileName);
- if (source.exists()) { //檢查是否有要更新的補丁
- //寫入前將舊的補丁刪除
- if (dest.exists() && !dest.delete()) { //刪除舊的補釘
- FileWriter writer = new FileWriter(dest, false);
- writer.write("");
- writer.flush();
- writer.close();
- }
- FileChannel inputChannel = new FileInputStream(source).getChannel();
- FileChannel outputChannel = new FileOutputStream(dest).getChannel();
- outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
- inputChannel.close();
- outputChannel.close();
- if (source.delete()) {
- FlutterLogger.i("delete patch");
- }
- FlutterLogger.i("copy fixed file finish: " + dest.getAbsolutePath());
- }
- } catch (Throwable error) {
- FlutterLogger.e("copy file error: " + error);
- }
- }
-
-
- void loadPatch() {
- File dest = new File(dir, hotfixFileName);
- if (dest.exists()) { //檢查如果補釘存在就載入
- FlutterManager.startInitialization(this, dest, FlutterVersion.VERSION_012000);
- }
- }
-
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- pref = getSharedPreferences("FlutterSharedPreferences", MODE_PRIVATE);
- dir = new File(getFilesDir(), "/flutter/hotfix"); //更新目錄
- setContentView(R.layout.bootloader_activity);
- //創建補丁存放資料夾
- checkPatchDir();
- //app版本更新刪除patch
- handleAppVersionUpdate();
- //處理更新補釘後app無法開啟
- handleAppCrash();
- //檢查補釘是否要更新
- handlePatchUpdate();
- //載入補釘
- loadPatch();
- //啟動flutter
- Intent intent = new Intent(this, MainActivity.class);
- BootLoaderActivity.this.startActivity(intent);
- BootLoaderActivity.this.finish();
- }
-
-
-}
diff --git a/android/app/src/main/kotlin/club/ntut/npc/tat/MainActivity.kt b/android/app/src/main/kotlin/club/ntut/npc/tat/MainActivity.kt
index 2b079625..2aa7c144 100644
--- a/android/app/src/main/kotlin/club/ntut/npc/tat/MainActivity.kt
+++ b/android/app/src/main/kotlin/club/ntut/npc/tat/MainActivity.kt
@@ -6,15 +6,15 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import androidx.annotation.NonNull
-import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin
import io.flutter.Log
import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import kotlin.system.exitProcess
-class MainActivity : FlutterActivity() {
+class MainActivity : FlutterFragmentActivity() {
private val channelName = "club.ntut.npc.tat.main.mothod.channel.name"
private val logTag = "FlutterActivity"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
@@ -27,7 +27,7 @@ class MainActivity : FlutterActivity() {
Log.i(logTag, "update_weight")
try {
val intend = Intent("android.appwidget.action.APPWIDGET_UPDATE") //顯示意圖
- context.sendBroadcast(intend)
+ this.sendBroadcast(intend)
result.success(true)
} catch (e: Exception) {
result.success(false)
@@ -36,7 +36,7 @@ class MainActivity : FlutterActivity() {
}
}
"restart_app" -> {
- doRestart(context);
+ doRestart(this)
}
else -> {
result.notImplemented()
diff --git a/android/app/src/main/kotlin/club/ntut/npc/tat/MyFlutterLocalNotificationsPlugin.java b/android/app/src/main/kotlin/club/ntut/npc/tat/MyFlutterLocalNotificationsPlugin.java
deleted file mode 100644
index 5626a91a..00000000
--- a/android/app/src/main/kotlin/club/ntut/npc/tat/MyFlutterLocalNotificationsPlugin.java
+++ /dev/null
@@ -1,980 +0,0 @@
-package club.ntut.npc.tat;
-
-import android.app.Activity;
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.AudioAttributes;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Build;
-import android.text.Html;
-import android.text.Spanned;
-
-import androidx.annotation.NonNull;
-import androidx.core.app.AlarmManagerCompat;
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-import androidx.core.app.Person;
-import androidx.core.graphics.drawable.IconCompat;
-
-import com.dexterous.flutterlocalnotifications.BitmapSource;
-import com.dexterous.flutterlocalnotifications.NotificationStyle;
-import com.dexterous.flutterlocalnotifications.RuntimeTypeAdapterFactory;
-import com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver;
-import com.dexterous.flutterlocalnotifications.SoundSource;
-import com.dexterous.flutterlocalnotifications.models.IconSource;
-import com.dexterous.flutterlocalnotifications.models.MessageDetails;
-import com.dexterous.flutterlocalnotifications.models.NotificationChannelAction;
-import com.dexterous.flutterlocalnotifications.models.NotificationChannelDetails;
-import com.dexterous.flutterlocalnotifications.models.NotificationDetails;
-import com.dexterous.flutterlocalnotifications.models.PersonDetails;
-import com.dexterous.flutterlocalnotifications.models.styles.BigPictureStyleInformation;
-import com.dexterous.flutterlocalnotifications.models.styles.BigTextStyleInformation;
-import com.dexterous.flutterlocalnotifications.models.styles.DefaultStyleInformation;
-import com.dexterous.flutterlocalnotifications.models.styles.InboxStyleInformation;
-import com.dexterous.flutterlocalnotifications.models.styles.MessagingStyleInformation;
-import com.dexterous.flutterlocalnotifications.models.styles.StyleInformation;
-import com.dexterous.flutterlocalnotifications.utils.BooleanUtils;
-import com.dexterous.flutterlocalnotifications.utils.StringUtils;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import io.flutter.embedding.engine.plugins.FlutterPlugin;
-import io.flutter.embedding.engine.plugins.activity.ActivityAware;
-import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
-import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.MethodCall;
-import io.flutter.plugin.common.MethodChannel;
-import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
-import io.flutter.plugin.common.MethodChannel.Result;
-import io.flutter.plugin.common.PluginRegistry;
-import io.flutter.plugin.common.PluginRegistry.Registrar;
-import io.flutter.view.FlutterMain;
-
-/**
- * FlutterLocalNotificationsPlugin
- */
-public class MyFlutterLocalNotificationsPlugin implements MethodCallHandler, PluginRegistry.NewIntentListener, FlutterPlugin, ActivityAware {
- private static final String SHARED_PREFERENCES_KEY = "notification_plugin_cache";
- private static final String DRAWABLE = "drawable";
- private static final String DEFAULT_ICON = "defaultIcon";
- private static final String SELECT_NOTIFICATION = "SELECT_NOTIFICATION";
- private static final String SCHEDULED_NOTIFICATIONS = "scheduled_notifications";
- private static final String INITIALIZE_METHOD = "initialize";
- private static final String CREATE_NOTIFICATION_CHANNEL_METHOD = "createNotificationChannel";
- private static final String DELETE_NOTIFICATION_CHANNEL_METHOD = "deleteNotificationChannel";
- private static final String PENDING_NOTIFICATION_REQUESTS_METHOD = "pendingNotificationRequests";
- private static final String SHOW_METHOD = "show";
- private static final String CANCEL_METHOD = "cancel";
- private static final String CANCEL_ALL_METHOD = "cancelAll";
- private static final String SCHEDULE_METHOD = "schedule";
- private static final String PERIODICALLY_SHOW_METHOD = "periodicallyShow";
- private static final String SHOW_DAILY_AT_TIME_METHOD = "showDailyAtTime";
- private static final String SHOW_WEEKLY_AT_DAY_AND_TIME_METHOD = "showWeeklyAtDayAndTime";
- private static final String GET_NOTIFICATION_APP_LAUNCH_DETAILS_METHOD = "getNotificationAppLaunchDetails";
- private static final String METHOD_CHANNEL = "dexterous.com/flutter/local_notifications";
- private static final String PAYLOAD = "payload";
- private static final String INVALID_ICON_ERROR_CODE = "INVALID_ICON";
- private static final String INVALID_LARGE_ICON_ERROR_CODE = "INVALID_LARGE_ICON";
- private static final String INVALID_BIG_PICTURE_ERROR_CODE = "INVALID_BIG_PICTURE";
- private static final String INVALID_SOUND_ERROR_CODE = "INVALID_SOUND";
- private static final String INVALID_LED_DETAILS_ERROR_CODE = "INVALID_LED_DETAILS";
- private static final String INVALID_LED_DETAILS_ERROR_MESSAGE = "Must specify both ledOnMs and ledOffMs to configure the blink cycle on older versions of Android before Oreo";
- private static final String NOTIFICATION_LAUNCHED_APP = "notificationLaunchedApp";
- private static final String INVALID_DRAWABLE_RESOURCE_ERROR_MESSAGE = "The resource %s could not be found. Please make sure it has been added as a drawable resource to your Android head project.";
- private static final String INVALID_RAW_RESOURCE_ERROR_MESSAGE = "The resource %s could not be found. Please make sure it has been added as a raw resource to your Android head project.";
- static String NOTIFICATION_ID = "notification_id";
- static String NOTIFICATION = "notification";
- static String NOTIFICATION_DETAILS = "notificationDetails";
- static String REPEAT = "repeat";
- static Gson gson;
- private MethodChannel channel;
- private Context applicationContext;
- private Activity mainActivity;
- private boolean initialized;
-
- public static void registerWith(Registrar registrar) {
- MyFlutterLocalNotificationsPlugin plugin = new MyFlutterLocalNotificationsPlugin();
- plugin.setActivity(registrar.activity());
- registrar.addNewIntentListener(plugin);
- plugin.onAttachedToEngine(registrar.context(), registrar.messenger());
- }
-
- static void rescheduleNotifications(Context context) {
- ArrayList scheduledNotifications = loadScheduledNotifications(context);
- for (NotificationDetails scheduledNotification : scheduledNotifications) {
- if (scheduledNotification.repeatInterval == null) {
- scheduleNotification(context, scheduledNotification, false);
- } else {
- repeatNotification(context, scheduledNotification, false);
- }
- }
- }
-
- private static Notification createNotification(Context context, NotificationDetails notificationDetails) {
- setupNotificationChannel(context, NotificationChannelDetails.fromNotificationDetails(notificationDetails));
- Intent intent = new Intent(context, getMainActivityClass(context));
- intent.setAction(SELECT_NOTIFICATION);
- intent.putExtra(PAYLOAD, notificationDetails.payload);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, notificationDetails.id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- DefaultStyleInformation defaultStyleInformation = (DefaultStyleInformation) notificationDetails.styleInformation;
- NotificationCompat.Builder builder = new NotificationCompat.Builder(context, notificationDetails.channelId)
- .setContentTitle(defaultStyleInformation.htmlFormatTitle ? fromHtml(notificationDetails.title) : notificationDetails.title)
- .setContentText(defaultStyleInformation.htmlFormatBody ? fromHtml(notificationDetails.body) : notificationDetails.body)
- .setTicker(notificationDetails.ticker)
- .setAutoCancel(BooleanUtils.getValue(notificationDetails.autoCancel))
- .setContentIntent(pendingIntent)
- .setPriority(notificationDetails.priority)
- .setOngoing(BooleanUtils.getValue(notificationDetails.ongoing))
- .setOnlyAlertOnce(BooleanUtils.getValue(notificationDetails.onlyAlertOnce));
-
- setSmallIcon(context, notificationDetails, builder);
- if (!StringUtils.isNullOrEmpty(notificationDetails.largeIcon)) {
- builder.setLargeIcon(getBitmapFromSource(context, notificationDetails.largeIcon, notificationDetails.largeIconBitmapSource));
- }
- if (notificationDetails.color != null) {
- builder.setColor(notificationDetails.color.intValue());
- }
-
- if (notificationDetails.showWhen != null) {
- builder.setShowWhen(BooleanUtils.getValue(notificationDetails.showWhen));
- }
-
- if (notificationDetails.when != null) {
- builder.setWhen(notificationDetails.when);
- }
-
- setVisibility(notificationDetails, builder);
- applyGrouping(notificationDetails, builder);
- setSound(context, notificationDetails, builder);
- setVibrationPattern(notificationDetails, builder);
- setLights(notificationDetails, builder);
- setStyle(context, notificationDetails, builder);
- setProgress(notificationDetails, builder);
- setCategory(notificationDetails, builder);
- setTimeoutAfter(notificationDetails, builder);
- Notification notification = builder.build();
- if (notificationDetails.additionalFlags != null && notificationDetails.additionalFlags.length > 0) {
- for(int additionalFlag:notificationDetails.additionalFlags) {
- notification.flags |= additionalFlag;
- }
- }
- return notification;
- }
-
- private static void setSmallIcon(Context context, NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (!StringUtils.isNullOrEmpty(notificationDetails.icon)) {
- builder.setSmallIcon(getDrawableResourceId(context, notificationDetails.icon));
- } else {
- SharedPreferences sharedPreferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
- String defaultIcon = sharedPreferences.getString(DEFAULT_ICON, null);
- if (StringUtils.isNullOrEmpty(defaultIcon)) {
- // for backwards compatibility: this is for handling the old way references to the icon used to be kept but should be removed in future
- builder.setSmallIcon(notificationDetails.iconResourceId);
-
- } else {
- builder.setSmallIcon(getDrawableResourceId(context, defaultIcon));
- }
- }
- }
-
- @NonNull
- static Gson buildGson() {
- if (gson == null) {
- RuntimeTypeAdapterFactory styleInformationAdapter =
- RuntimeTypeAdapterFactory
- .of(StyleInformation.class)
- .registerSubtype(DefaultStyleInformation.class)
- .registerSubtype(BigTextStyleInformation.class)
- .registerSubtype(BigPictureStyleInformation.class)
- .registerSubtype(InboxStyleInformation.class)
- .registerSubtype(MessagingStyleInformation.class);
- GsonBuilder builder = new GsonBuilder().registerTypeAdapterFactory(styleInformationAdapter);
- gson = builder.create();
- }
- return gson;
- }
-
- private static ArrayList loadScheduledNotifications(Context context) {
- ArrayList scheduledNotifications = new ArrayList<>();
- SharedPreferences sharedPreferences = context.getSharedPreferences(SCHEDULED_NOTIFICATIONS, Context.MODE_PRIVATE);
- String json = sharedPreferences.getString(SCHEDULED_NOTIFICATIONS, null);
- if (json != null) {
- Gson gson = buildGson();
- Type type = new TypeToken>() {
- }.getType();
- scheduledNotifications = gson.fromJson(json, type);
- }
- return scheduledNotifications;
- }
-
- private static void saveScheduledNotifications(Context context, ArrayList scheduledNotifications) {
- Gson gson = buildGson();
- String json = gson.toJson(scheduledNotifications);
- SharedPreferences sharedPreferences = context.getSharedPreferences(SCHEDULED_NOTIFICATIONS, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putString(SCHEDULED_NOTIFICATIONS, json);
- editor.commit();
- }
-
- static void removeNotificationFromCache(Integer notificationId, Context context) {
- ArrayList scheduledNotifications = loadScheduledNotifications(context);
- for (Iterator it = scheduledNotifications.iterator(); it.hasNext(); ) {
- NotificationDetails notificationDetails = it.next();
- if (notificationDetails.id.equals(notificationId)) {
- it.remove();
- break;
- }
- }
- saveScheduledNotifications(context, scheduledNotifications);
- }
-
- @SuppressWarnings("deprecation")
- private static Spanned fromHtml(String html) {
- if (html == null) {
- return null;
- }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
- } else {
- return Html.fromHtml(html);
- }
- }
-
- private static void scheduleNotification(Context context, final NotificationDetails notificationDetails, Boolean updateScheduledNotificationsCache) {
- Gson gson = buildGson();
- String notificationDetailsJson = gson.toJson(notificationDetails);
- Intent notificationIntent = new Intent(context, ScheduledNotificationReceiver.class);
- notificationIntent.putExtra(NOTIFICATION_DETAILS, notificationDetailsJson);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationDetails.id, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- AlarmManager alarmManager = getAlarmManager(context);
- if (BooleanUtils.getValue(notificationDetails.allowWhileIdle)) {
- AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, notificationDetails.millisecondsSinceEpoch, pendingIntent);
- } else {
- AlarmManagerCompat.setExact(alarmManager, AlarmManager.RTC_WAKEUP, notificationDetails.millisecondsSinceEpoch, pendingIntent);
- }
-
- if (updateScheduledNotificationsCache) {
- saveScheduledNotification(context, notificationDetails);
- }
- }
-
- private static void repeatNotification(Context context, NotificationDetails notificationDetails, Boolean updateScheduledNotificationsCache) {
- Gson gson = buildGson();
- String notificationDetailsJson = gson.toJson(notificationDetails);
- Intent notificationIntent = new Intent(context, ScheduledNotificationReceiver.class);
- notificationIntent.putExtra(NOTIFICATION_DETAILS, notificationDetailsJson);
- notificationIntent.putExtra(REPEAT, true);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationDetails.id, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- AlarmManager alarmManager = getAlarmManager(context);
- long repeatInterval = 0;
- switch (notificationDetails.repeatInterval) {
- case EveryMinute:
- repeatInterval = 60000;
- break;
- case Hourly:
- repeatInterval = 60000 * 60;
- break;
- case Daily:
- repeatInterval = 60000 * 60 * 24;
- break;
- case Weekly:
- repeatInterval = 60000 * 60 * 24 * 7;
- break;
- default:
- break;
- }
-
- long startTimeMilliseconds = notificationDetails.calledAt;
- if (notificationDetails.repeatTime != null) {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(System.currentTimeMillis());
- calendar.set(Calendar.HOUR_OF_DAY, notificationDetails.repeatTime.hour);
- calendar.set(Calendar.MINUTE, notificationDetails.repeatTime.minute);
- calendar.set(Calendar.SECOND, notificationDetails.repeatTime.second);
- if (notificationDetails.day != null) {
- calendar.set(Calendar.DAY_OF_WEEK, notificationDetails.day);
- }
-
- startTimeMilliseconds = calendar.getTimeInMillis();
- }
-
- // ensure that start time is in the future
- long currentTime = System.currentTimeMillis();
- while (startTimeMilliseconds < currentTime) {
- startTimeMilliseconds += repeatInterval;
- }
-
- alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, startTimeMilliseconds, repeatInterval, pendingIntent);
-
- if (updateScheduledNotificationsCache) {
- saveScheduledNotification(context, notificationDetails);
- }
- }
-
- private static void saveScheduledNotification(Context context, NotificationDetails notificationDetails) {
- ArrayList scheduledNotifications = loadScheduledNotifications(context);
- ArrayList scheduledNotificationsToSave = new ArrayList<>();
- for (NotificationDetails scheduledNotification : scheduledNotifications) {
- if (scheduledNotification.id == notificationDetails.id) {
- continue;
- }
- scheduledNotificationsToSave.add(scheduledNotification);
- }
- scheduledNotificationsToSave.add(notificationDetails);
- saveScheduledNotifications(context, scheduledNotificationsToSave);
- }
-
- private static int getDrawableResourceId(Context context, String name) {
- return context.getResources().getIdentifier(name, DRAWABLE, context.getPackageName());
- }
-
- private static Bitmap getBitmapFromSource(Context context, String bitmapPath, BitmapSource bitmapSource) {
- Bitmap bitmap = null;
- if (bitmapSource == BitmapSource.DrawableResource) {
- bitmap = BitmapFactory.decodeResource(context.getResources(), getDrawableResourceId(context, bitmapPath));
- } else if (bitmapSource == BitmapSource.FilePath) {
- bitmap = BitmapFactory.decodeFile(bitmapPath);
- }
-
- return bitmap;
- }
-
- private static IconCompat getIconFromSource(Context context, String iconPath, IconSource iconSource) {
- IconCompat icon = null;
- switch (iconSource) {
- case DrawableResource:
- icon = IconCompat.createWithResource(context, getDrawableResourceId(context, iconPath));
- break;
- case BitmapFilePath:
- icon = IconCompat.createWithBitmap(BitmapFactory.decodeFile(iconPath));
- break;
- case ContentUri:
- icon = IconCompat.createWithContentUri(iconPath);
- break;
- case FlutterBitmapAsset:
- try {
- AssetFileDescriptor assetFileDescriptor = context.getAssets().openFd(FlutterMain.getLookupKeyForAsset(iconPath));
- FileInputStream fileInputStream = assetFileDescriptor.createInputStream();
- icon = IconCompat.createWithBitmap(BitmapFactory.decodeStream(fileInputStream));
- fileInputStream.close();
- assetFileDescriptor.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- break;
- default:
- break;
- }
- return icon;
- }
-
- /**
- * Sets the visibility property to the input Notification Builder
- *
- * @throws IllegalArgumentException If `notificationDetails.visibility` is not null but also
- * not matches any known index.
- */
- private static void setVisibility(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (notificationDetails.visibility == null) {
- return;
- }
-
- int visibility;
- switch (notificationDetails.visibility) {
- case 0: // Private
- visibility = NotificationCompat.VISIBILITY_PRIVATE;
- break;
- case 1: // Public
- visibility = NotificationCompat.VISIBILITY_PUBLIC;
- break;
- case 2: // Secret
- visibility = NotificationCompat.VISIBILITY_SECRET;
- break;
-
- default:
- throw new IllegalArgumentException("Unknown index: " + notificationDetails.visibility);
- }
-
- builder.setVisibility(visibility);
- }
-
- private static void applyGrouping(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- boolean isGrouped = false;
- if (!StringUtils.isNullOrEmpty(notificationDetails.groupKey)) {
- builder.setGroup(notificationDetails.groupKey);
- isGrouped = true;
- }
-
- if (isGrouped) {
- if (BooleanUtils.getValue(notificationDetails.setAsGroupSummary)) {
- builder.setGroupSummary(true);
- }
-
- builder.setGroupAlertBehavior(notificationDetails.groupAlertBehavior);
- }
- }
-
- private static void setVibrationPattern(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (BooleanUtils.getValue(notificationDetails.enableVibration)) {
- if (notificationDetails.vibrationPattern != null && notificationDetails.vibrationPattern.length > 0) {
- builder.setVibrate(notificationDetails.vibrationPattern);
- }
- } else {
- builder.setVibrate(new long[]{0});
- }
- }
-
- private static void setLights(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (BooleanUtils.getValue(notificationDetails.enableLights) && notificationDetails.ledOnMs != null && notificationDetails.ledOffMs != null) {
- builder.setLights(notificationDetails.ledColor, notificationDetails.ledOnMs, notificationDetails.ledOffMs);
- }
- }
-
- private static void setSound(Context context, NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (BooleanUtils.getValue(notificationDetails.playSound)) {
- Uri uri = retrieveSoundResourceUri(context, notificationDetails.sound, notificationDetails.soundSource);
- builder.setSound(uri);
- } else {
- builder.setSound(null);
- }
- }
-
- private static void setCategory(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (notificationDetails.category == null) {
- return;
- }
- builder.setCategory(notificationDetails.category);
- }
-
- private static void setTimeoutAfter(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (notificationDetails.timeoutAfter == null) {
- return;
- }
- builder.setTimeoutAfter(notificationDetails.timeoutAfter);
- }
-
- private static Class getMainActivityClass(Context context) {
- String className = MainActivity.class.getName();
- try {
- return Class.forName(className);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- private static void setStyle(Context context, NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- switch (notificationDetails.style) {
- case BigPicture:
- setBigPictureStyle(context, notificationDetails, builder);
- break;
- case BigText:
- setBigTextStyle(notificationDetails, builder);
- break;
- case Inbox:
- setInboxStyle(notificationDetails, builder);
- break;
- case Messaging:
- setMessagingStyle(context, notificationDetails, builder);
- break;
- case Media:
- setMediaStyle(builder);
- break;
- default:
- break;
- }
- }
-
- private static void setProgress(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- if (BooleanUtils.getValue(notificationDetails.showProgress)) {
- builder.setProgress(notificationDetails.maxProgress, notificationDetails.progress, notificationDetails.indeterminate);
- }
- }
-
- private static void setBigPictureStyle(Context context, NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- BigPictureStyleInformation bigPictureStyleInformation = (BigPictureStyleInformation) notificationDetails.styleInformation;
- NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
- if (bigPictureStyleInformation.contentTitle != null) {
- CharSequence contentTitle = bigPictureStyleInformation.htmlFormatContentTitle ? fromHtml(bigPictureStyleInformation.contentTitle) : bigPictureStyleInformation.contentTitle;
- bigPictureStyle.setBigContentTitle(contentTitle);
- }
- if (bigPictureStyleInformation.summaryText != null) {
- CharSequence summaryText = bigPictureStyleInformation.htmlFormatSummaryText ? fromHtml(bigPictureStyleInformation.summaryText) : bigPictureStyleInformation.summaryText;
- bigPictureStyle.setSummaryText(summaryText);
- }
-
- if (bigPictureStyleInformation.hideExpandedLargeIcon) {
- bigPictureStyle.bigLargeIcon(null);
- } else {
- if (bigPictureStyleInformation.largeIcon != null) {
- bigPictureStyle.bigLargeIcon(getBitmapFromSource(context, bigPictureStyleInformation.largeIcon, bigPictureStyleInformation.largeIconBitmapSource));
- }
- }
- bigPictureStyle.bigPicture(getBitmapFromSource(context, bigPictureStyleInformation.bigPicture, bigPictureStyleInformation.bigPictureBitmapSource));
- builder.setStyle(bigPictureStyle);
- }
-
- private static void setInboxStyle(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- InboxStyleInformation inboxStyleInformation = (InboxStyleInformation) notificationDetails.styleInformation;
- NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
- if (inboxStyleInformation.contentTitle != null) {
- CharSequence contentTitle = inboxStyleInformation.htmlFormatContentTitle ? fromHtml(inboxStyleInformation.contentTitle) : inboxStyleInformation.contentTitle;
- inboxStyle.setBigContentTitle(contentTitle);
- }
- if (inboxStyleInformation.summaryText != null) {
- CharSequence summaryText = inboxStyleInformation.htmlFormatSummaryText ? fromHtml(inboxStyleInformation.summaryText) : inboxStyleInformation.summaryText;
- inboxStyle.setSummaryText(summaryText);
- }
- if (inboxStyleInformation.lines != null) {
- for (String line : inboxStyleInformation.lines) {
- inboxStyle.addLine(inboxStyleInformation.htmlFormatLines ? fromHtml(line) : line);
- }
- }
- builder.setStyle(inboxStyle);
- }
-
- private static void setMediaStyle(NotificationCompat.Builder builder) {
- androidx.media.app.NotificationCompat.MediaStyle mediaStyle = new androidx.media.app.NotificationCompat.MediaStyle();
- builder.setStyle(mediaStyle);
- }
-
- private static void setMessagingStyle(Context context, NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- MessagingStyleInformation messagingStyleInformation = (MessagingStyleInformation) notificationDetails.styleInformation;
- Person person = buildPerson(context, messagingStyleInformation.person);
- NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person);
- messagingStyle.setGroupConversation(BooleanUtils.getValue(messagingStyleInformation.groupConversation));
- if (messagingStyleInformation.conversationTitle != null) {
- messagingStyle.setConversationTitle(messagingStyleInformation.conversationTitle);
- }
- if (messagingStyleInformation.messages != null && !messagingStyleInformation.messages.isEmpty()) {
- for (MessageDetails messageDetails : messagingStyleInformation.messages) {
- NotificationCompat.MessagingStyle.Message message = createMessage(context, messageDetails);
- messagingStyle.addMessage(message);
- }
- }
- builder.setStyle(messagingStyle);
- }
-
- private static NotificationCompat.MessagingStyle.Message createMessage(Context context, MessageDetails messageDetails) {
- NotificationCompat.MessagingStyle.Message message = new NotificationCompat.MessagingStyle.Message(messageDetails.text, messageDetails.timestamp, buildPerson(context, messageDetails.person));
- if (messageDetails.dataUri != null && messageDetails.dataMimeType != null) {
- message.setData(messageDetails.dataMimeType, Uri.parse(messageDetails.dataUri));
- }
- return message;
- }
-
- private static Person buildPerson(Context context, PersonDetails personDetails) {
- if (personDetails == null) {
- return null;
- }
-
- Person.Builder personBuilder = new Person.Builder();
- personBuilder.setBot(BooleanUtils.getValue(personDetails.bot));
- if (personDetails.icon != null && personDetails.iconBitmapSource != null) {
- personBuilder.setIcon(getIconFromSource(context, personDetails.icon, personDetails.iconBitmapSource));
- }
- personBuilder.setImportant(BooleanUtils.getValue(personDetails.important));
- if (personDetails.key != null) {
- personBuilder.setKey(personDetails.key);
- }
- if (personDetails.name != null) {
- personBuilder.setName(personDetails.name);
- }
- if (personDetails.uri != null) {
- personBuilder.setUri(personDetails.uri);
- }
- return personBuilder.build();
- }
-
- private static void setBigTextStyle(NotificationDetails notificationDetails, NotificationCompat.Builder builder) {
- BigTextStyleInformation bigTextStyleInformation = (BigTextStyleInformation) notificationDetails.styleInformation;
- NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
- if (bigTextStyleInformation.bigText != null) {
- CharSequence bigText = bigTextStyleInformation.htmlFormatBigText ? fromHtml(bigTextStyleInformation.bigText) : bigTextStyleInformation.bigText;
- bigTextStyle.bigText(bigText);
- }
- if (bigTextStyleInformation.contentTitle != null) {
- CharSequence contentTitle = bigTextStyleInformation.htmlFormatContentTitle ? fromHtml(bigTextStyleInformation.contentTitle) : bigTextStyleInformation.contentTitle;
- bigTextStyle.setBigContentTitle(contentTitle);
- }
- if (bigTextStyleInformation.summaryText != null) {
- CharSequence summaryText = bigTextStyleInformation.htmlFormatSummaryText ? fromHtml(bigTextStyleInformation.summaryText) : bigTextStyleInformation.summaryText;
- bigTextStyle.setSummaryText(summaryText);
- }
- builder.setStyle(bigTextStyle);
- }
-
- private static void setupNotificationChannel(Context context, NotificationChannelDetails notificationChannelDetails) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- NotificationChannel notificationChannel = notificationManager.getNotificationChannel(notificationChannelDetails.id);
- // only create/update the channel when needed/specified. Allow this happen to when channelAction may be null to support cases where notifications had been
- // created on older versions of the plugin where channel management options weren't available back then
- if ((notificationChannel == null && (notificationChannelDetails.channelAction == null || notificationChannelDetails.channelAction == NotificationChannelAction.CreateIfNotExists)) || (notificationChannel != null && notificationChannelDetails.channelAction == NotificationChannelAction.Update)) {
- notificationChannel = new NotificationChannel(notificationChannelDetails.id, notificationChannelDetails.name, notificationChannelDetails.importance);
- notificationChannel.setDescription(notificationChannelDetails.description);
- if (notificationChannelDetails.playSound) {
- AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build();
- Uri uri = retrieveSoundResourceUri(context, notificationChannelDetails.sound, notificationChannelDetails.soundSource);
- notificationChannel.setSound(uri, audioAttributes);
- } else {
- notificationChannel.setSound(null, null);
- }
- notificationChannel.enableVibration(BooleanUtils.getValue(notificationChannelDetails.enableVibration));
- if (notificationChannelDetails.vibrationPattern != null && notificationChannelDetails.vibrationPattern.length > 0) {
- notificationChannel.setVibrationPattern(notificationChannelDetails.vibrationPattern);
- }
- boolean enableLights = BooleanUtils.getValue(notificationChannelDetails.enableLights);
- notificationChannel.enableLights(enableLights);
- if (enableLights && notificationChannelDetails.ledColor != null) {
- notificationChannel.setLightColor(notificationChannelDetails.ledColor);
- }
- notificationChannel.setShowBadge(BooleanUtils.getValue(notificationChannelDetails.showBadge));
- notificationManager.createNotificationChannel(notificationChannel);
- }
- }
- }
-
- private static Uri retrieveSoundResourceUri(Context context, String sound, SoundSource soundSource) {
- Uri uri = null;
- if (StringUtils.isNullOrEmpty(sound)) {
- uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
- } else {
- // allow null as soundSource was added later and prior to that, it was assumed to be a raw resource
- if (soundSource == null || soundSource == SoundSource.RawResource) {
- int soundResourceId = context.getResources().getIdentifier(sound, "raw", context.getPackageName());
- uri = Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId);
- } else if (soundSource == SoundSource.Uri) {
- uri = Uri.parse(sound);
- }
- }
- return uri;
- }
-
- private static AlarmManager getAlarmManager(Context context) {
- return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- }
-
- private static boolean isValidDrawableResource(Context context, String name, Result result, String errorCode) {
- int resourceId = context.getResources().getIdentifier(name, DRAWABLE, context.getPackageName());
- if (resourceId == 0) {
- result.error(errorCode, String.format(INVALID_DRAWABLE_RESOURCE_ERROR_MESSAGE, name), null);
- return false;
- }
- return true;
- }
-
- static void showNotification(Context context, NotificationDetails notificationDetails) {
- Notification notification = createNotification(context, notificationDetails);
- NotificationManagerCompat notificationManagerCompat = getNotificationManager(context);
- notificationManagerCompat.notify(notificationDetails.id, notification);
- }
-
- private static NotificationManagerCompat getNotificationManager(Context context) {
- return NotificationManagerCompat.from(context);
- }
-
- private void setActivity(Activity flutterActivity) {
- this.mainActivity = flutterActivity;
- }
-
- private void onAttachedToEngine(Context context, BinaryMessenger binaryMessenger) {
- this.applicationContext = context;
- this.channel = new MethodChannel(binaryMessenger, METHOD_CHANNEL);
- this.channel.setMethodCallHandler(this);
- }
-
- @Override
- public void onAttachedToEngine(FlutterPluginBinding binding) {
- onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger());
- }
-
- @Override
- public void onDetachedFromEngine(FlutterPluginBinding binding) {
- }
-
- @Override
- public void onAttachedToActivity(ActivityPluginBinding binding) {
- binding.addOnNewIntentListener(this);
- mainActivity = binding.getActivity();
- }
-
- @Override
- public void onDetachedFromActivityForConfigChanges() {
- this.mainActivity = null;
- }
-
- @Override
- public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
- binding.addOnNewIntentListener(this);
- mainActivity = binding.getActivity();
- }
-
- @Override
- public void onDetachedFromActivity() {
- this.mainActivity = null;
- }
-
- @Override
- public void onMethodCall(MethodCall call, Result result) {
- switch (call.method) {
- case INITIALIZE_METHOD: {
- initialize(call, result);
- break;
- }
- case GET_NOTIFICATION_APP_LAUNCH_DETAILS_METHOD: {
- getNotificationAppLaunchDetails(result);
- break;
- }
- case SHOW_METHOD: {
- show(call, result);
- break;
- }
- case SCHEDULE_METHOD: {
- schedule(call, result);
- break;
- }
- case PERIODICALLY_SHOW_METHOD:
- case SHOW_DAILY_AT_TIME_METHOD:
- case SHOW_WEEKLY_AT_DAY_AND_TIME_METHOD: {
- repeat(call, result);
- break;
- }
- case CANCEL_METHOD:
- cancel(call, result);
- break;
- case CANCEL_ALL_METHOD:
- cancelAllNotifications(result);
- break;
- case PENDING_NOTIFICATION_REQUESTS_METHOD:
- pendingNotificationRequests(result);
- break;
- case CREATE_NOTIFICATION_CHANNEL_METHOD:
- createNotificationChannel(call, result);
- break;
- case DELETE_NOTIFICATION_CHANNEL_METHOD:
- deleteNotificationChannel(call, result);
- break;
- default:
- result.notImplemented();
- break;
- }
- }
-
- private void pendingNotificationRequests(Result result) {
- ArrayList scheduledNotifications = loadScheduledNotifications(applicationContext);
- List