Commit 1b4ae70a authored by Viktor De Pasquale's avatar Viktor De Pasquale

Merge remote-tracking branch 'john/master' into development

parents 065051a3 b25c4972
...@@ -38,6 +38,27 @@ Default string resources for Magisk Manager are scattered throughout ...@@ -38,6 +38,27 @@ Default string resources for Magisk Manager are scattered throughout
Translate each and place them in the respective locations (`<module>/src/main/res/values-<lang>/strings.xml`). Translate each and place them in the respective locations (`<module>/src/main/res/values-<lang>/strings.xml`).
## Signature Verification
Official release zips and APKs are signed with my personal private key. You can verify the key certificate to make sure the binaries you downloaded are not manipulated in anyway.
``` bash
# Use the keytool command from JDK to print certificates
keytool -printcert -jarfile <APK or Magisk zip>
# The output should contain the following signature
Owner: CN=John Wu, L=Taipei, C=TW
Issuer: CN=John Wu, L=Taipei, C=TW
Serial number: 50514879
Valid from: Sun Aug 14 13:23:44 EDT 2016 until: Tue Jul 21 13:23:44 EDT 2116
Certificate fingerprints:
MD5: CE:DA:68:C1:E1:74:71:0A:EF:58:89:7D:AE:6E:AB:4F
SHA1: DC:0F:2B:61:CB:D7:E9:D3:DB:BE:06:0B:2B:87:0D:46:BB:06:02:11
SHA256: B4:CB:83:B4:DA:D9:9F:99:7D:BE:87:2F:01:3A:A1:6C:14:EE:C4:1D:16:70:21:F3:71:F7:E1:33:0F:27:3E:E6
Signature algorithm name: SHA256withRSA
Version: 3
```
## License ## License
Magisk, including all git submodules are free software: Magisk, including all git submodules are free software:
......
...@@ -59,10 +59,6 @@ dependencies { ...@@ -59,10 +59,6 @@ dependencies {
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}" implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}" implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
def butterKnifeVersion = '10.1.0'
implementation "com.jakewharton:butterknife-runtime:${butterKnifeVersion}"
kapt "com.jakewharton:butterknife-compiler:${butterKnifeVersion}"
def koin = "2.0.0-rc-2" def koin = "2.0.0-rc-2"
implementation "org.koin:koin-core:${koin}" implementation "org.koin:koin-core:${koin}"
implementation "org.koin:koin-android:${koin}" implementation "org.koin:koin-android:${koin}"
......
package com.topjohnwu.magisk.di package com.topjohnwu.magisk.di
import android.content.Intent
import android.net.Uri import android.net.Uri
import com.topjohnwu.magisk.ui.MainViewModel import com.topjohnwu.magisk.ui.MainViewModel
import com.topjohnwu.magisk.ui.flash.FlashViewModel import com.topjohnwu.magisk.ui.flash.FlashViewModel
...@@ -10,7 +9,6 @@ import com.topjohnwu.magisk.ui.log.LogViewModel ...@@ -10,7 +9,6 @@ import com.topjohnwu.magisk.ui.log.LogViewModel
import com.topjohnwu.magisk.ui.module.ModuleViewModel import com.topjohnwu.magisk.ui.module.ModuleViewModel
import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
import com.topjohnwu.magisk.ui.surequest.SuRequestViewModel import com.topjohnwu.magisk.ui.surequest.SuRequestViewModel
import com.topjohnwu.magisk.ui.surequest._SuRequestViewModel
import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module import org.koin.dsl.module
...@@ -23,8 +21,5 @@ val viewModelModules = module { ...@@ -23,8 +21,5 @@ val viewModelModules = module {
viewModel { ModuleViewModel(get(), get()) } viewModel { ModuleViewModel(get(), get()) }
viewModel { LogViewModel(get(), get()) } viewModel { LogViewModel(get(), get()) }
viewModel { (action: String, uri: Uri?) -> FlashViewModel(action, uri, get()) } viewModel { (action: String, uri: Uri?) -> FlashViewModel(action, uri, get()) }
viewModel { (intent: Intent, action: String?) ->
_SuRequestViewModel(intent, action.orEmpty(), get(), get())
}
viewModel { SuRequestViewModel(get(), get(), get(SUTimeout), get()) } viewModel { SuRequestViewModel(get(), get(), get(SUTimeout), get()) }
} }
package com.topjohnwu.magisk.model.entity.state package com.topjohnwu.magisk.model.entity.state
enum class IndeterminateState { enum class IndeterminateState {
INDETERMINATE, CHECKED, UNCHECKED CHECKED, INDETERMINATE, UNCHECKED
} }
package com.topjohnwu.magisk.model.navigation package com.topjohnwu.magisk.model.navigation
import com.topjohnwu.magisk.ui.hide.MagiskHideFragment import com.topjohnwu.magisk.ui.hide.MagiskHideFragment
import com.topjohnwu.magisk.ui.home.MagiskFragment import com.topjohnwu.magisk.ui.home.HomeFragment
import com.topjohnwu.magisk.ui.log.LogFragment import com.topjohnwu.magisk.ui.log.LogFragment
import com.topjohnwu.magisk.ui.module.ModulesFragment import com.topjohnwu.magisk.ui.module.ModulesFragment
import com.topjohnwu.magisk.ui.module.ReposFragment import com.topjohnwu.magisk.ui.module.ReposFragment
...@@ -12,8 +12,8 @@ import com.topjohnwu.magisk.ui.superuser.SuperuserFragment ...@@ -12,8 +12,8 @@ import com.topjohnwu.magisk.ui.superuser.SuperuserFragment
object Navigation { object Navigation {
fun home() = MagiskNavigationEvent { fun home() = MagiskNavigationEvent {
navDirections { destination = MagiskFragment::class } navDirections { destination = HomeFragment::class }
navOptions { popUpTo = MagiskFragment::class } navOptions { popUpTo = HomeFragment::class }
} }
fun superuser() = MagiskNavigationEvent { fun superuser() = MagiskNavigationEvent {
......
...@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.databinding.ActivityMainBinding ...@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.databinding.ActivityMainBinding
import com.topjohnwu.magisk.model.navigation.Navigation import com.topjohnwu.magisk.model.navigation.Navigation
import com.topjohnwu.magisk.ui.base.MagiskActivity import com.topjohnwu.magisk.ui.base.MagiskActivity
import com.topjohnwu.magisk.ui.hide.MagiskHideFragment import com.topjohnwu.magisk.ui.hide.MagiskHideFragment
import com.topjohnwu.magisk.ui.home.HomeFragment
import com.topjohnwu.magisk.ui.log.LogFragment import com.topjohnwu.magisk.ui.log.LogFragment
import com.topjohnwu.magisk.ui.module.ModulesFragment import com.topjohnwu.magisk.ui.module.ModulesFragment
import com.topjohnwu.magisk.ui.module.ReposFragment import com.topjohnwu.magisk.ui.module.ReposFragment
...@@ -22,7 +23,6 @@ import com.topjohnwu.net.Networking ...@@ -22,7 +23,6 @@ import com.topjohnwu.net.Networking
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlin.reflect.KClass import kotlin.reflect.KClass
import com.topjohnwu.magisk.ui.home.MagiskFragment as HomeFragment
open class MainActivity : MagiskActivity<MainViewModel, ActivityMainBinding>() { open class MainActivity : MagiskActivity<MainViewModel, ActivityMainBinding>() {
......
...@@ -14,6 +14,7 @@ import com.topjohnwu.magisk.model.entity.HideAppInfo ...@@ -14,6 +14,7 @@ import com.topjohnwu.magisk.model.entity.HideAppInfo
import com.topjohnwu.magisk.model.entity.HideTarget import com.topjohnwu.magisk.model.entity.HideTarget
import com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem import com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
import com.topjohnwu.magisk.model.entity.recycler.HideRvItem import com.topjohnwu.magisk.model.entity.recycler.HideRvItem
import com.topjohnwu.magisk.model.entity.state.IndeterminateState
import com.topjohnwu.magisk.model.events.HideProcessEvent import com.topjohnwu.magisk.model.events.HideProcessEvent
import com.topjohnwu.magisk.ui.base.MagiskViewModel import com.topjohnwu.magisk.ui.base.MagiskViewModel
import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.utils.Utils
...@@ -72,7 +73,8 @@ class HideViewModel( ...@@ -72,7 +73,8 @@ class HideViewModel(
.filter { it.processes.isNotEmpty() } .filter { it.processes.isNotEmpty() }
.map { HideRvItem(it, hideTargets.blockingGet()) } .map { HideRvItem(it, hideTargets.blockingGet()) }
.toList() .toList()
.map { it.sortBy { it.item.info.name }; it } .map { it.sortWith(compareBy(
{it.isHiddenState.value}, {it.item.info.name}, {it.packageName})); it }
.doOnSuccess { allItems.update(it) } .doOnSuccess { allItems.update(it) }
.flatMap { queryRaw() } .flatMap { queryRaw() }
.applyViewModel(this) .applyViewModel(this)
...@@ -94,7 +96,10 @@ class HideViewModel( ...@@ -94,7 +96,10 @@ class HideViewModel(
it.item.name.contains(query, ignoreCase = true) || it.item.name.contains(query, ignoreCase = true) ||
it.item.processes.any { it.contains(query, ignoreCase = true) } it.item.processes.any { it.contains(query, ignoreCase = true) }
} }
.filter { if (showSystem) true else it.item.info.flags and ApplicationInfo.FLAG_SYSTEM == 0 } .filter {
showSystem || (it.isHiddenState.value != IndeterminateState.UNCHECKED) ||
(it.item.info.flags and ApplicationInfo.FLAG_SYSTEM == 0)
}
.toList() .toList()
.map { it to items.calculateDiff(it) } .map { it to items.calculateDiff(it) }
......
package com.topjohnwu.magisk.ui.home package com.topjohnwu.magisk.ui.home
import android.app.Activity
import com.skoumal.teanity.viewevents.ViewEvent import com.skoumal.teanity.viewevents.ViewEvent
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentMagiskBinding import com.topjohnwu.magisk.databinding.FragmentMagiskBinding
import com.topjohnwu.magisk.model.events.* import com.topjohnwu.magisk.model.events.*
import com.topjohnwu.magisk.ui.base.MagiskActivity import com.topjohnwu.magisk.ui.base.MagiskActivity
import com.topjohnwu.magisk.ui.base.MagiskFragment
import com.topjohnwu.magisk.utils.ISafetyNetHelper import com.topjohnwu.magisk.utils.ISafetyNetHelper
import com.topjohnwu.magisk.view.MarkDownWindow import com.topjohnwu.magisk.view.MarkDownWindow
import com.topjohnwu.magisk.view.SafetyNet
import com.topjohnwu.magisk.view.SafetyNet.EXT_APK
import com.topjohnwu.magisk.view.dialogs.* import com.topjohnwu.magisk.view.dialogs.*
import com.topjohnwu.net.Networking import com.topjohnwu.net.Networking
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import dalvik.system.DexClassLoader
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import com.topjohnwu.magisk.ui.base.MagiskFragment as NewMagiskFragment import java.io.File
class MagiskFragment : NewMagiskFragment<HomeViewModel, FragmentMagiskBinding>(), class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
ISafetyNetHelper.Callback { ISafetyNetHelper.Callback {
override val layoutRes: Int = R.layout.fragment_magisk override val layoutRes: Int = R.layout.fragment_magisk
...@@ -83,7 +81,16 @@ class MagiskFragment : NewMagiskFragment<HomeViewModel, FragmentMagiskBinding>() ...@@ -83,7 +81,16 @@ class MagiskFragment : NewMagiskFragment<HomeViewModel, FragmentMagiskBinding>()
private fun updateSafetyNet(dieOnError: Boolean) { private fun updateSafetyNet(dieOnError: Boolean) {
try { try {
SafetyNet.dyRun(requireActivity(), this) val loader = DexClassLoader(EXT_APK.path, EXT_APK.parent, null,
ISafetyNetHelper::class.java.classLoader)
val clazz = loader.loadClass("com.topjohnwu.snet.Snet")
val helper = clazz.getMethod("newHelper",
Class::class.java, String::class.java, Activity::class.java, Any::class.java)
.invoke(null, ISafetyNetHelper::class.java, EXT_APK.path,
requireActivity(), this) as ISafetyNetHelper
if (helper.version < Const.SNET_EXT_VER)
throw Exception()
helper.attest()
} catch (e: Exception) { } catch (e: Exception) {
if (dieOnError) { if (dieOnError) {
viewModel.finishSafetyNetCheck(-1) viewModel.finishSafetyNetCheck(-1)
...@@ -94,5 +101,9 @@ class MagiskFragment : NewMagiskFragment<HomeViewModel, FragmentMagiskBinding>() ...@@ -94,5 +101,9 @@ class MagiskFragment : NewMagiskFragment<HomeViewModel, FragmentMagiskBinding>()
downloadSafetyNet(!dieOnError) downloadSafetyNet(!dieOnError)
} }
} }
companion object {
val EXT_APK = File("${App.self.filesDir.parent}/snet", "snet.apk")
}
} }
package com.topjohnwu.magisk.ui.surequest
import android.hardware.fingerprint.FingerprintManager
import android.os.CountDownTimer
import android.text.SpannableStringBuilder
import android.widget.Toast
import androidx.core.text.bold
import com.skoumal.teanity.viewevents.ViewEvent
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ActivitySuRequestBinding
import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.events.DieEvent
import com.topjohnwu.magisk.model.events.SuDialogEvent
import com.topjohnwu.magisk.ui.base.MagiskActivity
import com.topjohnwu.magisk.utils.FingerprintHelper
import com.topjohnwu.magisk.utils.feature.WIP
import com.topjohnwu.magisk.view.MagiskDialog
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import timber.log.Timber
import java.util.concurrent.TimeUnit.MILLISECONDS
import java.util.concurrent.TimeUnit.SECONDS
@WIP
open class _SuRequestActivity : MagiskActivity<_SuRequestViewModel, ActivitySuRequestBinding>() {
override val layoutRes: Int = R.layout.activity_su_request
override val viewModel: _SuRequestViewModel by viewModel {
parametersOf(intent, intent.action)
}
//private val timeoutPrefs: SharedPreferences by inject(SUTimeout)
private val canUseFingerprint get() = FingerprintHelper.useFingerprint()
private val countdown by lazy {
val seconds = Config.get<Int>(Config.Key.SU_REQUEST_TIMEOUT).toLong()
val millis = SECONDS.toMillis(seconds)
object : CountDownTimer(millis, 1000) {
override fun onFinish() {
viewModel.deny()
}
override fun onTick(millisUntilFinished: Long) {
dialog.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
Timber.e("Tick, tock")
title = "%s (%d)".format(
getString(R.string.deny),
MILLISECONDS.toSeconds(millisUntilFinished)
)
}
}
}
}
private var fingerprintHelper: SuFingerprint? = null
private lateinit var dialog: MagiskDialog
override fun onEventDispatched(event: ViewEvent) {
super.onEventDispatched(event)
when (event) {
is SuDialogEvent -> showDialog(event.policy)
is DieEvent -> finish()
}
}
override fun onBackPressed() {
if (::dialog.isInitialized && dialog.isShowing) {
return
}
super.onBackPressed()
}
override fun onDestroy() {
if (this::dialog.isInitialized && dialog.isShowing) {
dialog.dismiss()
}
fingerprintHelper?.cancel()
countdown.cancel()
super.onDestroy()
}
private fun showDialog(policy: Policy) {
val titleText = SpannableStringBuilder("Allow ")
.bold { append(policy.appName) }
.append(" to access superuser rights?")
val messageText = StringBuilder()
.appendln(policy.packageName)
.append(getString(R.string.su_warning))
dialog = MagiskDialog(this)
.applyIcon(policy.info.loadIcon(packageManager))
.applyTitle(titleText)
.applyMessage(messageText)
//.applyView()) {} //todo add a spinner
.cancellable(false)
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
titleRes = R.string.grant
onClick { viewModel.grant() }
if (canUseFingerprint) {
icon = R.drawable.ic_fingerprint
}
}
.applyButton(MagiskDialog.ButtonType.NEUTRAL) {
title = "%s %s".format(getString(R.string.grant), getString(R.string.once))
onClick { viewModel.grant(-1) }
}
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
titleRes = R.string.deny
onClick { viewModel.deny() }
}
.onDismiss { finish() }
.onShow {
startTimer().also { Timber.e("Starting timer") }
if (canUseFingerprint) {
startFingerprintQuery()
}
}
.reveal()
}
private fun startTimer() {
countdown.start()
}
private fun startFingerprintQuery() {
val result = runCatching {
fingerprintHelper = SuFingerprint().apply { authenticate() }
}
if (result.isFailure) {
dialog.applyButton(MagiskDialog.ButtonType.POSITIVE) {
icon = 0
}
}
}
private inner class SuFingerprint @Throws(Exception::class)
internal constructor() : FingerprintHelper() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
Toast.makeText(this@_SuRequestActivity, errString, Toast.LENGTH_LONG).show()
}
override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence) {
Toast.makeText(this@_SuRequestActivity, helpString, Toast.LENGTH_LONG).show()
}
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
viewModel.grant()
}
override fun onAuthenticationFailed() {
Toast.makeText(this@_SuRequestActivity, R.string.auth_fail, Toast.LENGTH_LONG).show()
}
}
companion object {
const val REQUEST = "request"
const val LOG = "log"
const val NOTIFY = "notify"
}
}
package com.topjohnwu.magisk.ui.surequest
import android.content.Intent
import android.content.pm.PackageManager
import com.skoumal.teanity.extensions.subscribeK
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.data.database.MagiskDB
import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.events.DieEvent
import com.topjohnwu.magisk.model.events.SuDialogEvent
import com.topjohnwu.magisk.ui.base.MagiskViewModel
import com.topjohnwu.magisk.utils.SuConnector
import com.topjohnwu.magisk.utils.SuLogger
import com.topjohnwu.magisk.utils.feature.WIP
import com.topjohnwu.magisk.utils.now
import io.reactivex.Single
import timber.log.Timber
import java.util.concurrent.TimeUnit.MILLISECONDS
import java.util.concurrent.TimeUnit.MINUTES
@WIP
class _SuRequestViewModel(
intent: Intent,
action: String,
private val packageManager: PackageManager,
private val database: MagiskDB
) : MagiskViewModel() {
private val connector: Single<SuConnector> = Single.fromCallable {
val socketName = intent.extras?.getString("socket") ?: let {
deny()
throw IllegalStateException("Socket is empty or null")
}
object : SuConnector(socketName) {
override fun onResponse() {
policy.subscribeK { out.writeInt(it.policy) } //this just might be incorrect, lol
}
} as SuConnector
}.cache()
private val policy: Single<Policy> = connector.map {
val bundle = it.readSocketInput() ?: throw IllegalStateException("Socket bundle is null")
val uid = bundle.getString("uid")?.toIntOrNull() ?: let {
deny()
throw IllegalStateException("UID is empty or null")
}
database.clearOutdated()
database.getPolicy(uid) ?: Policy(uid, packageManager)
}.cache()
init {
when (action) {
SuRequestActivity.LOG -> SuLogger.handleLogs(intent).also { die() }
SuRequestActivity.NOTIFY -> SuLogger.handleNotify(intent).also { die() }
SuRequestActivity.REQUEST -> process()
else -> back() // invalid action, should ignore
}
}
private fun process() {
policy.subscribeK(onError = ::deny) { process(it) }
}
private fun process(policy: Policy) {
if (policy.packageName == BuildConfig.APPLICATION_ID)
deny().also { return }
if (policy.policy != Policy.INTERACTIVE)
grant().also { return }
when (Config.get<Int>(Config.Key.SU_AUTO_RESPONSE)) {
Config.Value.SU_AUTO_DENY -> deny().also { return }
Config.Value.SU_AUTO_ALLOW -> grant().also { return }
}
requestDialog(policy)
}
fun deny(e: Throwable? = null) = updatePolicy(Policy.DENY, 0).also { Timber.e(e) }
fun grant(time: Long = 0) = updatePolicy(Policy.ALLOW, time)
private fun updatePolicy(action: Int, time: Long) {
fun finish(e: Throwable? = null) = die().also { Timber.e(e) }
policy
.map { it.policy = action; it }
.doOnSuccess {
if (time >= 0) {
it.until = if (time == 0L) {
0
} else {
MILLISECONDS.toSeconds(now) + MINUTES.toSeconds(time)
}
database.updatePolicy(it)
}
}
.flatMap { connector }
.subscribeK(onError = ::finish) {
it.response()
finish()
}
}
private fun requestDialog(policy: Policy) {
SuDialogEvent(policy).publish()
}
private fun die() = DieEvent().publish()
}
\ No newline at end of file
package com.topjohnwu.magisk.view;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.ISafetyNetHelper;
import com.topjohnwu.magisk.view.dialogs.CustomAlertDialog;
import com.topjohnwu.net.Networking;
import com.topjohnwu.superuser.Shell;
import java.io.File;
import androidx.annotation.StringRes;
import androidx.cardview.widget.CardView;
import butterknife.BindColor;
import butterknife.BindView;
import butterknife.OnClick;
import butterknife.Unbinder;
import dalvik.system.DexClassLoader;
public class SafetyNet implements ISafetyNetHelper.Callback {
public static final File EXT_APK =
new File(App.self.getFilesDir().getParent() + "/snet", "snet.apk");
/*@BindView(R.id.safetyNet_card) */ CardView safetyNetCard;
@BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon;
@BindView(R.id.safetyNet_status) TextView safetyNetStatusText;
@BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress;
@BindView(R.id.safetyNet_expand) ViewGroup expandLayout;
@BindView(R.id.cts_status_icon) ImageView ctsStatusIcon;
@BindView(R.id.cts_status) TextView ctsStatusText;
@BindView(R.id.basic_status_icon) ImageView basicStatusIcon;
@BindView(R.id.basic_status) TextView basicStatusText;
@BindColor(R.color.red500) int colorBad;
@BindColor(R.color.green500) int colorOK;
public Unbinder unbinder;
private final ExpandableViewHolder expandable;
public SafetyNet(View v) {
unbinder = new SafetyNet_ViewBinding(this, v);
expandable = new ExpandableViewHolder(expandLayout);
Context context = v.getContext();
safetyNetCard.setVisibility(hasGms(context) && Networking.checkNetworkStatus(context) ?
View.VISIBLE : View.GONE);
}
public static void dyRun(Activity activity, Object callback) throws Exception {
DexClassLoader loader = new DexClassLoader(EXT_APK.getPath(), EXT_APK.getParent(),
null, ISafetyNetHelper.class.getClassLoader());
Class<?> clazz = loader.loadClass("com.topjohnwu.snet.Snet");
ISafetyNetHelper helper = (ISafetyNetHelper) clazz.getMethod("newHelper",
Class.class, String.class, Activity.class, Object.class)
.invoke(null, ISafetyNetHelper.class, EXT_APK.getPath(), activity, callback);
if (helper.getVersion() < Const.SNET_EXT_VER)
throw new Exception();
helper.attest();
}
public void reset() {
safetyNetStatusText.setText(R.string.safetyNet_check_text);
expandable.setExpanded(false);
}
@Override
public void onResponse(int response) {
safetyNetProgress.setVisibility(View.GONE);
safetyNetRefreshIcon.setVisibility(View.VISIBLE);
if ((response & 0x0F) == 0) {
safetyNetStatusText.setText(R.string.safetyNet_check_success);
boolean b;
b = (response & ISafetyNetHelper.CTS_PASS) != 0;
ctsStatusText.setText("ctsProfile: " + b);
ctsStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel);
ctsStatusIcon.setColorFilter(b ? colorOK : colorBad);
b = (response & ISafetyNetHelper.BASIC_PASS) != 0;
basicStatusText.setText("basicIntegrity: " + b);
basicStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel);
basicStatusIcon.setColorFilter(b ? colorOK : colorBad);
expandable.expand();
} else {
@StringRes int resid;
switch (response) {
case ISafetyNetHelper.RESPONSE_ERR:
resid = R.string.safetyNet_res_invalid;
break;
case ISafetyNetHelper.CONNECTION_FAIL:
default:
resid = R.string.safetyNet_api_error;
break;
}
safetyNetStatusText.setText(resid);
}
}
@OnClick(R.id.safetyNet_refresh)
void safetyNet(View v) {
Runnable task = () -> {
safetyNetProgress.setVisibility(View.VISIBLE);
safetyNetRefreshIcon.setVisibility(View.INVISIBLE);
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
check((Activity) v.getContext());
expandable.collapse();
};
if (!EXT_APK.exists()) {
// Show dialog
new CustomAlertDialog(v.getContext())
.setTitle(R.string.proprietary_title)
.setMessage(R.string.proprietary_notice)
.setCancelable(true)
.setPositiveButton(R.string.yes, (d, i) -> task.run())
.setNegativeButton(R.string.no_thanks, null)
.show();
} else {
task.run();
}
}
private void check(Activity activity) {
try {
dyRun(activity, this);
} catch (Exception ignored) {
Shell.sh("rm -rf " + EXT_APK.getParent()).exec();
EXT_APK.getParentFile().mkdir();
Networking.get(Const.Url.SNET_URL).getAsFile(EXT_APK, f -> {
try {
dyRun(activity, this);
} catch (Exception e) {
e.printStackTrace();
onResponse(-1);
}
});
}
}
private boolean hasGms(Context context) {
PackageManager pm = context.getPackageManager();
PackageInfo info;
try {
info = pm.getPackageInfo("com.google.android.gms", 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return info.applicationInfo.enabled;
}
}
...@@ -4,18 +4,14 @@ import android.content.Context; ...@@ -4,18 +4,14 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import butterknife.BindView;
import com.topjohnwu.magisk.databinding.AlertDialogBinding;
public class CustomAlertDialog extends AlertDialog.Builder { public class CustomAlertDialog extends AlertDialog.Builder {
...@@ -24,32 +20,16 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -24,32 +20,16 @@ public class CustomAlertDialog extends AlertDialog.Builder {
private DialogInterface.OnClickListener neutralListener; private DialogInterface.OnClickListener neutralListener;
protected AlertDialog dialog; protected AlertDialog dialog;
protected ViewHolder vh; protected AlertDialogBinding binding;
public class ViewHolder {
@BindView(R.id.dialog_layout) public LinearLayout dialogLayout;
@BindView(R.id.button_panel) public LinearLayout buttons;
@BindView(R.id.message) public TextView messageView;
@BindView(R.id.negative) public Button negative;
@BindView(R.id.positive) public Button positive;
@BindView(R.id.neutral) public Button neutral;
ViewHolder(View v) {
new CustomAlertDialog$ViewHolder_ViewBinding(this, v);
messageView.setVisibility(View.GONE);
negative.setVisibility(View.GONE);
positive.setVisibility(View.GONE);
neutral.setVisibility(View.GONE);
buttons.setVisibility(View.GONE);
}
}
{ {
View v = LayoutInflater.from(getContext()).inflate(R.layout.alert_dialog, null); binding = AlertDialogBinding.inflate(LayoutInflater.from(getContext()));
vh = new ViewHolder(v); super.setView(binding.getRoot());
super.setView(v); binding.message.setVisibility(View.GONE);
binding.negative.setVisibility(View.GONE);
binding.positive.setVisibility(View.GONE);
binding.neutral.setVisibility(View.GONE);
binding.buttonPanel.setVisibility(View.GONE);
} }
public CustomAlertDialog(@NonNull Context context) { public CustomAlertDialog(@NonNull Context context) {
...@@ -60,10 +40,6 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -60,10 +40,6 @@ public class CustomAlertDialog extends AlertDialog.Builder {
super(context, themeResId); super(context, themeResId);
} }
public ViewHolder getViewHolder() {
return vh;
}
@Override @Override
public CustomAlertDialog setView(int layoutResId) { return this; } public CustomAlertDialog setView(int layoutResId) { return this; }
...@@ -72,8 +48,8 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -72,8 +48,8 @@ public class CustomAlertDialog extends AlertDialog.Builder {
@Override @Override
public CustomAlertDialog setMessage(@Nullable CharSequence message) { public CustomAlertDialog setMessage(@Nullable CharSequence message) {
vh.messageView.setVisibility(View.VISIBLE); binding.message.setVisibility(View.VISIBLE);
vh.messageView.setText(message); binding.message.setText(message);
return this; return this;
} }
...@@ -84,11 +60,11 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -84,11 +60,11 @@ public class CustomAlertDialog extends AlertDialog.Builder {
@Override @Override
public CustomAlertDialog setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) { public CustomAlertDialog setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) {
vh.buttons.setVisibility(View.VISIBLE); binding.buttonPanel.setVisibility(View.VISIBLE);
vh.positive.setVisibility(View.VISIBLE); binding.positive.setVisibility(View.VISIBLE);
vh.positive.setText(text); binding.positive.setText(text);
positiveListener = listener; positiveListener = listener;
vh.positive.setOnClickListener(v -> { binding.positive.setOnClickListener(v -> {
if (positiveListener != null) { if (positiveListener != null) {
positiveListener.onClick(dialog, DialogInterface.BUTTON_POSITIVE); positiveListener.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
} }
...@@ -104,11 +80,11 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -104,11 +80,11 @@ public class CustomAlertDialog extends AlertDialog.Builder {
@Override @Override
public CustomAlertDialog setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) { public CustomAlertDialog setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) {
vh.buttons.setVisibility(View.VISIBLE); binding.buttonPanel.setVisibility(View.VISIBLE);
vh.negative.setVisibility(View.VISIBLE); binding.negative.setVisibility(View.VISIBLE);
vh.negative.setText(text); binding.negative.setText(text);
negativeListener = listener; negativeListener = listener;
vh.negative.setOnClickListener(v -> { binding.negative.setOnClickListener(v -> {
if (negativeListener != null) { if (negativeListener != null) {
negativeListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE); negativeListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
} }
...@@ -124,11 +100,11 @@ public class CustomAlertDialog extends AlertDialog.Builder { ...@@ -124,11 +100,11 @@ public class CustomAlertDialog extends AlertDialog.Builder {
@Override @Override
public CustomAlertDialog setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) { public CustomAlertDialog setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) {
vh.buttons.setVisibility(View.VISIBLE); binding.buttonPanel.setVisibility(View.VISIBLE);
vh.neutral.setVisibility(View.VISIBLE); binding.neutral.setVisibility(View.VISIBLE);
vh.neutral.setText(text); binding.neutral.setText(text);
neutralListener = listener; neutralListener = listener;
vh.neutral.setOnClickListener(v -> { binding.neutral.setOnClickListener(v -> {
if (neutralListener != null) { if (neutralListener != null) {
neutralListener.onClick(dialog, DialogInterface.BUTTON_NEUTRAL); neutralListener.onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
} }
......
...@@ -36,9 +36,9 @@ public class FingerprintAuthDialog extends CustomAlertDialog { ...@@ -36,9 +36,9 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint}); TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint});
fingerprint.setTint(ta.getColor(0, Color.GRAY)); fingerprint.setTint(ta.getColor(0, Color.GRAY));
ta.recycle(); ta.recycle();
vh.messageView.setCompoundDrawables(null, null, null, fingerprint); binding.message.setCompoundDrawables(null, null, null, fingerprint);
vh.messageView.setCompoundDrawablePadding(Utils.dpInPx(20)); binding.message.setCompoundDrawablePadding(Utils.dpInPx(20));
vh.messageView.setGravity(Gravity.CENTER); binding.message.setGravity(Gravity.CENTER);
setMessage(R.string.auth_fingerprint); setMessage(R.string.auth_fingerprint);
setNegativeButton(R.string.close, (d, w) -> { setNegativeButton(R.string.close, (d, w) -> {
helper.cancel(); helper.cancel();
...@@ -81,20 +81,20 @@ public class FingerprintAuthDialog extends CustomAlertDialog { ...@@ -81,20 +81,20 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
@Override @Override
public void onAuthenticationError(int errorCode, CharSequence errString) { public void onAuthenticationError(int errorCode, CharSequence errString) {
vh.messageView.setTextColor(Color.RED); binding.message.setTextColor(Color.RED);
vh.messageView.setText(errString); binding.message.setText(errString);
} }
@Override @Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) { public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
vh.messageView.setTextColor(Color.RED); binding.message.setTextColor(Color.RED);
vh.messageView.setText(helpString); binding.message.setText(helpString);
} }
@Override @Override
public void onAuthenticationFailed() { public void onAuthenticationFailed() {
vh.messageView.setTextColor(Color.RED); binding.message.setTextColor(Color.RED);
vh.messageView.setText(R.string.auth_fail); binding.message.setText(R.string.auth_fail);
} }
@Override @Override
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/dialog_layout" android:id="@+id/dialog_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -60,4 +61,5 @@ ...@@ -60,4 +61,5 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</layout>
# 7.1.1 # v7.1.2
- Fix a bug that causes some modules using new format not showing up - Support patching Samsung AP firmware
- Much better module downloading mechanism
# v7.1.0
- Support the new module format
- Support per-application component granularity MagiskHide targets (only on v19+)
- Ask for fingerprint before deleting rules if enabled
- Fix the bug that causes repackaging to lose settings
- Several UI fixes
...@@ -160,7 +160,7 @@ ...@@ -160,7 +160,7 @@
<string name="auto_response">Automatická odezva</string> <string name="auto_response">Automatická odezva</string>
<string name="request_timeout">Časový limit požadavku</string> <string name="request_timeout">Časový limit požadavku</string>
<string name="superuser_notification">Oznámení Superuser</string> <string name="superuser_notification">Oznámení Superuser</string>
<string name="request_timeout_summary">%1$s sekund</string> <string name="request_timeout_summary">%1$d sekund</string>
<string name="settings_su_reauth_title">Opětovné ověření po aktualizaci</string> <string name="settings_su_reauth_title">Opětovné ověření po aktualizaci</string>
<string name="settings_su_reauth_summary">Opětovné ověření oprávnění Superuser po aktualizaci aplikace</string> <string name="settings_su_reauth_summary">Opětovné ověření oprávnění Superuser po aktualizaci aplikace</string>
<string name="settings_su_fingerprint_title">Povolit ověřování otisky prstů</string> <string name="settings_su_fingerprint_title">Povolit ověřování otisky prstů</string>
......
This diff is collapsed.
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<!--About Activity--> <!--About Activity-->
<string name="app_changelog">Список изменений</string> <string name="app_changelog">Список изменений</string>
<string name="translators">Displax [4PDA], igor-dyatlov, zertyuiop</string> <string name="translators" />
<string name="app_translators">Переводчики</string> <string name="app_translators">Переводчики</string>
<!-- System Components, Notifications --> <!-- System Components, Notifications -->
...@@ -74,6 +74,18 @@ ...@@ -74,6 +74,18 @@
<string name="magisk_update_title">Доступно обновление Magisk!</string> <string name="magisk_update_title">Доступно обновление Magisk!</string>
<string name="manager_update_title">Доступно обновление Magisk Manager!</string> <string name="manager_update_title">Доступно обновление Magisk Manager!</string>
<!-- Installation -->
<string name="manager_download_install">Нажмите, чтобы загрузить и установить.</string>
<string name="download_zip_only">Загрузка установочного ZIP</string>
<string name="direct_install">Прямая установка (Рекомендуется)</string>
<string name="install_inactive_slot">Установка в неактивный слот (После OTA)</string>
<string name="install_inactive_slot_msg">Ваше устройство будет принудительно перезагружено в неактивный слот!\nИспользуйте эту опцию только при установке OTA.\nПродолжить?</string>
<string name="select_method">Выбор способа</string>
<string name="setup_title">Дополнительная установка</string>
<string name="select_patch_file">Выбрать и пропатчить файл</string>
<string name="patch_file_msg">Выберите образ ядра (*.img) или архив ODIN (*.tar)</string>
<string name="reboot_delay_toast">Перезагрузка через 5 секунд…</string>
<!--Toasts, Dialogs--> <!--Toasts, Dialogs-->
<string name="close">Закрыть</string> <string name="close">Закрыть</string>
<string name="repo_install_title">Установка %1$s</string> <string name="repo_install_title">Установка %1$s</string>
...@@ -84,19 +96,14 @@ ...@@ -84,19 +96,14 @@
<string name="release_notes">О версии</string> <string name="release_notes">О версии</string>
<string name="repo_cache_cleared">Кэш репозитория очищен</string> <string name="repo_cache_cleared">Кэш репозитория очищен</string>
<string name="internal_storage">Расположение архива:\n[Внутреннее Хранилище]%1$s</string> <string name="internal_storage">Расположение архива:\n[Внутреннее Хранилище]%1$s</string>
<string name="manager_download_install">Нажмите, чтобы загрузить и установить.</string>
<string name="dtbo_patched_title">DTBO пропатчен!</string> <string name="dtbo_patched_title">DTBO пропатчен!</string>
<string name="dtbo_patched_reboot">Magisk Manager пропатчил dtbo.img. Перезагрузите устройство.</string> <string name="dtbo_patched_reboot">Magisk Manager пропатчил dtbo.img. Перезагрузите устройство.</string>
<string name="flashing">Прошивка</string> <string name="flashing">Прошивка</string>
<string name="hide_manager_title">Маскировка Magisk Manager…</string> <string name="hide_manager_title">Маскировка Magisk Manager…</string>
<string name="hide_manager_fail_toast">Не удалось замаскировать Magisk Manager</string> <string name="hide_manager_fail_toast">Не удалось замаскировать Magisk Manager</string>
<string name="open_link_failed_toast">Не найдено приложений для открытия ссылки.</string> <string name="open_link_failed_toast">Не найдено приложений для открытия ссылки.</string>
<string name="download_zip_only">Загрузка установочного ZIP</string>
<string name="direct_install">Прямая установка (Рекомендуется)</string>
<string name="install_inactive_slot">Установка в неактивный слот (После OTA)</string>
<string name="warning">Предупреждение</string> <string name="warning">Предупреждение</string>
<string name="install_inactive_slot_msg">Ваше устройство будет принудительно перезагружено в неактивный слот!\nИспользуйте эту опцию только при установке OTA.\nПродолжить?</string>
<string name="select_method">Выбор способа</string>
<string name="complete_uninstall">Полное удаление</string> <string name="complete_uninstall">Полное удаление</string>
<string name="restore_img">Восстановить разделы</string> <string name="restore_img">Восстановить разделы</string>
<string name="restore_img_msg">Восстановление…</string> <string name="restore_img_msg">Восстановление…</string>
...@@ -107,7 +114,6 @@ ...@@ -107,7 +114,6 @@
<string name="setup_fail">Ошибка установки.</string> <string name="setup_fail">Ошибка установки.</string>
<string name="env_fix_title">Требуется дополнительная установка</string> <string name="env_fix_title">Требуется дополнительная установка</string>
<string name="env_fix_msg">Вашему устройству требуется дополнительная установка Magisk для корректной работы. Будет загружен установочный ZIP Magisk, продолжить?</string> <string name="env_fix_msg">Вашему устройству требуется дополнительная установка Magisk для корректной работы. Будет загружен установочный ZIP Magisk, продолжить?</string>
<string name="setup_title">Дополнительная установка</string>
<string name="setup_msg">Настройка рабочей среды…</string> <string name="setup_msg">Настройка рабочей среды…</string>
<string name="downloading_toast">Загрузка %1$s</string> <string name="downloading_toast">Загрузка %1$s</string>
<string name="no_rw_storage">Требуется разрешение на запись во внешнее хранилище.</string> <string name="no_rw_storage">Требуется разрешение на запись во внешнее хранилище.</string>
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<!--About Activity--> <!--About Activity-->
<string name="app_changelog">Uygulama değişiklikleri</string> <string name="app_changelog">Uygulama değişiklikleri</string>
<string name="translators">Mevlüt TOPÇU - Muhammet Emin TURGUT</string> <string name="translators">Mevlüt TOPÇU - Muhammet Emin TURGUT - XORCAN</string>
<string name="app_translators">Çevirmenler</string> <string name="app_translators">Çevirmenler</string>
<!-- System Components, Notifications --> <!-- System Components, Notifications -->
...@@ -74,6 +74,18 @@ ...@@ -74,6 +74,18 @@
<string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string> <string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string>
<string name="manager_update_title">Yeni Magisk Manager Güncellemesi Mevcut!</string> <string name="manager_update_title">Yeni Magisk Manager Güncellemesi Mevcut!</string>
<!-- Installation -->
<string name="manager_download_install">İndirmek ve yüklemek için tıklayın.</string>
<string name="download_zip_only">Sadece Zip\'i indir</string>
<string name="direct_install">Doğrudan kurulum (Önerilen)</string>
<string name="install_inactive_slot">İnaktif slota yükle (OTA\'dan sonra)</string>
<string name="install_inactive_slot_msg">Cihazınız, yeniden başlatmanın ardından inaktif slota ön yüklemek için ZORUNLU olacaktır!\nBu seçeneği yalnızca OTA yapıldıktan sonra kullanın.\nDevam?</string>
<string name="select_method">Yöntem seçin</string>
<string name="setup_title">Ek kurulum</string>
<string name="select_patch_file">Dosya seçin ve yamalayın</string>
<string name="patch_file_msg">Bir raw yansısı (*.img) ya da ODIN tarfile dosyası (*.tar) seçin</string>
<string name="reboot_delay_toast">5 saniye içinde yeniden başlatılacak...</string>
<!--Toasts, Dialogs--> <!--Toasts, Dialogs-->
<string name="close">Kapat</string> <string name="close">Kapat</string>
<string name="repo_install_title">%1$s yükle</string> <string name="repo_install_title">%1$s yükle</string>
...@@ -84,19 +96,14 @@ ...@@ -84,19 +96,14 @@
<string name="release_notes">Sürüm notları</string> <string name="release_notes">Sürüm notları</string>
<string name="repo_cache_cleared">Repo önbelleği temizlendi</string> <string name="repo_cache_cleared">Repo önbelleği temizlendi</string>
<string name="internal_storage">Zip şuraya depolandı:\n[Dahili Hafıza]%1$s</string> <string name="internal_storage">Zip şuraya depolandı:\n[Dahili Hafıza]%1$s</string>
<string name="manager_download_install">İndirmek ve yüklemek için dokunun</string>
<string name="dtbo_patched_title">DTBO yamalandı!</string> <string name="dtbo_patched_title">DTBO yamalandı!</string>
<string name="dtbo_patched_reboot">Magisk Manager dtbo.img\'yi yamaladı, lütfen yeniden başlatın</string> <string name="dtbo_patched_reboot">Magisk Manager dtbo.img\'yi yamaladı, lütfen yeniden başlatın</string>
<string name="flashing">Yükleniyor</string> <string name="flashing">Yükleniyor</string>
<string name="hide_manager_title">Magisk Manager Gizleniyor…</string> <string name="hide_manager_title">Magisk Manager Gizleniyor…</string>
<string name="hide_manager_fail_toast">Magisk Manager\'ı Gizleme başarısız oldu…</string> <string name="hide_manager_fail_toast">Magisk Manager\'ı Gizleme başarısız oldu…</string>
<string name="open_link_failed_toast">Bağlantıyı açabilecek uygulama bulunamadı…</string> <string name="open_link_failed_toast">Bağlantıyı açabilecek uygulama bulunamadı…</string>
<string name="download_zip_only">Yalnızca Zip Dosyasını İndir</string>
<string name="direct_install">Doğrudan Yükle (Önerilen)</string>
<string name="install_inactive_slot">Pasif yuvaya yükle (OTA\'dan sonra)</string>
<string name="warning">Uyarı</string> <string name="warning">Uyarı</string>
<string name="install_inactive_slot_msg">Cihazınız yeniden başlatıldıktan sonra mevcut pasif yuvaya ZORLA önyüklenecek!\nBu seçeneği yalnızca OTA tamamlandıktan sonra kullanın.\nDevam mı?</string>
<string name="select_method">Yöntem Seçin</string>
<string name="complete_uninstall">Tamamen Kaldır</string> <string name="complete_uninstall">Tamamen Kaldır</string>
<string name="restore_img">Önyükleme İmajını Geri Yükle</string> <string name="restore_img">Önyükleme İmajını Geri Yükle</string>
<string name="restore_img_msg">Geri Yükleniyor…</string> <string name="restore_img_msg">Geri Yükleniyor…</string>
...@@ -106,8 +113,7 @@ ...@@ -106,8 +113,7 @@
<string name="proprietary_notice">Magisk Yöneticisi, FOSS olduğundan Google\'ın tescilli olduğu SafetyNet API kodunu içermez.\n\nMagisk Manager\'ın SafetyNet kontrolü için bir uzantıyı (GoogleApiClient içeriyor) indirmesine izin veriyor musunuz?</string> <string name="proprietary_notice">Magisk Yöneticisi, FOSS olduğundan Google\'ın tescilli olduğu SafetyNet API kodunu içermez.\n\nMagisk Manager\'ın SafetyNet kontrolü için bir uzantıyı (GoogleApiClient içeriyor) indirmesine izin veriyor musunuz?</string>
<string name="setup_fail">Kurulum başarısız</string> <string name="setup_fail">Kurulum başarısız</string>
<string name="env_fix_title">Ek Kurulum Gerekli</string> <string name="env_fix_title">Ek Kurulum Gerekli</string>
   <string name="env_fix_msg">Cihazınızın Magisk\'in düzgün çalışması için ek kuruluma ihtiyacı var. Bu Magisk kurulum zip dosyasını indirecektir, şimdi devam etmek istiyor musunuz?</string> <string name="env_fix_msg">Cihazınızın Magisk\'in düzgün çalışması için ek kuruluma ihtiyacı var. Bu Magisk kurulum zip dosyasını indirecektir, şimdi devam etmek istiyor musunuz?</string>
<string name="setup_title">Ek Kurulum</string>
<string name="setup_msg">Ortam kurulumu çalışıyor…</string> <string name="setup_msg">Ortam kurulumu çalışıyor…</string>
<string name="downloading_toast">%1$s indiriliyor</string> <string name="downloading_toast">%1$s indiriliyor</string>
<string name="no_rw_storage">Bu özellik harici depolamaya yazma izni olmadan çalışmaz.</string> <string name="no_rw_storage">Bu özellik harici depolamaya yazma izni olmadan çalışmaz.</string>
...@@ -127,7 +133,7 @@ ...@@ -127,7 +133,7 @@
<string name="system_default">(Sistem Varsayılanı)</string> <string name="system_default">(Sistem Varsayılanı)</string>
<string name="settings_update">Güncelleme Ayarları</string> <string name="settings_update">Güncelleme Ayarları</string>
<string name="settings_check_update_title">Güncellemeleri denetle</string> <string name="settings_check_update_title">Güncellemeleri denetle</string>
   <string name="settings_check_update_summary">Düzenli aralıklarla arka planda güncellemeleri denetle</string> <string name="settings_check_update_summary">Düzenli aralıklarla arka planda güncellemeleri denetle</string>
<string name="settings_update_channel_title">Güncelleme Kanalı</string> <string name="settings_update_channel_title">Güncelleme Kanalı</string>
<string name="settings_update_stable">Kararlı</string> <string name="settings_update_stable">Kararlı</string>
<string name="settings_update_beta">Beta</string> <string name="settings_update_beta">Beta</string>
...@@ -188,10 +194,10 @@ ...@@ -188,10 +194,10 @@
<string name="su_warning">Cihazınıza tam erişim izni verir.\nEmin değilseniz, reddedin!</string> <string name="su_warning">Cihazınıza tam erişim izni verir.\nEmin değilseniz, reddedin!</string>
<string name="forever">Daima</string> <string name="forever">Daima</string>
<string name="once">Bir kere</string> <string name="once">Bir kere</string>
   <string name="tenmin">10 dakika</string> <string name="tenmin">10 dakika</string>
   <string name="twentymin">20 dakika</string> <string name="twentymin">20 dakika</string>
   <string name="thirtymin">30 dakika</string> <string name="thirtymin">30 dakika</string>
   <string name="sixtymin">60 dakika</string> <string name="sixtymin">60 dakika</string>
<string name="su_allow_toast">%1$s için yetkili kullanıcı hakları verildi</string> <string name="su_allow_toast">%1$s için yetkili kullanıcı hakları verildi</string>
<string name="su_deny_toast">%1$s için yetkili kullanıcı hakları reddedildi</string> <string name="su_deny_toast">%1$s için yetkili kullanıcı hakları reddedildi</string>
<string name="no_apps_found">Hiçbir uygulama bulunamadı</string> <string name="no_apps_found">Hiçbir uygulama bulunamadı</string>
......
...@@ -12,11 +12,12 @@ buildscript { ...@@ -12,11 +12,12 @@ buildscript {
google() google()
jcenter() jcenter()
maven { url 'http://storage.googleapis.com/r8-releases/raw' } maven { url 'http://storage.googleapis.com/r8-releases/raw' }
maven { url 'https://kotlin.bintray.com/kotlinx' }
} }
dependencies { dependencies {
classpath 'com.android.tools:r8:1.4.79' classpath 'com.android.tools:r8:1.4.93'
classpath 'com.android.tools.build:gradle:3.5.0-alpha13' classpath 'com.android.tools.build:gradle:3.5.0-alpha13'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.30" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.31"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
......
# Magisk Documentations # Magisk Documentations
(Updated on 2019.3.28) (Updated on 2019.5.1)
- [Installation](install.md) - [Installation](install.md)
- [Prerequisite](install.md#prerequisite) - [Prerequisite](install.md#prerequisite)
- [Custom Recovery](install.md#custom-recovery) - [Custom Recovery](install.md#custom-recovery)
- [Boot Image Patching](install.md#boot-image-patching) - [Boot Image Patching](install.md#boot-image-patching)
- [Samsung (System-as-root)](install.md#samsung-system-as-root)
- [Huawei](install.md#huawei) - [Huawei](install.md#huawei)
- [Tutorials](tutorials.md) - [Tutorials](tutorials.md)
- [OTA Installation](tutorials.md#ota-installation) - [OTA Installation](tutorials.md#ota-installation)
......
This diff is collapsed.
...@@ -609,10 +609,8 @@ void MagiskInit::setup_rootfs() { ...@@ -609,10 +609,8 @@ void MagiskInit::setup_rootfs() {
sprintf(path, "/sbin/%s", applet_names[i]); sprintf(path, "/sbin/%s", applet_names[i]);
xsymlink("/sbin/magisk", path); xsymlink("/sbin/magisk", path);
} }
for (int i = 0; init_applet[i]; ++i) { xsymlink("/sbin/magiskinit", "/sbin/magiskpolicy");
sprintf(path, "/sbin/%s", init_applet[i]); xsymlink("/sbin/magiskinit", "/sbin/supolicy");
xsymlink("/sbin/magiskinit", path);
}
close(rootdir); close(rootdir);
close(sbin); close(sbin);
......
<resources>
<!--Not translatable-->
<string name="app_name" translatable="false">Magisk Manager</string>
<string name="re_app_name" translatable="false">Manager</string>
<string name="magisk" translatable="false">Magisk</string>
<string name="magiskhide" translatable="false">Magisk Hide</string>
<string name="empty" translatable="false"/>
<!--Used in both stub and full app-->
<string name="no_thanks">Не, благодарам</string>
<string name="yes">Да</string>
<string name="ok">ОК</string>
</resources>
<resources> <resources>
<string name="no_thanks">Hayır teşekkürler</string> <string name="no_thanks">Hayır, teşekkürler</string>
<string name="yes">Evet</string> <string name="yes">Evet</string>
<string name="ok">Tamam</string> <string name="ok">Tamam</string>
</resources> </resources>
<resources>
<string name="upgrade_msg">Надградете до целосната верзија на Magisk Manager за да го завршите поставувањето. Преземете и инсталирајте?</string>
<string name="no_internet_msg">Ве молиме поврзете се на интернет бидејќи е потребна надградба на целосната верзија на Magisk Manager.</string>
</resources>
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