Fix android bugs

This commit is contained in:
problematicconsumer
2023-10-14 17:44:18 +03:30
parent 18e6723f32
commit 635e11c519
6 changed files with 63 additions and 48 deletions

View File

@@ -15,9 +15,9 @@
<application <application
android:name=".Application" android:name=".Application"
android:label="Hiddify Next"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round" android:label="Hiddify Next"
android:roundIcon="@mipmap/ic_launcher_round"
tools:targetApi="31"> tools:targetApi="31">
<meta-data <meta-data
@@ -26,11 +26,11 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true" android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<meta-data <meta-data
@@ -42,25 +42,26 @@
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme" />
/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sing-box"/>
<data android:host="import-remote-profile"/> <data android:scheme="sing-box" />
<data android:scheme="clash"/> <data android:host="import-remote-profile" />
<data android:host="install-config"/> <data android:scheme="clash" />
<data android:scheme="clashmeta"/> <data android:host="install-config" />
<data android:scheme="hiddify"/> <data android:scheme="clashmeta" />
<data android:host="install-sub"/> <data android:scheme="hiddify" />
<data android:host="install-sub" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
@@ -104,8 +105,7 @@
</service> </service>
<service <service
android:name=".bg.ProxyService" android:name=".bg.ProxyService"
android:exported="false"> android:exported="false"></service>
</service>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data <meta-data

View File

@@ -1,6 +1,5 @@
package com.hiddify.hiddify package com.hiddify.hiddify
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel
@@ -14,12 +13,12 @@ class LogHandler : FlutterPlugin {
private lateinit var logsChannel: EventChannel private lateinit var logsChannel: EventChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
logsChannel = EventChannel(flutterPluginBinding.binaryMessenger, SERVICE_LOGS) logsChannel = EventChannel(flutterPluginBinding.binaryMessenger, SERVICE_LOGS)
logsChannel.setStreamHandler(object : EventChannel.StreamHandler { logsChannel.setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
MainActivity.instance.serviceLogs.observeForever { it -> MainActivity.instance.serviceLogs.observeForever {
if (it == null) return@observeForever if (it == null) return@observeForever
events?.success(it) events?.success(it)
} }

View File

@@ -8,7 +8,6 @@ import android.net.VpnService
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -46,7 +45,7 @@ class MainActivity : FlutterFragmentActivity(), ServiceConnection.Callback {
super.configureFlutterEngine(flutterEngine) super.configureFlutterEngine(flutterEngine)
instance = this instance = this
reconnect() reconnect()
flutterEngine.plugins.add(MethodHandler()) flutterEngine.plugins.add(MethodHandler(lifecycleScope))
flutterEngine.plugins.add(PlatformSettingsHandler()) flutterEngine.plugins.add(PlatformSettingsHandler())
flutterEngine.plugins.add(EventHandler()) flutterEngine.plugins.add(EventHandler())
flutterEngine.plugins.add(LogHandler()) flutterEngine.plugins.add(LogHandler())

View File

@@ -1,6 +1,6 @@
package com.hiddify.hiddify package com.hiddify.hiddify
import androidx.annotation.NonNull import android.util.Log
import com.hiddify.hiddify.bg.BoxService import com.hiddify.hiddify.bg.BoxService
import com.hiddify.hiddify.constant.Status import com.hiddify.hiddify.constant.Status
import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin
@@ -8,14 +8,17 @@ import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMethodCodec
import io.nekohasekai.libbox.Libbox import io.nekohasekai.libbox.Libbox
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler { class MethodHandler(private val scope: CoroutineScope) : FlutterPlugin,
MethodChannel.MethodCallHandler {
private var channel: MethodChannel? = null private var channel: MethodChannel? = null
companion object { companion object {
const val TAG = "A/MethodHandler"
const val channelName = "com.hiddify.app/method" const val channelName = "com.hiddify.app/method"
enum class Trigger(val method: String) { enum class Trigger(val method: String) {
@@ -29,7 +32,7 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
} }
} }
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue() val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue()
channel = MethodChannel( channel = MethodChannel(
flutterPluginBinding.binaryMessenger, flutterPluginBinding.binaryMessenger,
@@ -47,7 +50,7 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) { when (call.method) {
Trigger.ParseConfig.method -> { Trigger.ParseConfig.method -> {
GlobalScope.launch { scope.launch(Dispatchers.IO) {
result.runCatching { result.runCatching {
val args = call.arguments as Map<*, *> val args = call.arguments as Map<*, *>
val path = args["path"] as String val path = args["path"] as String
@@ -68,19 +71,35 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
} }
Trigger.Start.method -> { Trigger.Start.method -> {
val args = call.arguments as Map<*, *> result.runCatching {
Settings.activeConfigPath = args["path"] as String? ?: "" val args = call.arguments as Map<*, *>
MainActivity.instance.startService() Settings.activeConfigPath = args["path"] as String? ?: ""
result.success(true) val mainActivity = MainActivity.instance
val started = mainActivity.serviceStatus.value == Status.Started
if (started) {
Log.w(TAG, "service is already running")
return success(true)
}
mainActivity.startService()
success(true)
}
} }
Trigger.Stop.method -> { Trigger.Stop.method -> {
BoxService.stop() result.runCatching {
result.success(true) val mainActivity = MainActivity.instance
val started = mainActivity.serviceStatus.value == Status.Started
if (!started) {
Log.w(TAG, "service is not running")
return success(true)
}
BoxService.stop()
success(true)
}
} }
Trigger.Restart.method -> { Trigger.Restart.method -> {
GlobalScope.launch { scope.launch(Dispatchers.IO) {
result.runCatching { result.runCatching {
val args = call.arguments as Map<*, *> val args = call.arguments as Map<*, *>
Settings.activeConfigPath = args["path"] as String? ?: "" Settings.activeConfigPath = args["path"] as String? ?: ""
@@ -93,8 +112,7 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
BoxService.stop() BoxService.stop()
delay(200L) delay(200L)
mainActivity.startService() mainActivity.startService()
success(true) return@launch success(true)
return@launch
} }
runCatching { runCatching {
Libbox.newStandaloneCommandClient().serviceReload() Libbox.newStandaloneCommandClient().serviceReload()
@@ -107,7 +125,7 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
} }
Trigger.SelectOutbound.method -> { Trigger.SelectOutbound.method -> {
GlobalScope.launch { scope.launch {
result.runCatching { result.runCatching {
val args = call.arguments as Map<*, *> val args = call.arguments as Map<*, *>
Libbox.newStandaloneCommandClient() Libbox.newStandaloneCommandClient()
@@ -121,7 +139,7 @@ class MethodHandler : FlutterPlugin, MethodChannel.MethodCallHandler {
} }
Trigger.UrlTest.method -> { Trigger.UrlTest.method -> {
GlobalScope.launch { scope.launch {
result.runCatching { result.runCatching {
val args = call.arguments as Map<*, *> val args = call.arguments as Map<*, *>
Libbox.newStandaloneCommandClient() Libbox.newStandaloneCommandClient()

View File

@@ -1,18 +1,16 @@
package com.hiddify.hiddify package com.hiddify.hiddify
import android.Manifest import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.drawable.VectorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.util.Base64 import android.util.Base64
import androidx.annotation.NonNull
import androidx.core.graphics.drawable.toBitmap
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import com.hiddify.hiddify.Application.Companion.packageManager import com.hiddify.hiddify.Application.Companion.packageManager
@@ -48,7 +46,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
} }
} }
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue() val taskQueue = flutterPluginBinding.binaryMessenger.makeBackgroundTaskQueue()
channel = MethodChannel( channel = MethodChannel(
flutterPluginBinding.binaryMessenger, flutterPluginBinding.binaryMessenger,
@@ -69,7 +67,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
} }
override fun onDetachedFromActivityForConfigChanges() { override fun onDetachedFromActivityForConfigChanges() {
activity = null; activity = null
} }
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
@@ -78,7 +76,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
} }
override fun onDetachedFromActivity() { override fun onDetachedFromActivity() {
activity = null; activity = null
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
@@ -95,6 +93,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
@SerializedName("is-system-app") val isSystemApp: Boolean @SerializedName("is-system-app") val isSystemApp: Boolean
) )
@SuppressLint("BatteryLife")
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) { when (call.method) {
Trigger.IsIgnoringBatteryOptimizations.method -> { Trigger.IsIgnoringBatteryOptimizations.method -> {
@@ -166,7 +165,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
result.runCatching { result.runCatching {
val args = call.arguments as Map<*, *> val args = call.arguments as Map<*, *>
val packageName = val packageName =
args["packageName"] as String? ?: return error("provide packageName") args["packageName"] as String
val drawable = packageManager.getApplicationIcon(packageName) val drawable = packageManager.getApplicationIcon(packageName)
val bitmap = Bitmap.createBitmap( val bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth, drawable.intrinsicWidth,

View File

@@ -32,9 +32,9 @@ object Settings {
val perAppProxyList: List<String> val perAppProxyList: List<String>
get() { get() {
val stringValue = if (perAppProxyMode == PerAppProxyMode.INCLUDE) { val stringValue = if (perAppProxyMode == PerAppProxyMode.INCLUDE) {
preferences.getString(SettingsKey.PER_APP_PROXY_INCLUDE_LIST, "")!!; preferences.getString(SettingsKey.PER_APP_PROXY_INCLUDE_LIST, "")!!
} else { } else {
preferences.getString(SettingsKey.PER_APP_PROXY_EXCLUDE_LIST, "")!!; preferences.getString(SettingsKey.PER_APP_PROXY_EXCLUDE_LIST, "")!!
} }
if (!stringValue.startsWith(LIST_IDENTIFIER)) { if (!stringValue.startsWith(LIST_IDENTIFIER)) {
return emptyList() return emptyList()