mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-23 18:15:30 +00:00
parent
3f7f6e619a
commit
928a16d8cc
@ -9,6 +9,7 @@
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
|
||||
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29"
|
||||
|
@ -39,6 +39,16 @@ public final class APKInstall {
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerReceiver(
|
||||
Context context, BroadcastReceiver receiver, IntentFilter filter) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// noinspection InlinedApi
|
||||
context.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED);
|
||||
} else {
|
||||
context.registerReceiver(receiver, filter);
|
||||
}
|
||||
}
|
||||
|
||||
public static Session startSession(Context context) {
|
||||
return startSession(context, null, null, null);
|
||||
}
|
||||
@ -51,9 +61,9 @@ public final class APKInstall {
|
||||
// If pkg is not null, look for package added event
|
||||
var filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addDataScheme("package");
|
||||
context.registerReceiver(receiver, filter);
|
||||
registerReceiver(context, receiver, filter);
|
||||
}
|
||||
context.registerReceiver(receiver, new IntentFilter(receiver.sessionId));
|
||||
registerReceiver(context, receiver, new IntentFilter(receiver.sessionId));
|
||||
return receiver;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.topjohnwu.magisk.arch
|
||||
|
||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
import android.Manifest.permission.*
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import androidx.databinding.PropertyChangeRegistry
|
||||
@ -53,6 +52,17 @@ abstract class BaseViewModel : ViewModel(), ObservableHost {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
inline fun withPostNotificationPermission(crossinline callback: () -> Unit) {
|
||||
withPermission(POST_NOTIFICATIONS) {
|
||||
if (!it) {
|
||||
SnackbarEvent(R.string.post_notifications_denied).publish()
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun back() = BackPressEvent().publish()
|
||||
|
||||
fun <Event : ViewEvent> Event.publish() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.topjohnwu.magisk.core.base
|
||||
|
||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
import android.Manifest.permission.*
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
@ -82,12 +81,18 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun withPermission(permission: String, callback: (Boolean) -> Unit) {
|
||||
if (permission == WRITE_EXTERNAL_STORAGE &&
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
||||
permission == WRITE_EXTERNAL_STORAGE) {
|
||||
// We do not need external rw on R+
|
||||
callback(true)
|
||||
return
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU &&
|
||||
permission == POST_NOTIFICATIONS) {
|
||||
// All apps have notification permissions before T
|
||||
callback(true)
|
||||
return
|
||||
}
|
||||
permissionCallback = callback
|
||||
if (permission == REQUEST_INSTALL_PACKAGES) {
|
||||
requestInstall.launch(Unit)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.core.download
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.app.PendingIntent.*
|
||||
@ -13,17 +14,14 @@ import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.StubApk
|
||||
import com.topjohnwu.magisk.core.ActivityTracker
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.ktx.copyAndClose
|
||||
import com.topjohnwu.magisk.ktx.forEach
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.magisk.ktx.*
|
||||
import com.topjohnwu.magisk.utils.APKInstall
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -51,7 +49,7 @@ class DownloadService : NotificationService() {
|
||||
}
|
||||
|
||||
private fun download(subject: Subject) {
|
||||
update(subject.notifyId)
|
||||
notifyUpdate(subject.notifyId)
|
||||
val coroutineScope = CoroutineScope(job + Dispatchers.IO)
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
@ -62,7 +60,7 @@ class DownloadService : NotificationService() {
|
||||
}
|
||||
val activity = ActivityTracker.foreground
|
||||
if (activity != null && subject.autoLaunch) {
|
||||
remove(subject.notifyId)
|
||||
notifyRemove(subject.notifyId)
|
||||
subject.pendingIntent(activity)?.send()
|
||||
} else {
|
||||
notifyFinish(subject)
|
||||
@ -92,7 +90,7 @@ class DownloadService : NotificationService() {
|
||||
|
||||
if (Info.stub!!.version < subject.stub.versionCode) {
|
||||
// Also upgrade stub
|
||||
update(subject.notifyId) {
|
||||
notifyUpdate(subject.notifyId) {
|
||||
it.setProgress(0, 0, true)
|
||||
.setContentTitle(getString(R.string.hide_app_title))
|
||||
.setContentText("")
|
||||
@ -118,7 +116,7 @@ class DownloadService : NotificationService() {
|
||||
StubApk.restartProcess(it)
|
||||
} ?: run {
|
||||
// Or else kill the current process after posting notification
|
||||
subject.intent = Notifications.selfLaunchIntent(this)
|
||||
subject.intent = selfLaunchIntent()
|
||||
subject.postDownload = { Runtime.getRuntime().exit(0) }
|
||||
}
|
||||
return
|
||||
@ -206,12 +204,16 @@ class DownloadService : NotificationService() {
|
||||
}
|
||||
}
|
||||
|
||||
fun start(context: Context, subject: Subject) {
|
||||
val app = context.applicationContext
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
app.startForegroundService(intent(app, subject))
|
||||
} else {
|
||||
app.startService(intent(app, subject))
|
||||
@SuppressLint("InlinedApi")
|
||||
fun start(activity: BaseActivity, subject: Subject) {
|
||||
activity.withPermission(Manifest.permission.POST_NOTIFICATIONS) {
|
||||
// Always download regardless of notification permission status
|
||||
val app = activity.applicationContext
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
app.startForegroundService(intent(app, subject))
|
||||
} else {
|
||||
app.startService(intent(app, subject))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.core.download
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseService
|
||||
@ -30,11 +31,11 @@ open class NotificationService : BaseService() {
|
||||
val total = max.toFloat() / 1048576
|
||||
val id = subject.notifyId
|
||||
|
||||
update(id) { it.setContentTitle(subject.title) }
|
||||
notifyUpdate(id) { it.setContentTitle(subject.title) }
|
||||
|
||||
return ProgressInputStream(byteStream()) {
|
||||
val progress = it.toFloat() / 1048576
|
||||
update(id) { notification ->
|
||||
notifyUpdate(id) { notification ->
|
||||
if (max > 0) {
|
||||
broadcast(progress / total, subject)
|
||||
notification
|
||||
@ -49,7 +50,7 @@ open class NotificationService : BaseService() {
|
||||
}
|
||||
|
||||
private fun finalNotify(id: Int, editor: (Notification.Builder) -> Unit): Int {
|
||||
val notification = remove(id)?.also(editor) ?: return -1
|
||||
val notification = notifyRemove(id)?.also(editor) ?: return -1
|
||||
val newId = Notifications.nextId()
|
||||
Notifications.mgr.notify(newId, notification.build())
|
||||
return newId
|
||||
@ -73,28 +74,31 @@ open class NotificationService : BaseService() {
|
||||
subject.pendingIntent(this)?.let { intent -> it.setContentIntent(intent) }
|
||||
}
|
||||
|
||||
private fun create() = Notifications.progress(this, "")
|
||||
|
||||
private fun updateForeground() {
|
||||
private fun updateForegroundState() {
|
||||
if (hasNotifications) {
|
||||
val (id, notification) = notifications.entries.first()
|
||||
startForeground(id, notification.build())
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
stopForeground(STOP_FOREGROUND_DETACH)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
stopForeground(false)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun update(id: Int, editor: (Notification.Builder) -> Unit = {}) {
|
||||
protected fun notifyUpdate(id: Int, editor: (Notification.Builder) -> Unit = {}) {
|
||||
fun create() = Notifications.startProgress(this, "")
|
||||
|
||||
val wasEmpty = !hasNotifications
|
||||
val notification = notifications.getOrPut(id, ::create).also(editor)
|
||||
if (wasEmpty)
|
||||
updateForeground()
|
||||
updateForegroundState()
|
||||
else
|
||||
Notifications.mgr.notify(id, notification.build())
|
||||
}
|
||||
|
||||
protected fun remove(id: Int): Notification.Builder? {
|
||||
val n = notifications.remove(id)?.also { updateForeground() }
|
||||
protected fun notifyRemove(id: Int): Notification.Builder? {
|
||||
val n = notifications.remove(id)?.also { updateForegroundState() }
|
||||
Notifications.mgr.cancel(id)
|
||||
return n
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import android.content.IntentFilter
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.PowerManager
|
||||
import androidx.core.content.getSystemService
|
||||
import com.topjohnwu.magisk.ktx.registerRuntimeReceiver
|
||||
|
||||
@TargetApi(23)
|
||||
class MarshmallowNetworkObserver(
|
||||
@ -21,7 +22,7 @@ class MarshmallowNetworkObserver(
|
||||
|
||||
init {
|
||||
val filter = IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)
|
||||
app.registerReceiver(receiver, filter)
|
||||
app.registerRuntimeReceiver(receiver, filter)
|
||||
}
|
||||
|
||||
override fun stopObserving() {
|
||||
|
@ -8,9 +8,7 @@ import com.topjohnwu.magisk.view.MagiskDialog
|
||||
abstract class DialogEvent : ViewEvent(), ActivityExecutor {
|
||||
|
||||
override fun invoke(activity: UIActivity<*>) {
|
||||
MagiskDialog(activity)
|
||||
.apply { setOwnerActivity(activity) }
|
||||
.apply(this::build).show()
|
||||
MagiskDialog(activity).apply(this::build).show()
|
||||
}
|
||||
|
||||
abstract fun build(dialog: MagiskDialog)
|
||||
|
@ -29,7 +29,7 @@ class ManagerInstallDialog : MarkDownDialog() {
|
||||
setCancelable(true)
|
||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
text = R.string.install
|
||||
onClick { DownloadService.start(context, Subject.App()) }
|
||||
onClick { DownloadService.start(activity, Subject.App()) }
|
||||
}
|
||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
text = android.R.string.cancel
|
||||
|
@ -5,7 +5,6 @@ import android.widget.TextView
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -24,7 +23,7 @@ abstract class MarkDownDialog : DialogEvent() {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.markdown_window_md2, null)
|
||||
setView(view)
|
||||
val tv = view.findViewById<TextView>(R.id.md_txt)
|
||||
(ownerActivity as BaseActivity).lifecycleScope.launch {
|
||||
activity.lifecycleScope.launch {
|
||||
try {
|
||||
val text = withContext(Dispatchers.IO) { getMarkdownText() }
|
||||
ServiceLocator.markwon.setMarkdown(tv, text)
|
||||
|
@ -24,7 +24,7 @@ class ModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() {
|
||||
fun download(install: Boolean) {
|
||||
val action = if (install) Action.Flash else Action.Download
|
||||
val subject = Subject.Module(item, action)
|
||||
DownloadService.start(context, subject)
|
||||
DownloadService.start(activity, subject)
|
||||
}
|
||||
|
||||
val title = context.getString(R.string.repo_install_title,
|
||||
|
@ -2,10 +2,7 @@ package com.topjohnwu.magisk.ktx
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.*
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
@ -33,6 +30,7 @@ import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||
import com.topjohnwu.magisk.utils.APKInstall
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import java.io.File
|
||||
import kotlin.Array
|
||||
@ -266,3 +264,14 @@ fun PackageManager.getPackageInfo(uid: Int, pid: Int): PackageInfo? {
|
||||
}
|
||||
throw PackageManager.NameNotFoundException()
|
||||
}
|
||||
|
||||
fun Context.registerRuntimeReceiver(receiver: BroadcastReceiver, filter: IntentFilter) {
|
||||
APKInstall.registerReceiver(this, receiver, filter)
|
||||
}
|
||||
|
||||
fun Context.selfLaunchIntent(): Intent {
|
||||
val pm = packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(packageName)!!
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
return intent
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.topjohnwu.magisk.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.os.Bundle
|
||||
@ -52,11 +54,19 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
||||
|
||||
private var isRootFragment = true
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun showMainUI(savedInstanceState: Bundle?) {
|
||||
setContentView()
|
||||
showUnsupportedMessage()
|
||||
askForHomeShortcut()
|
||||
|
||||
// Ask permission to post notifications for background update check
|
||||
if (Config.checkUpdate) {
|
||||
withPermission(Manifest.permission.POST_NOTIFICATIONS) {
|
||||
Config.checkUpdate = it
|
||||
}
|
||||
}
|
||||
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
|
||||
navigation.addOnDestinationChangedListener { _, destination, _ ->
|
||||
|
@ -8,6 +8,7 @@ import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.ktx.activity
|
||||
import com.topjohnwu.magisk.utils.TextHolder
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
|
||||
@ -57,6 +58,8 @@ sealed class BaseSettingsItem : ObservableRvItem() {
|
||||
set(checked, value, { onPressed(view, handler) })
|
||||
|
||||
override fun onPressed(view: View, handler: Handler) {
|
||||
// Make sure the checked state is synced
|
||||
notifyPropertyChanged(BR.checked)
|
||||
handler.onItemPressed(view, this) {
|
||||
value = !value
|
||||
notifyPropertyChanged(BR.checked)
|
||||
@ -72,7 +75,7 @@ sealed class BaseSettingsItem : ObservableRvItem() {
|
||||
|
||||
override fun onPressed(view: View, handler: Handler) {
|
||||
handler.onItemPressed(view, this) {
|
||||
MagiskDialog(view.context).apply {
|
||||
MagiskDialog(view.activity).apply {
|
||||
setTitle(title.getText(view.resources))
|
||||
setView(getView(view.context))
|
||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
@ -115,7 +118,7 @@ sealed class BaseSettingsItem : ObservableRvItem() {
|
||||
|
||||
override fun onPressed(view: View, handler: Handler) {
|
||||
handler.onItemPressed(view, this) {
|
||||
MagiskDialog(view.context).apply {
|
||||
MagiskDialog(view.activity).apply {
|
||||
setTitle(title.getText(view.resources))
|
||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
text = android.R.string.cancel
|
||||
|
@ -23,6 +23,7 @@ import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
||||
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
||||
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
||||
import com.topjohnwu.magisk.databinding.set
|
||||
import com.topjohnwu.magisk.ktx.activity
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.utils.asText
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
@ -111,7 +112,7 @@ object Restore : BaseSettingsItem.Blank() {
|
||||
|
||||
override fun onPressed(view: View, handler: Handler) {
|
||||
handler.onItemPressed(view, this) {
|
||||
MagiskDialog(view.context).apply {
|
||||
MagiskDialog(view.activity).apply {
|
||||
setTitle(R.string.settings_restore_app_title)
|
||||
setMessage(R.string.restore_app_confirmation)
|
||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
|
@ -96,6 +96,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
||||
override fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit) {
|
||||
when (item) {
|
||||
DownloadPath -> withExternalRW(andThen)
|
||||
UpdateChecker -> withPostNotificationPermission(andThen)
|
||||
Biometrics -> authenticate(andThen)
|
||||
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
|
||||
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.topjohnwu.magisk.view
|
||||
|
||||
import android.content.Context
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.Drawable
|
||||
@ -21,22 +21,26 @@ import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.databinding.*
|
||||
import com.topjohnwu.magisk.view.MagiskDialog.DialogClickListener
|
||||
|
||||
typealias DialogButtonClickListener = (DialogInterface) -> Unit
|
||||
|
||||
class MagiskDialog(
|
||||
context: Context, theme: Int = 0
|
||||
context: Activity, theme: Int = 0
|
||||
) : AppCompatDialog(context, theme) {
|
||||
|
||||
private val binding: DialogMagiskBaseBinding =
|
||||
DialogMagiskBaseBinding.inflate(LayoutInflater.from(context))
|
||||
private val data = Data()
|
||||
|
||||
val activity: BaseActivity get() = ownerActivity as BaseActivity
|
||||
|
||||
init {
|
||||
binding.setVariable(BR.data, data)
|
||||
setCancelable(true)
|
||||
setOwnerActivity(context)
|
||||
}
|
||||
|
||||
inner class Data : ObservableHost {
|
||||
|
@ -6,7 +6,6 @@ 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 android.os.Build.VERSION.SDK_INT
|
||||
import androidx.core.content.getSystemService
|
||||
@ -16,6 +15,7 @@ import com.topjohnwu.magisk.core.di.AppContext
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.ktx.getBitmap
|
||||
import com.topjohnwu.magisk.ktx.selfLaunchIntent
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@ -44,18 +44,10 @@ object Notifications {
|
||||
}
|
||||
}
|
||||
|
||||
fun selfLaunchIntent(context: Context): Intent {
|
||||
val pm = context.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(context.packageName)!!
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
return intent
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
fun updateDone(context: Context) {
|
||||
setup(context)
|
||||
val flag = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
val pending = PendingIntent.getActivity(context, 0, selfLaunchIntent(context), flag)
|
||||
val pending = PendingIntent.getActivity(context, 0, context.selfLaunchIntent(), flag)
|
||||
val builder = if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Notification.Builder(context, UPDATED_CHANNEL)
|
||||
.setSmallIcon(context.getBitmap(R.drawable.ic_magisk_outline).toIcon())
|
||||
@ -72,7 +64,6 @@ object Notifications {
|
||||
|
||||
fun updateAvailable(context: Context) {
|
||||
val intent = DownloadService.getPendingIntent(context, Subject.App())
|
||||
|
||||
val bitmap = context.getBitmap(R.drawable.ic_magisk_outline)
|
||||
val builder = if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Notification.Builder(context, UPDATE_CHANNEL)
|
||||
@ -90,7 +81,7 @@ object Notifications {
|
||||
mgr.notify(APP_UPDATE_NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
||||
fun progress(context: Context, title: CharSequence): Notification.Builder {
|
||||
fun startProgress(context: Context, title: CharSequence): Notification.Builder {
|
||||
val builder = if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Notification.Builder(context, PROGRESS_CHANNEL)
|
||||
} else {
|
||||
|
@ -230,6 +230,7 @@
|
||||
<string name="unsupport_nonroot_stub_msg">The hidden Magisk app cannot continue to work because root was lost. Please restore the original APK.</string>
|
||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||
<string name="external_rw_permission_denied">Grant storage permission to enable this functionality</string>
|
||||
<string name="post_notifications_denied">Grant notifications permission to enable this functionality</string>
|
||||
<string name="install_unknown_denied">Allow "install unknown apps" to enable this functionality</string>
|
||||
<string name="add_shortcut_title">Add shortcut to home screen</string>
|
||||
<string name="add_shortcut_msg">After hiding this app, its name and icon might become difficult to recognize. Do you want to add a pretty shortcut to the home screen?</string>
|
||||
|
@ -43,13 +43,13 @@ private val Project.android: BaseAppModuleExtension
|
||||
|
||||
fun Project.setupCommon() {
|
||||
androidBase {
|
||||
compileSdkVersion(32)
|
||||
compileSdkVersion(33)
|
||||
buildToolsVersion = "32.0.0"
|
||||
ndkPath = "$sdkDirectory/ndk/magisk"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
targetSdk = 32
|
||||
targetSdk = 33
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
Loading…
Reference in New Issue
Block a user