From d261fbd4c0b5b8a58028d94b45fbba4cbda9af87 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Tue, 12 Apr 2022 15:03:21 -0700 Subject: [PATCH] kotlin powermanagement info and exemption request --- android/app/src/main/AndroidManifest.xml | 4 ++ .../kotlin/im/cwtch/flwtch/MainActivity.kt | 58 +++++++++++-------- lib/cwtch/gomobile.dart | 12 ++++ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ff06f437..88c79b7b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -46,6 +46,10 @@ + + + diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index fc6e54dc..2798ffef 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -1,49 +1,44 @@ package im.cwtch.flwtch import SplashView +import android.annotation.TargetApi import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import androidx.annotation.NonNull import android.content.pm.PackageManager +import android.net.Uri +import android.os.PowerManager +import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS import android.util.Log import android.view.Window +import androidx.annotation.NonNull import androidx.lifecycle.Observer import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.work.* -import io.flutter.embedding.android.SplashScreen +import cwtch.Cwtch import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.android.SplashScreen import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.ErrorLogResult - +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.Result import org.json.JSONObject -import java.util.concurrent.TimeUnit -import java.io.File import java.nio.file.Files import java.nio.file.Paths -import java.nio.file.StandardCopyOption - -import android.net.Uri -import android.provider.DocumentsContract -import android.content.ContentUris -import android.os.Build -import android.os.Environment -import android.database.Cursor -import android.provider.MediaStore - -import cwtch.Cwtch +import java.util.concurrent.TimeUnit class MainActivity: FlutterActivity() { override fun provideSplashScreen(): SplashScreen? = SplashView() + // Channel to get app info private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo" private val CALL_APP_INFO = "getNativeLibDir" + private val CALL_ASK_BATTERY_EXEMPTION = "requestBatteryExemption" + private val CALL_IS_BATTERY_EXEMPT = "isBatteryExempt" // Channel to get cwtch api calls on private val CHANNEL_CWTCH = "cwtch" @@ -67,6 +62,7 @@ class MainActivity: FlutterActivity() { private val FILEPICKER_REQUEST_CODE = 234 private val PREVIEW_EXPORT_REQUEST_CODE = 235 private val PROFILE_EXPORT_REQUEST_CODE = 236 + private val REQUEST_DOZE_WHITELISTING_CODE:Int = 9 private var dlToProfile = "" private var dlToHandle = "" private var dlToFileKey = "" @@ -99,7 +95,7 @@ class MainActivity: FlutterActivity() { super.onActivityResult(requestCode, result, intent); if (intent == null || intent!!.getData() == null) { - Log.i("MainActivity:onActivityResult", "user canceled activity"); + Log.i(TAG, "user canceled activity"); return; } @@ -139,6 +135,8 @@ class MainActivity: FlutterActivity() { os?.close(); //Files.delete(sourcePath); } + } else if (requestCode == REQUEST_DOZE_WHITELISTING_CODE) { + checkIgnoreBatteryOpt() } } @@ -158,10 +156,26 @@ class MainActivity: FlutterActivity() { when (call.method) { CALL_APP_INFO -> result.success(getNativeLibDir()) ?: result.error("Unavailable", "nativeLibDir not available", null); + CALL_ASK_BATTERY_EXEMPTION -> result.success(checkIgnoreBatteryOpt()) ?: false; + CALL_IS_BATTERY_EXEMPT -> result.success(requestBatteryExemption()); else -> result.notImplemented() } } + @TargetApi(23) + private fun checkIgnoreBatteryOpt(): Boolean { + val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager + return powerManager.isIgnoringBatteryOptimizations(this.packageName) ?: false; + } + + @TargetApi(23) + private fun requestBatteryExemption() { + val i = Intent() + i.action = ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + i.data = Uri.parse("package:" + this.packageName) + startActivityForResult(i, REQUEST_DOZE_WHITELISTING_CODE); + } + private fun getNativeLibDir(): String { val ainfo = this.applicationContext.packageManager.getApplicationInfo( "im.cwtch.flwtch", // Must be app name @@ -489,9 +503,7 @@ class MainActivity: FlutterActivity() { // We need to do this here because after a "pause" flutter is still running // but we might have lost sync with the background process... Log.i("MainActivity.kt", "Call ReconnectCwtchForeground") - val data: Data = Data.Builder().putString(FlwtchWorker.KEY_METHOD, "ReconnectCwtchForeground").putString(FlwtchWorker.KEY_ARGS, "{}").build() - val workRequest = OneTimeWorkRequestBuilder().setInputData(data).build() - WorkManager.getInstance(applicationContext).enqueue(workRequest) + Cwtch.reconnectCwtchForeground() } override fun onStop() { diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index 7bd4f888..fac90776 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -57,6 +57,18 @@ class CwtchGomobile implements Cwtch { return cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath}); } + //* Android Only Requests + + Future IsBatteryExempt() async { + return await appInfoPlatform?.invokeMethod('isBatteryExempt') ?? false; + } + + Future RequestBatteryExemption() async { + await appInfoPlatform?.invokeMethod('requestBatteryExemption'); + } + + //* End Android Only Requests + @override // ignore: non_constant_identifier_names Future ReconnectCwtchForeground() async {