Organize application initialization

This commit is contained in:
topjohnwu 2017-11-06 04:47:24 +08:00
parent c39170c42e
commit ce5b13824e
7 changed files with 146 additions and 200 deletions

View File

@ -159,7 +159,7 @@ public class MagiskFragment extends Fragment
@Override @Override
public void onRefresh() { public void onRefresh() {
mm.getMagiskInfo(); mm.loadMagiskInfo();
updateUI(); updateUI();
magiskUpdateText.setText(R.string.checking_for_updates); magiskUpdateText.setText(R.string.checking_for_updates);

View File

@ -1,43 +1,26 @@
package com.topjohnwu.magisk; package com.topjohnwu.magisk;
import android.annotation.SuppressLint;
import android.app.Application; import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.widget.Toast; import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.DownloadBusybox;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.container.Module; import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.database.RepoDatabaseHelper; import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
public class MagiskManager extends Application { public class MagiskManager extends Application {
@ -54,6 +37,7 @@ public class MagiskManager extends Application {
public final Topic localeDone = new Topic(); public final Topic localeDone = new Topic();
// Info // Info
public boolean hasInit = false;
public int userId; public int userId;
public String magiskVersionString; public String magiskVersionString;
public int magiskVersionCode = -1; public int magiskVersionCode = -1;
@ -102,7 +86,6 @@ public class MagiskManager extends Application {
public Shell shell; public Shell shell;
private static Handler mHandler = new Handler(); private static Handler mHandler = new Handler();
private boolean started = false;
public MagiskManager() { public MagiskManager() {
weakSelf = new WeakReference<>(this); weakSelf = new WeakReference<>(this);
@ -180,127 +163,7 @@ public class MagiskManager extends Application {
mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show()); mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show());
} }
@SuppressLint("StaticFieldLeak") public void loadMagiskInfo() {
public void startup() {
if (started)
return;
started = true;
// Dynamic detect all locales
new ParallelTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
locales = Utils.getAvailableLocale();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
localeDone.publish();
}
}.exec();
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Const.ID.NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
getMagiskInfo();
// Magisk working as expected
if (Shell.rootAccess() && magiskVersionCode > 0) {
// Load utility shell scripts
try (InputStream in = getAssets().open(Const.UTIL_FUNCTIONS)) {
shell.loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
LoadModules loadModuleTask = new LoadModules();
if (Utils.checkNetworkStatus()) {
// Make sure we have busybox
if (!Utils.itemExist(Const.BUSYBOXPATH + "/busybox")) {
try {
// Force synchronous, make sure we have busybox to use
new DownloadBusybox().exec().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
// Fire update check
new CheckUpdates().exec();
// Add repo update check
loadModuleTask.setCallBack(() -> new UpdateRepos(false).exec());
}
// Root shell initialization
Shell.su_raw(
"export PATH=" + Const.BUSYBOXPATH + ":$PATH",
"mount_partitions",
"BOOTIMAGE=",
"find_boot_image",
"migrate_boot_backup"
);
List<String> ret = Shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(ret)) {
bootBlock = ret.get(0);
} else {
blockList = Shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
}
// Setup suDB
SuDatabaseHelper.setupSuDB();
// Check alternative Magisk Manager
String pkg;
if (getPackageName().equals(Const.ORIG_PKG_NAME) &&
(pkg = suDB.getStrings(Const.Key.SU_REQUESTER, null)) != null) {
Shell.su_raw("pm uninstall " + pkg);
suDB.setStrings(Const.Key.SU_REQUESTER, null);
}
// Add update checking service
if (Const.Value.UPDATE_SERVICE_VER > updateServiceVersion) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(info);
updateServiceVersion = Const.Value.UPDATE_SERVICE_VER;
}
// Fire asynctasks
loadModuleTask.exec();
}
// Write back default values
prefs.edit()
.putBoolean(Const.Key.DARK_THEME, isDarkTheme)
.putBoolean(Const.Key.MAGISKHIDE, magiskHide)
.putBoolean(Const.Key.UPDATE_NOTIFICATION, updateNotification)
.putBoolean(Const.Key.HOSTS, Utils.itemExist(Const.MAGISK_HOST_FILE))
.putBoolean(Const.Key.DISABLE, Utils.itemExist(Const.MAGISK_DISABLE_FILE))
.putBoolean(Const.Key.SU_REAUTH, suReauth)
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(suRequestTimeout))
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(suResponseType))
.putString(Const.Key.SU_NOTIFICATION, String.valueOf(suNotificationType))
.putString(Const.Key.ROOT_ACCESS, String.valueOf(suAccessState))
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(multiuserMode))
.putString(Const.Key.SU_MNT_NS, String.valueOf(suNamespaceMode))
.putString(Const.Key.UPDATE_CHANNEL, String.valueOf(updateChannel))
.putString(Const.Key.LOCALE, localeConfig)
.putString(Const.Key.BOOT_FORMAT, bootFormat)
.putInt(Const.Key.UPDATE_SERVICE_VER, updateServiceVersion)
.apply();
}
public void getMagiskInfo() {
List<String> ret; List<String> ret;
ret = Shell.sh("su -v"); ret = Shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) { if (Utils.isValidShellResponse(ret)) {

View File

@ -39,11 +39,22 @@ public class MainActivity extends Activity
@Override @Override
protected void onCreate(final Bundle savedInstanceState) { protected void onCreate(final Bundle savedInstanceState) {
getMagiskManager().startup();
prefs = getMagiskManager().prefs; MagiskManager mm = getMagiskManager();
if (getMagiskManager().isDarkTheme) { if (!mm.hasInit) {
Intent intent = new Intent(this, SplashActivity.class);
String section = getIntent().getStringExtra(Const.Key.OPEN_SECTION);
if (section != null) {
intent.putExtra(Const.Key.OPEN_SECTION, section);
}
startActivity(intent);
finish();
}
prefs = mm.prefs;
if (mm.isDarkTheme) {
setTheme(R.style.AppTheme_Dark); setTheme(R.style.AppTheme_Dark);
} }
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -74,7 +85,6 @@ public class MainActivity extends Activity
navigate(getIntent().getStringExtra(Const.Key.OPEN_SECTION)); navigate(getIntent().getStringExtra(Const.Key.OPEN_SECTION));
navigationView.setNavigationItemSelectedListener(this); navigationView.setNavigationItemSelectedListener(this);
} }
@Override @Override

View File

@ -1,10 +1,29 @@
package com.topjohnwu.magisk; package com.topjohnwu.magisk;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.Activity; import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class SplashActivity extends Activity { public class SplashActivity extends Activity {
@ -12,7 +31,103 @@ public class SplashActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
getMagiskManager().startup(); MagiskManager mm = getMagiskManager();
// Dynamic detect all locales
new LoadLocale().exec();
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Const.ID.NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
mm.loadMagiskInfo();
LoadModules loadModuleTask = new LoadModules();
if (Utils.checkNetworkStatus()) {
// Fire update check
new CheckUpdates().exec();
// Add repo update check
loadModuleTask.setCallBack(() -> new UpdateRepos(false).exec());
}
// Magisk working as expected
if (Shell.rootAccess() && mm.magiskVersionCode > 0) {
// Load utility shell scripts
try (InputStream in = getAssets().open(Const.UTIL_FUNCTIONS)) {
Shell.getShell().loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
// Root shell initialization
Shell.su_raw(
"export PATH=" + Const.BUSYBOXPATH + ":$PATH",
"mount_partitions",
"BOOTIMAGE=",
"find_boot_image",
"migrate_boot_backup"
);
List<String> ret = Shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(ret)) {
mm.bootBlock = ret.get(0);
} else {
mm.blockList = Shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
}
// Setup suDB
SuDatabaseHelper.setupSuDB();
// Check alternative Magisk Manager
String pkg;
if (getPackageName().equals(Const.ORIG_PKG_NAME) &&
(pkg = mm.suDB.getStrings(Const.Key.SU_REQUESTER, null)) != null) {
Shell.su_raw("pm uninstall " + pkg);
mm.suDB.setStrings(Const.Key.SU_REQUESTER, null);
}
// Add update checking service
if (Const.Value.UPDATE_SERVICE_VER > mm.updateServiceVersion) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(info);
mm.updateServiceVersion = Const.Value.UPDATE_SERVICE_VER;
}
// Fire asynctasks
loadModuleTask.exec();
}
// Write back default values
mm.prefs.edit()
.putBoolean(Const.Key.DARK_THEME, mm.isDarkTheme)
.putBoolean(Const.Key.MAGISKHIDE, mm.magiskHide)
.putBoolean(Const.Key.UPDATE_NOTIFICATION, mm.updateNotification)
.putBoolean(Const.Key.HOSTS, Utils.itemExist(Const.MAGISK_HOST_FILE))
.putBoolean(Const.Key.DISABLE, Utils.itemExist(Const.MAGISK_DISABLE_FILE))
.putBoolean(Const.Key.SU_REAUTH, mm.suReauth)
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(mm.suRequestTimeout))
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(mm.suResponseType))
.putString(Const.Key.SU_NOTIFICATION, String.valueOf(mm.suNotificationType))
.putString(Const.Key.ROOT_ACCESS, String.valueOf(mm.suAccessState))
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(mm.multiuserMode))
.putString(Const.Key.SU_MNT_NS, String.valueOf(mm.suNamespaceMode))
.putString(Const.Key.UPDATE_CHANNEL, String.valueOf(mm.updateChannel))
.putString(Const.Key.LOCALE, mm.localeConfig)
.putString(Const.Key.BOOT_FORMAT, mm.bootFormat)
.putInt(Const.Key.UPDATE_SERVICE_VER, mm.updateServiceVersion)
.apply();
mm.hasInit = true;
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(Const.Key.OPEN_SECTION); String section = getIntent().getStringExtra(Const.Key.OPEN_SECTION);
@ -22,4 +137,16 @@ public class SplashActivity extends Activity {
startActivity(intent); startActivity(intent);
finish(); finish();
} }
static class LoadLocale extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
MagiskManager.get().locales = Utils.getAvailableLocale();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
MagiskManager.get().localeDone.publish();
}
}
} }

View File

@ -1,52 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.os.Build;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
Context context = MagiskManager.get();
File busybox = new File(context.getCacheDir(), "busybox");
Utils.removeItem(context.getApplicationInfo().dataDir + "/busybox");
try (FileOutputStream out = new FileOutputStream(busybox)) {
HttpURLConnection conn = WebService.request(
Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ?
Const.Url.BUSYBOX_X86 :
Const.Url.BUSYBOX_ARM,
null
);
if (conn == null) throw new IOException();
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
Utils.inToOut(bis, out);
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
if (busybox.exists()) {
Shell.su(
"rm -rf " + Const.BUSYBOXPATH,
"mkdir -p " + Const.BUSYBOXPATH,
"cp " + busybox + " " + Const.BUSYBOXPATH,
"chmod -R 755 " + Const.BUSYBOXPATH,
Const.BUSYBOXPATH + "/busybox --install -s " + Const.BUSYBOXPATH
);
busybox.delete();
}
return null;
}
}

View File

@ -10,7 +10,7 @@ public class UpdateCheckService extends JobService {
@Override @Override
public boolean onStartJob(JobParameters params) { public boolean onStartJob(JobParameters params) {
Utils.getMagiskManager(this).getMagiskInfo(); Utils.getMagiskManager(this).loadMagiskInfo();
new CheckUpdates(true) new CheckUpdates(true)
.setCallBack(() -> jobFinished(params, false)).exec(); .setCallBack(() -> jobFinished(params, false)).exec();
return true; return true;

View File

@ -56,8 +56,6 @@ public class Const {
public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/stable.json"; public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/stable.json";
public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/beta.json"; public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/beta.json";
public static final String SNET_URL = "https://www.dropbox.com/s/jg2yhcrn3l9fckc/snet.apk?dl=1"; public static final String SNET_URL = "https://www.dropbox.com/s/jg2yhcrn3l9fckc/snet.apk?dl=1";
public static final String BUSYBOX_ARM = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-arm";
public static final String BUSYBOX_X86 = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-x86";
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&page=%d"; public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&page=%d";
public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s"; public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip"; public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";