diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index c40f81e6b..8c480b501 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -19,13 +19,13 @@ android { namespace = "com.pranshulgg.weather_master_app" compileSdk = flutter.compileSdkVersion ndkVersion = "27.0.12077973" - + compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 isCoreLibraryDesugaringEnabled = true - + } kotlinOptions { @@ -37,7 +37,7 @@ android { applicationId = "com.pranshulgg.weather_master_app" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = 23 + minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c58ede3dd..393dd9ac4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,9 +5,9 @@ - + - + @@ -31,12 +31,11 @@ while the Flutter UI initializes. After that, this theme continues to determine the Window background behind the Flutter UI. --> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" /> - - + + - - - - - + + + + + - + @@ -67,7 +68,10 @@ android:resource="@xml/weather_widget_info" /> - + @@ -77,7 +81,10 @@ android:resource="@xml/weather_widget_info_cast" /> - + @@ -87,7 +94,10 @@ android:resource="@xml/pill_widget_info" /> - + @@ -97,7 +107,10 @@ android:resource="@xml/clock_hourly_info" /> - + @@ -107,11 +120,14 @@ android:resource="@xml/date_temp_widget_info" /> - - - + android:exported="true"> + @@ -130,8 +146,24 @@ + + + + + + + + + - - + + diff --git a/android/app/src/main/kotlin/com/pranshulgg/weather_master_app/WeatherDreamService.kt b/android/app/src/main/kotlin/com/pranshulgg/weather_master_app/WeatherDreamService.kt new file mode 100644 index 000000000..ef1d3e358 --- /dev/null +++ b/android/app/src/main/kotlin/com/pranshulgg/weather_master_app/WeatherDreamService.kt @@ -0,0 +1,101 @@ +package com.pranshulgg.weather_master_app + +import android.service.dreams.DreamService +import android.view.ViewGroup +import io.flutter.FlutterInjector +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.android.FlutterView +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint +import io.flutter.plugins.GeneratedPluginRegistrant + + +class WeatherDreamService : DreamService() { + private var flutterEngine: FlutterEngine? = null + private var flutterView: FlutterView? = null + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + + // Allow click to propagate to the FlutterView + isInteractive = true + + // Make the window fullscreen + isFullscreen = true + + // TODO: figure out if this is required or not + isScreenBright = true + + // It doesn't seem work with applicationContext, use this instead: + val engine = flutterEngine ?: FlutterEngine(this, null).also { + it.dartExecutor.executeDartEntrypoint( + DartEntrypoint( + dartEntrypointFunctionName = "onDreamServiceStarted" + ) + ) + flutterEngine = it + } + + + //setContentView(R.layout.flutter_view) + //flutterView = findViewById(R.id.flutter_view).also { + // it.attachToFlutterEngine(engine) + //} + + flutterView = FlutterView(this).also { + it.id = FlutterActivity.FLUTTER_VIEW_ID + it.layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + it.isFocusable = true + it.isFocusableInTouchMode = true + + setContentView(it) + + it.attachToFlutterEngine(engine) + it.requestFocus() + } + } + + override fun onDreamingStarted() { + super.onDreamingStarted() + flutterEngine?.lifecycleChannel?.appIsResumed() + } + + override fun onDreamingStopped() { + super.onDreamingStopped() + flutterEngine?.lifecycleChannel?.appIsInactive() + flutterEngine?.lifecycleChannel?.appIsPaused() + } + + override fun onDetachedFromWindow() { + flutterView?.let { + it.detachFromFlutterEngine() + flutterView = null + } + super.onDetachedFromWindow() + } +} + +fun DartEntrypoint( + pathToBundle: String? = null, + dartEntrypointLibrary: String? = null, + dartEntrypointFunctionName: String = "main" +): DartEntrypoint { + val pathToBundle = pathToBundle ?: FlutterInjector.instance().flutterLoader().let { + if (!it.initialized()) { + throw AssertionError( + "DartEntrypoints can only be created once a FlutterEngine is created." + ) + } + it.findAppBundlePath() + } + return dartEntrypointLibrary?.let { + DartEntrypoint( + pathToBundle, + it, + dartEntrypointFunctionName + ) + } ?: DartEntrypoint(pathToBundle, dartEntrypointFunctionName) +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/flutter_view.xml b/android/app/src/main/res/layout/flutter_view.xml new file mode 100644 index 000000000..edf82ca22 --- /dev/null +++ b/android/app/src/main/res/layout/flutter_view.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/android/app/src/main/res/xml/weather_dream.xml b/android/app/src/main/res/xml/weather_dream.xml new file mode 100644 index 000000000..af3d2051c --- /dev/null +++ b/android/app/src/main/res/xml/weather_dream.xml @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c95385e8b..d0d0ec7ba 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -172,6 +172,38 @@ void main() async { ); } +@pragma('vm:entry-point') +void onDreamServiceStarted() { + WidgetsFlutterBinding.ensureInitialized(); + runApp(MaterialApp( + theme: ThemeData.light(), + darkTheme: ThemeData.dark(), + home: Builder(builder: (context) { + return Scaffold( + body: Center( + child: FilledButton( + onPressed: () => showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Headline"), + content: Text("Supporting text"), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text("Cancel")), + TextButton( + onPressed: () => Navigator.pop(context), + child: Text("OK")) + ], + ), + ), + child: Text("Hello world!")), + ), + ); + }), + )); +} + class MyApp extends StatelessWidget { final String? cacheKey; final String? cityName; diff --git a/pubspec.lock b/pubspec.lock index 2f6ae01d5..689ab675d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -376,26 +376,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -772,10 +772,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" typed_data: dependency: transitive description: @@ -876,10 +876,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: