add temp acquire
This commit is contained in:
7 files changed
+93
-6
No files matched your search
@@ -7,6 +7,7 @@ import android.content.IntentFilter
|
||||
import android.graphics.drawable.Icon
|
||||
import android.service.quicksettings.Tile
|
||||
import android.service.quicksettings.TileService
|
||||
import com.github.kr328.clash.common.Permissions
|
||||
import com.github.kr328.clash.remote.RemoteUtils
|
||||
import com.github.kr328.clash.common.ids.Intents
|
||||
import com.github.kr328.clash.utils.startClashService
|
||||
@@ -84,7 +85,9 @@ class TileService : TileService() {
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STARTED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
}
|
||||
},
|
||||
Permissions.PERMISSION_ACCESS_CLASH,
|
||||
null
|
||||
)
|
||||
|
||||
val name = RemoteUtils.getCurrentClashProfileName(this)
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.IntentFilter
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.github.kr328.clash.common.Permissions
|
||||
import com.github.kr328.clash.common.ids.Intents
|
||||
|
||||
object Broadcasts {
|
||||
@@ -70,8 +71,7 @@ object Broadcasts {
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STARTED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
})
|
||||
|
||||
}, Permissions.PERMISSION_ACCESS_CLASH, null)
|
||||
|
||||
val current = RemoteUtils.detectClashRunning(application)
|
||||
if (current != clashRunning) {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
android:process=":background" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:name=".ProfileProvider"
|
||||
android:authorities="${applicationId}.profiles"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
@@ -27,7 +27,15 @@ object ProfileProcessor {
|
||||
context.resolveBaseDir(metadata.id)
|
||||
)
|
||||
|
||||
val entity = metadata.toProfileEntity()
|
||||
val entity = if (metadata.type == Type.FILE)
|
||||
metadata.copy(
|
||||
uri = ProfileProvider.resolveUri(
|
||||
context,
|
||||
context.resolveProfileFile(metadata.id)
|
||||
)
|
||||
).toProfileEntity()
|
||||
else
|
||||
metadata.toProfileEntity()
|
||||
|
||||
if (ProfileDao.queryById(metadata.id) == null)
|
||||
ProfileDao.insert(entity)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.github.kr328.clash.service
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.os.bundleOf
|
||||
import com.github.kr328.clash.service.util.resolveProfileFile
|
||||
import com.github.kr328.clash.service.util.resolveTempProfileFile
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
class ProfileProvider : FileProvider() {
|
||||
companion object {
|
||||
private const val METHOD_ACQUIRE_TEMP = "acquireTemp"
|
||||
private const val METHOD_RELEASE_TEMP = "releaseTemp"
|
||||
|
||||
// service side functions
|
||||
fun resolveUri(context: Context, file: File): Uri {
|
||||
return getUriForFile(
|
||||
context,
|
||||
context.packageName + Constants.PROFILE_PROVIDER_SUFFIX,
|
||||
file
|
||||
)
|
||||
}
|
||||
|
||||
// client side functions
|
||||
suspend fun acquireTemp(context: Context, id: Long): Uri = withContext(Dispatchers.IO) {
|
||||
val uri = Uri.parse(context.packageName + Constants.PROFILE_PROVIDER_SUFFIX)
|
||||
|
||||
context.contentResolver
|
||||
.call(uri, METHOD_ACQUIRE_TEMP, id.toString(), null)?.getParcelable<Uri>("uri")
|
||||
?: throw FileNotFoundException("No such profile")
|
||||
}
|
||||
|
||||
suspend fun releaseTemp(context: Context, id: Long) = withContext(Dispatchers.IO) {
|
||||
val uri = Uri.parse(context.packageName + Constants.PROFILE_PROVIDER_SUFFIX)
|
||||
|
||||
context.contentResolver
|
||||
.call(uri, METHOD_RELEASE_TEMP, id.toString(), null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
|
||||
when (method) {
|
||||
METHOD_ACQUIRE_TEMP -> {
|
||||
val id = arg?.toLongOrNull() ?: return null
|
||||
|
||||
val file = context!!.resolveProfileFile(id)
|
||||
if (!file.exists())
|
||||
return null
|
||||
|
||||
val temp = context!!.resolveTempProfileFile(id)
|
||||
if (!temp.exists())
|
||||
file.copyTo(context!!.resolveTempProfileFile(id))
|
||||
|
||||
return bundleOf("uri" to resolveUri(context!!, temp))
|
||||
}
|
||||
METHOD_RELEASE_TEMP -> {
|
||||
val id = arg?.toLongOrNull() ?: return null
|
||||
|
||||
context!!.resolveTempProfileFile(id).delete()
|
||||
}
|
||||
}
|
||||
return super.call(method, arg, extras)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.github.kr328.clash.service.model.toProfileMetadata
|
||||
import com.github.kr328.clash.service.util.broadcastProfileChanged
|
||||
import com.github.kr328.clash.service.util.resolveBaseDir
|
||||
import com.github.kr328.clash.service.util.resolveProfileFile
|
||||
import com.github.kr328.clash.service.util.resolveTempProfileFile
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
@@ -87,11 +88,13 @@ class ProfileService : BaseService() {
|
||||
override fun delete(id: Long) {
|
||||
launch {
|
||||
lock.withLock {
|
||||
pending.remove(id)
|
||||
if (pending.remove(id) != null)
|
||||
service.resolveBaseDir(id).deleteRecursively()
|
||||
ProfileDao.remove(id)
|
||||
}
|
||||
|
||||
service.resolveProfileFile(id).delete()
|
||||
service.resolveTempProfileFile(id).delete()
|
||||
service.resolveBaseDir(id).deleteRecursively()
|
||||
|
||||
service.broadcastProfileChanged()
|
||||
|
||||
@@ -10,4 +10,8 @@ fun Context.resolveProfileFile(id: Long): File {
|
||||
|
||||
fun Context.resolveBaseDir(id: Long): File {
|
||||
return filesDir.resolve(Constants.CLASH_DIR).resolve(id.toString())
|
||||
}
|
||||
|
||||
fun Context.resolveTempProfileFile(id: Long): File {
|
||||
return cacheDir.resolve(Constants.PROFILES_DIR).resolve("$id.yaml")
|
||||
}
|
||||
Reference in new issue
Block a user