Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
qiuxiang committed Oct 1, 2021
1 parent bfd1dea commit ce087fd
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 96 deletions.
1 change: 1 addition & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package="qiuxiang.android_window">

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<service android:name=".WindowService" />
</application>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,8 @@ class AndroidWindow(
windowManager.updateViewLayout(rootView, layoutParams)
}
}

val AndroidWindow.app: AndroidWindowApplication?
get() {
return service.application as? AndroidWindowApplication
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
package qiuxiang.android_window

class AndroidWindowApi(private val androidWindow: AndroidWindow) : Pigeon.AndroidWindowApi {
override fun setLayout(width: Long, height: Long) {
androidWindow.setLayout(width.toInt(), height.toInt())
class AndroidWindowApi(private val window: AndroidWindow) : Pigeon.AndroidWindowApi {
override fun resize(width: Long, height: Long) {
window.setLayout(width.toInt(), height.toInt())
}

override fun setPosition(x: Long, y: Long) {
androidWindow.setPosition(x.toInt(), y.toInt())
window.setPosition(x.toInt(), y.toInt())
}

override fun dragStart() {
androidWindow.dragStart()
window.dragStart()
}

override fun dragEnd() {
androidWindow.dragEnd()
window.dragEnd()
}

override fun close() {
androidWindow.service.stopSelf()
window.service.stopSelf()
}

override fun post(data: MutableMap<Any, Any>?, result: Pigeon.Result<MutableMap<Any, Any>>?) {
window.app?.mainBinaryMessenger?.let {
Pigeon.MainHandler(it).handler(data) { response -> result?.success(response) }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package qiuxiang.android_window

import io.flutter.app.FlutterApplication
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BinaryMessenger

open class AndroidWindowApplication : FlutterApplication() {
var engine: FlutterEngine? = null
var mainBinaryMessenger: BinaryMessenger? = null
var androidWindowBinaryMessenger: BinaryMessenger? = null
var mainApi: MainApi? = null
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding

class AndroidWindowPlugin : FlutterPlugin, ActivityAware {
lateinit var pluginBinding: FlutterPluginBinding
private lateinit var pluginBinding: FlutterPluginBinding

override fun onDetachedFromEngine(binding: FlutterPluginBinding) {}
override fun onDetachedFromActivityForConfigChanges() {}
Expand All @@ -19,7 +19,10 @@ class AndroidWindowPlugin : FlutterPlugin, ActivityAware {

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
val mainApi = MainApi(binding.activity)
binding.activity.app?.mainApi = mainApi
Pigeon.MainApi.setup(pluginBinding.binaryMessenger, mainApi)
binding.activity.app?.let {
it.mainApi = mainApi
it.mainBinaryMessenger = pluginBinding.binaryMessenger
}
}
}
18 changes: 9 additions & 9 deletions android/src/main/kotlin/qiuxiang/android_window/MainApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import android.provider.Settings
class MainApi(private val activity: Activity) : Pigeon.MainApi {
private var onActivityResultCallback: (() -> Unit)? = null

override fun openAndroidWindow(entry: String, width: Long, height: Long, x: Long, y: Long) {
override fun open(entry: String, width: Long, height: Long, x: Long, y: Long) {
val intent = Intent(activity, WindowService::class.java)
intent.putExtra("entry", entry)
intent.putExtra("width", width.toInt())
Expand All @@ -19,29 +19,29 @@ class MainApi(private val activity: Activity) : Pigeon.MainApi {
if (canDrawOverlays()) {
activity.startService(intent)
} else {
requestOverlayDisplayPermission {
requestPermission {
if (canDrawOverlays()) {
activity.startService(intent)
}
}
}
}

override fun closeAndroidWindow() {
override fun close() {
activity.stopService(Intent(activity, WindowService::class.java))
}

override fun canDrawOverlays(result: Pigeon.Result<Boolean>) {
result.success(canDrawOverlays())
}

override fun requestOverlayDisplayPermission(result: Pigeon.Result<Void>) {
requestOverlayDisplayPermission { result.success(null) }
override fun requestPermission(result: Pigeon.Result<Void>) {
requestPermission { result.success(null) }
}

override fun send(name: String?, data: MutableMap<Any, Any>?, result: Pigeon.Result<Void>?) {
(activity.application as? AndroidWindowApplication)?.engine?.dartExecutor?.binaryMessenger?.let {
Pigeon.AndroidWindowHandler(it).handler(name, data) { result?.success(null) }
override fun post(data: MutableMap<Any, Any>?, result: Pigeon.Result<MutableMap<Any, Any>>?) {
activity.app?.androidWindowBinaryMessenger?.let {
Pigeon.AndroidWindowHandler(it).handler(data) { response -> result?.success(response) }
}
}

Expand All @@ -53,7 +53,7 @@ class MainApi(private val activity: Activity) : Pigeon.MainApi {
}
}

private fun requestOverlayDisplayPermission(callback: () -> Unit) {
private fun requestPermission(callback: () -> Unit) {
onActivityResultCallback = callback
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
val intent = Intent(
Expand Down
20 changes: 19 additions & 1 deletion android/src/main/kotlin/qiuxiang/android_window/WindowService.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package qiuxiang.android_window

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.os.Build
import android.os.IBinder
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.dart.DartExecutor
Expand All @@ -9,6 +13,7 @@ class WindowService : android.app.Service() {
private lateinit var engine: FlutterEngine
private lateinit var androidWindow: AndroidWindow
private var running = false
private val channelId = "foreground"

override fun onBind(intent: Intent): IBinder? {
return null
Expand All @@ -17,7 +22,7 @@ class WindowService : android.app.Service() {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (!running) {
engine = FlutterEngine(application)
(application as AndroidWindowApplication).engine = engine
(application as AndroidWindowApplication).androidWindowBinaryMessenger = engine.dartExecutor.binaryMessenger
val entry = intent.getStringExtra("entry") ?: "androidWindow"
val entryPoint = DartExecutor.DartEntrypoint(findAppBundlePath(), entry)
engine.dartExecutor.executeDartEntrypoint(entryPoint)
Expand All @@ -28,11 +33,24 @@ class WindowService : android.app.Service() {
val y = intent.getIntExtra("y", 0)
androidWindow = AndroidWindow(this, width, height, x, y, engine)
androidWindow.open()
startForeground(1, getNotification())
running = true
}
return super.onStartCommand(intent, flags, startId)
}

private fun getNotification(): Notification {
return if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, "Window Service", NotificationManager.IMPORTANCE_DEFAULT)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
Notification.Builder(this, channel.id)
} else {
@Suppress("Deprecation")
Notification.Builder(this)
}.build()
}

override fun onDestroy() {
androidWindow.close()
engine.destroy()
Expand Down
73 changes: 37 additions & 36 deletions example/lib/android_window.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import 'package:android_window/android_window.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

import 'package:android_window/android_window.dart';

class AndroidWindowApp extends StatelessWidget {
const AndroidWindowApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
FloatingHandler.setup(_FloatingHandler());
return const MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
Expand All @@ -18,56 +16,53 @@ class AndroidWindowApp extends StatelessWidget {
}
}

class _FloatingHandler extends FloatingHandler {
@override
void handler(String name, Map data) {
switch (name) {
case 'layout':
floatingApi.setLayout(data['width'], data['height']);
break;
case 'position':
floatingApi.setPosition(data['x'], data['y']);
break;
}
}
}

class HomePage extends StatefulWidget {
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);

@override
State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
Size size = const Size(0, 0);

@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: (event) => floatingApi.dragStart(),
onPanEnd: (event) => floatingApi.dragEnd(),
AndroidWindow.setHandler((name, data) async {
switch (name) {
case 'hello':
showSnackBar(context, 'message from main app: $data');
return 'hello main app';
}
});
return AndroidWindow(
child: ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Scaffold(
backgroundColor: Colors.grey.withOpacity(0.8),
body: Stack(children: [
ListView(children: [
Container(height: 100, color: Colors.lightGreen),
Container(height: 100, color: Colors.blueGrey),
Container(height: 100, color: Colors.lightGreen),
Container(height: 100, color: Colors.blueGrey),
Ink(
height: 400 / 3,
color: Colors.lightGreen,
child: InkWell(onTap: () async {
final response = await AndroidWindow.post(
'hello',
'hello main app',
);
showSnackBar(
context,
'response from main app: $response',
);
}),
),
Container(height: 400 / 3, color: Colors.blueGrey),
Container(height: 400 / 3, color: Colors.lightGreen),
Container(height: 400 / 3, color: Colors.blueGrey),
]),
Positioned(
const Positioned(
right: 0,
child: Material(
color: Colors.transparent,
borderRadius: const BorderRadius.all(Radius.circular(24)),
borderRadius: BorderRadius.all(Radius.circular(24)),
clipBehavior: Clip.hardEdge,
child: IconButton(
onPressed: floatingApi.close,
icon: const Icon(Icons.close, color: Colors.white),
onPressed: AndroidWindow.close,
icon: Icon(Icons.close, color: Colors.white),
),
),
),
Expand All @@ -76,4 +71,10 @@ class _HomePageState extends State<HomePage> {
),
);
}

showSnackBar(BuildContext context, String title) {
final snackBar =
SnackBar(content: Text(title), padding: const EdgeInsets.all(8));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
Loading

0 comments on commit ce087fd

Please sign in to comment.