WIP: partial android service migration
This commit is contained in:
parent
d8059197fe
commit
a99a00de30
|
@ -69,6 +69,15 @@ android {
|
|||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
|
@ -82,4 +91,24 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||
implementation "com.airbnb.android:lottie:3.5.0"
|
||||
implementation "com.android.support.constraint:constraint-layout:2.0.4"
|
||||
|
||||
// WorkManager
|
||||
|
||||
// (Java only)
|
||||
//implementation("androidx.work:work-runtime:$work_version")
|
||||
|
||||
// Kotlin + coroutines
|
||||
implementation("androidx.work:work-runtime-ktx:2.5.0")
|
||||
|
||||
// optional - RxJava2 support
|
||||
//implementation("androidx.work:work-rxjava2:$work_version")
|
||||
|
||||
// optional - GCMNetworkManager support
|
||||
//implementation("androidx.work:work-gcm:$work_version")
|
||||
|
||||
// optional - Test helpers
|
||||
//androidTestImplementation("androidx.work:work-testing:$work_version")
|
||||
|
||||
// optional - Multiprocess support
|
||||
implementation "androidx.work:work-multiprocess:2.5.0"
|
||||
}
|
||||
|
|
|
@ -42,4 +42,6 @@
|
|||
<!--Needed to access Tor socket-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!--Needed to run in background (lol)-->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
</manifest>
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package im.cwtch.flwtch
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.Data
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.WorkManager
|
||||
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
import cwtch.Cwtch
|
||||
|
||||
class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
||||
CoroutineWorker(context, parameters) {
|
||||
private val CWTCH_EVENTBUS = "test.flutter.dev/eventBus"
|
||||
|
||||
private val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as
|
||||
NotificationManager
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val appDir = inputData.getString(KEY_APP_DIR)
|
||||
?: return Result.failure()
|
||||
val torPath = inputData.getString(KEY_TOR_PATH)
|
||||
?: return Result.failure()
|
||||
// Mark the Worker as important
|
||||
val progress = "Trying to do a Flwtch"
|
||||
setForeground(createForegroundInfo(progress))
|
||||
download(appDir, torPath)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private suspend fun download(appDir: String, torPath: String) {
|
||||
Cwtch.startCwtch(appDir, torPath)
|
||||
// seperate coroutine to poll event bus and send to dart
|
||||
//Log.i("FlwtchWorker.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
while(true) {
|
||||
val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||
Log.i("FlwtchWorker.kt", "got appbusEvent: " + evt)
|
||||
launch(Dispatchers.Main) {
|
||||
//todo: this elides evt.EventID which may be needed at some point?
|
||||
val flutterEngine = FlutterEngine(applicationContext)
|
||||
val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
||||
eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an instance of ForegroundInfo which can be used to update the
|
||||
// ongoing notification.
|
||||
private fun createForegroundInfo(progress: String): ForegroundInfo {
|
||||
val id = "flwtch"
|
||||
val title = "Flwtch"
|
||||
val cancel = "Nevermind"//todo: translate
|
||||
// This PendingIntent can be used to cancel the worker
|
||||
val intent = WorkManager.getInstance(applicationContext)
|
||||
.createCancelPendingIntent(getId())
|
||||
|
||||
val channelId =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel(id, id)
|
||||
} else {
|
||||
// If earlier version channel ID is not used
|
||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||
""
|
||||
}
|
||||
|
||||
val notification = NotificationCompat.Builder(applicationContext, id)
|
||||
.setContentTitle(title)
|
||||
.setTicker(title)
|
||||
.setContentText(progress)
|
||||
.setSmallIcon(R.mipmap.knott)
|
||||
.setOngoing(true)
|
||||
// Add the cancel action to the notification which can
|
||||
// be used to cancel the worker
|
||||
.addAction(android.R.drawable.ic_delete, cancel, intent)
|
||||
.build()
|
||||
|
||||
return ForegroundInfo(101, notification)
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun createNotificationChannel(channelId: String, channelName: String): String{
|
||||
val chan = NotificationChannel(channelId,
|
||||
channelName, NotificationManager.IMPORTANCE_NONE)
|
||||
chan.lightColor = Color.BLUE
|
||||
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||
notificationManager.createNotificationChannel(chan)
|
||||
return channelId
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_APP_DIR = "KEY_APP_DIR"
|
||||
const val KEY_TOR_PATH = "KEY_TOR_PATH"
|
||||
}
|
||||
|
||||
class AppbusEvent(json: String) : JSONObject(json) {
|
||||
val EventType = this.optString("EventType")
|
||||
val EventID = this.optString("EventID")
|
||||
val Data = this.optString("Data")
|
||||
}
|
||||
}
|
|
@ -7,6 +7,11 @@ import android.os.Bundle
|
|||
import android.os.Looper
|
||||
import android.util.Log
|
||||
|
||||
import androidx.work.Data
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkRequest
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -44,8 +49,6 @@ class MainActivity: FlutterActivity() {
|
|||
// Note: this methods are invoked on the main thread.
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_APP_INFO).setMethodCallHandler { call, result -> handleAppInfo(call, result) }
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_CWTCH).setMethodCallHandler { call, result -> handleCwtch(call, result) }
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun handleAppInfo(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
|
@ -70,21 +73,25 @@ class MainActivity: FlutterActivity() {
|
|||
val appDir = (call.argument("appDir") as? String) ?: "";
|
||||
val torPath = (call.argument("torPath") as? String) ?: "tor";
|
||||
Log.i("MainActivity.kt", " appDir: '" + appDir + "' torPath: '" + torPath + "'")
|
||||
Cwtch.startCwtch(appDir, torPath)
|
||||
|
||||
//Cwtch.startCwtch(appDir, torPath)// todo
|
||||
val data: Data = Data.Builder().putString(FlwtchWorker.KEY_APP_DIR, appDir).putString(FlwtchWorker.KEY_TOR_PATH, torPath).build()
|
||||
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<FlwtchWorker>().setInputData(data).build()
|
||||
WorkManager.getInstance(this).enqueue(uploadWorkRequest)
|
||||
|
||||
// seperate coroutine to poll event bus and send to dart
|
||||
val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
||||
Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
while(true) {
|
||||
val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||
Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
||||
launch(Dispatchers.Main) {
|
||||
//todo: this elides evt.EventID which may be needed at some point?
|
||||
eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
// val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
||||
// Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||
// GlobalScope.launch(Dispatchers.IO) {
|
||||
// while(true) {
|
||||
// val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||
// Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
||||
// launch(Dispatchers.Main) {
|
||||
// //todo: this elides evt.EventID which may be needed at some point?
|
||||
// eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
"SelectProfile" -> {
|
||||
val onion = (call.argument("profile") as? String) ?: "";
|
||||
|
|
|
@ -14,7 +14,7 @@ packages:
|
|||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.5.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -371,7 +371,7 @@ packages:
|
|||
name: vm_service
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "6.1.0+1"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
Loading…
Reference in New Issue