mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 14:17:26 +00:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
32fc34f922 | ||
![]() |
b82a393692 | ||
![]() |
3c7e792167 | ||
![]() |
0ad66875ab | ||
![]() |
1191ac2671 | ||
![]() |
928b3425e3 | ||
![]() |
0726a00e3b | ||
![]() |
5a88984d34 | ||
![]() |
18de60f68c | ||
![]() |
1893359142 | ||
![]() |
f5e5ab2436 | ||
![]() |
ff5ea1a70d | ||
![]() |
54ee63a409 | ||
![]() |
f095606b50 | ||
![]() |
e8f31c78d7 |
14
README.MD
14
README.MD
@@ -12,19 +12,19 @@ Some highlight features:
|
||||
- **MagiskSU**: Provide root access for applications
|
||||
- **Magisk Modules**: Modify read-only partitions by installing modules
|
||||
- **MagiskBoot**: The most complete tool for unpacking and repacking Android boot images
|
||||
- **Zygisk**: Run code in every Android applications' processes
|
||||
|
||||
## Downloads
|
||||
|
||||
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v23.0)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v23.0)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v24.0)
|
||||
[](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)
|
||||
|
||||
## Useful Links
|
||||
|
||||
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
|
||||
- [Frequently Asked Questions](https://topjohnwu.github.io/Magisk/faq.html)
|
||||
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
||||
- [Magisk Troubleshoot Wiki](https://www.didgeridoohan.com/magisk/HomePage) (by [@Didgeridoohan](https://github.com/Didgeridoohan))
|
||||
|
||||
@@ -41,15 +41,15 @@ For Magisk app crashes, record and upload the logcat when the crash occurs.
|
||||
- Magisk builds on any OS Android Studio supports. Install Android Studio and do the initial setups.
|
||||
- Clone sources: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
|
||||
- Install Python 3.6+ \
|
||||
(Windows only: select **'Add Python to PATH'** in installer, and run `pip install colorama` after install)
|
||||
(Windows only: select **'Add Python to PATH'** in installer, and run `pip install colorama` after install)
|
||||
- Configure to use the JDK bundled in Android Studio:
|
||||
- macOS: `export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home"`
|
||||
- Linux: `export PATH="/path/to/androidstudio/jre/bin:$PATH"`
|
||||
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
|
||||
- macOS: `export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home"`
|
||||
- Linux: `export PATH="/path/to/androidstudio/jre/bin:$PATH"`
|
||||
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
|
||||
- Set environment variable `ANDROID_SDK_ROOT` to the Android SDK folder (can be found in Android Studio settings)
|
||||
- Run `./build.py ndk` to let the script download and install NDK for you
|
||||
- To start building, run `build.py` to see your options. \
|
||||
For each action, use `-h` to access help (e.g. `./build.py all -h`)
|
||||
For each action, use `-h` to access help (e.g. `./build.py all -h`)
|
||||
- To start development, open the project with Android Studio. The IDE can be used for both app (Kotlin/Java) and native (C++/C) sources.
|
||||
- Optionally, set custom configs with `config.prop`. A sample `config.prop.sample` is provided.
|
||||
- To sign APKs and zips with your own private keys, set signing configs in `config.prop`. For more info, check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key).
|
||||
|
@@ -57,6 +57,7 @@ android {
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs = listOf("-Xjvm-default=enable")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,19 +110,19 @@ dependencies {
|
||||
implementation("androidx.room:room-ktx:${vRoom}")
|
||||
kapt("androidx.room:room-compiler:${vRoom}")
|
||||
|
||||
val vNav = "2.4.0-rc01"
|
||||
val vNav = "2.5.0-alpha01"
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
|
||||
|
||||
implementation("androidx.biometric:biometric:1.1.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.2")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.3")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.appcompat:appcompat:1.4.1")
|
||||
implementation("androidx.preference:preference:1.1.1")
|
||||
implementation("androidx.preference:preference:1.2.0")
|
||||
implementation("androidx.recyclerview:recyclerview:1.2.1")
|
||||
implementation("androidx.fragment:fragment-ktx:1.4.0")
|
||||
implementation("androidx.fragment:fragment-ktx:1.4.1")
|
||||
implementation("androidx.transition:transition:1.4.1")
|
||||
implementation("androidx.core:core-ktx:1.7.0")
|
||||
implementation("androidx.core:core-splashscreen:1.0.0-beta01")
|
||||
implementation("com.google.android.material:material:1.4.0")
|
||||
implementation("com.google.android.material:material:1.5.0")
|
||||
}
|
||||
|
@@ -15,11 +15,11 @@ import com.topjohnwu.magisk.ktx.startAnimations
|
||||
|
||||
abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHolder {
|
||||
|
||||
val activity get() = requireActivity() as NavigationActivity<*>
|
||||
val activity get() = getActivity() as? NavigationActivity<*>
|
||||
protected lateinit var binding: Binding
|
||||
protected abstract val layoutRes: Int
|
||||
|
||||
private val navigation get() = activity.navigation
|
||||
private val navigation get() = activity?.navigation
|
||||
open val snackbarAnchorView: View? get() = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -41,12 +41,12 @@ abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHo
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.supportActionBar?.subtitle = null
|
||||
activity?.supportActionBar?.subtitle = null
|
||||
}
|
||||
|
||||
override fun onEventDispatched(event: ViewEvent) = when(event) {
|
||||
is ContextExecutor -> event(requireContext())
|
||||
is ActivityExecutor -> event(activity)
|
||||
is ActivityExecutor -> activity?.let { event(it) } ?: Unit
|
||||
is FragmentExecutor -> event(this)
|
||||
else -> Unit
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ open class App() : Application() {
|
||||
}
|
||||
|
||||
base.resources.patch()
|
||||
app.registerActivityLifecycleCallbacks(ForegroundTracker)
|
||||
app.registerActivityLifecycleCallbacks(ActivityTracker)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
@@ -86,7 +86,7 @@ open class App() : Application() {
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object ForegroundTracker : Application.ActivityLifecycleCallbacks {
|
||||
object ActivityTracker : Application.ActivityLifecycleCallbacks {
|
||||
|
||||
@Volatile
|
||||
var foreground: Activity? = null
|
||||
|
@@ -11,7 +11,7 @@ import android.os.IBinder
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.ForegroundTracker
|
||||
import com.topjohnwu.magisk.core.ActivityTracker
|
||||
import com.topjohnwu.magisk.core.base.BaseService
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
import com.topjohnwu.magisk.core.utils.ProgressInputStream
|
||||
@@ -25,7 +25,6 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.ResponseBody
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
class DownloadService : BaseService() {
|
||||
@@ -66,17 +65,18 @@ class DownloadService : BaseService() {
|
||||
val stream = service.fetchFile(subject.url).toProgressStream(subject)
|
||||
when (subject) {
|
||||
is Subject.Manager -> handleAPK(subject, stream)
|
||||
else -> stream.toModule(subject.file, service.fetchInstaller().byteStream())
|
||||
is Subject.Module -> stream.toModule(subject.file, assets.open("module_installer.sh"))
|
||||
}
|
||||
if (ForegroundTracker.hasForeground) {
|
||||
val activity = ActivityTracker.foreground
|
||||
if (activity != null && subject.autoStart) {
|
||||
remove(subject.notifyId)
|
||||
subject.pendingIntent(this@DownloadService)?.send()
|
||||
subject.pendingIntent(activity).send()
|
||||
} else {
|
||||
notifyFinish(subject)
|
||||
}
|
||||
if (!hasNotifications)
|
||||
stopSelf()
|
||||
} catch (e: IOException) {
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
notifyFail(subject)
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.ForegroundTracker
|
||||
import com.topjohnwu.magisk.core.ActivityTracker
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
@@ -64,7 +64,7 @@ suspend fun DownloadService.handleAPK(subject: Subject.Manager, stream: InputStr
|
||||
//noinspection InlinedApi
|
||||
val flag = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
val pending = PendingIntent.getActivity(this, id, intent, flag)
|
||||
if (ForegroundTracker.hasForeground) {
|
||||
if (ActivityTracker.hasForeground) {
|
||||
val alarm = getSystemService<AlarmManager>()
|
||||
alarm!!.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pending)
|
||||
}
|
||||
|
@@ -34,8 +34,9 @@ sealed class Subject : Parcelable {
|
||||
abstract val file: Uri
|
||||
abstract val title: String
|
||||
abstract val notifyId: Int
|
||||
open val autoStart: Boolean get() = true
|
||||
|
||||
abstract fun pendingIntent(context: Context): PendingIntent?
|
||||
abstract fun pendingIntent(context: Context): PendingIntent
|
||||
|
||||
@Parcelize
|
||||
class Module(
|
||||
@@ -45,16 +46,15 @@ sealed class Subject : Parcelable {
|
||||
) : Subject() {
|
||||
override val url: String get() = module.zipUrl
|
||||
override val title: String get() = module.downloadFilename
|
||||
override val autoStart: Boolean get() = action == Action.Flash
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
MediaStoreUtils.getFile(title).uri
|
||||
}
|
||||
|
||||
override fun pendingIntent(context: Context) = when (action) {
|
||||
Action.Flash -> FlashFragment.installIntent(context, file)
|
||||
else -> null
|
||||
}
|
||||
override fun pendingIntent(context: Context) =
|
||||
FlashFragment.installIntent(context, file)
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
|
@@ -38,8 +38,7 @@ fun InputStream.unzip(folder: File, path: String, junkPath: Boolean) {
|
||||
}
|
||||
SuFileOutputStream.open(dest).use { out -> zin.copyTo(out) }
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
throw e
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
@@ -6,26 +6,16 @@ import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.*
|
||||
|
||||
private const val REVISION = "revision"
|
||||
private const val BRANCH = "branch"
|
||||
private const val REPO = "repo"
|
||||
private const val FILE = "file"
|
||||
|
||||
const val MAGISK_MAIN = "topjohnwu/Magisk"
|
||||
|
||||
interface GithubPageServices {
|
||||
|
||||
@GET("{$FILE}")
|
||||
suspend fun fetchUpdateJSON(@Path(FILE) file: String): UpdateInfo
|
||||
}
|
||||
|
||||
interface JSDelivrServices {
|
||||
|
||||
@GET("$MAGISK_MAIN@{$REVISION}/scripts/module_installer.sh")
|
||||
@Streaming
|
||||
suspend fun fetchInstaller(@Path(REVISION) revision: String): ResponseBody
|
||||
}
|
||||
|
||||
interface RawServices {
|
||||
|
||||
@GET
|
||||
|
@@ -7,7 +7,9 @@ import com.topjohnwu.magisk.core.Config.Value.CUSTOM_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.DEFAULT_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.data.network.*
|
||||
import com.topjohnwu.magisk.data.network.GithubApiServices
|
||||
import com.topjohnwu.magisk.data.network.GithubPageServices
|
||||
import com.topjohnwu.magisk.data.network.RawServices
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
@@ -15,7 +17,6 @@ import java.io.IOException
|
||||
class NetworkService(
|
||||
private val pages: GithubPageServices,
|
||||
private val raw: RawServices,
|
||||
private val jsd: JSDelivrServices,
|
||||
private val api: GithubApiServices
|
||||
) {
|
||||
suspend fun fetchUpdate() = safe {
|
||||
@@ -59,13 +60,7 @@ class NetworkService(
|
||||
}
|
||||
|
||||
// Fetch files
|
||||
suspend fun fetchInstaller() = wrap {
|
||||
val sha = fetchMainVersion()
|
||||
jsd.fetchInstaller(sha)
|
||||
}
|
||||
suspend fun fetchFile(url: String) = wrap { raw.fetchFile(url) }
|
||||
suspend fun fetchString(url: String) = wrap { raw.fetchString(url) }
|
||||
suspend fun fetchModuleJson(url: String) = wrap { raw.fetchModuleJson(url) }
|
||||
|
||||
private suspend fun fetchMainVersion() = api.fetchBranch(MAGISK_MAIN, "master").commit.sha
|
||||
}
|
||||
|
@@ -47,21 +47,20 @@ object ServiceLocator {
|
||||
NetworkService(
|
||||
createApiService(retrofit, Const.Url.GITHUB_PAGE_URL),
|
||||
createApiService(retrofit, Const.Url.GITHUB_RAW_URL),
|
||||
createApiService(retrofit, Const.Url.JS_DELIVR_URL),
|
||||
createApiService(retrofit, Const.Url.GITHUB_API_URL)
|
||||
)
|
||||
}
|
||||
|
||||
object VMFactory : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel?> create(clz: Class<T>): T {
|
||||
return when (clz) {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return when (modelClass) {
|
||||
HomeViewModel::class.java -> HomeViewModel(networkService)
|
||||
LogViewModel::class.java -> LogViewModel(logRepo)
|
||||
SuperuserViewModel::class.java -> SuperuserViewModel(policyDB)
|
||||
InstallViewModel::class.java -> InstallViewModel(networkService)
|
||||
SuRequestViewModel::class.java -> SuRequestViewModel(policyDB, timeoutPrefs)
|
||||
else -> clz.newInstance()
|
||||
else -> modelClass.newInstance()
|
||||
} as T
|
||||
}
|
||||
}
|
||||
@@ -69,7 +68,7 @@ object ServiceLocator {
|
||||
|
||||
inline fun <reified VM : ViewModel> ViewModelStoreOwner.viewModel() =
|
||||
lazy(LazyThreadSafetyMode.NONE) {
|
||||
ViewModelProvider(this, ServiceLocator.VMFactory).get(VM::class.java)
|
||||
ViewModelProvider(this, ServiceLocator.VMFactory)[VM::class.java]
|
||||
}
|
||||
|
||||
private fun createSuLogDatabase(context: Context) =
|
||||
|
@@ -83,7 +83,7 @@ class SelectModuleEvent : ViewEvent(), FragmentExecutor {
|
||||
override fun invoke(fragment: BaseFragment<*>) {
|
||||
try {
|
||||
fragment.apply {
|
||||
activity.getContent("application/zip") {
|
||||
activity?.getContent("application/zip") {
|
||||
MainDirections.actionFlashFragment(Const.Value.FLASH_ZIP, it).navigate()
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>() {
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
activity.setTitle(R.string.denylist)
|
||||
activity?.setTitle(R.string.denylist)
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
|
@@ -31,10 +31,10 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setHasOptionsMenu(true)
|
||||
activity.setTitle(R.string.flash_screen_title)
|
||||
activity?.setTitle(R.string.flash_screen_title)
|
||||
|
||||
viewModel.subtitle.observe(this) {
|
||||
activity.supportActionBar?.setSubtitle(it)
|
||||
activity?.supportActionBar?.setSubtitle(it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,15 +49,15 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
defaultOrientation = activity.requestedOrientation
|
||||
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
viewModel.startFlashing()
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
override fun onDestroyView() {
|
||||
if (defaultOrientation != -1) {
|
||||
activity.requestedOrientation = defaultOrientation
|
||||
activity?.requestedOrientation = defaultOrientation
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@@ -103,9 +103,11 @@ class FlashViewModel : BaseViewModel() {
|
||||
val name = "magisk_install_log_%s.log".format(now.toTime(timeFormatStandard))
|
||||
val file = MediaStoreUtils.getFile(name, true)
|
||||
file.uri.outputStream().bufferedWriter().use { writer ->
|
||||
logItems.forEach {
|
||||
writer.write(it)
|
||||
writer.newLine()
|
||||
synchronized(logItems) {
|
||||
logItems.forEach {
|
||||
writer.write(it)
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
SnackbarEvent(file.toString()).publish()
|
||||
|
@@ -19,7 +19,7 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>() {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.title = resources.getString(R.string.section_home)
|
||||
activity?.title = resources.getString(R.string.section_home)
|
||||
setHasOptionsMenu(true)
|
||||
DownloadService.observeProgress(this, viewModel::onProgressUpdate)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>() {
|
||||
when (item.itemId) {
|
||||
R.id.action_settings ->
|
||||
HomeFragmentDirections.actionHomeFragmentToSettingsFragment().navigate()
|
||||
R.id.action_reboot -> RebootEvent.inflateMenu(activity).show()
|
||||
R.id.action_reboot -> activity?.let { RebootEvent.inflateMenu(it).show() }
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
|
@@ -38,7 +38,7 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setHasOptionsMenu(true)
|
||||
activity.title = resources.getString(R.string.logs)
|
||||
activity?.title = resources.getString(R.string.logs)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@@ -19,7 +19,7 @@ class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setHasOptionsMenu(true)
|
||||
activity.title = resources.getString(R.string.modules)
|
||||
activity?.title = resources.getString(R.string.modules)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@@ -18,7 +18,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
activity.title = resources.getString(R.string.settings)
|
||||
activity?.title = resources.getString(R.string.settings)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@@ -17,7 +17,7 @@ class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.title = resources.getString(R.string.superuser)
|
||||
activity?.title = resources.getString(R.string.superuser)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@@ -73,7 +73,7 @@ class SuRequestViewModel(
|
||||
val itemBinding = ItemBinding.of<String>(BR.item, R.layout.item_spinner)
|
||||
|
||||
private val handler = SuRequestHandler(AppContext.packageManager, policyDB)
|
||||
private lateinit var timer: CountDownTimer
|
||||
private var timer: CountDownTimer? = null
|
||||
|
||||
fun grantPressed() {
|
||||
cancelTimer()
|
||||
@@ -121,7 +121,7 @@ class SuRequestViewModel(
|
||||
}
|
||||
|
||||
private fun respond(action: Int) {
|
||||
timer.cancel()
|
||||
timer?.cancel()
|
||||
|
||||
val pos = selectedItemPosition
|
||||
timeoutPrefs.edit().putInt(handler.policy.packageName, pos).apply()
|
||||
@@ -132,7 +132,7 @@ class SuRequestViewModel(
|
||||
}
|
||||
|
||||
private fun cancelTimer() {
|
||||
timer.cancel()
|
||||
timer?.cancel()
|
||||
denyText.seconds = 0
|
||||
}
|
||||
|
||||
|
@@ -61,7 +61,7 @@ class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
activity.title = getString(R.string.section_theme)
|
||||
activity?.title = getString(R.string.section_theme)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -121,15 +121,15 @@ class MagiskDialog(
|
||||
super.onCreate(savedInstanceState)
|
||||
super.setContentView(binding.root)
|
||||
|
||||
val default = MaterialColors.getColor(context, R.attr.colorSurface, javaClass.canonicalName)
|
||||
val default = MaterialColors.getColor(context, com.google.android.material.R.attr.colorSurface, javaClass.canonicalName)
|
||||
val surfaceColor = MaterialColors.getColor(context, R.attr.colorSurfaceSurfaceVariant, default)
|
||||
val materialShapeDrawable = MaterialShapeDrawable(context, null, R.attr.alertDialogStyle, R.style.MaterialAlertDialog_MaterialComponents)
|
||||
val materialShapeDrawable = MaterialShapeDrawable(context, null, androidx.appcompat.R.attr.alertDialogStyle, com.google.android.material.R.style.MaterialAlertDialog_MaterialComponents)
|
||||
materialShapeDrawable.initializeElevationOverlay(context)
|
||||
materialShapeDrawable.fillColor = ColorStateList.valueOf(surfaceColor)
|
||||
materialShapeDrawable.elevation = context.resources.getDimension(R.dimen.margin_generic)
|
||||
materialShapeDrawable.setCornerSize(context.resources.getDimension(R.dimen.l_50))
|
||||
|
||||
val inset = context.resources.getDimensionPixelSize(R.dimen.appcompat_dialog_background_inset)
|
||||
val inset = context.resources.getDimensionPixelSize(com.google.android.material.R.dimen.appcompat_dialog_background_inset)
|
||||
window?.apply {
|
||||
setBackgroundDrawable(InsetDrawable(materialShapeDrawable, inset, inset, inset, inset))
|
||||
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
@@ -29,11 +29,11 @@ public class ConcealableBottomNavigationView extends BottomNavigationView {
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.bottomNavigationStyle);
|
||||
this(context, attrs, com.google.android.material.R.attr.bottomNavigationStyle);
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, R.style.Widget_Design_BottomNavigationView);
|
||||
this(context, attrs, defStyleAttr, com.google.android.material.R.style.Widget_Design_BottomNavigationView);
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
|
@@ -106,7 +106,7 @@
|
||||
<string name="module_version_author">%1$s nga %2$s</string>
|
||||
<string name="module_state_remove">Hiqe</string>
|
||||
<string name="module_state_restore">Rikëthe</string>
|
||||
<string name="module_action_install_external">Instaloni nga ruajtja</string>
|
||||
<string name="module_action_install_external">Instaloni nga sdcard</string>
|
||||
<string name="update_available">Përditësimi në dispozicion</string>
|
||||
<string name="suspend_text_riru">Moduli u pezullua sepse %1$s është aktivizuar</string>
|
||||
<string name="suspend_text_zygisk">Moduli është pezulluar sepse %1$s nuk është i aktivizuar</string>
|
||||
@@ -157,7 +157,7 @@
|
||||
<string name="settings_su_request_60">60 Sekonda</string>
|
||||
<string name="superuser_access">Aksesi i Super-përdorues</string>
|
||||
<string name="auto_response">Përgjigje automatike</string>
|
||||
<string name="request_timeout">Kërkesës i mbaroi koha</string>
|
||||
<string name="request_timeout">Koha për mbarimit të Kërkesës</string>
|
||||
<string name="superuser_notification">Njoftimi i Super-përdoruesit</string>
|
||||
<string name="settings_su_reauth_title">Ri-vërtetimi pas azhurnimit</string>
|
||||
<string name="settings_su_reauth_summary">Ri-vërtetoni lejet e super-përdoruesit pas azhurnimit të aplikacionit</string>
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
@@ -15,10 +17,16 @@ gradlePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("gradle-plugin", "1.6.10"))
|
||||
implementation("com.android.tools.build:gradle:7.0.4")
|
||||
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.0-rc01")
|
||||
implementation("com.android.tools.build:gradle:7.1.0")
|
||||
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha01")
|
||||
implementation("io.michaelrocks:paranoid-gradle-plugin:0.3.7")
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit:5.12.0.202106070339-r")
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ fun Project.setupCommon() {
|
||||
androidBase {
|
||||
compileSdkVersion(31)
|
||||
buildToolsVersion = "31.0.0"
|
||||
ndkPath = "${System.getenv("ANDROID_SDK_ROOT")}/ndk/magisk"
|
||||
ndkPath = "$sdkDirectory/ndk/magisk"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
@@ -123,7 +123,8 @@ fun Project.setupApp() {
|
||||
inputs.property("versionCode", Config.versionCode)
|
||||
into("src/main/assets")
|
||||
from(rootProject.file("scripts")) {
|
||||
include("util_functions.sh", "boot_patch.sh", "uninstaller.sh", "addon.d.sh")
|
||||
include("util_functions.sh", "boot_patch.sh", "addon.d.sh")
|
||||
include("uninstaller.sh", "module_installer.sh")
|
||||
}
|
||||
from(rootProject.file("tools/bootctl"))
|
||||
into("chromeos") {
|
||||
|
@@ -1,10 +1,14 @@
|
||||
# Magisk Changelog
|
||||
|
||||
### v24.1
|
||||
|
||||
- [App] Stability improvements
|
||||
|
||||
### v24.0
|
||||
|
||||
- [General] MagiskHide is removed from Magisk
|
||||
- [General] Support 64-bit only systems
|
||||
- [General] Support Android 12
|
||||
- [General] Support devices that do not support 32-bit and only runs 64-bit code
|
||||
- [General] Update BusyBox to 1.34.1
|
||||
- [Zygisk] Introduce new feature: Zygisk
|
||||
- [Zygisk] Introduce DenyList feature to revert Magisk features in user selected processes
|
||||
|
@@ -34,11 +34,11 @@ Next, we need to know whether your device has a separate `vbmeta` partition.
|
||||
- If you find `vbmeta`, `vbmeta_a`, or `vbmeta_b`, then yes, your device **has** a separate `vbmeta` partition
|
||||
- Otherwise, your device **does not** have a separate `vbmeta` partition.
|
||||
|
||||
Quick recap, at this point, you should know and prepared:
|
||||
Quick recap, at this point, you should have known and prepared:
|
||||
|
||||
1. Whether your device has boot ramdisk
|
||||
2. Whether your device has a separate `vbmeta` partition
|
||||
3. A `boot.img` or `recovery.img` based on the result of (1)
|
||||
3. A `boot.img` or `recovery.img` based on (1)
|
||||
|
||||
Let's continue to [Patching Images](#patching-images).
|
||||
|
||||
@@ -103,16 +103,15 @@ Unlocking the bootloader on modern Samsung devices have some caveats. The newly
|
||||
- Use either [samfirm.js](https://github.com/jesec/samfirm.js), [Frija](https://forum.xda-developers.com/s10-plus/how-to/tool-frija-samsung-firmware-downloader-t3910594), or [Samloader](https://forum.xda-developers.com/s10-plus/how-to/tool-samloader-samfirm-frija-replacement-t4105929) to download the latest firmware zip of your device directly from Samsung servers.
|
||||
- Unzip the firmware and copy the `AP` tar file to your device. It is normally named as `AP_[device_model_sw_ver].tar.md5`
|
||||
- Press the **Install** button in the Magisk card
|
||||
- If you are patching a recovery image, check the **"Recovery Mode"** option
|
||||
- If your device does **NOT** have boot ramdisk, check the **"Recovery Mode"** option
|
||||
- Choose **"Select and Patch a File"** in method, and select the `AP` tar file
|
||||
- The Magisk app will patch the whole firmware file to `[Internal Storage]/Download/magisk_patched_[random_strings].tar`
|
||||
- Start the installation, and copy the patched tar file to your PC using ADB:<br>
|
||||
`adb pull /sdcard/Download/magisk_patched_[random_strings].tar`<br>
|
||||
**DO NOT USE MTP** as it is known to corrupt large files.
|
||||
- Reboot to download mode. Open Odin on your PC, and flash `magisk_patched.tar` as `AP`, together with `BL`, `CP`, and `CSC` (**NOT** `HOME_CSC` because we want to **wipe data**) from the original firmware.
|
||||
- Your device should reboot automatically once Odin finished flashing. Agree to do a factory reset if asked.
|
||||
- If your device does **NOT** have boot ramdisk, reboot to recovery now to enable Magisk (reason stated in [Magisk in Recovery](#magisk-in-recovery)).
|
||||
- Install the Magisk app you've downloaded and launch the app. It should show a dialog asking for additional setup.
|
||||
- Install the Magisk app you've already downloaded and launch the app. It should show a dialog asking for additional setup.
|
||||
- Let the app do its job and automatically reboot the device. Voila!
|
||||
|
||||
### Upgrading the OS
|
||||
|
23
docs/releases/24100.md
Normal file
23
docs/releases/24100.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## 2022.1.28 Magisk v24.1
|
||||
|
||||
> For those coming from v24.0, v24.1 only has some minor app improvements. The following are copied from v24.0 release notes.
|
||||
|
||||
It has been a while since the last public release, long time no see! A personal update for those unaware: I am now working at Google on the Android Platform Security team. Without further ado, let's jump right into it!
|
||||
|
||||
### MagiskHide Removal
|
||||
|
||||
I have lost interest in fighting this battle for quite a while; plus, the existing MagiskHide implementation is flawed in so many ways. Decoupling Magisk from root hiding is, in my opinion, beneficial to the community. Ever since my announcement on Twitter months ago, highly effective "root hiding" modules (much **MUCH** better than MagiskHide) has been flourishing, which again shows that people are way more capable than I am on this subject. So why not give those determined their time to shine, and let me focus on improving Magisk instead of drowning in the everlasting cat-and-mouse game 😉.
|
||||
|
||||
### Sunsetting Magisk-Modules-Repo
|
||||
|
||||
Due to lack of time and maintenance, the centralized Magisk-Modules-Repo was frozen, and the functionality to download modules from the repo is removed in v24.0. As a supplement, module developers can now specify an `updateJson` URL in their modules. The Magisk app will use that to check, download, and install module updates.
|
||||
|
||||
### Introducing Zygisk
|
||||
|
||||
Zygisk is **Magisk in Zygote**, the next big thing for Magisk! When this feature is enabled, a part of Magisk will run in the `Zygote` daemon process, allowing module developers to run code directly in every Android apps' processes. If you've heard of [Riru](https://github.com/RikkaApps/Riru), then Zygisk is inspired by that project and is functionally similar, though the implementation is quite different internally. I cannot wait to see what module developers can achieve using Zygisk!
|
||||
|
||||
### Documentation
|
||||
|
||||
For developers, details about `updateJson` and building Zygisk modules can all be found in the updated [documentation](https://topjohnwu.github.io/Magisk/guides.html#magisk-modules).
|
||||
|
||||
### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
|
@@ -1,5 +1,6 @@
|
||||
# Release Notes
|
||||
|
||||
- [v24.1](24100.md)
|
||||
- [v24.0](24000.md)
|
||||
- [v23.0](23000.md)
|
||||
- [v22.1](22100.md)
|
||||
|
@@ -24,9 +24,10 @@ org.gradle.caching=true
|
||||
android.useAndroidX=true
|
||||
android.databinding.incremental=true
|
||||
android.injected.testOnly=false
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Magisk
|
||||
magisk.stubVersion=23
|
||||
magisk.versionCode=24000
|
||||
magisk.stubVersion=24
|
||||
magisk.versionCode=24100
|
||||
magisk.ndkVersion=21e
|
||||
magisk.fullNdkVersion=21.4.7075529
|
||||
|
Reference in New Issue
Block a user