Add hide Magisk Manager feature
1
.gitignore
vendored
@ -9,3 +9,4 @@ app/.externalNativeBuild/
|
|||||||
*.sh
|
*.sh
|
||||||
public.certificate.x509.pem
|
public.certificate.x509.pem
|
||||||
private.key.pk8
|
private.key.pk8
|
||||||
|
*.apk
|
||||||
|
@ -53,10 +53,11 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.android.support:recyclerview-v7:26.0.0'
|
implementation project(':resource')
|
||||||
implementation 'com.android.support:cardview-v7:26.0.0'
|
implementation 'com.android.support:recyclerview-v7:26.0.1'
|
||||||
implementation 'com.android.support:design:26.0.0'
|
implementation 'com.android.support:cardview-v7:26.0.1'
|
||||||
implementation 'com.android.support:support-v4:26.0.0'
|
implementation 'com.android.support:design:26.0.1'
|
||||||
|
implementation 'com.android.support:support-v4:26.0.1'
|
||||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||||
implementation 'com.atlassian.commonmark:commonmark:0.9.0'
|
implementation 'com.atlassian.commonmark:commonmark:0.9.0'
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.57'
|
implementation 'org.bouncycastle:bcprov-jdk15on:1.57'
|
||||||
|
@ -53,6 +53,9 @@ public class MagiskFragment extends Fragment
|
|||||||
|
|
||||||
public static final String SHOW_DIALOG = "dialog";
|
public static final String SHOW_DIALOG = "dialog";
|
||||||
|
|
||||||
|
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||||
|
private static final String UTIL_FUNCTIONS= "util_functions.sh";
|
||||||
|
|
||||||
private static int expandHeight = 0;
|
private static int expandHeight = 0;
|
||||||
private static boolean mExpanded = false;
|
private static boolean mExpanded = false;
|
||||||
|
|
||||||
@ -176,8 +179,8 @@ public class MagiskFragment extends Fragment
|
|||||||
.setMessage(R.string.uninstall_magisk_msg)
|
.setMessage(R.string.uninstall_magisk_msg)
|
||||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||||
try {
|
try {
|
||||||
InputStream in = magiskManager.getAssets().open(MagiskManager.UNINSTALLER);
|
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
||||||
File uninstaller = new File(magiskManager.getCacheDir(), MagiskManager.UNINSTALLER);
|
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
||||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||||
byte[] bytes = new byte[1024];
|
byte[] bytes = new byte[1024];
|
||||||
int read;
|
int read;
|
||||||
@ -186,8 +189,8 @@ public class MagiskFragment extends Fragment
|
|||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
out.close();
|
out.close();
|
||||||
in = magiskManager.getAssets().open(MagiskManager.UTIL_FUNCTIONS);
|
in = magiskManager.getAssets().open(UTIL_FUNCTIONS);
|
||||||
File utils = new File(magiskManager.getCacheDir(), MagiskManager.UTIL_FUNCTIONS);
|
File utils = new File(magiskManager.getCacheDir(), UTIL_FUNCTIONS);
|
||||||
out = new FileOutputStream(utils);
|
out = new FileOutputStream(utils);
|
||||||
while ((read = in.read(bytes)) != -1) {
|
while ((read = in.read(bytes)) != -1) {
|
||||||
out.write(bytes, 0, read);
|
out.write(bytes, 0, read);
|
||||||
@ -207,8 +210,8 @@ public class MagiskFragment extends Fragment
|
|||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||||
Shell.getShell(getActivity()).su_raw(
|
Shell.getShell(getActivity()).su_raw(
|
||||||
"mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER,
|
"mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
||||||
"mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS,
|
"mv -f " + utils + " /data/magisk/" + UTIL_FUNCTIONS,
|
||||||
"reboot"
|
"reboot"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,6 @@ public class MagiskManager extends Application {
|
|||||||
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
|
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
|
||||||
public static final String TMP_FOLDER_PATH = "/dev/tmp";
|
public static final String TMP_FOLDER_PATH = "/dev/tmp";
|
||||||
public static final String MAGISK_PATH = "/magisk";
|
public static final String MAGISK_PATH = "/magisk";
|
||||||
public static final String UNINSTALLER = "magisk_uninstaller.sh";
|
|
||||||
public static final String UTIL_FUNCTIONS= "util_functions.sh";
|
|
||||||
public static final String INTENT_SECTION = "section";
|
public static final String INTENT_SECTION = "section";
|
||||||
public static final String INTENT_VERSION = "version";
|
public static final String INTENT_VERSION = "version";
|
||||||
public static final String INTENT_LINK = "link";
|
public static final String INTENT_LINK = "link";
|
||||||
|
@ -4,6 +4,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@ -13,6 +14,7 @@ import android.support.v7.app.ActionBar;
|
|||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.asyncs.HideManager;
|
||||||
import com.topjohnwu.magisk.components.Activity;
|
import com.topjohnwu.magisk.components.Activity;
|
||||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
@ -98,6 +100,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
|||||||
multiuserMode = (ListPreference) findPreference("multiuser_mode");
|
multiuserMode = (ListPreference) findPreference("multiuser_mode");
|
||||||
namespaceMode = (ListPreference) findPreference("mnt_ns");
|
namespaceMode = (ListPreference) findPreference("mnt_ns");
|
||||||
SwitchPreference reauth = (SwitchPreference) findPreference("su_reauth");
|
SwitchPreference reauth = (SwitchPreference) findPreference("su_reauth");
|
||||||
|
Preference hideManager = findPreference("hide");
|
||||||
|
|
||||||
setSummary();
|
setSummary();
|
||||||
|
|
||||||
@ -105,6 +108,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
|||||||
if (getActivity().getApplicationInfo().uid > 99999) {
|
if (getActivity().getApplicationInfo().uid > 99999) {
|
||||||
prefScreen.removePreference(magiskCategory);
|
prefScreen.removePreference(magiskCategory);
|
||||||
prefScreen.removePreference(suCategory);
|
prefScreen.removePreference(suCategory);
|
||||||
|
generalCatagory.removePreference(hideManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove re-authentication option on Android O, it will not work
|
// Remove re-authentication option on Android O, it will not work
|
||||||
@ -117,6 +121,11 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
hideManager.setOnPreferenceClickListener((pref) -> {
|
||||||
|
new HideManager(getActivity()).exec();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
if (!BuildConfig.DEBUG) {
|
if (!BuildConfig.DEBUG) {
|
||||||
prefScreen.removePreference(developer);
|
prefScreen.removePreference(developer);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
|
import com.topjohnwu.magisk.R;
|
||||||
|
import com.topjohnwu.magisk.superuser.Policy;
|
||||||
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HideManager extends ParallelTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
|
public HideManager(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
getMagiskManager().toast(R.string.hide_manager_toast, Toast.LENGTH_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Void... voids) {
|
||||||
|
MagiskManager magiskManager = getMagiskManager();
|
||||||
|
if (magiskManager == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Generate a new unhide app with random package name
|
||||||
|
File unhideAPK = new File(magiskManager.getCacheDir(), "unhide.apk");
|
||||||
|
String pkg = ZipUtils.generateUnhide(magiskManager, unhideAPK);
|
||||||
|
|
||||||
|
// Install the application
|
||||||
|
List<String> ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
|
||||||
|
unhideAPK.delete();
|
||||||
|
if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Allow the application to gain root by default
|
||||||
|
PackageManager pm = magiskManager.getPackageManager();
|
||||||
|
int uid = pm.getApplicationInfo(pkg, 0).uid;
|
||||||
|
Policy policy = new Policy(uid, pm);
|
||||||
|
policy.policy = Policy.ALLOW;
|
||||||
|
policy.notification = false;
|
||||||
|
policy.logging = false;
|
||||||
|
magiskManager.suDB.addPolicy(policy);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide myself!
|
||||||
|
getShell().su_raw("pm hide " + magiskManager.getPackageName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean b) {
|
||||||
|
MagiskManager magiskManager = getMagiskManager();
|
||||||
|
if (magiskManager == null)
|
||||||
|
return;
|
||||||
|
if (!b) {
|
||||||
|
magiskManager.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
|
||||||
|
}
|
||||||
|
super.onPostExecute(b);
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
|||||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -288,4 +289,25 @@ public class Utils {
|
|||||||
|
|
||||||
return locales;
|
return locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String genPackageName(String prefix, int length) {
|
||||||
|
StringBuilder builder = new StringBuilder(length);
|
||||||
|
builder.append(prefix);
|
||||||
|
length -= prefix.length();
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
String base = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
String alpha = base + base.toUpperCase();
|
||||||
|
String full = alpha + "0123456789..........";
|
||||||
|
char next, prev = '\0';
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
if (prev == '.' || i == length - 1 || i == 0) {
|
||||||
|
next = alpha.charAt(random.nextInt(alpha.length()));
|
||||||
|
} else {
|
||||||
|
next = full.charAt(random.nextInt(full.length()));
|
||||||
|
}
|
||||||
|
builder.append(next);
|
||||||
|
prev = next;
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.ASN1InputStream;
|
import org.bouncycastle.asn1.ASN1InputStream;
|
||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||||
@ -65,6 +66,7 @@ public class ZipUtils {
|
|||||||
// File name in assets
|
// File name in assets
|
||||||
private static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
|
private static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
|
||||||
private static final String PRIVATE_KEY_NAME = "private.key.pk8";
|
private static final String PRIVATE_KEY_NAME = "private.key.pk8";
|
||||||
|
private static final String UNHIDE_NAME = "unhide.apk";
|
||||||
|
|
||||||
private static final String CERT_SF_NAME = "META-INF/CERT.SF";
|
private static final String CERT_SF_NAME = "META-INF/CERT.SF";
|
||||||
private static final String CERT_SIG_NAME = "META-INF/CERT.%s";
|
private static final String CERT_SIG_NAME = "META-INF/CERT.%s";
|
||||||
@ -82,6 +84,45 @@ public class ZipUtils {
|
|||||||
|
|
||||||
public native static void zipAdjust(String filenameIn, String filenameOut);
|
public native static void zipAdjust(String filenameIn, String filenameOut);
|
||||||
|
|
||||||
|
public static String generateUnhide(Context context, File output) {
|
||||||
|
File temp = new File(context.getCacheDir(), "temp.apk");
|
||||||
|
String pkg = "";
|
||||||
|
try {
|
||||||
|
JarInputStream source = new JarInputStream(context.getAssets().open(UNHIDE_NAME));
|
||||||
|
JarOutputStream dest = new JarOutputStream(new FileOutputStream(temp));
|
||||||
|
JarEntry entry;
|
||||||
|
int size;
|
||||||
|
byte buffer[] = new byte[4096];
|
||||||
|
while ((entry = source.getNextJarEntry()) != null) {
|
||||||
|
dest.putNextEntry(new JarEntry(entry.getName()));
|
||||||
|
if (TextUtils.equals(entry.getName(), "AndroidManifest.xml")) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
while((size = source.read(buffer)) != -1) {
|
||||||
|
baos.write(buffer, 0, size);
|
||||||
|
}
|
||||||
|
byte xml[] = baos.toByteArray();
|
||||||
|
pkg = Utils.genPackageName("com.", 20);
|
||||||
|
for (int i = 0; i < 20; ++i) {
|
||||||
|
xml[424 + i] = (byte) pkg.charAt(i);
|
||||||
|
}
|
||||||
|
dest.write(xml);
|
||||||
|
} else {
|
||||||
|
while((size = source.read(buffer)) != -1) {
|
||||||
|
dest.write(buffer, 0, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source.close();
|
||||||
|
dest.close();
|
||||||
|
signZip(context, temp, output, false);
|
||||||
|
temp.delete();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
|
||||||
public static void removeTopFolder(InputStream in, File output) throws IOException {
|
public static void removeTopFolder(InputStream in, File output) throws IOException {
|
||||||
try {
|
try {
|
||||||
JarInputStream source = new JarInputStream(in);
|
JarInputStream source = new JarInputStream(in);
|
||||||
@ -102,7 +143,7 @@ public class ZipUtils {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dest.putNextEntry(new JarEntry(path));
|
dest.putNextEntry(new JarEntry(path));
|
||||||
while((size = source.read(buffer, 0, 2048)) != -1) {
|
while((size = source.read(buffer)) != -1) {
|
||||||
dest.write(buffer, 0, size);
|
dest.write(buffer, 0, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,8 @@
|
|||||||
<string name="manager_download_install">Press to download and install</string>
|
<string name="manager_download_install">Press to download and install</string>
|
||||||
<string name="magisk_updates">Magisk Updates</string>
|
<string name="magisk_updates">Magisk Updates</string>
|
||||||
<string name="flashing">Flashing</string>
|
<string name="flashing">Flashing</string>
|
||||||
|
<string name="hide_manager_toast">Hiding Magisk Manager…</string>
|
||||||
|
<string name="hide_manager_fail_toast">Hide Magisk Manager failed…</string>
|
||||||
|
|
||||||
<!--Settings Activity -->
|
<!--Settings Activity -->
|
||||||
<string name="settings_general_category">General</string>
|
<string name="settings_general_category">General</string>
|
||||||
@ -145,6 +147,8 @@
|
|||||||
<string name="settings_notification_summary">Show update notifications when new version is available</string>
|
<string name="settings_notification_summary">Show update notifications when new version is available</string>
|
||||||
<string name="settings_clear_cache_title">Clear Repo Cache</string>
|
<string name="settings_clear_cache_title">Clear Repo Cache</string>
|
||||||
<string name="settings_clear_cache_summary">Clear the cached information for online repos, forces the app to refresh online</string>
|
<string name="settings_clear_cache_summary">Clear the cached information for online repos, forces the app to refresh online</string>
|
||||||
|
<string name="settings_hide_manager_title">Hide Magisk Manager</string>
|
||||||
|
<string name="settings_hide_manager_summary">Temporarily hide Magisk Manager.\nThis will install a new app called \"Unhide Magisk Manager\"</string>
|
||||||
<string name="language">Language</string>
|
<string name="language">Language</string>
|
||||||
<string name="system_default">(System Default)</string>
|
<string name="system_default">(System Default)</string>
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@
|
|||||||
android:title="@string/settings_clear_cache_title"
|
android:title="@string/settings_clear_cache_title"
|
||||||
android:summary="@string/settings_clear_cache_summary" />
|
android:summary="@string/settings_clear_cache_summary" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="hide"
|
||||||
|
android:title="@string/settings_hide_manager_title"
|
||||||
|
android:summary="@string/settings_hide_manager_summary" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
1
resource/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
23
resource/build.gradle
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 26
|
||||||
|
buildToolsVersion "26.0.1"
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 26
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
}
|
1
resource/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="com.topjohnwu.resource" />
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@ -1 +1 @@
|
|||||||
include ':app'
|
include ':app', ':unhide', ':resource'
|
1
unhide/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
25
unhide/build.gradle
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 26
|
||||||
|
buildToolsVersion "26.0.1"
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.topjohnwu.unhide"
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 26
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
shrinkResources true
|
||||||
|
minifyEnabled true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
implementation project(':resource')
|
||||||
|
}
|
25
unhide/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/topjohnwu/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
17
unhide/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.topjohnwu.unhide">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="Unhide Magisk Manager"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
<activity android:name=".MainActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
33
unhide/src/main/java/com/topjohnwu/unhide/MainActivity.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.topjohnwu.unhide;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class MainActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
String command = String.format(
|
||||||
|
"pm unhide com.topjohnwu.magisk\n" +
|
||||||
|
"am start -n com.topjohnwu.magisk/.SplashActivity\n" +
|
||||||
|
"pm uninstall %s\n" +
|
||||||
|
"exit\n",
|
||||||
|
getApplicationInfo().packageName);
|
||||||
|
Process process;
|
||||||
|
try {
|
||||||
|
process = Runtime.getRuntime().exec("su");
|
||||||
|
OutputStream in = process.getOutputStream();
|
||||||
|
in.write(command.getBytes("UTF-8"));
|
||||||
|
in.flush();
|
||||||
|
process.waitFor();
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|