feat: Move over the service/background service API

This commit is contained in:
2023-09-09 00:28:01 +02:00
parent 42ff70a966
commit dfbb64c8ae
19 changed files with 1137 additions and 3 deletions

View File

@@ -4,7 +4,7 @@
<application>
<provider
android:name="org.moxxy.moxxy_native.content.MoxxyFileProvider"
android:authorities="org.moxxy.moxxyv2.fileprovider"
android:authorities="org.moxxy.moxxyv2.fileprovider2"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
@@ -12,8 +12,36 @@
android:resource="@xml/file_paths" />
</provider>
<service
android:enabled="true"
android:exported="true"
android:name="org.moxxy.moxxy_native.service.BackgroundService"
/>
<receiver
android:name="org.moxxy.moxxy_native.service.WatchdogReceiver"
android:enabled="true"
android:exported="true"
/>
<receiver android:name="org.moxxy.moxxy_native.service.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name="org.moxxy.moxxy_native.notifications.NotificationReceiver" />
</application>
<!-- Foreground service -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- Notifications -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
</manifest>

View File

@@ -37,3 +37,16 @@ const val SHARED_PREFERENCES_AVATAR_KEY = "avatar_path"
const val PICK_FILE_REQUEST = 42
const val PICK_FILES_REQUEST = 43
const val PICK_FILE_WITH_DATA_REQUEST = 44
// Service
const val SERVICE_SHARED_PREFERENCES_KEY = "me.polynom.moxplatform_android"
const val SERVICE_ENTRYPOINT_KEY = "entrypoint_handle"
const val SERVICE_EXTRA_DATA_KEY = "extra_data"
const val SERVICE_START_AT_BOOT_KEY = "auto_start_at_boot"
const val SERVICE_MANUALLY_STOPPED_KEY = "manually_stopped"
// https://github.com/ekasetiawans/flutter_background_service/blob/e427f3b70138ec26f9671c2617f9061f25eade6f/packages/flutter_background_service_android/android/src/main/java/id/flutter/flutter_background_service/BootReceiver.java#L20
const val SERVICE_WAKELOCK_DURATION = 10 * 60 * 1000L
const val SERVICE_DEFAULT_TITLE = "Moxxy"
const val SERVICE_DEFAULT_BODY = "Preparing..."
const val SERVICE_BACKGROUND_METHOD_CHANNEL_KEY = "org.moxxy.moxxy_native/background"

View File

@@ -10,6 +10,8 @@ import androidx.annotation.NonNull
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.embedding.engine.plugins.service.ServiceAware
import io.flutter.embedding.engine.plugins.service.ServicePluginBinding
import io.flutter.plugin.common.EventChannel
import org.moxxy.moxxy_native.contacts.ContactsImplementation
import org.moxxy.moxxy_native.contacts.MoxxyContactsApi
@@ -25,6 +27,10 @@ import org.moxxy.moxxy_native.picker.MoxxyPickerApi
import org.moxxy.moxxy_native.picker.PickerResultListener
import org.moxxy.moxxy_native.platform.MoxxyPlatformApi
import org.moxxy.moxxy_native.platform.PlatformImplementation
import org.moxxy.moxxy_native.service.BackgroundService
import org.moxxy.moxxy_native.service.MoxxyServiceApi
import org.moxxy.moxxy_native.service.PluginTracker
import org.moxxy.moxxy_native.service.ServiceImplementation
object MoxxyEventChannels {
var notificationChannel: EventChannel? = null
@@ -50,7 +56,7 @@ object NotificationCache {
var lastEvent: NotificationEvent? = null
}
class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi {
class MoxxyNativePlugin : FlutterPlugin, ActivityAware, ServiceAware, MoxxyPickerApi {
private var context: Context? = null
private var activity: Activity? = null
private lateinit var pickerListener: PickerResultListener
@@ -59,12 +65,20 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi {
private lateinit var platformImplementation: PlatformImplementation
private val mediaImplementation = MediaImplementation()
private lateinit var notificationsImplementation: NotificationsImplementation
private lateinit var serviceImplementation: ServiceImplementation
var service: BackgroundService? = null
init {
PluginTracker.instances.add(this)
}
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
context = flutterPluginBinding.applicationContext
contactsImplementation = ContactsImplementation(context!!)
platformImplementation = PlatformImplementation(context!!)
notificationsImplementation = NotificationsImplementation(context!!)
serviceImplementation = ServiceImplementation(context!!)
// Register the pigeon handlers
MoxxyPickerApi.setUp(flutterPluginBinding.binaryMessenger, this)
@@ -73,6 +87,7 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi {
MoxxyContactsApi.setUp(flutterPluginBinding.binaryMessenger, contactsImplementation)
MoxxyPlatformApi.setUp(flutterPluginBinding.binaryMessenger, platformImplementation)
MoxxyMediaApi.setUp(flutterPluginBinding.binaryMessenger, mediaImplementation)
MoxxyServiceApi.setUp(flutterPluginBinding.binaryMessenger, serviceImplementation)
// Register the picker handler
pickerListener = PickerResultListener(context!!)
@@ -103,6 +118,16 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi {
Log.d(TAG, "Detached from activity")
}
override fun onAttachedToService(binding: ServicePluginBinding) {
Log.d(TAG, "Attached to service")
service = binding.getService() as BackgroundService
}
override fun onDetachedFromService() {
Log.d(TAG, "Detached from service")
service = null
}
override fun pickFiles(
type: FilePickerType,
multiple: Boolean,

View File

@@ -0,0 +1,280 @@
package org.moxxy.moxxy_native.service
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import android.os.PowerManager.WakeLock
import android.util.Log
import androidx.core.app.AlarmManagerCompat
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import io.flutter.FlutterInjector
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterCallbackInformation
import org.moxxy.moxxy_native.R
import org.moxxy.moxxy_native.SERVICE_BACKGROUND_METHOD_CHANNEL_KEY
import org.moxxy.moxxy_native.SERVICE_DEFAULT_BODY
import org.moxxy.moxxy_native.SERVICE_DEFAULT_TITLE
import org.moxxy.moxxy_native.SERVICE_ENTRYPOINT_KEY
import org.moxxy.moxxy_native.SERVICE_EXTRA_DATA_KEY
import org.moxxy.moxxy_native.SERVICE_MANUALLY_STOPPED_KEY
import org.moxxy.moxxy_native.SERVICE_SHARED_PREFERENCES_KEY
import org.moxxy.moxxy_native.SERVICE_START_AT_BOOT_KEY
import org.moxxy.moxxy_native.SERVICE_WAKELOCK_DURATION
import org.moxxy.moxxy_native.TAG
import org.moxxy.moxxy_native.service.background.MoxxyBackgroundServiceApi
import java.util.concurrent.atomic.AtomicBoolean
object BackgroundServiceStatic {
@Volatile
var wakeLock: WakeLock? = null
fun acquireWakeLock(context: Context): WakeLock {
if (wakeLock == null) {
val manager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock =
manager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "${this.javaClass.name}.class")
wakeLock!!.setReferenceCounted(true)
}
return wakeLock!!
}
fun enqueue(context: Context) {
val mutable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
val pendingIntent = PendingIntent.getBroadcast(
context,
111,
Intent(context, WatchdogReceiver::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or mutable,
)
AlarmManagerCompat.setAndAllowWhileIdle(
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager,
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 5000,
pendingIntent,
)
}
fun getStartAtBoot(context: Context): Boolean {
return context.getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
.getBoolean(
SERVICE_START_AT_BOOT_KEY,
false,
)
}
fun setStartAtBoot(context: Context, value: Boolean) {
context.getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE).edit()
.putBoolean(SERVICE_START_AT_BOOT_KEY, value)
.apply()
}
fun getManuallyStopped(context: Context): Boolean {
return context.getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
.getBoolean(
SERVICE_MANUALLY_STOPPED_KEY,
false,
)
}
}
class BackgroundService : Service(), MoxxyBackgroundServiceApi {
// Indicates whether the background service is running or not
private var isRunning = AtomicBoolean(false)
// Indicates whether the service was stopped manually
private var isManuallyStopped = false
// If non-null, the Flutter Engine that is running the background service's code
private var engine: FlutterEngine? = null
// The callback for Dart to start execution at
private var dartCallback: DartExecutor.DartCallback? = null
// Method channel for Java -> Dart
private var methodChannel: MethodChannel? = null
// Data for the notification
private var notificationTitle: String = SERVICE_DEFAULT_TITLE
private var notificationBody: String = SERVICE_DEFAULT_BODY
private fun setManuallyStopped(context: Context, value: Boolean) {
context.getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE).edit()
.putBoolean(SERVICE_MANUALLY_STOPPED_KEY, value)
.apply()
}
private fun getHandle(): Long {
return getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE).getLong(
SERVICE_ENTRYPOINT_KEY,
0,
)
}
private fun updateNotificationInfo() {
val mutable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
val pendingIntent = PendingIntent.getActivity(
this,
99778,
packageManager.getLaunchIntentForPackage(applicationContext.packageName),
PendingIntent.FLAG_CANCEL_CURRENT or mutable,
)
val notification = NotificationCompat.Builder(this, "foreground_service").apply {
setSmallIcon(R.drawable.ic_service)
setAutoCancel(false)
setOngoing(true)
setContentTitle(notificationTitle)
setContentText(notificationBody)
setContentIntent(pendingIntent)
}.build()
startForeground(99778, notification)
}
private fun runService() {
try {
if (isRunning.get() || (engine?.getDartExecutor()?.isExecutingDart() ?: false)) return
if (BackgroundServiceStatic.wakeLock == null) {
Log.d(TAG, "WakeLock is null. Acquiring and grabbing WakeLock...")
BackgroundServiceStatic.acquireWakeLock(applicationContext)
.acquire(SERVICE_WAKELOCK_DURATION)
Log.d(TAG, "WakeLock grabbed")
}
// Update the notification
updateNotificationInfo()
// Set-up the Flutter Engine, if it's not already set up
if (!FlutterInjector.instance().flutterLoader().initialized()) {
FlutterInjector.instance().flutterLoader().startInitialization(applicationContext)
}
FlutterInjector.instance().flutterLoader().ensureInitializationComplete(
applicationContext,
null,
)
val callback: FlutterCallbackInformation =
FlutterCallbackInformation.lookupCallbackInformation(getHandle())
if (callback == null) {
Log.e(TAG, "Callback handle not found")
return
}
isRunning.set(true)
engine = FlutterEngine(this)
engine!!.getServiceControlSurface().attachToService(this, null, true)
methodChannel = MethodChannel(
engine!!.getDartExecutor()!!.getBinaryMessenger(),
SERVICE_BACKGROUND_METHOD_CHANNEL_KEY,
)
MoxxyBackgroundServiceApi.setUp(engine!!.getDartExecutor()!!.getBinaryMessenger(), this)
Log.d(TAG, "MoxxyBackgroundServiceApi ready")
dartCallback = DartExecutor.DartCallback(
assets,
FlutterInjector.instance().flutterLoader().findAppBundlePath(),
callback,
)
engine!!.getDartExecutor().executeDartCallback(dartCallback!!)
} catch (ex: UnsatisfiedLinkError) {
Log.e(TAG, "Failed to set up background service: ${ex.message}")
}
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
notificationBody = SERVICE_DEFAULT_BODY
updateNotificationInfo()
}
override fun onDestroy() {
if (!isManuallyStopped) {
BackgroundServiceStatic.enqueue(this)
} else {
setManuallyStopped(applicationContext, true)
}
// Dispose of the engine
engine?.apply {
getServiceControlSurface().detachFromService()
destroy()
}
engine = null
dartCallback = null
// Stop the service
stopForeground(true)
isRunning.set(false)
super.onDestroy()
}
fun receiveData(data: String) {
methodChannel?.invokeMethod("dataReceived", data)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
setManuallyStopped(this, false)
BackgroundServiceStatic.enqueue(this)
runService()
return START_STICKY
}
override fun getHandler(): Long {
return getHandle()
}
override fun getExtraData(): String {
return getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE).getString(
SERVICE_EXTRA_DATA_KEY,
"",
)!!
}
override fun setNotificationBody(body: String) {
notificationBody = body
updateNotificationInfo()
}
override fun sendData(data: String) {
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(
Intent(SERVICE_BACKGROUND_METHOD_CHANNEL_KEY).apply {
putExtra("data", data)
},
)
}
override fun stop() {
isManuallyStopped = true
val mutable =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
val pendingIntent = PendingIntent.getBroadcast(
applicationContext,
111,
Intent(this, WatchdogReceiver::class.java),
PendingIntent.FLAG_CANCEL_CURRENT or mutable,
)
val stopManager = getSystemService(ALARM_SERVICE) as AlarmManager
stopManager.cancel(pendingIntent)
stopSelf()
BackgroundServiceStatic.setStartAtBoot(applicationContext, false)
}
}

View File

@@ -0,0 +1,25 @@
package org.moxxy.moxxy_native.service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.content.ContextCompat
import org.moxxy.moxxy_native.TAG
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (BackgroundServiceStatic.getStartAtBoot(context)) {
if (BackgroundServiceStatic.wakeLock == null) {
Log.d(TAG, "WakeLock is null. Acquiring it...")
BackgroundServiceStatic.acquireWakeLock(context)
Log.d(TAG, "WakeLock acquired")
}
ContextCompat.startForegroundService(
context,
Intent(context, BackgroundService::class.java),
)
}
}
}

View File

@@ -0,0 +1,134 @@
// Autogenerated from Pigeon (v11.0.1), do not edit directly.
// See also: https://pub.dev/packages/pigeon
package org.moxxy.moxxy_native.service
import android.util.Log
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MessageCodec
import io.flutter.plugin.common.StandardMessageCodec
private fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
private fun wrapError(exception: Throwable): List<Any?> {
if (exception is FlutterError) {
return listOf(
exception.code,
exception.message,
exception.details,
)
} else {
return listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception),
)
}
}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
* @property message The error message.
* @property details The error details. Must be a datatype supported by the api codec.
*/
class FlutterError(
val code: String,
override val message: String? = null,
val details: Any? = null,
) : Throwable()
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface MoxxyServiceApi {
fun configure(handle: Long, extraData: String)
fun isRunning(): Boolean
fun start()
fun sendData(data: String)
companion object {
/** The codec used by MoxxyServiceApi. */
val codec: MessageCodec<Any?> by lazy {
StandardMessageCodec()
}
/** Sets up an instance of `MoxxyServiceApi` to handle messages through the `binaryMessenger`. */
@Suppress("UNCHECKED_CAST")
fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyServiceApi?) {
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyServiceApi.configure", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val handleArg = args[0].let { if (it is Int) it.toLong() else it as Long }
val extraDataArg = args[1] as String
var wrapped: List<Any?>
try {
api.configure(handleArg, extraDataArg)
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyServiceApi.isRunning", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped: List<Any?>
try {
wrapped = listOf<Any?>(api.isRunning())
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyServiceApi.start", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped: List<Any?>
try {
api.start()
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyServiceApi.sendData", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val dataArg = args[0] as String
var wrapped: List<Any?>
try {
api.sendData(dataArg)
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
package org.moxxy.moxxy_native.service
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.content.ContextCompat
import org.moxxy.moxxy_native.MoxxyNativePlugin
import org.moxxy.moxxy_native.SERVICE_ENTRYPOINT_KEY
import org.moxxy.moxxy_native.SERVICE_EXTRA_DATA_KEY
import org.moxxy.moxxy_native.SERVICE_SHARED_PREFERENCES_KEY
import org.moxxy.moxxy_native.TAG
import org.moxxy.moxxy_native.service.BackgroundServiceStatic.setStartAtBoot
object PluginTracker {
var instances: MutableList<MoxxyNativePlugin> = mutableListOf()
}
class ServiceImplementation(private val context: Context) : MoxxyServiceApi {
override fun configure(handle: Long, extraData: String) {
context.getSharedPreferences(SERVICE_SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE).edit()
.putLong(SERVICE_ENTRYPOINT_KEY, handle)
.putString(SERVICE_EXTRA_DATA_KEY, extraData)
.apply()
}
override fun isRunning(): Boolean {
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (info in manager.getRunningServices(Int.MAX_VALUE)) {
if (BackgroundService::class.java.name == info.service.className) {
return true
}
}
return false
}
override fun start() {
setStartAtBoot(context, true)
BackgroundServiceStatic.enqueue(context)
ContextCompat.startForegroundService(
context,
Intent(context, BackgroundService::class.java),
)
Log.d(TAG, "Background service started")
}
override fun sendData(data: String) {
for (plugin in PluginTracker.instances) {
val service = plugin.service
if (service != null) {
service.receiveData(data)
break
}
}
}
}

View File

@@ -0,0 +1,18 @@
package org.moxxy.moxxy_native.service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
import org.moxxy.moxxy_native.service.BackgroundServiceStatic.getManuallyStopped
class WatchdogReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (!getManuallyStopped(context)) {
ContextCompat.startForegroundService(
context,
Intent(context, BackgroundService::class.java),
)
}
}
}

View File

@@ -0,0 +1,150 @@
// Autogenerated from Pigeon (v11.0.1), do not edit directly.
// See also: https://pub.dev/packages/pigeon
package org.moxxy.moxxy_native.service.background
import android.util.Log
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MessageCodec
import io.flutter.plugin.common.StandardMessageCodec
private fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
private fun wrapError(exception: Throwable): List<Any?> {
if (exception is FlutterError) {
return listOf(
exception.code,
exception.message,
exception.details,
)
} else {
return listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception),
)
}
}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
* @property message The error message.
* @property details The error details. Must be a datatype supported by the api codec.
*/
class FlutterError(
val code: String,
override val message: String? = null,
val details: Any? = null,
) : Throwable()
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface MoxxyBackgroundServiceApi {
fun getHandler(): Long
fun getExtraData(): String
fun setNotificationBody(body: String)
fun sendData(data: String)
fun stop()
companion object {
/** The codec used by MoxxyBackgroundServiceApi. */
val codec: MessageCodec<Any?> by lazy {
StandardMessageCodec()
}
/** Sets up an instance of `MoxxyBackgroundServiceApi` to handle messages through the `binaryMessenger`. */
@Suppress("UNCHECKED_CAST")
fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyBackgroundServiceApi?) {
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyBackgroundServiceApi.getHandler", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped: List<Any?>
try {
wrapped = listOf<Any?>(api.getHandler())
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyBackgroundServiceApi.getExtraData", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped: List<Any?>
try {
wrapped = listOf<Any?>(api.getExtraData())
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyBackgroundServiceApi.setNotificationBody", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val bodyArg = args[0] as String
var wrapped: List<Any?>
try {
api.setNotificationBody(bodyArg)
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyBackgroundServiceApi.sendData", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val dataArg = args[0] as String
var wrapped: List<Any?>
try {
api.sendData(dataArg)
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyBackgroundServiceApi.stop", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
var wrapped: List<Any?>
try {
api.stop()
wrapped = listOf<Any?>(null)
} catch (exception: Throwable) {
wrapped = wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}