fix external intent lost & replace application observer
This commit is contained in:
9 files changed
+133
-87
No files matched your search
@@ -15,6 +15,7 @@ import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import com.github.kr328.clash.common.util.intent
|
||||
import com.github.kr328.clash.remote.withProfile
|
||||
import com.github.kr328.clash.service.model.Profile
|
||||
import com.github.kr328.clash.service.model.Profile.Type
|
||||
import kotlinx.android.synthetic.main.activity_create_profile.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -47,7 +48,7 @@ class CreateProfileActivity : BaseActivity() {
|
||||
|
||||
self.launch {
|
||||
val id = withProfile {
|
||||
acquireUnused(item.type)
|
||||
acquireUnused(item.type, item.intent?.toUri(0))
|
||||
}
|
||||
|
||||
startActivityForResult(
|
||||
|
||||
@@ -118,7 +118,7 @@ class ProfileEditActivity : BaseActivity() {
|
||||
launch {
|
||||
try {
|
||||
withProfile {
|
||||
updateMetadata(metadata.id, metadata)
|
||||
update(metadata.id, metadata)
|
||||
commitAsync(metadata.id).await()
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
|
||||
val profile = editorStack.pop()
|
||||
|
||||
withProfile {
|
||||
updateMetadata(profile.id, profile)
|
||||
update(profile.id, profile)
|
||||
startUpdate(profile.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.github.kr328.clash.common.Global
|
||||
import com.github.kr328.clash.common.Permissions
|
||||
import com.github.kr328.clash.common.ids.Intents
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import com.github.kr328.clash.utils.ApplicationObserver
|
||||
|
||||
object Broadcasts {
|
||||
interface Receiver {
|
||||
@@ -63,35 +63,37 @@ object Broadcasts {
|
||||
receivers.remove(receiver)
|
||||
}
|
||||
|
||||
fun init(application: Application) {
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
application.registerReceiver(broadcastReceiver, IntentFilter().apply {
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_CHANGED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STARTED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
}, Permissions.PERMISSION_RECEIVE_BROADCASTS, null)
|
||||
private val observer = ApplicationObserver {
|
||||
Log.d("Global Broadcast Receiver State = $it")
|
||||
|
||||
val current = RemoteUtils.detectClashRunning(application)
|
||||
if (current != clashRunning) {
|
||||
clashRunning = current
|
||||
if ( it ) {
|
||||
Global.application.registerReceiver(broadcastReceiver, IntentFilter().apply {
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_CHANGED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STARTED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
}, Permissions.PERMISSION_RECEIVE_BROADCASTS, null)
|
||||
|
||||
if (current) {
|
||||
receivers.forEach {
|
||||
it.onStarted()
|
||||
}
|
||||
} else {
|
||||
receivers.forEach {
|
||||
it.onStopped(null)
|
||||
}
|
||||
val current = RemoteUtils.detectClashRunning(Global.application)
|
||||
if (current != clashRunning) {
|
||||
clashRunning = current
|
||||
|
||||
if (current) {
|
||||
receivers.forEach { receiver ->
|
||||
receiver.onStarted()
|
||||
}
|
||||
} else {
|
||||
receivers.forEach { receiver ->
|
||||
receiver.onStopped(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Global.application.unregisterReceiver(broadcastReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
application.unregisterReceiver(broadcastReceiver)
|
||||
}
|
||||
})
|
||||
fun init(application: Application) {
|
||||
observer.register(application)
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ProfileClient(private val service: IProfileService) {
|
||||
suspend fun acquireUnused(type: Profile.Type) = withContext(Dispatchers.IO) {
|
||||
service.acquireUnused(type.name)
|
||||
suspend fun acquireUnused(type: Profile.Type, source: String?) = withContext(Dispatchers.IO) {
|
||||
service.acquireUnused(type.name, source)
|
||||
}
|
||||
|
||||
suspend fun acquireCloned(id: Long) = withContext(Dispatchers.IO) {
|
||||
@@ -22,8 +22,8 @@ class ProfileClient(private val service: IProfileService) {
|
||||
service.acquireTempUri(id)
|
||||
}
|
||||
|
||||
suspend fun updateMetadata(id: Long, metadata: Profile) = withContext(Dispatchers.IO) {
|
||||
service.updateMetadata(id, metadata)
|
||||
suspend fun update(id: Long, metadata: Profile) = withContext(Dispatchers.IO) {
|
||||
service.update(id, metadata)
|
||||
}
|
||||
|
||||
suspend fun commitAsync(id: Long) = withContext(Dispatchers.IO) {
|
||||
|
||||
@@ -9,16 +9,16 @@ import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.IBinder
|
||||
import androidx.core.content.edit
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.github.kr328.clash.ApkBrokenActivity
|
||||
import com.github.kr328.clash.Constants
|
||||
import com.github.kr328.clash.common.Global
|
||||
import com.github.kr328.clash.common.util.intent
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import com.github.kr328.clash.service.ClashManagerService
|
||||
import com.github.kr328.clash.service.IClashManager
|
||||
import com.github.kr328.clash.service.IProfileService
|
||||
import com.github.kr328.clash.service.ProfileService
|
||||
import com.github.kr328.clash.utils.ApplicationObserver
|
||||
import com.microsoft.appcenter.crashes.Crashes
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
@@ -82,60 +82,63 @@ object Remote {
|
||||
}
|
||||
}
|
||||
|
||||
fun init(application: Application) {
|
||||
val handler = Handler()
|
||||
private val handler = Handler()
|
||||
private val observer = ApplicationObserver {
|
||||
Log.d("Remote Connection State = $it")
|
||||
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
handler.removeMessages(0)
|
||||
val application = Global.application
|
||||
|
||||
GlobalScope.launch {
|
||||
val valid = withContext(Dispatchers.IO) {
|
||||
verifyApk(application)
|
||||
}
|
||||
if ( it ) {
|
||||
handler.removeMessages(0)
|
||||
|
||||
if (!valid) {
|
||||
application.startActivity(
|
||||
ApkBrokenActivity::class.intent
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
)
|
||||
return@launch
|
||||
}
|
||||
GlobalScope.launch {
|
||||
val valid = withContext(Dispatchers.IO) {
|
||||
verifyApk(application)
|
||||
}
|
||||
|
||||
clashConnection = ClashConnection().apply {
|
||||
application.bindService(
|
||||
ClashManagerService::class.intent,
|
||||
this,
|
||||
Context.BIND_AUTO_CREATE
|
||||
)
|
||||
}
|
||||
if (!valid) {
|
||||
application.startActivity(
|
||||
ApkBrokenActivity::class.intent
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
)
|
||||
return@launch
|
||||
}
|
||||
|
||||
profileConnection = ProfileConnection().apply {
|
||||
application.bindService(
|
||||
ProfileService::class.intent,
|
||||
this,
|
||||
Context.BIND_AUTO_CREATE
|
||||
)
|
||||
}
|
||||
clashConnection = ClashConnection().apply {
|
||||
application.bindService(
|
||||
ClashManagerService::class.intent,
|
||||
this,
|
||||
Context.BIND_AUTO_CREATE
|
||||
)
|
||||
}
|
||||
|
||||
profileConnection = ProfileConnection().apply {
|
||||
application.bindService(
|
||||
ProfileService::class.intent,
|
||||
this,
|
||||
Context.BIND_AUTO_CREATE
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler.postDelayed({
|
||||
clashConnection?.also {
|
||||
application.unbindService(it)
|
||||
it.onServiceDisconnected(null)
|
||||
}
|
||||
profileConnection?.also {
|
||||
application.unbindService(it)
|
||||
it.onServiceDisconnected(null)
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
handler.postDelayed({
|
||||
clashConnection?.also {
|
||||
application.unbindService(it)
|
||||
it.onServiceDisconnected(null)
|
||||
}
|
||||
profileConnection?.also {
|
||||
application.unbindService(it)
|
||||
it.onServiceDisconnected(null)
|
||||
}
|
||||
clashConnection = null
|
||||
profileConnection = null
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
|
||||
clashConnection = null
|
||||
profileConnection = null
|
||||
}, 5000)
|
||||
}
|
||||
})
|
||||
fun init(application: Application) {
|
||||
observer.register(application)
|
||||
}
|
||||
|
||||
private fun verifyApk(application: Application): Boolean {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.github.kr328.clash.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
|
||||
class ApplicationObserver(val stateChanged: (Boolean) -> Unit) {
|
||||
private var applicationRunning = false
|
||||
private set(value) {
|
||||
if ( field != value )
|
||||
stateChanged(value)
|
||||
|
||||
field = value
|
||||
}
|
||||
private var activityCount: Int = 0
|
||||
|
||||
private val activityObserver = object: Application.ActivityLifecycleCallbacks {
|
||||
override fun onActivityPaused(activity: Activity) {}
|
||||
override fun onActivityStarted(activity: Activity) {}
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||
override fun onActivityStopped(activity: Activity) {}
|
||||
override fun onActivityResumed(activity: Activity) {}
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
synchronized(this) {
|
||||
activityCount--
|
||||
applicationRunning = activityCount > 0
|
||||
}
|
||||
}
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
synchronized(this) {
|
||||
activityCount++
|
||||
applicationRunning = activityCount > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun register(application: Application) {
|
||||
application.registerActivityLifecycleCallbacks(activityObserver)
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,11 @@ import com.github.kr328.clash.service.transact.IStreamCallback;
|
||||
import com.github.kr328.clash.service.model.Profile;
|
||||
|
||||
interface IProfileService {
|
||||
long acquireUnused(String type);
|
||||
long acquireUnused(String type, String source);
|
||||
long acquireCloned(long id);
|
||||
String acquireTempUri(long id);
|
||||
void release(long id);
|
||||
void updateMetadata(long id, in Profile metadata);
|
||||
void update(long id, in Profile metadata);
|
||||
void commit(long id, in IStreamCallback callback);
|
||||
void delete(long id);
|
||||
void clear(long id);
|
||||
|
||||
@@ -52,7 +52,7 @@ class ProfileService : BaseService() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun acquireUnused(type: String): Long {
|
||||
override fun acquireUnused(type: String, source: String?): Long {
|
||||
return runBlocking {
|
||||
lock.withLock {
|
||||
val id = generateNextId()
|
||||
@@ -62,7 +62,7 @@ class ProfileService : BaseService() {
|
||||
name = "",
|
||||
type = Profile.Type.valueOf(type),
|
||||
uri = Uri.EMPTY,
|
||||
source = null,
|
||||
source = source?.let { Uri.parse(it) },
|
||||
active = false,
|
||||
interval = 0,
|
||||
lastModified = 0
|
||||
@@ -152,7 +152,7 @@ class ProfileService : BaseService() {
|
||||
return ProfileProvider.resolveUri(service, tempFile).toString()
|
||||
}
|
||||
|
||||
override fun updateMetadata(id: Long, metadata: Profile?) {
|
||||
override fun update(id: Long, metadata: Profile?) {
|
||||
launch {
|
||||
lock.withLock {
|
||||
pending[id] = metadata ?: return@launch
|
||||
|
||||
Reference in new issue
Block a user