Implement stub Magisk Manager

This commit is contained in:
topjohnwu 2018-06-02 22:00:52 +08:00
parent 7b9ddc9b3b
commit 48085b5573
91 changed files with 891 additions and 678 deletions

View File

@ -52,7 +52,8 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
fullImplementation project(':utils')
implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:support-core-utils:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:preference-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:recyclerview-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:cardview-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:design:${rootProject.ext.supportLibVersion}"

View File

@ -3,7 +3,6 @@
package="com.topjohnwu.magisk">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<application

View File

@ -24,6 +24,7 @@ import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.ShowUI;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
@ -271,7 +272,7 @@ public class MagiskFragment extends Fragment
|| mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
install();
} else if (mm.remoteMagiskVersionCode >= Const.MAGISK_VER.FIX_ENV &&
!Utils.cmdResult("env_check")) {
!RootUtils.cmdResult("env_check")) {
ShowUI.envFixDialog(getActivity());
}
}

View File

@ -89,7 +89,7 @@ public class MagiskLogFragment extends Fragment {
return true;
case R.id.menu_save:
Utils.runWithPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
() -> new LogManager().save());
return true;
case R.id.menu_clear:

View File

@ -8,21 +8,28 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.widget.Toast;
import android.util.Xml;
import com.topjohnwu.magisk.components.Application;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.BusyBox;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.io.SuFile;
import com.topjohnwu.superuser.io.SuFileInputStream;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
@ -32,10 +39,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
public class MagiskManager extends Shell.ContainerApp {
// Global weak reference to self
private static WeakReference<MagiskManager> weakSelf;
public class MagiskManager extends Application implements Shell.Container {
// Topics
public final Topic magiskHideDone = new Topic();
@ -65,10 +69,6 @@ public class MagiskManager extends Shell.ContainerApp {
public Map<String, Module> moduleMap;
public List<Locale> locales;
// Configurations
public static Locale locale;
public static Locale defaultLocale;
public boolean magiskHide;
public boolean isDarkTheme;
public int suRequestTimeout;
@ -87,12 +87,23 @@ public class MagiskManager extends Shell.ContainerApp {
public SharedPreferences prefs;
public MagiskDatabaseHelper mDB;
public RepoDatabaseHelper repoDB;
public Runnable permissionGrantCallback = null;
private static Handler mHandler = new Handler();
private volatile Shell mShell;
public MagiskManager() {
weakSelf = new WeakReference<>(this);
Shell.setContainer(this);
}
@Nullable
@Override
public Shell getShell() {
return mShell;
}
@Override
public void setShell(@Nullable Shell shell) {
mShell = shell;
}
@Override
@ -137,17 +148,16 @@ public class MagiskManager extends Shell.ContainerApp {
String pkg = mDB.getStrings(Const.Key.SU_REQUESTER, Const.ORIG_PKG_NAME);
if (getPackageName().equals(Const.ORIG_PKG_NAME) && !pkg.equals(Const.ORIG_PKG_NAME)) {
mDB.setStrings(Const.Key.SU_REQUESTER, null);
Utils.uninstallPkg(pkg);
RootUtils.uninstallPkg(pkg);
mDB = MagiskDatabaseHelper.getInstance(this);
}
defaultLocale = Locale.getDefault();
setLocale();
loadConfig();
}
public static MagiskManager get() {
return weakSelf.get();
return (MagiskManager) weakSelf.get();
}
public void setLocale() {
@ -183,7 +193,7 @@ public class MagiskManager extends Shell.ContainerApp {
prefs.edit()
.putBoolean(Const.Key.DARK_THEME, isDarkTheme)
.putBoolean(Const.Key.MAGISKHIDE, magiskHide)
.putBoolean(Const.Key.HOSTS, Const.MAGISK_HOST_FILE().exists())
.putBoolean(Const.Key.HOSTS, Const.MAGISK_HOST_FILE.exists())
.putBoolean(Const.Key.COREONLY, Const.MAGISK_DISABLE_FILE.exists())
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(suRequestTimeout))
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(suResponseType))
@ -199,36 +209,24 @@ public class MagiskManager extends Shell.ContainerApp {
.apply();
}
public static void toast(CharSequence msg, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), msg, duration).show());
}
public static void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show());
}
public void loadMagiskInfo() {
try {
magiskVersionString = Utils.cmd("magisk -v").split(":")[0];
magiskVersionCode = Integer.parseInt(Utils.cmd("magisk -V"));
String s = Utils.cmd((magiskVersionCode >= Const.MAGISK_VER.RESETPROP_PERSIST ? "resetprop -p " : "getprop ")
magiskVersionString = RootUtils.cmd("magisk -v").split(":")[0];
magiskVersionCode = Integer.parseInt(RootUtils.cmd("magisk -V"));
String s = RootUtils.cmd((magiskVersionCode >= Const.MAGISK_VER.RESETPROP_PERSIST ? "resetprop -p " : "getprop ")
+ Const.MAGISKHIDE_PROP);
magiskHide = s == null || Integer.parseInt(s) != 0;
} catch (Exception ignored) {}
bootBlock = Utils.cmd("echo \"$BOOTIMAGE\"");
bootBlock = RootUtils.cmd("echo \"$BOOTIMAGE\"");
}
public void getDefaultInstallFlags() {
keepVerity = Boolean.parseBoolean(Utils.cmd("getvar KEEPVERITY; echo $KEEPVERITY")) ||
Utils.cmd("echo \"$DTBOIMAGE\"") != null;
keepVerity = Boolean.parseBoolean(RootUtils.cmd("getvar KEEPVERITY; echo $KEEPVERITY")) ||
RootUtils.cmd("echo \"$DTBOIMAGE\"") != null;
keepEnc = Boolean.parseBoolean(Utils.cmd("getvar KEEPFORCEENCRYPT; echo $KEEPFORCEENCRYPT")) ||
TextUtils.equals("encrypted", Utils.cmd("getprop ro.crypto.state"));
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
keepEnc = Boolean.parseBoolean(RootUtils.cmd("getvar KEEPFORCEENCRYPT; echo $KEEPFORCEENCRYPT")) ||
TextUtils.equals("encrypted", RootUtils.cmd("getprop ro.crypto.state"));
}
public void setupUpdateCheck() {
@ -249,4 +247,72 @@ public class MagiskManager extends Shell.ContainerApp {
scheduler.cancel(Const.UPDATE_SERVICE_VER);
}
}
public void dumpPrefs() {
// Flush prefs to disk
prefs.edit().commit();
File xml = new File(getFilesDir().getParent() + "/shared_prefs",
getPackageName() + "_preferences.xml");
Shell.Sync.su(Utils.fmt("for usr in /data/user/*; do cat %s > ${usr}/%s; done", xml, Const.MANAGER_CONFIGS));
}
public void loadPrefs() {
SuFile config = new SuFile(Utils.fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true);
if (config.exists()) {
SharedPreferences.Editor editor = prefs.edit();
try {
SuFileInputStream is = new SuFileInputStream(config);
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, "UTF-8");
parser.nextTag();
parser.require(XmlPullParser.START_TAG, null, "map");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG)
continue;
String key = parser.getAttributeValue(null, "name");
String value = parser.getAttributeValue(null, "value");
switch (parser.getName()) {
case "string":
parser.require(XmlPullParser.START_TAG, null, "string");
editor.putString(key, parser.nextText());
parser.require(XmlPullParser.END_TAG, null, "string");
break;
case "boolean":
parser.require(XmlPullParser.START_TAG, null, "boolean");
editor.putBoolean(key, Boolean.parseBoolean(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "boolean");
break;
case "int":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putInt(key, Integer.parseInt(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
case "long":
parser.require(XmlPullParser.START_TAG, null, "long");
editor.putLong(key, Long.parseLong(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "long");
break;
case "float":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putFloat(key, Float.parseFloat(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
default:
parser.next();
}
}
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
editor.remove(Const.Key.ETAG_KEY);
editor.apply();
loadConfig();
config.delete();
}
}
}

View File

@ -40,7 +40,8 @@ public class ModulesFragment extends Fragment implements Topic.Subscriber {
@BindView(R.id.empty_rv) TextView emptyRv;
@OnClick(R.id.fab)
public void selectFile() {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
Utils.runWithPermission(getActivity(),
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },() -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/zip");
startActivityForResult(intent, Const.ID.FETCH_ZIP);

View File

@ -5,17 +5,18 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
@ -63,7 +64,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
setFloating();
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(R.id.container, new SettingsFragment()).commit();
getSupportFragmentManager().beginTransaction().add(R.id.container, new SettingsFragment()).commit();
}
}
@ -78,7 +79,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
return new Topic[] { getMagiskManager().reloadActivity };
}
public static class SettingsFragment extends PreferenceFragment
public static class SettingsFragment extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener, Topic.Subscriber {
private SharedPreferences prefs;
@ -90,9 +91,8 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
private PreferenceCategory generalCatagory;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.app_settings);
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.app_settings, rootKey);
mm = Utils.getMagiskManager(getActivity());
prefs = mm.prefs;
prefScreen = getPreferenceScreen();
@ -166,7 +166,8 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
} else {
if (Utils.checkNetworkStatus()) {
restoreManager.setOnPreferenceClickListener((pref) -> {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
Utils.runWithPermission(getActivity(),
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(Const.Key.INTENT_SET_LINK, mm.managerLink);
intent.putExtra(Const.Key.INTENT_SET_FILENAME,
@ -224,17 +225,17 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
}
@Override
public void onResume() {
super.onResume();
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
prefs.registerOnSharedPreferenceChangeListener(this);
subscribeTopics();
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onPause() {
public void onDestroyView() {
prefs.unregisterOnSharedPreferenceChangeListener(this);
unsubscribeTopics();
super.onPause();
super.onDestroyView();
}
@Override
@ -244,7 +245,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
case Const.Key.DARK_THEME:
mm.isDarkTheme = prefs.getBoolean(key, false);
mm.reloadActivity.publish(false);
break;
return;
case Const.Key.COREONLY:
if (prefs.getBoolean(key, false)) {
try {
@ -265,12 +266,12 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
case Const.Key.HOSTS:
if (prefs.getBoolean(key, false)) {
Shell.Async.su(
"cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE(),
"mount -o bind " + Const.MAGISK_HOST_FILE() + " /system/etc/hosts");
"cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE,
"mount -o bind " + Const.MAGISK_HOST_FILE + " /system/etc/hosts");
} else {
Shell.Async.su(
"umount -l /system/etc/hosts",
"rm -f " + Const.MAGISK_HOST_FILE());
"rm -f " + Const.MAGISK_HOST_FILE);
}
break;
case Const.Key.ROOT_ACCESS:

View File

@ -14,6 +14,7 @@ import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
@ -23,12 +24,13 @@ public class SplashActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RootUtils.init();
MagiskManager mm = getMagiskManager();
mm.repoDB = new RepoDatabaseHelper(this);
mm.loadMagiskInfo();
mm.getDefaultInstallFlags();
Utils.loadPrefs();
mm.loadPrefs();
// Dynamic detect all locales
new LoadLocale().exec();
@ -59,7 +61,7 @@ public class SplashActivity extends Activity {
// Fire asynctasks
loadModuleTask.exec();
// Check dtbo status
Utils.patchDTBO();
RootUtils.patchDTBO();
}
// Write back default values

View File

@ -7,7 +7,9 @@ import android.view.View;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import com.topjohnwu.superuser.Shell;
@ -39,7 +41,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
private boolean unzipAndCheck() throws Exception {
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true);
String s = Utils.cmd("head -n 1 " + new File(mCachedFile.getParentFile(), "updater-script"));
String s = RootUtils.cmd("head -n 1 " + new File(mCachedFile.getParentFile(), "updater-script"));
return s != null && s.contains("#MAGISK");
}
@ -93,7 +95,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
switch (result) {
case -1:
console.add("! Installation failed");
Utils.showUriSnack(getActivity(), mUri);
SnackbarMaker.showUri(getActivity(), mUri);
break;
case 0:
console.add("! This zip is not a Magisk Module!");

View File

@ -7,7 +7,7 @@ import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.ZipUtils;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
@ -136,8 +136,8 @@ public class HideManager extends ParallelTask<Void, Void, Boolean> {
repack.delete();
mm.mDB.setStrings(Const.Key.SU_REQUESTER, pkg);
Utils.dumpPrefs();
Utils.uninstallPkg(Const.ORIG_PKG_NAME);
mm.dumpPrefs();
RootUtils.uninstallPkg(Const.ORIG_PKG_NAME);
return true;
}

View File

@ -13,6 +13,7 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.TarEntry;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import com.topjohnwu.superuser.Shell;
@ -147,7 +148,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
case DIRECT_MODE:
console.add("- Patch boot/ramdisk image: " + mBootLocation);
if (mm.remoteMagiskVersionCode >= 1463) {
highCompression = Integer.parseInt(Utils.cmd(Utils.fmt(
highCompression = Integer.parseInt(RootUtils.cmd(Utils.fmt(
"%s/magiskboot --parse %s; echo $?",
install, mBootLocation))) == 2;
if (highCompression)

View File

@ -11,7 +11,7 @@ import java.util.List;
public class LoadModules extends ParallelTask<Void, Void, Void> {
private List<String> getModList() {
String command = "ls -d " + Const.MAGISK_PATH() + "/* | grep -v lost+found";
String command = "ls -d " + Const.MAGISK_PATH + "/* | grep -v lost+found";
return Shell.Sync.su(command);
}

View File

@ -12,6 +12,7 @@ import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
@ -147,7 +148,7 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
activity.startActivity(intent);
} else {
Utils.showUriSnack(activity, uri);
SnackbarMaker.showUri(activity, uri);
}
} else {
MagiskManager.toast(R.string.process_error, Toast.LENGTH_LONG);
@ -157,7 +158,7 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
@Override
public ParallelTask<Void, Object, Boolean> exec(Void... voids) {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE,
Utils.runWithPermission(getActivity(), new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
() -> super.exec(voids));
return this;
}

View File

@ -4,7 +4,7 @@ import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
@ -13,9 +13,9 @@ public class RestoreImages extends ParallelTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
String sha1;
sha1 = Utils.cmd("cat /.backup/.sha1");
sha1 = RootUtils.cmd("cat /.backup/.sha1");
if (sha1 == null) {
sha1 = Utils.cmd("cat /init.magisk.rc | grep STOCKSHA1");
sha1 = RootUtils.cmd("cat /init.magisk.rc | grep STOCKSHA1");
if (sha1 == null)
return false;
sha1 = sha1.substring(sha1.indexOf('=') + 1);

View File

@ -1,13 +1,9 @@
package com.topjohnwu.magisk.components;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v7.app.AppCompatActivity;
@ -16,33 +12,29 @@ import android.view.WindowManager;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
public abstract class Activity extends AppCompatActivity {
public abstract class FlavorActivity extends AppCompatActivity {
private AssetManager swappedAssetManager = null;
private Resources swappedResources = null;
private Resources.Theme swappedTheme = null;
private ActivityResultListener activityResultListener;
public Activity() {
super();
Configuration configuration = new Configuration();
configuration.setLocale(MagiskManager.locale);
applyOverrideConfiguration(configuration);
}
@StyleRes
public int getDarkTheme() {
return -1;
}
public MagiskManager getMagiskManager() {
return (MagiskManager) super.getApplicationContext();
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).subscribeTopics();
}
if (getMagiskManager().isDarkTheme && getDarkTheme() != -1) {
setTheme(getDarkTheme());
}
@ -56,35 +48,16 @@ public abstract class Activity extends AppCompatActivity {
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
MagiskManager mm = getMagiskManager();
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (mm.permissionGrantCallback != null) {
mm.permissionGrantCallback.run();
private static AssetManager getAssets(String apk) {
try {
AssetManager asset = AssetManager.class.newInstance();
AssetManager.class.getMethod("addAssetPath", String.class).invoke(asset, apk);
return asset;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
mm.permissionGrantCallback = null;
}
@Override
public Resources.Theme getTheme() {
return swappedTheme == null ? super.getTheme() : swappedTheme;
}
@Override
public AssetManager getAssets() {
return swappedAssetManager == null ? super.getAssets() : swappedAssetManager;
}
@Override
public Resources getResources() {
return swappedResources == null ? super.getResources() : swappedResources;
}
public MagiskManager getMagiskManager() {
return (MagiskManager) super.getApplicationContext();
}
protected void setFloating() {
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
@ -101,20 +74,23 @@ public abstract class Activity extends AppCompatActivity {
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (activityResultListener != null)
activityResultListener.onActivityResult(requestCode, resultCode, data);
activityResultListener = null;
public Resources.Theme getTheme() {
return swappedTheme == null ? super.getTheme() : swappedTheme;
}
public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) {
activityResultListener = listener;
super.startActivityForResult(intent, requestCode);
@Override
public AssetManager getAssets() {
return swappedAssetManager == null ? super.getAssets() : swappedAssetManager;
}
@Override
public Resources getResources() {
return swappedResources == null ? super.getResources() : swappedResources;
}
@Keep
public void swapResources(String dexPath, int resId) {
swappedAssetManager = Utils.getAssets(dexPath);
swappedAssetManager = getAssets(dexPath);
if (swappedAssetManager == null)
return;
Resources res = super.getResources();
@ -129,9 +105,4 @@ public abstract class Activity extends AppCompatActivity {
swappedResources = null;
swappedTheme = null;
}
public interface ActivityResultListener {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
}

View File

@ -1,11 +1,15 @@
package com.topjohnwu.magisk.components;
import android.app.Activity;
import android.net.Uri;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
public class SnackbarMaker {
public static Snackbar make(Activity activity, CharSequence text, int duration) {
@ -34,4 +38,10 @@ public class SnackbarMaker {
text.setMaxLines(Integer.MAX_VALUE);
}
public static void showUri(Activity activity, Uri uri) {
make(activity, activity.getString(R.string.internal_storage,
"/MagiskManager/" + Utils.getNameFromUri(activity, uri)),
Snackbar.LENGTH_LONG)
.setAction(R.string.ok, (v)->{}).show();
}
}

View File

@ -8,6 +8,7 @@ import android.support.v4.app.NotificationCompat;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
@ -43,7 +44,7 @@ public class OnBootIntentService extends IntentService {
mm.loadMagiskInfo();
mm.getDefaultInstallFlags();
if (Shell.rootAccess()) {
Utils.patchDTBO();
RootUtils.patchDTBO();
}
}
}

View File

@ -0,0 +1,43 @@
package com.topjohnwu.magisk.utils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import com.topjohnwu.superuser.io.SuFile;
public class RootUtils {
public static void init() {
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk", true);
SuFile file = new SuFile("/sbin/.core/img", true);
if (file.exists()) {
Const.MAGISK_PATH = file;
} else if ((file = new SuFile("/dev/magisk/img", true)).exists()) {
Const.MAGISK_PATH = file;
} else {
Const.MAGISK_PATH = new SuFile("/magisk", true);
}
Const.MAGISK_HOST_FILE = new SuFile(Const.MAGISK_PATH + "/.core/hosts");
}
public static String cmd(String cmd) {
return ShellUtils.fastCmd(Shell.getShell(), cmd);
}
public static boolean cmdResult(String cmd) {
return ShellUtils.fastCmdResult(Shell.getShell(), cmd);
}
public static void uninstallPkg(String pkg) {
Shell.Sync.su("db_clean " + Const.USER_ID, "pm uninstall " + pkg);
}
public static void patchDTBO() {
MagiskManager mm = MagiskManager.get();
if (mm.magiskVersionCode >= Const.MAGISK_VER.DTBO_SUPPORT && !mm.keepVerity) {
if (ShellUtils.fastCmdResult(Shell.getShell(), "patch_dtbo_image")) {
ShowUI.dtboPatchedNotification();
}
}
}
}

View File

@ -20,6 +20,7 @@ import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import com.topjohnwu.magisk.asyncs.RestoreImages;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.receivers.RebootReceiver;
@ -136,7 +137,7 @@ public class ShowUI {
if (Shell.rootAccess()) {
options.add(mm.getString(R.string.direct_install));
}
String s = Utils.cmd("echo $SLOT");
String s = RootUtils.cmd("echo $SLOT");
if (s != null) {
options.add(mm.getString(R.string.install_second_slot));
}
@ -185,7 +186,7 @@ public class ShowUI {
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Utils.showUriSnack(activity, uri);
SnackbarMaker.showUri(activity, uri);
}
};
break;
@ -210,7 +211,7 @@ public class ShowUI {
if (slot[1] == 'a') slot[1] = 'b';
else slot[1] = 'a';
// Then find the boot image again
boot = Utils.cmd(
boot = RootUtils.cmd(
"SLOT=" + String.valueOf(slot) +
"; find_boot_image;" +
"echo \"$BOOTIMAGE\""
@ -254,7 +255,8 @@ public class ShowUI {
.setMessage(mm.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
Utils.runWithPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
Utils.runWithPermission(activity,
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(Const.Key.INTENT_SET_LINK, mm.managerLink);
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
@ -297,10 +299,10 @@ public class ShowUI {
} catch (IOException ignored) {}
MagiskManager.toast(R.string.uninstall_toast, Toast.LENGTH_LONG);
new Handler().postDelayed(() -> Utils.uninstallPkg(mm.getPackageName()), 5000);
new Handler().postDelayed(() -> RootUtils.uninstallPkg(mm.getPackageName()), 5000);
})
.setNeutralButton(R.string.restore_img, (d, i) -> new RestoreImages().exec())
.setNegativeButton(R.string.uninstall_app, (d, i) -> Utils.uninstallPkg(mm.getPackageName()))
.setNegativeButton(R.string.uninstall_app, (d, i) -> RootUtils.uninstallPkg(mm.getPackageName()))
.show();
}
}

View File

@ -1,8 +1,7 @@
package com.topjohnwu.magisk.utils;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
public class Topic {
@ -15,23 +14,24 @@ public class Topic {
private List<WeakReference<Subscriber>> subscribers;
private Object[] results;
public void subscribe(Subscriber sub) {
if (subscribers == null) {
subscribers = new LinkedList<>();
public Topic() {
subscribers = new SyncArrayList<>();
}
public synchronized void subscribe(Subscriber sub) {
subscribers.add(new WeakReference<>(sub));
}
public void unsubscribe() {
subscribers = null;
public synchronized void unsubscribe() {
subscribers = new SyncArrayList<>();
}
public void unsubscribe(Subscriber sub) {
for (Iterator<WeakReference<Subscriber>> i = subscribers.iterator(); i.hasNext();) {
WeakReference<Subscriber> subscriber = i.next();
if (subscriber.get() == null || subscriber.get() == sub) {
i.remove();
}
public synchronized void unsubscribe(Subscriber sub) {
List<WeakReference<Subscriber>> subs = subscribers;
subscribers = new ArrayList<>();
for (WeakReference<Subscriber> subscriber : subs) {
if (subscriber.get() != null && subscriber.get() != sub)
subscribers.add(subscriber);
}
}
@ -52,13 +52,13 @@ public class Topic {
if (record)
state = PUBLISHED;
this.results = results;
if (subscribers != null) {
for (WeakReference<Subscriber> subscriber : subscribers) {
if (subscriber.get() != null)
// Snapshot
List<WeakReference<Subscriber>> subs = subscribers;
for (WeakReference<Subscriber> subscriber : subs) {
if (subscriber != null && subscriber.get() != null)
subscriber.get().onTopicPublished(this);
}
}
}
public Object[] getResults() {
return results;
@ -89,4 +89,11 @@ public class Topic {
void onTopicPublished(Topic topic);
Topic[] getSubscription();
}
private static class SyncArrayList<E> extends ArrayList<E> {
@Override
public synchronized boolean add(E e) {
return super.add(e);
}
}
}

View File

@ -63,15 +63,10 @@
<string name="support_thread">منتدى الدعم</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">أن هذه الميزة لا تعمل دون الحصول على إذن الكتابة على التخزين الخارجي.</string>
<string name="no_thanks">لا شكراً</string>
<string name="yes">نعم</string>
<string name="ok">موافق</string>
<string name="close">إغلاق</string>
<string name="repo_install_title">تثبيت %1$s</string>
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
<string name="download">التنزيل</string>
<string name="download_file_error">خطأ تنزيل الملف</string>
<string name="reboot">إعادة التشغيل</string>
<string name="zip_process_msg">معالجة الملف المضغوط …</string>
<string name="downloading_toast">جاري التنزيل %1$s</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Страница за поддръжка</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Тази функция няма да работи без разрешение за запис във външната памет.</string>
<string name="no_thanks">Не, благодаря</string>
<string name="yes">Да</string>
<string name="ok">OK</string>
<string name="close">Затваряне</string>
<string name="repo_install_title">Инсталиране на %1$s</string>
<string name="repo_install_msg">Желаете ли да инсталирате %1$s сега?</string>
<string name="download">Изтегляне</string>
<string name="download_file_error">Грешка при изтеглянето на файла</string>
<string name="reboot">Рестартиране</string>
<string name="downloading_toast">Изтегляне на %1$s</string>
<string name="magisk_update_title">Налице е нова версия на Magisk!</string>
<string name="settings_reboot_toast">Трябва да рестартирате за прилагане на настройките</string>
<string name="release_notes">Бележки</string>

View File

@ -60,18 +60,13 @@
<string name="support_thread">Vlákno podpory na fóru</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Tato funkce nebude fungovat bez povolení k zápisu na externí úložiště.</string>
<string name="no_thanks">Ne, díky</string>
<string name="yes">Ano</string>
<string name="ok">OK</string>
<string name="close">Zavřít</string>
<string name="repo_install_title">Instalovat %1$s</string>
<string name="repo_install_msg">Chcete nainstalovat %1$s ?</string>
<string name="download">Stáhnout</string>
<string name="download_file_error">Chyba při Stahování souboru</string>
<string name="reboot">Restart</string>
<string name="zip_process_msg">Zpracování zip souboru …</string>
<string name="downloading_toast">Stahování %1$s</string>
<string name="magisk_update_title">K dispozici je aktualizace Magisk!</string>
<string name="settings_reboot_toast">Restartovat pro použití nastavení</string>
<string name="release_notes">Poznámky k vydání</string>

View File

@ -77,17 +77,11 @@
<string name="support_thread">Hilfeforum</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Diese Funktion benötigt Rechte zum Schreiben auf den externen Speicher.</string>
<string name="no_thanks">Nein danke</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
<string name="close">Schließen</string>
<string name="repo_install_title">Installiere %1$s</string>
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
<string name="download">Herunterladen</string>
<string name="download_file_error">Fehler beim Herunterladen der Datei</string>
<string name="reboot">Neustart</string>
<string name="downloading_toast">Herunterladen von %1$s</string>
<string name="magisk_update_title">Neue Magisk-Aktualisierung verfügbar!</string>
<string name="settings_reboot_toast">Neustarten, um die Änderungen anzuwenden</string>
<string name="release_notes">Änderungen</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Σύνδεσμος υποστήριξης</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Η λειτουργία αυτή δεν θα δουλέψει χωρίς την άδεια εγγραφής στον εξωτερικό χώρο αποθηκεύσης.</string>
<string name="no_thanks">Όχι ευχαριστώ</string>
<string name="yes">Ναι</string>
<string name="ok">OK</string>
<string name="close">Κλείσιμο</string>
<string name="repo_install_title">Εγκατάσταση %1$s</string>
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
<string name="download">Λήψη</string>
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
<string name="reboot">Επανεκκίνηση</string>
<string name="downloading_toast">Κατέβασμα %1$s</string>
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
<string name="settings_reboot_toast">Επανεκκίνηση για εφαρμογή ρυθμίσεων</string>
<string name="release_notes">Σημειώσεις έκδοσης</string>

View File

@ -74,18 +74,12 @@
<string name="support_thread">Hilo de soporte</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Esta opción no funcionará sin permiso de escritura en la memoria externa.</string>
<string name="no_thanks">No gracias</string>
<string name="yes"></string>
<string name="ok">Aceptar</string>
<string name="close">Cerrar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">¿Quieres instalar %1$s ahora?</string>
<string name="download">Descargar</string>
<string name="download_file_error">Error descargando archivo</string>
<string name="reboot">Reiniciar</string>
<string name="zip_process_msg">Procesando archivo zip…</string>
<string name="downloading_toast">Descargando %1$s</string>
<string name="magisk_update_title">¡Nueva actualización de Magisk disponible!</string>
<string name="settings_reboot_toast">Reinicia para aplicar los ajustes</string>
<string name="release_notes">Notas de lanzamiento</string>

View File

@ -11,11 +11,11 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magisk pole installitud</string>
<string name="checking_for_updates">Kontrollin uuendusi...</string>
<string name="checking_for_updates">Kontrollin uuendusi</string>
<string name="magisk_update_available">Magisk v%1$s on saadaval!</string>
<string name="invalid_update_channel">Sobimatu uuenduste kanal</string>
<string name="safetyNet_check_text">Koputa, et alustada SafetyNet\'i kontrolli</string>
<string name="checking_safetyNet_status">Kontrollin SafetyNet\'i olekut...</string>
<string name="checking_safetyNet_status">Kontrollin SafetyNet\'i olekut</string>
<string name="safetyNet_check_success">SafetyNet\'i kontroll edukas</string>
<string name="safetyNet_api_error">SafetyNet\'i API viga</string>
<string name="safetyNet_network_loss">Võrguühendus puudub</string>
@ -74,17 +74,11 @@
<string name="support_thread">Foorumi tugiteema</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">See funktsioon ei tööta ilma välismälule kirjutamise õiguseta.</string>
<string name="no_thanks">Tänan ei</string>
<string name="yes">Jah</string>
<string name="ok">OK</string>
<string name="close">Sulge</string>
<string name="repo_install_title">Installi %1$s</string>
<string name="repo_install_msg">Kas soovid kohe installida %1$s?</string>
<string name="download">Allalaadimine</string>
<string name="download_file_error">Faili allalaadimisel esines viga</string>
<string name="reboot">Taaskäivita</string>
<string name="downloading_toast">Laadin %1$s alla</string>
<string name="magisk_update_title">Magisk\'ile on uuendus saadaval!</string>
<string name="settings_reboot_toast">Taaskäivita seadete rakendamiseks</string>
<string name="release_notes">Väljalaskemärkmed</string>
@ -93,18 +87,18 @@
<string name="internal_storage">ZIP on salvestatud:\n
[Sisemälu]%1$s</string>
<string name="zip_download_title">Laadin alla</string>
<string name="zip_download_msg">Laadin ZIP-faili alla (%1$d%%)...</string>
<string name="zip_download_msg">Laadin ZIP-faili alla (%1$d%%)</string>
<string name="zip_process_title">Töötlen</string>
<string name="zip_process_msg">Töötlen ZIP-faili...</string>
<string name="zip_process_msg">Töötlen ZIP-faili</string>
<string name="manager_update_title">Magisk Manager\'ile on uuendus saadaval!</string>
<string name="manager_download_install">Vajuta allalaadimiseks ja installimiseks</string>
<string name="dtbo_patched_title">DTBO sai paigatud!</string>
<string name="dtbo_patched_reboot">Magisk Manager on paiganud dtbo.img, palun taaskäivita</string>
<string name="magisk_updates">Magisk\'i uuendused</string>
<string name="flashing">Välgutamine</string>
<string name="hide_manager_toast">Peidan Magisk Manager\'i...</string>
<string name="hide_manager_toast2">See võib aega võtta...</string>
<string name="hide_manager_fail_toast">Magisk Manager\'i peitmine ebaõnnestus...</string>
<string name="hide_manager_toast">Peidan Magisk Manager\'i</string>
<string name="hide_manager_toast2">See võib aega võtta</string>
<string name="hide_manager_fail_toast">Magisk Manager\'i peitmine ebaõnnestus</string>
<string name="download_zip_only">Laadi ainult ZIP alla</string>
<string name="patch_boot_file">Paika käivituspildi fail</string>
<string name="direct_install">Otsene install (soovitatud)</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Fil d\'assistance</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Cette fonctionnalité ne marchera pas sans la permission d\'écriture sur le stockage externe.</string>
<string name="no_thanks">Non merci</string>
<string name="yes">Oui</string>
<string name="ok">OK</string>
<string name="close">Fermer</string>
<string name="repo_install_title">Installer %1$s</string>
<string name="repo_install_msg">Voulez-vous installer %1$s maintenant ?</string>
<string name="download">Télécharger</string>
<string name="download_file_error">Erreur de téléchargement du fichier</string>
<string name="reboot">Redémarrer</string>
<string name="downloading_toast">Téléchargement %1$s</string>
<string name="magisk_update_title">Nouvelle mis à jour Magisk disponible!</string>
<string name="settings_reboot_toast">Redémarrer afin d\'appliquer les réglages</string>
<string name="release_notes">Notes de version</string>

View File

@ -12,7 +12,7 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magisk nije instaliran</string>
<string name="checking_for_updates">Provjera ažuriranja...</string>
<string name="checking_for_updates">Provjera ažuriranja</string>
<string name="magisk_update_available">Dostupna je Maigsk inačica v%1$s!</string>
<string name="safetyNet_check_text">Dodirni za SafetyNet provjeru</string>
<string name="checking_safetyNet_status">Provjera SafetyNet statusa</string>
@ -67,17 +67,11 @@
<string name="support_thread">Tema podrške</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ova značajka neće raditi bez dopuštenja za korištenje vanjske pohrane.</string>
<string name="no_thanks">Ne hvala</string>
<string name="yes">Da</string>
<string name="ok">OK</string>
<string name="close">Zatvori</string>
<string name="repo_install_title">Instaliraj %1$s</string>
<string name="repo_install_msg">Da li želite instalirati %1$s sada?</string>
<string name="download">Preuzmi</string>
<string name="download_file_error">Pogreška prilikom preuzimanja datoteke</string>
<string name="reboot">Ponovno podizanje sustava</string>
<string name="downloading_toast">Preuzimanje %1$s</string>
<string name="magisk_update_title">Dostupno je novo Magisk ažuriranje!</string>
<string name="settings_reboot_toast">Ponovno pokrenite kako biste primjenili postavke</string>
<string name="release_notes">Bilješke o izdavanju aplikacije</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Thread dukungan</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Fitur ini tidak akan bekerja tanpa izin untuk menulis ke penyimpanan eksternal.</string>
<string name="no_thanks">Tidak, terima kasih</string>
<string name="yes">Ya</string>
<string name="ok">OK</string>
<string name="close">Tutup</string>
<string name="repo_install_title">Pasang %1$s</string>
<string name="repo_install_msg">Apakah Anda ingin memasang %1$s sekarang?</string>
<string name="download">Unduh</string>
<string name="download_file_error">Kesalahan mengunduh file</string>
<string name="reboot">Reboot</string>
<string name="downloading_toast">Mengunduh %1$s</string>
<string name="magisk_update_title">Pembaruan Magisk Tersedia!</string>
<string name="settings_reboot_toast">Reboot untuk menerapkan pengaturan</string>
<string name="release_notes">Catatan rilis</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Thread di supporto</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Questa funzione non sarà attiva senza l\'autorizzazione di scrittura nella memoria di archiviazione esterna</string>
<string name="no_thanks">No, grazie</string>
<string name="yes"></string>
<string name="ok">OK</string>
<string name="close">Chiudi</string>
<string name="repo_install_title">Installazione di %1$s</string>
<string name="repo_install_msg">Vuoi installare %1$s?</string>
<string name="download">Download</string>
<string name="download_file_error">Errore nel download del file</string>
<string name="reboot">Riavvia</string>
<string name="downloading_toast">Download di %1$s</string>
<string name="magisk_update_title">È disponibile un nuovo aggiornamento di Magisk!</string>
<string name="settings_reboot_toast">Riavvia per applicare</string>
<string name="release_notes">Note di rilascio</string>

View File

@ -11,7 +11,7 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magiskがインストールされていません</string>
<string name="checking_for_updates">更新を確認中...</string>
<string name="checking_for_updates">更新を確認中</string>
<string name="magisk_update_available">Magisk v%1$s が利用可能です!</string>
<string name="invalid_update_channel">不正な更新チャンネルです</string>
<string name="safetyNet_check_text">タップしてSafetyNetチェックを開始</string>
@ -74,17 +74,11 @@
<string name="support_thread">サポートスレッド</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">この機能は外部ストレージへの書き込み権限がないと動作しません</string>
<string name="no_thanks">いいえ</string>
<string name="yes">はい</string>
<string name="ok">OK</string>
<string name="close">閉じる</string>
<string name="repo_install_title">%1$s をインストール</string>
<string name="repo_install_msg">%1$s をインストールしますか?</string>
<string name="download">ダウンロード</string>
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
<string name="reboot">再起動</string>
<string name="downloading_toast">%1$s をダウンロード中</string>
<string name="magisk_update_title">新しいMagiskの更新が利用可能です</string>
<string name="settings_reboot_toast">再起動して設定を適用する</string>
<string name="release_notes">更新履歴</string>

View File

@ -60,17 +60,11 @@
<string name="support_thread">지원 스레드</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">이 기능은 외부 저장소 쓰기 권한 없이는 작동하지 않습니다.</string>
<string name="no_thanks">아니오, 괜찮습니다</string>
<string name="yes"></string>
<string name="ok">확인</string>
<string name="close">닫기</string>
<string name="repo_install_title">%1$s 설치</string>
<string name="repo_install_msg">정말 %1$s을(를) 설치하시겠습니까?</string>
<string name="download_file_error">파일 다운로드 오류</string>
<string name="reboot">다시 시작</string>
<string name="zip_process_msg">zip 파일 처리 중…</string>
<string name="downloading_toast">%1$s 다운로드 중</string>
<string name="magisk_update_title">새 버전의 Magisk를 사용할 수 있습니다!</string>
<string name="settings_reboot_toast">기기를 다시 시작하면 설정이 적용됩니다.</string>
<string name="release_notes">릴리즈 노트</string>

View File

@ -75,17 +75,11 @@
<string name="support_thread">Mūsų XDA puslapis</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ši funkija neveiks be prieigos prie saugyklos</string>
<string name="no_thanks">Ačiū, nereikia</string>
<string name="yes">Taip</string>
<string name="ok">Gerai</string>
<string name="close">Uždaryti</string>
<string name="repo_install_title">Instaliuoti %1$s</string>
<string name="repo_install_msg">Ar jūs norite instaliuoti %1$s?</string>
<string name="download">Atsisiųsti</string>
<string name="download_file_error">Atsisiunčiant failą įvyko klaida</string>
<string name="reboot">Perkrauti</string>
<string name="downloading_toast">Atsisiunčiamas %1$s</string>
<string name="magisk_update_title">Atsirado nauja Magisk versija!</string>
<string name="settings_reboot_toast">Nustatymų įgalinimui prašome perkrauti telefoną</string>
<string name="release_notes">Pakeitimai</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Hulp thread</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Deze functie werkt niet zonder schrijfpermissie voor externe opslag.</string>
<string name="no_thanks">Nee bedankt</string>
<string name="yes">Ja</string>
<string name="ok">Oké</string>
<string name="close">Sluiten</string>
<string name="repo_install_title">%1$s installeren</string>
<string name="repo_install_msg">Zeker weten %1$s installeren?</string>
<string name="download">Downloaden</string>
<string name="download_file_error">Fout tijdens downloaden</string>
<string name="reboot">Herstarten</string>
<string name="downloading_toast">%1$s downloaden</string>
<string name="magisk_update_title">Nieuwe Magisk update beschikbaar!</string>
<string name="settings_reboot_toast">Herstarten om instellingen toe te passen</string>
<string name="release_notes">Publicatie notities</string>

View File

@ -1,10 +1,7 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moduły</string>
<string name="downloads">Pobieranie</string>
<string name="superuser">Superuser</string>
@ -77,17 +74,11 @@
<string name="support_thread">Strona Wsparcia</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ta funkcja nie będzie działać bez uprawnień do zapisu na pamięci zewnętrznej.</string>
<string name="no_thanks">Nie dziękuję</string>
<string name="yes">Tak</string>
<string name="ok">OK</string>
<string name="close">Zamknij</string>
<string name="repo_install_title">Zainstaluj %1$s</string>
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
<string name="download">Pobierz</string>
<string name="download_file_error">Błąd pobierania pliku</string>
<string name="reboot">Restart</string>
<string name="downloading_toast">Pobieranie %1$s</string>
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
<string name="settings_reboot_toast">Uruchom ponownie, aby zastosować ustawienia</string>
<string name="release_notes">Zmiany</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">Tópico de suporte</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Este recurso não funcionará sem permissão para gravar no armazenamento externo.</string>
<string name="no_thanks">Não</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Instalar %1$s agora?</string>
<string name="download">Baixar</string>
<string name="download_file_error">Erro ao baixar arquivo</string>
<string name="reboot">Reiniciar</string>
<string name="downloading_toast">Baixando %1$s</string>
<string name="magisk_update_title">Nova Atualização do Magisk Disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar as definições</string>
<string name="release_notes">Notas de lançamento</string>

View File

@ -11,7 +11,6 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magisk não instalado</string>
<string name="checking_for_updates">A procurar por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="safetyNet_check_text">Pressione para verificar SafetyNet</string>
@ -65,17 +64,11 @@
<string name="support_thread">Suporte</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Esta funcionalidade não funcionará sem permissão de escrita do armazenamento externo.</string>
<string name="no_thanks">Não, Obrigado</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Deseja instalar%1$s agora?</string>
<string name="download">Transferir</string>
<string name="download_file_error">Erro ao transferir ficheiro</string>
<string name="reboot">Reiniciar</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar definições</string>
<string name="release_notes">Notas da atualização</string>

View File

@ -68,17 +68,11 @@
<string name="support_thread">Pagina de suport</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Această caracteristică nu va funcționa fără permisiunea de a scrie pe memoria externă.</string>
<string name="no_thanks">Nu, mulţumesc</string>
<string name="yes">Da</string>
<string name="ok">OK</string>
<string name="close">Închide</string>
<string name="repo_install_title">Instalare %1$s</string>
<string name="repo_install_msg">Instalaţi %1$s?</string>
<string name="download">Descărcare</string>
<string name="download_file_error">Eroare la descărcarea fișierului</string>
<string name="reboot">Repornire</string>
<string name="downloading_toast">Descărcare %1$s</string>
<string name="magisk_update_title">O nouă actualizare Magisk este disponibilă!</string>
<string name="settings_reboot_toast">Reporniți pentru a aplica setările</string>
<string name="release_notes">Note de lansare</string>

View File

@ -1,10 +1,7 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Модули</string>
<string name="downloads">Репозиторий</string>
<string name="superuser">Суперпользователь</string>
@ -77,17 +74,11 @@
<string name="support_thread">Домашняя страница</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Требуется разрешение на запись во внешнее хранилище.</string>
<string name="no_thanks">Нет</string>
<string name="yes">Да</string>
<string name="ok">OK</string>
<string name="close">Закрыть</string>
<string name="repo_install_title">Установка %1$s</string>
<string name="repo_install_msg">Установить %1$s ?</string>
<string name="download">Скачать</string>
<string name="download_file_error">Ошибка загрузки файла</string>
<string name="reboot">Перезагрузка</string>
<string name="downloading_toast">Загрузка %1$s</string>
<string name="magisk_update_title">Доступно обновление Magisk!</string>
<string name="settings_reboot_toast">Для применения настроек перезагрузите устройство</string>
<string name="release_notes">О версии</string>

View File

@ -67,17 +67,11 @@
<string name="support_thread">Подршка</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ово својство неће радити без дозволе приступу екстерном складишту.</string>
<string name="no_thanks">Не хвала</string>
<string name="yes">Да</string>
<string name="ok">ОК</string>
<string name="close">Затвори</string>
<string name="repo_install_title">Инсталирај %1$s</string>
<string name="repo_install_msg">Да ли желите да инсталирате %1$s?</string>
<string name="download">Преузми</string>
<string name="download_file_error">Грешка при преузимању фајла</string>
<string name="reboot">Рестартуј</string>
<string name="downloading_toast">Преузимање %1$s</string>
<string name="magisk_update_title">Нови Адбејт Магиска Доступан!</string>
<string name="settings_reboot_toast">Рестартуј да примениш подешавања</string>
<string name="release_notes">Белешке обљављивања</string>

View File

@ -65,18 +65,12 @@
<string name="support_thread">Supporttråd</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Denna funktionen måste ha behörighet att skriva till externt lagringsutrymme.</string>
<string name="no_thanks">Nej tack</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
<string name="close">Stäng</string>
<string name="repo_install_title">Installera %1$s</string>
<string name="repo_install_msg">Vill du installera %1$s ?</string>
<string name="download">Ladda ner</string>
<string name="download_file_error">Fel vid nerladdning av fil</string>
<string name="reboot">Starta om</string>
<string name="zip_process_msg">Bearbetar ZIP-filen …</string>
<string name="downloading_toast">Laddar ner %1$s</string>
<string name="magisk_update_title">En uppdatering av Magisk finns tillgänglig!</string>
<string name="settings_reboot_toast">Starta om för att tillämpa inställningar</string>
<string name="release_notes">Release notes</string>

View File

@ -73,17 +73,11 @@
<string name="support_thread">Destek konusu</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Bu özellik harici depolamaya yazma izni olmadan çalışmaz.</string>
<string name="no_thanks">Hayır teşekkürler</string>
<string name="yes">Evet</string>
<string name="ok">Tamam</string>
<string name="close">Kapat</string>
<string name="repo_install_title">%1$s yükle</string>
<string name="repo_install_msg">%1$s yüklensin mi?</string>
<string name="download">İndir</string>
<string name="download_file_error">Dosya indirme hatası</string>
<string name="reboot">Yeniden başlat</string>
<string name="downloading_toast">%1$s indiriliyor</string>
<string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string>
<string name="settings_reboot_toast">Ayarları uygulamak için yeniden başlatın</string>
<string name="release_notes">Sürüm notları</string>

View File

@ -73,17 +73,11 @@
<string name="support_thread">Сторінка підтримки</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ця функція не працюватиме без дозволу на запис у Внутрішнє сховище</string>
<string name="no_thanks">Ні, дякую</string>
<string name="yes">Так</string>
<string name="ok">OK</string>
<string name="close">Закрити</string>
<string name="repo_install_title">Встановити %1$s</string>
<string name="repo_install_msg">Бажаєте встановити %1$s ?</string>
<string name="download">Завантажити</string>
<string name="download_file_error">Помилка завантаження файлу</string>
<string name="reboot">Перезавантаження</string>
<string name="downloading_toast">Завантаження %1$s</string>
<string name="magisk_update_title">Доступне оновлення Magisk!</string>
<string name="settings_reboot_toast">Для застосування змін перезавантажте пристрій</string>
<string name="release_notes">Особливості версії</string>

View File

@ -60,18 +60,12 @@
<string name="support_thread">Chủ đề hỗ trợ</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Tính năng này không hoạt động nếu thiếu quyền ghi vào bộ nhớ ngoài.</string>
<string name="no_thanks">Không, cảm ơn</string>
<string name="yes"></string>
<string name="ok">OK</string>
<string name="close">Đóng</string>
<string name="repo_install_title">Cài đặt %1$s</string>
<string name="repo_install_msg">Bạn muốn cài đặt %1$s ?</string>
<string name="download">Tải xuống</string>
<string name="download_file_error">Lỗi tải tập tin</string>
<string name="reboot">Khởi động lại</string>
<string name="zip_process_msg">Đang xử lý tập tin zip …</string>
<string name="downloading_toast">Đang tải xuống %1$s</string>
<string name="magisk_update_title">Có cập nhật Magisk mới!</string>
<string name="settings_reboot_toast">Khởi động lại để áp dụng thiết lập</string>
<string name="release_notes">Ghi chú phát hành</string>

View File

@ -74,17 +74,11 @@
<string name="support_thread">支持主题</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">未授予写入内置存储权限,此功能无法正常工作。</string>
<string name="no_thanks">不,谢谢</string>
<string name="yes"></string>
<string name="ok"></string>
<string name="close">关闭</string>
<string name="repo_install_title">安装 %1$s</string>
<string name="repo_install_msg">是否立即安装 %1$s </string>
<string name="download">下载</string>
<string name="download_file_error">下载文件时出错</string>
<string name="reboot">重启</string>
<string name="downloading_toast">正在下载 %1$s</string>
<string name="magisk_update_title">Magisk 可更新!</string>
<string name="settings_reboot_toast">重启以应用设置</string>
<string name="release_notes">发布说明</string>

View File

@ -59,15 +59,10 @@
<string name="support_thread">討論串</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">未授予寫入外部存儲權限,此功能無法正常工作。</string>
<string name="no_thanks">不,謝謝</string>
<string name="yes"></string>
<string name="repo_install_title">安裝 %1$s</string>
<string name="repo_install_msg">你想要安裝 %1$s 嗎?</string>
<string name="download_file_error">下載文件時出錯</string>
<string name="reboot">重啟</string>
<string name="zip_process_msg">正在處理 zip 文件 …</string>
<string name="downloading_toast">正在下載 %1$s</string>
<string name="magisk_update_title">Magisk 可更新!</string>
<string name="settings_reboot_toast">重啟以完成設定</string>
<string name="release_notes">發布說明</string>
@ -79,7 +74,6 @@
<string name="settings_dark_theme_summary">使用深色主題</string>
<string name="settings_clear_cache_title">清除資源庫快取</string>
<string name="settings_clear_cache_summary">清除已暫存的在線資源庫快取,強制刷新在線數據</string>
<string name="settings_core_only_title">Magisk 核心功能模式</string>
<string name="settings_magiskhide_summary">隱藏 Magisk 使其不被多種方法檢測到</string>
<string name="settings_hosts_title">Systemless hosts</string>
@ -133,7 +127,6 @@
<string name="command">"指令: "</string>
<string name="close">關閉</string>
<string name="internal_storage">Zip 已被儲存到:\n[內部儲存空間]%1$s</string>
<string name="ok"></string>
<string name="process_error">處理失敗</string>
<string name="download">下載</string>
<string name="zip_process_title">處理中</string>

View File

@ -73,17 +73,11 @@
<string name="support_thread">Support thread</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">This feature will not work without permission to write external storage.</string>
<string name="no_thanks">No thanks</string>
<string name="yes">Yes</string>
<string name="ok">OK</string>
<string name="close">Close</string>
<string name="repo_install_title">Install %1$s</string>
<string name="repo_install_msg">Do you want to install %1$s now?</string>
<string name="download">Download</string>
<string name="download_file_error">Error downloading file</string>
<string name="reboot">Reboot</string>
<string name="downloading_toast">Downloading %1$s</string>
<string name="magisk_update_title">New Magisk Update Available!</string>
<string name="settings_reboot_toast">Reboot to apply settings</string>
<string name="release_notes">Release notes</string>

View File

@ -13,6 +13,7 @@
<item name="windowNoTitle">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="imageColorTint">@android:color/secondary_text_light</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
<style name="AppTheme.Dark" parent="Theme.AppCompat.NoActionBar">
@ -26,6 +27,7 @@
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:textColorSecondary">@color/dark_secondary_text</item>
<item name="imageColorTint">@color/dark_secondary_text</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
<style name="CardViewStyle.Dark" parent="CardView">

View File

@ -7,13 +7,14 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:name=".MagiskManager"
android:allowBackup="false"
android:directBootAware="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
tools:ignore="UnusedAttribute">

View File

@ -0,0 +1,62 @@
package com.topjohnwu.magisk.components;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.support.annotation.NonNull;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
public abstract class Activity extends FlavorActivity {
private ActivityResultListener activityResultListener;
public Activity() {
super();
Configuration configuration = new Configuration();
configuration.setLocale(MagiskManager.locale);
applyOverrideConfiguration(configuration);
}
@Override
public Application getApplicationContext() {
return (Application) super.getApplicationContext();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean grant = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED)
grant = false;
}
Application app = getApplicationContext();
if (grant) {
if (app.permissionGrantCallback != null) {
app.permissionGrantCallback.run();
}
} else {
MagiskManager.toast(R.string.no_rw_storage, Toast.LENGTH_LONG);
}
app.permissionGrantCallback = null;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (activityResultListener != null)
activityResultListener.onActivityResult(requestCode, resultCode, data);
activityResultListener = null;
}
public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) {
activityResultListener = listener;
super.startActivityForResult(intent, requestCode);
}
public interface ActivityResultListener {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
}

View File

@ -0,0 +1,40 @@
package com.topjohnwu.magisk.components;
import android.os.Handler;
import android.widget.Toast;
import java.lang.ref.WeakReference;
import java.util.Locale;
public abstract class Application extends android.app.Application {
public static WeakReference<Application> weakSelf;
public static Locale locale;
public static Locale defaultLocale;
private static Handler mHandler = new Handler();
public Runnable permissionGrantCallback = null;
public Application() {
weakSelf = new WeakReference<>(this);
}
@Override
public void onCreate() {
super.onCreate();
locale = defaultLocale = Locale.getDefault();
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
}
public static void toast(CharSequence msg, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), msg, duration).show());
}
public static void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show());
}
}

View File

@ -21,7 +21,7 @@ public class ManagerUpdate extends BroadcastReceiver {
@Override
public void onDownloadDone(Uri uri) {
if (!context.getPackageName().equals(Const.ORIG_PKG_NAME)) {
Utils.dumpPrefs();
Utils.getMagiskManager(context).dumpPrefs();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);

View File

@ -5,7 +5,6 @@ import android.os.Process;
import com.topjohnwu.magisk.BuildConfig;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.superuser.io.SuFile;
import java.io.File;
import java.util.Arrays;
@ -26,8 +25,10 @@ public class Const {
public static final String SU_KEYSTORE_KEY = "su_key";
// Paths
private static SuFile MAGISK_PATH = null;
public static final SuFile MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk", true);
public static File MAGISK_PATH;
public static File MAGISK_DISABLE_FILE;
public static File MAGISK_HOST_FILE;
public static final String BUSYBOX_PATH = "/sbin/.core/busybox";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_LOG = "/cache/magisk.log";
@ -42,25 +43,6 @@ public class Const {
return MagiskManager.get().magiskVersionCode >= MAGISK_VER.REMOVE_LEGACY_LINK ? 1500 : 1400;
}
public synchronized static SuFile MAGISK_PATH() {
SuFile file;
if (MAGISK_PATH == null) {
file = new SuFile("/sbin/.core/img", true);
if (file.exists()) {
MAGISK_PATH = file;
} else if ((file = new SuFile("/dev/magisk/img", true)).exists()) {
MAGISK_PATH = file;
} else {
MAGISK_PATH = new SuFile("/magisk", true);
}
}
return MAGISK_PATH;
}
public static SuFile MAGISK_HOST_FILE() {
return new SuFile(MAGISK_PATH() + "/.core/hosts");
}
/* A list of apps that should not be shown as hide-able */
public static final List<String> HIDE_BLACKLIST = Arrays.asList(
"android",

View File

@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.ConnectivityManager;
@ -16,27 +15,16 @@ import android.net.NetworkInfo;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Xml;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import com.topjohnwu.superuser.io.SuFile;
import com.topjohnwu.superuser.io.SuFileInputStream;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@ -47,28 +35,15 @@ public class Utils {
public static boolean isDownloading = false;
public static String cmd(String cmd) {
return ShellUtils.fastCmd(Shell.getShell(), cmd);
}
public static boolean cmdResult(String cmd) {
return ShellUtils.fastCmdResult(Shell.getShell(), cmd);
}
public static void uninstallPkg(String pkg) {
Shell.Sync.su("db_clean " + Const.USER_ID, "pm uninstall " + pkg);
}
public static void dlAndReceive(Context context, DownloadReceiver receiver, String link, String filename) {
if (isDownloading)
return;
runWithPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
runWithPermission(context, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
File file = new File(Const.EXTERNAL_PATH, getLegalFilename(filename));
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs())
|| (file.exists() && !file.delete())) {
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
return;
}
@ -121,13 +96,6 @@ public class Utils {
return name;
}
public static void showUriSnack(Activity activity, Uri uri) {
SnackbarMaker.make(activity, activity.getString(R.string.internal_storage,
"/MagiskManager/" + Utils.getNameFromUri(activity, uri)),
Snackbar.LENGTH_LONG)
.setAction(R.string.ok, (v)->{}).show();
}
public static boolean checkNetworkStatus() {
ConnectivityManager manager = (ConnectivityManager)
MagiskManager.get().getSystemService(Context.CONNECTIVITY_SERVICE);
@ -174,41 +142,25 @@ public class Utils {
return locales;
}
public static void runWithPermission(Context context, String permission, Runnable callback) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
public static void runWithPermission(Context context, String[] permissions, Runnable callback) {
boolean granted = true;
for (String perm : permissions) {
if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED)
granted = false;
}
if (granted) {
callback.run();
} else {
// Passed in context should be an activity if not granted, need to show dialog!
Utils.getMagiskManager(context).setPermissionGrantCallback(callback);
getMagiskManager(context).setPermissionGrantCallback(callback);
if (!(context instanceof com.topjohnwu.magisk.components.Activity)) {
// Start activity to show dialog
Intent intent = new Intent(context, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Const.Key.INTENT_PERM, permission);
intent.putExtra(Const.Key.INTENT_PERM, permissions);
context.startActivity(intent);
} else {
ActivityCompat.requestPermissions((Activity) context, new String[] { permission }, 0);
}
} else {
callback.run();
}
}
public static AssetManager getAssets(String apk) {
try {
AssetManager asset = AssetManager.class.newInstance();
AssetManager.class.getMethod("addAssetPath", String.class).invoke(asset, apk);
return asset;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void patchDTBO() {
MagiskManager mm = MagiskManager.get();
if (mm.magiskVersionCode >= Const.MAGISK_VER.DTBO_SUPPORT && !mm.keepVerity) {
if (ShellUtils.fastCmdResult(Shell.getShell(), "patch_dtbo_image")) {
ShowUI.dtboPatchedNotification();
ActivityCompat.requestPermissions((Activity) context, permissions, 0);
}
}
}
@ -219,76 +171,6 @@ public class Utils {
return (int) (dp * scale + 0.5);
}
public static void dumpPrefs() {
MagiskManager mm = MagiskManager.get();
// Flush prefs to disk
mm.prefs.edit().commit();
File xml = new File(mm.getFilesDir().getParent() + "/shared_prefs",
mm.getPackageName() + "_preferences.xml");
Shell.Sync.su(fmt("for usr in /data/user/*; do cat %s > ${usr}/%s; done", xml, Const.MANAGER_CONFIGS));
}
public static void loadPrefs() {
SuFile config = new SuFile(fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true);
if (config.exists()) {
MagiskManager mm = MagiskManager.get();
SharedPreferences.Editor editor = mm.prefs.edit();
try {
SuFileInputStream is = new SuFileInputStream(config);
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, "UTF-8");
parser.nextTag();
parser.require(XmlPullParser.START_TAG, null, "map");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG)
continue;
String key = parser.getAttributeValue(null, "name");
String value = parser.getAttributeValue(null, "value");
switch (parser.getName()) {
case "string":
parser.require(XmlPullParser.START_TAG, null, "string");
editor.putString(key, parser.nextText());
parser.require(XmlPullParser.END_TAG, null, "string");
break;
case "boolean":
parser.require(XmlPullParser.START_TAG, null, "boolean");
editor.putBoolean(key, Boolean.parseBoolean(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "boolean");
break;
case "int":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putInt(key, Integer.parseInt(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
case "long":
parser.require(XmlPullParser.START_TAG, null, "long");
editor.putLong(key, Long.parseLong(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "long");
break;
case "float":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putFloat(key, Float.parseFloat(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
default:
parser.next();
}
}
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
editor.remove(Const.Key.ETAG_KEY);
editor.apply();
mm.loadConfig();
config.delete();
}
}
public static String fmt(String fmt, Object... args) {
return String.format(Locale.US, fmt, args);
}

View File

@ -0,0 +1,7 @@
<resources>
<string name="download_file_error">خطأ تنزيل الملف</string>
<string name="no_rw_storage">أن هذه الميزة لا تعمل دون الحصول على إذن الكتابة على التخزين الخارجي.</string>
<string name="no_thanks">لا شكراً</string>
<string name="yes">نعم</string>
<string name="ok">موافق</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="downloading_toast">Изтегляне на %1$s</string>
<string name="download_file_error">Грешка при изтеглянето на файла</string>
<string name="no_rw_storage">Тази функция няма да работи без разрешение за запис във външната памет.</string>
<string name="no_thanks">Не, благодаря</string>
<string name="yes">Да</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Chyba při Stahování souboru</string>
<string name="downloading_toast">Stahování %1$s</string>
<string name="no_rw_storage">Tato funkce nebude fungovat bez povolení k zápisu na externí úložiště.</string>
<string name="no_thanks">Ne, díky</string>
<string name="yes">Ano</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Fehler beim Herunterladen der Datei</string>
<string name="downloading_toast">Herunterladen von %1$s</string>
<string name="no_rw_storage">Diese Funktion benötigt Rechte zum Schreiben auf den externen Speicher.</string>
<string name="no_thanks">Nein danke</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
<string name="downloading_toast">Κατέβασμα %1$s</string>
<string name="no_rw_storage">Η λειτουργία αυτή δεν θα δουλέψει χωρίς την άδεια εγγραφής στον εξωτερικό χώρο αποθηκεύσης.</string>
<string name="no_thanks">Όχι ευχαριστώ</string>
<string name="yes">Ναι</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Error descargando archivo</string>
<string name="downloading_toast">Descargando %1$s</string>
<string name="no_rw_storage">Esta opción no funcionará sin permiso de escritura en la memoria externa.</string>
<string name="no_thanks">No gracias</string>
<string name="yes"></string>
<string name="ok">Aceptar</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Faili allalaadimisel esines viga</string>
<string name="downloading_toast">Laadin %1$s alla</string>
<string name="no_rw_storage">See funktsioon ei tööta ilma välismälule kirjutamise õiguseta.</string>
<string name="no_thanks">Tänan ei</string>
<string name="yes">Jah</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Erreur de téléchargement du fichier</string>
<string name="downloading_toast">Téléchargement %1$s</string>
<string name="no_rw_storage">Cette fonctionnalité ne marchera pas sans la permission d\'écriture sur le stockage externe.</string>
<string name="no_thanks">Non merci</string>
<string name="yes">Oui</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Pogreška prilikom preuzimanja datoteke</string>
<string name="downloading_toast">Preuzimanje %1$s</string>
<string name="no_rw_storage">Ova značajka neće raditi bez dopuštenja za korištenje vanjske pohrane.</string>
<string name="no_thanks">Ne hvala</string>
<string name="yes">Da</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Kesalahan mengunduh file</string>
<string name="downloading_toast">Mengunduh %1$s</string>
<string name="no_rw_storage">Fitur ini tidak akan bekerja tanpa izin untuk menulis ke penyimpanan eksternal.</string>
<string name="no_thanks">Tidak, terima kasih</string>
<string name="yes">Ya</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Errore nel download del file</string>
<string name="downloading_toast">Download di %1$s</string>
<string name="no_rw_storage">Questa funzione non sarà attiva senza l\'autorizzazione di scrittura nella memoria di archiviazione esterna</string>
<string name="no_thanks">No, grazie</string>
<string name="yes"></string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
<string name="downloading_toast">%1$s をダウンロード中</string>
<string name="no_rw_storage">この機能は外部ストレージへの書き込み権限がないと動作しません</string>
<string name="no_thanks">いいえ</string>
<string name="yes">はい</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">파일 다운로드 오류</string>
<string name="downloading_toast">%1$s 다운로드 중</string>
<string name="no_rw_storage">이 기능은 외부 저장소 쓰기 권한 없이는 작동하지 않습니다.</string>
<string name="no_thanks">아니오, 괜찮습니다</string>
<string name="yes"></string>
<string name="ok">확인</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Atsisiunčiant failą įvyko klaida</string>
<string name="downloading_toast">Atsisiunčiamas %1$s</string>
<string name="no_rw_storage">Ši funkija neveiks be prieigos prie saugyklos</string>
<string name="no_thanks">Ačiū, nereikia</string>
<string name="yes">Taip</string>
<string name="ok">Gerai</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Fout tijdens downloaden</string>
<string name="downloading_toast">%1$s downloaden</string>
<string name="no_rw_storage">Deze functie werkt niet zonder schrijfpermissie voor externe opslag.</string>
<string name="no_thanks">Nee bedankt</string>
<string name="yes">Ja</string>
<string name="ok">Oké</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Błąd pobierania pliku</string>
<string name="downloading_toast">Pobieranie %1$s</string>
<string name="no_rw_storage">Ta funkcja nie będzie działać bez uprawnień do zapisu na pamięci zewnętrznej.</string>
<string name="no_thanks">Nie dziękuję</string>
<string name="yes">Tak</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Erro ao baixar arquivo</string>
<string name="downloading_toast">Baixando %1$s</string>
<string name="no_rw_storage">Este recurso não funcionará sem permissão para gravar no armazenamento externo.</string>
<string name="no_thanks">Não</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Erro ao transferir ficheiro</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="no_rw_storage">Esta funcionalidade não funcionará sem permissão de escrita do armazenamento externo.</string>
<string name="no_thanks">Não, Obrigado</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Eroare la descărcarea fișierului</string>
<string name="downloading_toast">Descărcare %1$s</string>
<string name="no_rw_storage">Această caracteristică nu va funcționa fără permisiunea de a scrie pe memoria externă.</string>
<string name="no_thanks">Nu, mulţumesc</string>
<string name="yes">Da</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Ошибка загрузки файла</string>
<string name="downloading_toast">Загрузка %1$s</string>
<string name="no_rw_storage">Требуется разрешение на запись во внешнее хранилище.</string>
<string name="no_thanks">Нет</string>
<string name="yes">Да</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Грешка при преузимању фајла</string>
<string name="downloading_toast">Преузимање %1$s</string>
<string name="no_rw_storage">Ово својство неће радити без дозволе приступу екстерном складишту.</string>
<string name="no_thanks">Не хвала</string>
<string name="yes">Да</string>
<string name="ok">ОК</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Fel vid nerladdning av fil</string>
<string name="downloading_toast">Laddar ner %1$s</string>
<string name="no_rw_storage">Denna funktionen måste ha behörighet att skriva till externt lagringsutrymme.</string>
<string name="no_thanks">Nej tack</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Dosya indirme hatası</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_thanks">Hayır teşekkürler</string>
<string name="yes">Evet</string>
<string name="ok">Tamam</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Помилка завантаження файлу</string>
<string name="downloading_toast">Завантаження %1$s</string>
<string name="no_rw_storage">Ця функція не працюватиме без дозволу на запис у Внутрішнє сховище</string>
<string name="no_thanks">Ні, дякую</string>
<string name="yes">Так</string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">Lỗi tải tập tin</string>
<string name="downloading_toast">Đang tải xuống %1$s</string>
<string name="no_rw_storage">Tính năng này không hoạt động nếu thiếu quyền ghi vào bộ nhớ ngoài.</string>
<string name="no_thanks">Không, cảm ơn</string>
<string name="yes"></string>
<string name="ok">OK</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">下载文件时出错</string>
<string name="downloading_toast">正在下载 %1$s</string>
<string name="no_rw_storage">未授予写入内置存储权限,此功能无法正常工作。</string>
<string name="no_thanks">不,谢谢</string>
<string name="yes"></string>
<string name="ok"></string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="download_file_error">下載文件時出錯</string>
<string name="downloading_toast">正在下載 %1$s</string>
<string name="no_rw_storage">未授予寫入外部存儲權限,此功能無法正常工作。</string>
<string name="no_thanks">不,謝謝</string>
<string name="yes"></string>
<string name="ok"></string>
</resources>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--Not translatable-->
<string name="app_name" translatable="false">Magisk Manager</string>
<string name="magisk" translatable="false">Magisk</string>
<string name="magiskhide" translatable="false">Magisk Hide</string>
<!--Used in both stub and full app-->
<string name="download_file_error">Error downloading file</string>
<string name="downloading_toast">Downloading %1$s</string>
<string name="no_rw_storage">This feature will not work without permission to write external storage.</string>
<string name="no_thanks">No thanks</string>
<string name="yes">Yes</string>
<string name="ok">OK</string>
</resources>

View File

@ -4,13 +4,15 @@
<application>
<activity
android:name=".StubActivity"
android:name=".SplashActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".receivers.ManagerUpdate" />
</application>
</manifest>

View File

@ -0,0 +1,14 @@
package com.topjohnwu.magisk;
import com.topjohnwu.magisk.components.Application;
public class MagiskManager extends Application {
public int magiskVersionCode = -1;
public static MagiskManager get() {
return (MagiskManager) weakSelf.get();
}
public void dumpPrefs() {/* NOP */}
}

View File

@ -0,0 +1,71 @@
package com.topjohnwu.magisk;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import org.json.JSONException;
import org.json.JSONObject;
public class SplashActivity extends Activity {
private String apkLink;
private String version;
private int versionCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Utils.checkNetworkStatus()) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
String str = WebService.getString(Const.Url.STABLE_URL);
try {
JSONObject json = new JSONObject(str);
JSONObject manager = json.getJSONObject("app");
version = manager.getString("version");
versionCode = manager.getInt("versionCode");
apkLink = manager.getString("link");
} catch (JSONException e) {
e.printStackTrace();
finish();
return;
}
runOnUiThread(() -> {
String filename = Utils.fmt("MagiskManager-v%s(%d).apk", version, versionCode);
new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setCancelable(false)
.setTitle(R.string.app_name)
.setMessage(R.string.upgrade_msg)
.setPositiveButton(R.string.yes, (d, w) -> {
Utils.runWithPermission(this, new String[]
{ Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
Intent intent = new Intent(this, ManagerUpdate.class);
intent.putExtra(Const.Key.INTENT_SET_LINK, apkLink);
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
sendBroadcast(intent);
finish();
});
})
.setNegativeButton(R.string.no_thanks, (d, w) -> finish())
.show();
});
});
} else {
new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setCancelable(false)
.setTitle(R.string.app_name)
.setMessage(R.string.no_internet_msg)
.setNegativeButton(R.string.ok, (d, w) -> finish())
.show();
}
}
}

View File

@ -1,14 +0,0 @@
package com.topjohnwu.magisk;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
public class StubActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* TODO: Implement stub */
}
}

View File

@ -0,0 +1,5 @@
package com.topjohnwu.magisk.components;
import android.app.Activity;
public abstract class FlavorActivity extends Activity {}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="upgrade_msg">Upgrade to full Magisk Manager to finish the setup. Download and install?</string>
<string name="no_internet_msg">Please connect to the Internet! Upgrading to full Magisk Manager is required.</string>
</resources>