mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 23:17:39 +00:00
Minor fixes and cleanups
This commit is contained in:
parent
6fb032b3c2
commit
094c3d559a
@ -2,6 +2,7 @@ package com.topjohnwu.magisk
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.os.Environment
|
||||||
import android.util.Xml
|
import android.util.Xml
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.topjohnwu.magisk.data.database.SettingsDao
|
import com.topjohnwu.magisk.data.database.SettingsDao
|
||||||
@ -97,10 +98,8 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
if (Utils.isCanary) Value.CANARY_DEBUG_CHANNEL
|
if (Utils.isCanary) Value.CANARY_DEBUG_CHANNEL
|
||||||
else Value.DEFAULT_CHANNEL
|
else Value.DEFAULT_CHANNEL
|
||||||
|
|
||||||
private val defaultDownloadPath get() = Const.EXTERNAL_PATH.toRelativeString(Const.EXTERNAL_PATH.parentFile)
|
|
||||||
|
|
||||||
var isDownloadCacheEnabled by preference(Key.DOWNLOAD_CACHE, true)
|
var isDownloadCacheEnabled by preference(Key.DOWNLOAD_CACHE, true)
|
||||||
var downloadPath by preference(Key.DOWNLOAD_PATH, defaultDownloadPath)
|
var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS)
|
||||||
var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE)
|
var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE)
|
||||||
|
|
||||||
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
|
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
|
||||||
@ -128,14 +127,9 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
var suManager by dbStrings(Key.SU_MANAGER, "")
|
var suManager by dbStrings(Key.SU_MANAGER, "")
|
||||||
|
|
||||||
fun downloadsFile(path: String = downloadPath) =
|
// Always return a path in external storage where we can write
|
||||||
File(Const.EXTERNAL_PATH.parentFile, path).run {
|
val downloadDirectory get() =
|
||||||
if (exists()) {
|
Utils.ensureDownloadPath(downloadPath) ?: get<Context>().getExternalFilesDir(null)!!
|
||||||
if (isDirectory) this else null
|
|
||||||
} else {
|
|
||||||
if (mkdirs()) this else null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initialize() = prefs.edit {
|
fun initialize() = prefs.edit {
|
||||||
parsePrefs(this)
|
parsePrefs(this)
|
||||||
|
@ -6,13 +6,13 @@ import android.app.PendingIntent
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.RequiresPermission
|
import androidx.annotation.RequiresPermission
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import com.topjohnwu.magisk.ClassMap
|
import com.topjohnwu.magisk.ClassMap
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.Config
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.*
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.*
|
||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
|
||||||
@ -31,7 +31,7 @@ import kotlin.random.Random.Default.nextInt
|
|||||||
open class DownloadService : RemoteFileService() {
|
open class DownloadService : RemoteFileService() {
|
||||||
|
|
||||||
private val context get() = this
|
private val context get() = this
|
||||||
private val String.downloadsFile get() = Config.downloadsFile()?.let { File(it, this) }
|
private val String.downloadsFile get() = File(Config.downloadDirectory, this)
|
||||||
private val File.type
|
private val File.type
|
||||||
get() = MimeTypeMap.getSingleton()
|
get() = MimeTypeMap.getSingleton()
|
||||||
.getMimeTypeFromExtension(extension)
|
.getMimeTypeFromExtension(extension)
|
||||||
@ -40,7 +40,6 @@ open class DownloadService : RemoteFileService() {
|
|||||||
override fun onFinished(file: File, subject: DownloadSubject) = when (subject) {
|
override fun onFinished(file: File, subject: DownloadSubject) = when (subject) {
|
||||||
is Magisk -> onFinishedInternal(file, subject)
|
is Magisk -> onFinishedInternal(file, subject)
|
||||||
is Module -> onFinishedInternal(file, subject)
|
is Module -> onFinishedInternal(file, subject)
|
||||||
else -> Unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onFinishedInternal(
|
private fun onFinishedInternal(
|
||||||
@ -71,7 +70,6 @@ open class DownloadService : RemoteFileService() {
|
|||||||
) = when (subject) {
|
) = when (subject) {
|
||||||
is Magisk -> addActionsInternal(file, subject)
|
is Magisk -> addActionsInternal(file, subject)
|
||||||
is Module -> addActionsInternal(file, subject)
|
is Module -> addActionsInternal(file, subject)
|
||||||
else -> this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun NotificationCompat.Builder.addActionsInternal(
|
private fun NotificationCompat.Builder.addActionsInternal(
|
||||||
@ -109,13 +107,7 @@ open class DownloadService : RemoteFileService() {
|
|||||||
// ---
|
// ---
|
||||||
|
|
||||||
private fun moveToDownloads(file: File) {
|
private fun moveToDownloads(file: File) {
|
||||||
val destination = file.name.downloadsFile ?: let {
|
val destination = file.name.downloadsFile
|
||||||
Utils.toast(
|
|
||||||
getString(R.string.download_file_folder_error),
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file != destination) {
|
if (file != destination) {
|
||||||
destination.deleteRecursively()
|
destination.deleteRecursively()
|
||||||
@ -125,32 +117,18 @@ open class DownloadService : RemoteFileService() {
|
|||||||
Utils.toast(
|
Utils.toast(
|
||||||
getString(
|
getString(
|
||||||
R.string.internal_storage,
|
R.string.internal_storage,
|
||||||
"/" + destination.toRelativeString(Const.EXTERNAL_PATH.parentFile)
|
"/" + destination.toRelativeString(Environment.getExternalStorageDirectory())
|
||||||
),
|
),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fileIntent(fileName: String): Intent {
|
private fun fileIntent(fileName: String): Intent {
|
||||||
val file = fileName.downloadsFile ?: let {
|
return fileIntent(fileName.downloadsFile)
|
||||||
Utils.toast(
|
|
||||||
getString(R.string.download_file_folder_error),
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
)
|
|
||||||
return Intent()
|
|
||||||
}
|
|
||||||
return fileIntent(file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fileParentIntent(fileName: String): Intent {
|
private fun fileParentIntent(fileName: String): Intent {
|
||||||
val file = fileName.downloadsFile?.parentFile ?: let {
|
return fileIntent(fileName.downloadsFile.parentFile!!)
|
||||||
Utils.toast(
|
|
||||||
getString(R.string.download_file_folder_error),
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
)
|
|
||||||
return Intent()
|
|
||||||
}
|
|
||||||
return fileIntent(file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fileIntent(file: File): Intent {
|
private fun fileIntent(file: File): Intent {
|
||||||
|
@ -8,7 +8,8 @@ import com.topjohnwu.magisk.Const
|
|||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.data.repository.FileRepository
|
import com.topjohnwu.magisk.data.repository.FileRepository
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Magisk
|
||||||
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Module
|
||||||
import com.topjohnwu.magisk.utils.ProgInputStream
|
import com.topjohnwu.magisk.utils.ProgInputStream
|
||||||
import com.topjohnwu.magisk.utils.cachedFile
|
import com.topjohnwu.magisk.utils.cachedFile
|
||||||
import com.topjohnwu.magisk.utils.firstMap
|
import com.topjohnwu.magisk.utils.firstMap
|
||||||
@ -30,8 +31,7 @@ abstract class RemoteFileService : NotificationService() {
|
|||||||
private val supportedFolders
|
private val supportedFolders
|
||||||
get() = listOfNotNull(
|
get() = listOfNotNull(
|
||||||
cacheDir,
|
cacheDir,
|
||||||
Config.downloadsFile(),
|
Config.downloadDirectory
|
||||||
Const.EXTERNAL_PATH
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override val defaultNotification: NotificationCompat.Builder
|
override val defaultNotification: NotificationCompat.Builder
|
||||||
@ -46,31 +46,27 @@ abstract class RemoteFileService : NotificationService() {
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
private fun startInternal(subject: DownloadSubject): Single<File> = search(subject)
|
private fun start(subject: DownloadSubject) = search(subject)
|
||||||
.onErrorResumeNext(download(subject))
|
.onErrorResumeNext(download(subject))
|
||||||
.doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } }
|
.doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnSuccess {
|
.doOnSuccess {
|
||||||
runCatching { onFinished(it, subject) }.onFailure { Timber.e(it) }
|
runCatching { onFinished(it, subject) }.onFailure { Timber.e(it) }
|
||||||
finish(it, subject)
|
finish(it, subject)
|
||||||
}
|
}.subscribeK()
|
||||||
|
|
||||||
private fun start(subject: DownloadSubject) = startInternal(subject).subscribeK()
|
|
||||||
|
|
||||||
private fun search(subject: DownloadSubject) = Single.fromCallable {
|
private fun search(subject: DownloadSubject) = Single.fromCallable {
|
||||||
if (!Config.isDownloadCacheEnabled) {
|
if (!Config.isDownloadCacheEnabled) {
|
||||||
throw IllegalStateException("The download cache is disabled")
|
throw IllegalStateException("The download cache is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
val file = supportedFolders.firstMap { it.find(subject.fileName) }
|
supportedFolders.firstMap { it.find(subject.fileName) }.also {
|
||||||
|
if (subject is Magisk) {
|
||||||
if (subject is Magisk) {
|
if (!ShellUtils.checkSum("MD5", it, subject.magisk.hash)) {
|
||||||
if (!ShellUtils.checkSum("MD5", file, subject.magisk.hash)) {
|
throw IllegalStateException("The given file doesn't match the hash")
|
||||||
throw IllegalStateException("The given file doesn't match the hash")
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url)
|
private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url)
|
||||||
@ -107,8 +103,6 @@ abstract class RemoteFileService : NotificationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun finish(file: File, subject: DownloadSubject) = finishWork(subject.hashCode()) {
|
private fun finish(file: File, subject: DownloadSubject) = finishWork(subject.hashCode()) {
|
||||||
if (subject is Installer) return@finishWork null
|
|
||||||
|
|
||||||
it.addActions(file, subject)
|
it.addActions(file, subject)
|
||||||
.setContentText(getString(R.string.download_complete))
|
.setContentText(getString(R.string.download_complete))
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||||
|
@ -14,10 +14,6 @@ sealed class Configuration : Parcelable {
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
object Secondary : Flash()
|
object Secondary : Flash()
|
||||||
|
|
||||||
companion object {
|
|
||||||
operator fun invoke(): Flash = Primary
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.internal
|
|
||||||
|
|
||||||
import com.skoumal.teanity.util.KObservableField
|
|
||||||
import com.topjohnwu.magisk.Config
|
|
||||||
import com.topjohnwu.magisk.model.observer.Observer
|
|
||||||
|
|
||||||
class DownloadDialogData(initialValue: String) {
|
|
||||||
|
|
||||||
val text = KObservableField(initialValue)
|
|
||||||
val path = Observer(text) { Config.downloadsFile(text.value)?.absolutePath.orEmpty() }
|
|
||||||
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.internal
|
package com.topjohnwu.magisk.model.entity.internal
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.Const
|
|
||||||
import com.topjohnwu.magisk.Info
|
import com.topjohnwu.magisk.Info
|
||||||
import com.topjohnwu.magisk.model.entity.MagiskJson
|
import com.topjohnwu.magisk.model.entity.MagiskJson
|
||||||
import com.topjohnwu.magisk.model.entity.Repo
|
import com.topjohnwu.magisk.model.entity.Repo
|
||||||
@ -39,10 +37,4 @@ sealed class DownloadSubject : Parcelable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
object Installer : DownloadSubject() {
|
|
||||||
override val fileName: String get() = "module_installer(${BuildConfig.VERSION_CODE}).sh"
|
|
||||||
override val url: String get() = Const.Url.MODULE_INSTALLER
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ open class FlashActivity : MagiskActivity<FlashViewModel, ActivityFlashBinding>(
|
|||||||
override val layoutRes: Int = R.layout.activity_flash
|
override val layoutRes: Int = R.layout.activity_flash
|
||||||
override val viewModel: FlashViewModel by viewModel {
|
override val viewModel: FlashViewModel by viewModel {
|
||||||
val uri = intent.data ?: let { finish(); Uri.EMPTY }
|
val uri = intent.data ?: let { finish(); Uri.EMPTY }
|
||||||
val additionalUri = intent.getParcelableExtra<Uri>(Const.Key.FLASH_DATA) ?: uri
|
val additionalUri = intent.getParcelableExtra(Const.Key.FLASH_DATA) ?: uri
|
||||||
val action = intent.getStringExtra(Const.Key.FLASH_ACTION) ?: let { finish();"" }
|
val action = intent.getStringExtra(Const.Key.FLASH_ACTION) ?: let { finish();"" }
|
||||||
parametersOf(action, uri, additionalUri)
|
parametersOf(action, uri, additionalUri)
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class ReposFragment : MagiskFragment<ModuleViewModel, FragmentReposBinding>(),
|
|||||||
fun download(install: Boolean) = context.withExternalRW {
|
fun download(install: Boolean) = context.withExternalRW {
|
||||||
onSuccess {
|
onSuccess {
|
||||||
DownloadService(context) {
|
DownloadService(context) {
|
||||||
val config = if (install) Configuration.Flash() else Configuration.Download
|
val config = if (install) Configuration.Flash.Primary else Configuration.Download
|
||||||
subject = DownloadSubject.Module(item, config)
|
subject = DownloadSubject.Module(item, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.settings
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -14,19 +15,21 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.SwitchPreferenceCompat
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import com.skoumal.teanity.extensions.subscribeK
|
import com.skoumal.teanity.extensions.subscribeK
|
||||||
|
import com.skoumal.teanity.util.KObservableField
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.Config
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.Const
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.data.database.RepoDatabaseHelper
|
import com.topjohnwu.magisk.data.database.RepoDatabaseHelper
|
||||||
import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
|
import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadDialogData
|
import com.topjohnwu.magisk.model.observer.Observer
|
||||||
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment
|
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment
|
||||||
import com.topjohnwu.magisk.utils.*
|
import com.topjohnwu.magisk.utils.*
|
||||||
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
||||||
import com.topjohnwu.net.Networking
|
import com.topjohnwu.net.Networking
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class SettingsFragment : BasePreferenceFragment() {
|
class SettingsFragment : BasePreferenceFragment() {
|
||||||
|
|
||||||
@ -297,6 +300,13 @@ class SettingsFragment : BasePreferenceFragment() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class DownloadDialogData(initialValue: String) {
|
||||||
|
val text = KObservableField(initialValue)
|
||||||
|
val path = Observer(text) {
|
||||||
|
File(Environment.getExternalStorageDirectory(), text.value).absolutePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun showDownloadDialog(
|
private inline fun showDownloadDialog(
|
||||||
initialValue: String = Config.downloadPath,
|
initialValue: String = Config.downloadPath,
|
||||||
crossinline onSuccess: (String) -> Unit
|
crossinline onSuccess: (String) -> Unit
|
||||||
@ -310,10 +320,10 @@ class SettingsFragment : BasePreferenceFragment() {
|
|||||||
.setTitle(R.string.settings_download_path_title)
|
.setTitle(R.string.settings_download_path_title)
|
||||||
.setView(binding.root)
|
.setView(binding.root)
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
.setPositiveButton(R.string.ok) { _, _ ->
|
||||||
Config.downloadsFile(data.text.value)?.let { onSuccess(data.text.value) }
|
Utils.ensureDownloadPath(data.text.value)?.let { onSuccess(data.text.value) }
|
||||||
?: Utils.toast(R.string.settings_download_path_error, Toast.LENGTH_SHORT)
|
?: Utils.toast(R.string.settings_download_path_error, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.close, null)
|
.setNegativeButton(R.string.close, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import android.content.pm.PackageManager
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Environment
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
@ -19,6 +20,7 @@ import com.topjohnwu.net.Networking
|
|||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.topjohnwu.superuser.io.SuFile
|
import com.topjohnwu.superuser.io.SuFile
|
||||||
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -120,4 +122,9 @@ object Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ensureDownloadPath(path : String) =
|
||||||
|
File(Environment.getExternalStorageDirectory(), path).run {
|
||||||
|
if ((exists() && isDirectory) || mkdirs()) this else null
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="data"
|
name="data"
|
||||||
type="com.topjohnwu.magisk.model.entity.internal.DownloadDialogData" />
|
type="com.topjohnwu.magisk.ui.settings.SettingsFragment.DownloadDialogData" />
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
@ -3,4 +3,6 @@
|
|||||||
<files-path name="internal_files" path="."/>
|
<files-path name="internal_files" path="."/>
|
||||||
<cache-path name="cache_files" path="." />
|
<cache-path name="cache_files" path="." />
|
||||||
<external-path name="external_files" path="."/>
|
<external-path name="external_files" path="."/>
|
||||||
</paths>
|
<external-cache-path name="external_cache_files" path="."/>
|
||||||
|
<external-files-path name="private_external_files" path="."/>
|
||||||
|
</paths>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user