WIP: partial android service migration
This commit is contained in:
parent
d8059197fe
commit
a99a00de30
|
@ -69,6 +69,15 @@ android {
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
|
@ -82,4 +91,24 @@ dependencies {
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||||
implementation "com.airbnb.android:lottie:3.5.0"
|
implementation "com.airbnb.android:lottie:3.5.0"
|
||||||
implementation "com.android.support.constraint:constraint-layout:2.0.4"
|
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-->
|
<!--Needed to access Tor socket-->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<!--Needed to run in background (lol)-->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
</manifest>
|
</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.os.Looper
|
||||||
import android.util.Log
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -44,8 +49,6 @@ class MainActivity: FlutterActivity() {
|
||||||
// Note: this methods are invoked on the main thread.
|
// 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_APP_INFO).setMethodCallHandler { call, result -> handleAppInfo(call, result) }
|
||||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_CWTCH).setMethodCallHandler { call, result -> handleCwtch(call, result) }
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_CWTCH).setMethodCallHandler { call, result -> handleCwtch(call, result) }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAppInfo(@NonNull call: MethodCall, @NonNull result: 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 appDir = (call.argument("appDir") as? String) ?: "";
|
||||||
val torPath = (call.argument("torPath") as? String) ?: "tor";
|
val torPath = (call.argument("torPath") as? String) ?: "tor";
|
||||||
Log.i("MainActivity.kt", " appDir: '" + appDir + "' torPath: '" + torPath + "'")
|
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
|
// seperate coroutine to poll event bus and send to dart
|
||||||
val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
// val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS)
|
||||||
Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
// Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...")
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
// GlobalScope.launch(Dispatchers.IO) {
|
||||||
while(true) {
|
// while(true) {
|
||||||
val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
// val evt = AppbusEvent(Cwtch.getAppBusEvent())
|
||||||
Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
// Log.i("MainActivity.kt", "got appbusEvent: " + evt)
|
||||||
launch(Dispatchers.Main) {
|
// launch(Dispatchers.Main) {
|
||||||
//todo: this elides evt.EventID which may be needed at some point?
|
// //todo: this elides evt.EventID which may be needed at some point?
|
||||||
eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
// eventbus_chan.invokeMethod(evt.EventType, evt.Data)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
"SelectProfile" -> {
|
"SelectProfile" -> {
|
||||||
val onion = (call.argument("profile") as? String) ?: "";
|
val onion = (call.argument("profile") as? String) ?: "";
|
||||||
|
|
|
@ -14,7 +14,7 @@ packages:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.6.1"
|
version: "2.5.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -371,7 +371,7 @@ packages:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.0"
|
version: "6.1.0+1"
|
||||||
webdriver:
|
webdriver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Reference in New Issue