Commit 71d855e8 authored by topjohnwu's avatar topjohnwu

Cleanup more code

parent 33b7ab59
package com.topjohnwu.magisk package com.topjohnwu.magisk
import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
...@@ -39,7 +38,6 @@ open class App : Application() { ...@@ -39,7 +38,6 @@ open class App : Application() {
} }
deContext = base deContext = base
self = this
if (Build.VERSION.SDK_INT >= 24) { if (Build.VERSION.SDK_INT >= 24) {
deContext = base.createDeviceProtectedStorageContext() deContext = base.createDeviceProtectedStorageContext()
...@@ -61,11 +59,6 @@ open class App : Application() { ...@@ -61,11 +59,6 @@ open class App : Application() {
companion object { companion object {
@SuppressLint("StaticFieldLeak")
@Deprecated("Use dependency injection")
@JvmStatic
lateinit var self: App
init { init {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
Shell.Config.setFlags(Shell.FLAG_MOUNT_MASTER or Shell.FLAG_USE_MAGISK_BUSYBOX) Shell.Config.setFlags(Shell.FLAG_MOUNT_MASTER or Shell.FLAG_USE_MAGISK_BUSYBOX)
......
...@@ -55,7 +55,7 @@ val ApplicationInfo.packageInfo: PackageInfo? ...@@ -55,7 +55,7 @@ val ApplicationInfo.packageInfo: PackageInfo?
val Uri.fileName: String val Uri.fileName: String
get() { get() {
var name: String? = null var name: String? = null
App.self.contentResolver.query(this, null, null, null, null)?.use { c -> get<Context>().contentResolver.query(this, null, null, null, null)?.use { c ->
val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME) val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (nameIndex != -1) { if (nameIndex != -1) {
c.moveToFirst() c.moveToFirst()
......
package com.topjohnwu.magisk.extensions package com.topjohnwu.magisk.extensions
import android.net.Uri import android.net.Uri
import android.os.Build
import androidx.core.net.toFile import androidx.core.net.toFile
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.*
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import kotlin.NoSuchElementException
fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) { fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
var entry: ZipEntry? = nextEntry var entry: ZipEntry? = nextEntry
...@@ -38,4 +41,63 @@ inline fun <T, R> List<T>.firstMap(mapper: (T) -> R?): R { ...@@ -38,4 +41,63 @@ inline fun <T, R> List<T>.firstMap(mapper: (T) -> R?): R {
return mapper(item) ?: continue return mapper(item) ?: continue
} }
throw NoSuchElementException("Collection contains no element matching the predicate.") throw NoSuchElementException("Collection contains no element matching the predicate.")
}
fun String.langTagToLocale(): Locale {
if (Build.VERSION.SDK_INT >= 21) {
return Locale.forLanguageTag(this)
} else {
val tok = split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if (tok.isEmpty()) {
return Locale("")
}
val language = when (tok[0]) {
"und" -> "" // Undefined
"fil" -> "tl" // Filipino
else -> tok[0]
}
if (language.length != 2 && language.length != 3)
return Locale("")
if (tok.size == 1)
return Locale(language)
val country = tok[1]
return if (country.length != 2 && country.length != 3) Locale(language)
else Locale(language, country)
}
}
fun Locale.toLangTag(): String {
if (Build.VERSION.SDK_INT >= 21) {
return toLanguageTag()
} else {
var language = language
var country = country
var variant = variant
when {
language.isEmpty() || !language.matches("\\p{Alpha}{2,8}".toRegex()) ->
language = "und" // Follow the Locale#toLanguageTag() implementation
language == "iw" -> language = "he" // correct deprecated "Hebrew"
language == "in" -> language = "id" // correct deprecated "Indonesian"
language == "ji" -> language = "yi" // correct deprecated "Yiddish"
}
// ensure valid country code, if not well formed, it's omitted
// variant subtags that begin with a letter must be at least 5 characters long
// ensure valid country code, if not well formed, it's omitted
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}".toRegex())) {
country = ""
}
// variant subtags that begin with a letter must be at least 5 characters long
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}".toRegex())) {
variant = ""
}
val tag = StringBuilder(language)
if (country.isNotEmpty())
tag.append('-').append(country)
if (variant.isNotEmpty())
tag.append('-').append(variant)
return tag.toString()
}
} }
\ No newline at end of file
package com.topjohnwu.magisk.extensions package com.topjohnwu.magisk.extensions
import com.topjohnwu.magisk.utils.LocaleManager import com.topjohnwu.magisk.utils.currentLocale
import java.text.DateFormat import java.text.DateFormat
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
...@@ -14,8 +14,7 @@ fun String.toTime(format: DateFormat) = try { ...@@ -14,8 +14,7 @@ fun String.toTime(format: DateFormat) = try {
-1L -1L
} }
private val locale get() = LocaleManager.locale val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss", currentLocale) }
val timeFormatFull by lazy { SimpleDateFormat("yyyy/MM/dd_HH:mm:ss", locale) } val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", currentLocale) }
val timeFormatStandard by lazy { SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", locale) } val timeFormatMedium by lazy { DateFormat.getDateInstance(DateFormat.MEDIUM, currentLocale) }
val timeFormatMedium by lazy { DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale) } val timeFormatTime by lazy { SimpleDateFormat("h:mm a", currentLocale) }
val timeFormatTime by lazy { SimpleDateFormat("h:mm a", LocaleManager.locale) }
\ No newline at end of file
package com.topjohnwu.magisk.model.entity;
import android.content.ContentValues;
import com.topjohnwu.magisk.utils.LocaleManager;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SuLogEntry {
public int fromUid, toUid, fromPid;
public String packageName, appName, command;
public boolean action;
public Date date;
public SuLogEntry(MagiskPolicy policy) {
fromUid = policy.getUid();
packageName = policy.getPackageName();
appName = policy.getAppName();
action = policy.getPolicy() == Policy.ALLOW;
}
public SuLogEntry(ContentValues values) {
fromUid = values.getAsInteger("from_uid");
packageName = values.getAsString("package_name");
appName = values.getAsString("app_name");
fromPid = values.getAsInteger("from_pid");
command = values.getAsString("command");
toUid = values.getAsInteger("to_uid");
action = values.getAsInteger("action") != 0;
date = new Date(values.getAsLong("time"));
}
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
values.put("from_uid", fromUid);
values.put("package_name", packageName);
values.put("app_name", appName);
values.put("from_pid", fromPid);
values.put("command", command);
values.put("to_uid", toUid);
values.put("action", action ? 1 : 0);
values.put("time", date.getTime());
return values;
}
public String getDateString() {
return DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.getLocale()).format(date);
}
public String getTimeString() {
return new SimpleDateFormat("h:mm a", LocaleManager.getLocale()).format(date);
}
}
...@@ -47,7 +47,7 @@ open class GeneralReceiver : BroadcastReceiver() { ...@@ -47,7 +47,7 @@ open class GeneralReceiver : BroadcastReceiver() {
// Actual boot completed event // Actual boot completed event
Shell.su("mm_patch_dtbo").submit { result -> Shell.su("mm_patch_dtbo").submit { result ->
if (result.isSuccess) if (result.isSuccess)
Notifications.dtboPatched() Notifications.dtboPatched(context)
} }
return return
} }
......
...@@ -19,9 +19,9 @@ class UpdateCheckService : DelegateWorker() { ...@@ -19,9 +19,9 @@ class UpdateCheckService : DelegateWorker() {
return runCatching { return runCatching {
magiskRepo.fetchUpdate().blockingGet() magiskRepo.fetchUpdate().blockingGet()
if (BuildConfig.VERSION_CODE < Info.remote.app.versionCode) if (BuildConfig.VERSION_CODE < Info.remote.app.versionCode)
Notifications.managerUpdate() Notifications.managerUpdate(applicationContext)
else if (Info.magiskVersionCode < Info.remote.magisk.versionCode) else if (Info.magiskVersionCode < Info.remote.magisk.versionCode)
Notifications.magiskUpdate() Notifications.magiskUpdate(applicationContext)
ListenableWorker.Result.success() ListenableWorker.Result.success()
}.getOrElse { }.getOrElse {
ListenableWorker.Result.failure() ListenableWorker.Result.failure()
......
...@@ -32,6 +32,7 @@ import com.topjohnwu.magisk.model.navigation.Navigator ...@@ -32,6 +32,7 @@ import com.topjohnwu.magisk.model.navigation.Navigator
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
import com.topjohnwu.magisk.utils.LocaleManager import com.topjohnwu.magisk.utils.LocaleManager
import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.currentLocale
import timber.log.Timber import timber.log.Timber
import kotlin.reflect.KClass import kotlin.reflect.KClass
...@@ -68,12 +69,12 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin ...@@ -68,12 +69,12 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
override fun applyOverrideConfiguration(config: Configuration?) { override fun applyOverrideConfiguration(config: Configuration?) {
// Force applying our preferred local // Force applying our preferred local
config?.setLocale(LocaleManager.locale) config?.setLocale(currentLocale)
super.applyOverrideConfiguration(config) super.applyOverrideConfiguration(config)
} }
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleManager.getLocaleContext(base, LocaleManager.locale)) super.attachBaseContext(LocaleManager.getLocaleContext(base))
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
......
package com.topjohnwu.magisk.ui.home package com.topjohnwu.magisk.ui.home
import android.app.Activity import android.app.Activity
import android.content.Context
import android.os.Bundle import android.os.Bundle
import com.skoumal.teanity.extensions.subscribeK import com.skoumal.teanity.extensions.subscribeK
import com.skoumal.teanity.viewevents.ViewEvent import com.skoumal.teanity.viewevents.ViewEvent
import com.topjohnwu.magisk.* import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.MagiskRepository import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.databinding.FragmentMagiskBinding import com.topjohnwu.magisk.databinding.FragmentMagiskBinding
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.inject import com.topjohnwu.magisk.extensions.inject
import com.topjohnwu.magisk.extensions.writeTo import com.topjohnwu.magisk.extensions.writeTo
import com.topjohnwu.magisk.model.events.* import com.topjohnwu.magisk.model.events.*
...@@ -114,7 +119,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(), ...@@ -114,7 +119,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
} }
companion object { companion object {
val EXT_APK = File("${App.self.filesDir.parent}/snet", "snet.apk") val EXT_APK by lazy { File("${get<Context>().filesDir.parent}/snet", "snet.apk") }
} }
} }
...@@ -21,15 +21,13 @@ import com.topjohnwu.magisk.Const ...@@ -21,15 +21,13 @@ import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.database.RepoDao import com.topjohnwu.magisk.data.database.RepoDao
import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
import com.topjohnwu.magisk.extensions.toLangTag
import com.topjohnwu.magisk.model.download.DownloadService import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.entity.internal.Configuration import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.model.observer.Observer 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.FingerprintHelper import com.topjohnwu.magisk.utils.*
import com.topjohnwu.magisk.utils.LocaleManager
import com.topjohnwu.magisk.utils.PatchAPK
import com.topjohnwu.magisk.utils.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
...@@ -226,21 +224,18 @@ class SettingsFragment : BasePreferenceFragment() { ...@@ -226,21 +224,18 @@ class SettingsFragment : BasePreferenceFragment() {
private fun setLocalePreference(lp: ListPreference) { private fun setLocalePreference(lp: ListPreference) {
lp.isEnabled = false lp.isEnabled = false
LocaleManager.availableLocales availableLocales.map {
.map {
val names = mutableListOf<String>() val names = mutableListOf<String>()
val values = mutableListOf<String>() val values = mutableListOf<String>()
names.add( names.add(
LocaleManager.getString( LocaleManager.getString(defaultLocale, R.string.system_default)
LocaleManager.defaultLocale, R.string.system_default
)
) )
values.add("") values.add("")
it.forEach { locale -> it.forEach { locale ->
names.add(locale.getDisplayName(locale)) names.add(locale.getDisplayName(locale))
values.add(LocaleManager.toLanguageTag(locale)) values.add(locale.toLangTag())
} }
Pair(names.toTypedArray(), values.toTypedArray()) Pair(names.toTypedArray(), values.toTypedArray())
...@@ -248,7 +243,7 @@ class SettingsFragment : BasePreferenceFragment() { ...@@ -248,7 +243,7 @@ class SettingsFragment : BasePreferenceFragment() {
lp.isEnabled = true lp.isEnabled = true
lp.entries = names lp.entries = names
lp.entryValues = values lp.entryValues = values
lp.summary = LocaleManager.locale.getDisplayName(LocaleManager.locale) lp.summary = currentLocale.getDisplayName(currentLocale)
} }
} }
......
...@@ -4,133 +4,65 @@ import android.content.Context ...@@ -4,133 +4,65 @@ import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.os.Build
import androidx.annotation.StringRes import androidx.annotation.StringRes
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.inject import com.topjohnwu.magisk.extensions.inject
import com.topjohnwu.magisk.extensions.langTagToLocale
import com.topjohnwu.superuser.internal.InternalUtils import com.topjohnwu.superuser.internal.InternalUtils
import io.reactivex.Single import io.reactivex.Single
import java.util.* import java.util.*
object LocaleManager { var currentLocale = Locale.getDefault()!!
@JvmStatic private set
var locale = Locale.getDefault()
@JvmStatic
val defaultLocale = Locale.getDefault()
@JvmStatic
val availableLocales = Single.fromCallable {
val compareId = R.string.app_changelog
val res: Resources by inject()
mutableListOf<Locale>().apply {
// Add default locale
add(Locale.ENGLISH)
// Add some special locales val defaultLocale = Locale.getDefault()!!
add(Locale.TAIWAN)
add(Locale("pt", "BR"))
// Other locales val availableLocales = Single.fromCallable {
val otherLocales = res.assets.locales val compareId = R.string.app_changelog
.map { forLanguageTag(it) } val res: Resources by inject()
.distinctBy { getString(it, compareId) } mutableListOf<Locale>().apply {
// Add default locale
add(Locale.ENGLISH)
listOf("", "").toTypedArray() // Add some special locales
add(Locale.TAIWAN)
addAll(otherLocales) add(Locale("pt", "BR"))
}.sortedWith(Comparator { a, b ->
a.getDisplayName(a).toLowerCase(a)
.compareTo(b.getDisplayName(b).toLowerCase(b))
})
}.cache()
private fun forLanguageTag(tag: String): Locale { // Other locales
if (Build.VERSION.SDK_INT >= 21) { val otherLocales = res.assets.locales
return Locale.forLanguageTag(tag) .map { it.langTagToLocale() }
} else { .distinctBy { LocaleManager.getString(it, compareId) }
val tok = tag.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if (tok.isEmpty()) {
return Locale("")
}
val language = when (tok[0]) {
"und" -> "" // Undefined
"fil" -> "tl" // Filipino
else -> tok[0]
}
if (language.length != 2 && language.length != 3)
return Locale("")
if (tok.size == 1)
return Locale(language)
val country = tok[1]
return if (country.length != 2 && country.length != 3) Locale(language)
else Locale(language, country)
}
}
@JvmStatic listOf("", "").toTypedArray()
fun toLanguageTag(loc: Locale): String {
if (Build.VERSION.SDK_INT >= 21) {
return loc.toLanguageTag()
} else {
var language = loc.language
var country = loc.country
var variant = loc.variant
when {
language.isEmpty() || !language.matches("\\p{Alpha}{2,8}".toRegex()) ->
language = "und" // Follow the Locale#toLanguageTag() implementation
language == "iw" -> language = "he" // correct deprecated "Hebrew"
language == "in" -> language = "id" // correct deprecated "Indonesian"
language == "ji" -> language = "yi" // correct deprecated "Yiddish"
}
// ensure valid country code, if not well formed, it's omitted
// variant subtags that begin with a letter must be at least 5 characters long addAll(otherLocales)
// ensure valid country code, if not well formed, it's omitted }.sortedWith(Comparator { a, b ->
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}".toRegex())) { a.getDisplayName(a).toLowerCase(a)
country = "" .compareTo(b.getDisplayName(b).toLowerCase(b))
} })
}.cache()!!
// variant subtags that begin with a letter must be at least 5 characters long object LocaleManager {
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}".toRegex())) {
variant = ""
}
val tag = StringBuilder(language)
if (country.isNotEmpty())
tag.append('-').append(country)
if (variant.isNotEmpty())
tag.append('-').append(variant)
return tag.toString()
}
}
@JvmStatic
fun setLocale(wrapper: ContextWrapper) { fun setLocale(wrapper: ContextWrapper) {
val localeConfig = Config.locale val localeConfig = Config.locale
locale = when { currentLocale = when {
localeConfig.isEmpty() -> defaultLocale localeConfig.isEmpty() -> defaultLocale
else -> forLanguageTag(localeConfig) else -> localeConfig.langTagToLocale()
} }
Locale.setDefault(locale) Locale.setDefault(currentLocale)
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(locale)) InternalUtils.replaceBaseContext(wrapper, getLocaleContext(wrapper, currentLocale))
} }
@JvmStatic fun getLocaleContext(context: Context, locale: Locale = currentLocale): Context {
fun getLocaleContext(context: Context, locale: Locale): Context {
val config = Configuration(context.resources.configuration) val config = Configuration(context.resources.configuration)
config.setLocale(locale) config.setLocale(locale)
return context.createConfigurationContext(config) return context.createConfigurationContext(config)
} }
@JvmStatic
fun getLocaleContext(locale: Locale): Context {
return getLocaleContext(App.self.baseContext, locale)
}
@JvmStatic
fun getString(locale: Locale, @StringRes id: Int): String { fun getString(locale: Locale, @StringRes id: Int): String {
return getLocaleContext(locale).getString(id) return getLocaleContext(get(), locale).getString(id)
} }
} }
...@@ -15,7 +15,6 @@ import com.topjohnwu.magisk.* ...@@ -15,7 +15,6 @@ import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.get import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.model.update.UpdateCheckService import com.topjohnwu.magisk.model.update.UpdateCheckService
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 java.io.File import java.io.File
...@@ -24,8 +23,7 @@ import java.util.concurrent.TimeUnit ...@@ -24,8 +23,7 @@ import java.util.concurrent.TimeUnit
object Utils { object Utils {
val isCanary: Boolean val isCanary: Boolean = BuildConfig.VERSION_NAME.contains("-")
get() = BuildConfig.VERSION_NAME.contains("-")
fun toast(msg: CharSequence, duration: Int) { fun toast(msg: CharSequence, duration: Int) {
UiThreadHandler.run { Toast.makeText(get(), msg, duration).show() } UiThreadHandler.run { Toast.makeText(get(), msg, duration).show() }
...@@ -35,11 +33,6 @@ object Utils { ...@@ -35,11 +33,6 @@ object Utils {
UiThreadHandler.run { Toast.makeText(get(), resId, duration).show() } UiThreadHandler.run { Toast.makeText(get(), resId, duration).show() }
} }
fun dlString(url: String): String {
val s = Networking.get(url).execForString().result
return s ?: ""
}
fun getPrefsInt(prefs: SharedPreferences, key: String, def: Int = 0): Int { fun getPrefsInt(prefs: SharedPreferences, key: String, def: Int = 0): Int {
return prefs.getString(key, def.toString())!!.toInt() return prefs.getString(key, def.toString())!!.toInt()
} }
...@@ -58,7 +51,7 @@ object Utils { ...@@ -58,7 +51,7 @@ object Utils {
if (info.labelRes > 0) { if (info.labelRes > 0) {
val res = pm.getResourcesForApplication(info) val res = pm.getResourcesForApplication(info)
val config = Configuration() val config = Configuration()
config.setLocale(LocaleManager.locale) config.setLocale(currentLocale)
res.updateConfiguration(config, res.displayMetrics) res.updateConfiguration(config, res.displayMetrics)
return res.getString(info.labelRes) return res.getString(info.labelRes)
} }
......
package com.topjohnwu.magisk.view;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.TaskStackBuilder;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.ClassMap;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Info;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.model.receiver.GeneralReceiver;
import com.topjohnwu.magisk.ui.SplashActivity;
public class Notifications {
public static NotificationManagerCompat mgr = NotificationManagerCompat.from(App.self);
public static void setup(Context c) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mgr.deleteNotificationChannel("magisk_notification");
NotificationChannel channel =
new NotificationChannel(Const.ID.UPDATE_NOTIFICATION_CHANNEL,
c.getString(R.string.update_channel), NotificationManager.IMPORTANCE_DEFAULT);
mgr.createNotificationChannel(channel);
channel = new NotificationChannel(Const.ID.PROGRESS_NOTIFICATION_CHANNEL,
c.getString(R.string.progress_channel), NotificationManager.IMPORTANCE_LOW);
mgr.createNotificationChannel(channel);
}
}
public static void magiskUpdate() {
App app = App.self;
Intent intent = new Intent(app, ClassMap.get(SplashActivity.class));
intent.putExtra(Const.Key.OPEN_SECTION, "magisk");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(app);
stackBuilder.addParentStack(ClassMap.get(SplashActivity.class));
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(app, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(app.getString(R.string.magisk_update_title))
.setContentText(app.getString(R.string.manager_download_install))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true)
.setContentIntent(pendingIntent);
mgr.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void managerUpdate() {
App app = App.self;
Intent intent = new Intent(app, ClassMap.get(GeneralReceiver.class));
intent.setAction(Const.Key.BROADCAST_MANAGER_UPDATE);
intent.putExtra(Const.Key.INTENT_SET_APP, Info.remote.getApp());
PendingIntent pendingIntent = PendingIntent.getBroadcast(app,
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(app, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(app.getString(R.string.manager_update_title))
.setContentText(app.getString(R.string.manager_download_install))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true)
.setContentIntent(pendingIntent);
mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void dtboPatched() {
App app = App.self;
Intent intent = new Intent(app, ClassMap.get(GeneralReceiver.class))
.setAction(Const.Key.BROADCAST_REBOOT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(app,
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(app, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(app.getString(R.string.dtbo_patched_title))
.setContentText(app.getString(R.string.dtbo_patched_reboot))
.setVibrate(new long[]{0, 100, 100, 100})
.addAction(R.drawable.ic_refresh, app.getString(R.string.reboot), pendingIntent);
mgr.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build());
}
public static NotificationCompat.Builder progress(Context context, CharSequence title) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, Const.ID.PROGRESS_NOTIFICATION_CHANNEL);
builder.setPriority(NotificationCompat.PRIORITY_LOW)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle(title)
.setProgress(0, 0, true)
.setOngoing(true);
return builder;
}
}
package com.topjohnwu.magisk.view
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
import com.topjohnwu.magisk.ui.SplashActivity
object Notifications {
val mgr by lazy { NotificationManagerCompat.from(get()) }
fun setup(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mgr.deleteNotificationChannel("magisk_notification")
var channel = NotificationChannel(Const.ID.UPDATE_NOTIFICATION_CHANNEL,
context.getString(R.string.update_channel), NotificationManager.IMPORTANCE_DEFAULT)
mgr.createNotificationChannel(channel)
channel = NotificationChannel(Const.ID.PROGRESS_NOTIFICATION_CHANNEL,
context.getString(R.string.progress_channel), NotificationManager.IMPORTANCE_LOW)
mgr.createNotificationChannel(channel)
}
}
fun magiskUpdate(context: Context) {
val intent = Intent(context, ClassMap[SplashActivity::class.java])
intent.putExtra(Const.Key.OPEN_SECTION, "magisk")
val stackBuilder = TaskStackBuilder.create(context)
stackBuilder.addParentStack(ClassMap.get<Class<*>>(SplashActivity::class.java))
stackBuilder.addNextIntent(intent)
val pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(context.getString(R.string.magisk_update_title))
.setContentText(context.getString(R.string.manager_download_install))
.setVibrate(longArrayOf(0, 100, 100, 100))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
mgr.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build())
}
fun managerUpdate(context: Context) {
val intent = Intent(context, ClassMap[GeneralReceiver::class.java])
intent.action = Const.Key.BROADCAST_MANAGER_UPDATE
intent.putExtra(Const.Key.INTENT_SET_APP, Info.remote.app)
val pendingIntent = PendingIntent.getBroadcast(context,
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(context.getString(R.string.manager_update_title))
.setContentText(context.getString(R.string.manager_download_install))
.setVibrate(longArrayOf(0, 100, 100, 100))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build())
}
fun dtboPatched(context: Context) {
val intent = Intent(context, ClassMap[GeneralReceiver::class.java])
.setAction(Const.Key.BROADCAST_REBOOT)
val pendingIntent = PendingIntent.getBroadcast(context,
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
.setContentTitle(context.getString(R.string.dtbo_patched_title))
.setContentText(context.getString(R.string.dtbo_patched_reboot))
.setVibrate(longArrayOf(0, 100, 100, 100))
.addAction(R.drawable.ic_refresh, context.getString(R.string.reboot), pendingIntent)
mgr.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build())
}
fun progress(context: Context, title: CharSequence): NotificationCompat.Builder {
val builder = NotificationCompat.Builder(context, Const.ID.PROGRESS_NOTIFICATION_CHANNEL)
builder.setPriority(NotificationCompat.PRIORITY_LOW)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle(title)
.setProgress(0, 0, true)
.setOngoing(true)
return builder
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment