From d99252f3945e8cbe81e1781cb226f9084ed78b62 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 17 Feb 2017 08:51:51 +0800 Subject: [PATCH] Add update notification --- app/src/main/AndroidManifest.xml | 8 +- .../com/topjohnwu/magisk/AboutActivity.java | 2 +- .../com/topjohnwu/magisk/MagiskManager.java | 1 + .../com/topjohnwu/magisk/MainActivity.java | 83 +++++++++++++------ .../topjohnwu/magisk/SettingsActivity.java | 5 +- .../com/topjohnwu/magisk/SplashActivity.java | 37 +++++++-- .../com/topjohnwu/magisk/StatusFragment.java | 40 ++------- .../topjohnwu/magisk/asyncs/CheckUpdates.java | 44 +++++++++- .../topjohnwu/magisk/components/Activity.java | 3 +- .../magisk/receivers/BootReceiver.java | 30 +------ .../magisk/services/BootupIntentService.java | 34 ++++++++ .../magisk/services/UpdateCheckService.java | 31 +++++++ .../magisk/superuser/RequestActivity.java | 5 +- .../magisk/superuser/SuRequestActivity.java | 2 +- .../com/topjohnwu/magisk/utils/Logger.java | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- 16 files changed, 222 insertions(+), 107 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/services/BootupIntentService.java create mode 100644 app/src/main/java/com/topjohnwu/magisk/services/UpdateCheckService.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6bad618a8..ea3d526ac 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ + - + + + repoMap; diff --git a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java index 00150704d..2c74c0aed 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java @@ -29,8 +29,11 @@ import butterknife.ButterKnife; public class MainActivity extends Activity implements NavigationView.OnNavigationItemSelectedListener, CallbackEvent.Listener { + public static final String SECTION = "section"; + private final Handler mDrawerHandler = new Handler(); private SharedPreferences prefs; + private int mDrawerItem; @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.drawer_layout) DrawerLayout drawer; @@ -41,9 +44,9 @@ public class MainActivity extends Activity @Override protected void onCreate(final Bundle savedInstanceState) { - prefs = getTopApplication().prefs; + prefs = getApplicationContext().prefs; - if (getTopApplication().isDarkTheme) { + if (getApplicationContext().isDarkTheme) { setTheme(R.style.AppTheme_Dark); } super.onCreate(savedInstanceState); @@ -75,32 +78,31 @@ public class MainActivity extends Activity drawer.addDrawerListener(toggle); toggle.syncState(); - navigate(R.id.status); + if (savedInstanceState != null) + navigate(savedInstanceState.getInt(SECTION, R.id.status)); + else + navigate(getIntent().getStringExtra(SECTION)); navigationView.setNavigationItemSelectedListener(this); - getTopApplication().reloadMainActivity.register(this); - - if (getTopApplication().updateCheckDone.isTriggered) - onTrigger(getTopApplication().updateCheckDone); + getApplicationContext().reloadMainActivity.register(this); } @Override protected void onResume() { super.onResume(); - getTopApplication().updateCheckDone.register(this); checkHideSection(); } @Override - protected void onPause() { - getTopApplication().updateCheckDone.unRegister(this); - super.onPause(); + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(SECTION, mDrawerItem); } @Override protected void onDestroy() { - getTopApplication().reloadMainActivity.unRegister(this); + getApplicationContext().reloadMainActivity.unRegister(this); super.onDestroy(); } @@ -122,28 +124,61 @@ public class MainActivity extends Activity @Override public void onTrigger(CallbackEvent event) { - if (event == getTopApplication().updateCheckDone) { - Menu menu = navigationView.getMenu(); - menu.findItem(R.id.install).setVisible( - getTopApplication().remoteMagiskVersion > 0 && Shell.rootAccess()); - } else if (event == getTopApplication().reloadMainActivity) { - recreate(); - } + recreate(); } private void checkHideSection() { Menu menu = navigationView.getMenu(); if (Shell.rootAccess()) { menu.findItem(R.id.magiskhide).setVisible( - getTopApplication().magiskVersion >= 8 && prefs.getBoolean("magiskhide", false)); - menu.findItem(R.id.modules).setVisible(getTopApplication().magiskVersion >= 4); - menu.findItem(R.id.downloads).setVisible(getTopApplication().magiskVersion >= 4); + getApplicationContext().magiskVersion >= 8 && prefs.getBoolean("magiskhide", false)); + menu.findItem(R.id.modules).setVisible(getApplicationContext().magiskVersion >= 4); + menu.findItem(R.id.downloads).setVisible(getApplicationContext().magiskVersion >= 4); menu.findItem(R.id.log).setVisible(true); - menu.findItem(R.id.superuser).setVisible(getTopApplication().isSuClient); + menu.findItem(R.id.superuser).setVisible(getApplicationContext().isSuClient); } + menu.findItem(R.id.install).setVisible(getApplicationContext().remoteMagiskVersion > 0); + } + + public void navigate(String item) { + int itemId = R.id.status; + if (item != null) { + switch (item) { + case "status": + itemId = R.id.status; + break; + case "install": + itemId = R.id.install; + break; + case "superuser": + itemId = R.id.superuser; + break; + case "modules": + itemId = R.id.modules; + break; + case "downloads": + itemId = R.id.downloads; + break; + case "magiskhide": + itemId = R.id.magiskhide; + break; + case "log": + itemId = R.id.log; + break; + case "settings": + itemId = R.id.settings; + break; + case "about": + itemId = R.id.app_about; + break; + } + } + navigate(itemId); } public void navigate(int itemId) { + mDrawerItem = itemId; + navigationView.setCheckedItem(itemId); switch (itemId) { case R.id.status: displayFragment(new StatusFragment(), "status", true); @@ -165,7 +200,6 @@ public class MainActivity extends Activity break; case R.id.log: displayFragment(new LogFragment(), "log", false); - toolbar.setElevation(0); break; case R.id.settings: startActivity(new Intent(this, SettingsActivity.class)); @@ -182,5 +216,6 @@ public class MainActivity extends Activity transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); transaction.replace(R.id.content_frame, navFragment, tag).commitNow(); if (setElevation) toolbar.setElevation(toolbarElevation); + else toolbar.setElevation(0); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java index 871e76ac3..76f30d022 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java @@ -31,7 +31,7 @@ public class SettingsActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (getTopApplication().isDarkTheme) { + if (getApplicationContext().isDarkTheme) { setTheme(R.style.AppTheme_Dark); } @@ -146,8 +146,9 @@ public class SettingsActivity extends Activity { enabled = prefs.getBoolean("dark_theme", false); if (getApplication().isDarkTheme != enabled) { getApplication().isDarkTheme = enabled; - getActivity().recreate(); getApplication().reloadMainActivity.trigger(); + getActivity().finish(); + getActivity().recreate(); } break; case "disable": diff --git a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java index fe8f71f15..9902d20ff 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java @@ -1,5 +1,9 @@ package com.topjohnwu.magisk; +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -10,19 +14,22 @@ import com.topjohnwu.magisk.asyncs.LoadModules; import com.topjohnwu.magisk.asyncs.LoadRepos; import com.topjohnwu.magisk.asyncs.MagiskHide; import com.topjohnwu.magisk.components.Activity; +import com.topjohnwu.magisk.services.UpdateCheckService; import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Utils; import java.util.List; -public class SplashActivity extends Activity { +public class SplashActivity extends Activity{ + + private static final int UPDATE_SERVICE_ID = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - MagiskManager magiskManager = getTopApplication(); + MagiskManager magiskManager = getApplicationContext(); // Init the info and configs and root shell magiskManager.init(); @@ -31,8 +38,17 @@ public class SplashActivity extends Activity { List ret = Shell.sh("getprop persist.magisk.hide"); boolean started = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0; + // Initialize the update check service, notify every 3 hours + ComponentName service = new ComponentName(magiskManager, UpdateCheckService.class); + JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) + .setPersisted(true) + .setPeriodic(3 * 60 * 60 * 1000) + .build(); + JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); + scheduler.schedule(jobInfo); + // Now fire all async tasks - new CheckUpdates(this).exec(); new GetBootBlocks(this).exec(); if (magiskManager.magiskHide && !magiskManager.disabled && magiskManager.magiskVersion > 11 && !started) { @@ -46,10 +62,15 @@ public class SplashActivity extends Activity { } }.exec(); new LoadApps(this).exec(); - - // Preparation done, now start main activity - Intent intent = new Intent(getApplicationContext(), MainActivity.class); - startActivity(intent); - finish(); + new CheckUpdates(this, true){ + @Override + protected void onPostExecute(Void v) { + super.onPostExecute(v); + Intent intent = getIntent().setClass(magiskManager, MainActivity.class) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + }.exec(); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java b/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java index 9bdbb1098..b02efc1dd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java @@ -1,12 +1,9 @@ package com.topjohnwu.magisk; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -58,8 +55,6 @@ public class StatusFragment extends Fragment implements CallbackEvent.Listener { + ((MainActivity) getActivity()).navigationView.setCheckedItem(R.id.install); + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); + try { + transaction.replace(R.id.content_frame, new InstallFragment(), "install").commit(); + } catch (IllegalStateException ignored) {} + }); + if (getApplication().magiskVersion < 0 && Shell.rootAccess() && !noDialog) { noDialog = true; new AlertDialogBuilder(getActivity()) @@ -229,32 +233,6 @@ public class StatusFragment extends Fragment implements CallbackEvent.Listener { - ((MainActivity) getActivity()).navigationView.setCheckedItem(R.id.install); - FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); - try { - transaction.replace(R.id.content_frame, new InstallFragment(), "install").commit(); - } catch (IllegalStateException ignored) {} - }) - .setNeutralButton(R.string.release_notes, (dialog, which) -> { - getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getApplication().releaseNoteLink))); - }) - .setNegativeButton(R.string.no_thanks, null) - .create(); - - if (getApplication().magiskVersion < getApplication().remoteMagiskVersion && Shell.rootAccess()) { - magiskStatusContainer.setOnClickListener(view -> updateMagisk.show()); - if (!noDialog) { - noDialog = true; - updateMagisk.show(); - } - } } private void updateSafetyNetUI() { diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java index efb20c103..87ecb433d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java @@ -1,7 +1,16 @@ package com.topjohnwu.magisk.asyncs; -import android.app.Activity; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.NotificationCompat; +import com.topjohnwu.magisk.MainActivity; +import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.SplashActivity; +import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebService; import org.json.JSONException; @@ -9,10 +18,18 @@ import org.json.JSONObject; public class CheckUpdates extends ParallelTask { - public static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json"; + private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json"; + private static final int NOTIFICATION_ID = 1; - public CheckUpdates(Activity context) { - super(context); + private boolean showNotification = false; + + public CheckUpdates(Context context, boolean b) { + this(context); + showNotification = b && !magiskManager.isNotified; + } + + public CheckUpdates(Context context) { + magiskManager = Utils.getMagiskManager(context); } @Override @@ -31,6 +48,25 @@ public class CheckUpdates extends ParallelTask { @Override protected void onPostExecute(Void v) { + if (magiskManager.magiskVersion < magiskManager.remoteMagiskVersion && showNotification) { + magiskManager.isNotified = true; + NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager); + builder.setSmallIcon(R.drawable.ic_magisk) + .setContentTitle(magiskManager.getString(R.string.magisk_update_title)) + .setContentText(magiskManager.getString(R.string.magisk_update_available, magiskManager.remoteMagiskVersion)) + .setVibrate(new long[]{0, 100, 100, 100}) + .setAutoCancel(true); + Intent intent = new Intent(magiskManager, SplashActivity.class); + intent.putExtra(MainActivity.SECTION, "install"); + TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager); + stackBuilder.addParentStack(MainActivity.class); + stackBuilder.addNextIntent(intent); + PendingIntent pendingIntent = stackBuilder.getPendingIntent(NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT); + builder.setContentIntent(pendingIntent); + NotificationManager notificationManager = + (NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(NOTIFICATION_ID, builder.build()); + } magiskManager.updateCheckDone.trigger(); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java index 207433082..3dcfab11b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java @@ -6,7 +6,8 @@ import com.topjohnwu.magisk.MagiskManager; public class Activity extends AppCompatActivity { - public MagiskManager getTopApplication() { + @Override + public MagiskManager getApplicationContext() { return (MagiskManager) getApplication(); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/receivers/BootReceiver.java b/app/src/main/java/com/topjohnwu/magisk/receivers/BootReceiver.java index 858dc5c86..0b0fe549c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/receivers/BootReceiver.java +++ b/app/src/main/java/com/topjohnwu/magisk/receivers/BootReceiver.java @@ -1,17 +1,10 @@ package com.topjohnwu.magisk.receivers; -import android.app.IntentService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.widget.Toast; -import com.topjohnwu.magisk.MagiskManager; -import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.utils.Shell; -import com.topjohnwu.magisk.utils.Utils; - -import java.util.List; +import com.topjohnwu.magisk.services.BootupIntentService; public class BootReceiver extends BroadcastReceiver { @@ -20,25 +13,4 @@ public class BootReceiver extends BroadcastReceiver { context.startService(new Intent(context, BootupIntentService.class)); } - public static class BootupIntentService extends IntentService { - - public BootupIntentService() { - super("BootupIntentService"); - } - - @Override - protected void onHandleIntent(Intent intent) { - MagiskManager magiskManager = Utils.getMagiskManager(this); - magiskManager.initSuAccess(); - magiskManager.updateMagiskInfo(); - List ret = Shell.sh("getprop persist.magisk.hide"); - boolean started = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0; - if (magiskManager.prefs.getBoolean("magiskhide", false) && - !magiskManager.disabled && !started && magiskManager.magiskVersion > 11) { - magiskManager.toast(R.string.start_magiskhide, Toast.LENGTH_LONG); - Shell.su(true, MagiskManager.MAGISK_HIDE_PATH + "enable", - "setprop persist.magisk.hide 1"); - } - } - } } diff --git a/app/src/main/java/com/topjohnwu/magisk/services/BootupIntentService.java b/app/src/main/java/com/topjohnwu/magisk/services/BootupIntentService.java new file mode 100644 index 000000000..b90ba2d73 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/services/BootupIntentService.java @@ -0,0 +1,34 @@ +package com.topjohnwu.magisk.services; + +import android.app.IntentService; +import android.content.Intent; +import android.widget.Toast; + +import com.topjohnwu.magisk.MagiskManager; +import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.utils.Shell; +import com.topjohnwu.magisk.utils.Utils; + +import java.util.List; + +public class BootupIntentService extends IntentService { + + public BootupIntentService() { + super("BootupIntentService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + MagiskManager magiskManager = Utils.getMagiskManager(this); + magiskManager.initSuAccess(); + magiskManager.updateMagiskInfo(); + List ret = Shell.sh("getprop persist.magisk.hide"); + boolean started = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0; + if (magiskManager.prefs.getBoolean("magiskhide", false) && + !magiskManager.disabled && !started && magiskManager.magiskVersion > 11) { + magiskManager.toast(R.string.start_magiskhide, Toast.LENGTH_LONG); + Shell.su(true, MagiskManager.MAGISK_HIDE_PATH + "enable", + "setprop persist.magisk.hide 1"); + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/services/UpdateCheckService.java b/app/src/main/java/com/topjohnwu/magisk/services/UpdateCheckService.java new file mode 100644 index 000000000..f07154ac6 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/services/UpdateCheckService.java @@ -0,0 +1,31 @@ +package com.topjohnwu.magisk.services; + +import android.app.job.JobParameters; +import android.app.job.JobService; + +import com.topjohnwu.magisk.asyncs.CheckUpdates; + +public class UpdateCheckService extends JobService { + @Override + public boolean onStartJob(JobParameters params) { + new CheckUpdates(this, true){ + @Override + protected Void doInBackground(Void... voids) { + magiskManager.updateMagiskInfo(); + return super.doInBackground(voids); + } + + @Override + protected void onPostExecute(Void v) { + jobFinished(params, false); + super.onPostExecute(v); + } + }.exec(); + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + return true; + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java b/app/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java index 12b98177e..9a52b8941 100644 --- a/app/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java @@ -17,9 +17,8 @@ public class RequestActivity extends Activity { return; } - getTopApplication().initSuConfigs(); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClass(this, SuRequestActivity.class); + getApplicationContext().initSuConfigs(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class); startActivity(intent); finish(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/superuser/SuRequestActivity.java b/app/src/main/java/com/topjohnwu/magisk/superuser/SuRequestActivity.java index b9d02f72c..784225f6f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/superuser/SuRequestActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/superuser/SuRequestActivity.java @@ -66,7 +66,7 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene supportRequestWindowFeature(Window.FEATURE_NO_TITLE); pm = getPackageManager(); - magiskManager = getTopApplication(); + magiskManager = getApplicationContext(); Intent intent = getIntent(); socketPath = intent.getStringExtra("socket"); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Logger.java b/app/src/main/java/com/topjohnwu/magisk/utils/Logger.java index d70edf888..452e6ac4c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Logger.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Logger.java @@ -28,7 +28,7 @@ public class Logger { public static void dev(String msg) { if (MagiskManager.devLogging) { - Log.d(TAG, "DEBUG: " + msg); + Log.d(TAG, "DEV: " + msg); } } diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 020983fa9..a9fbe4e7b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -183,7 +183,7 @@ 目標 UID:\u0020 "指令: " 關閉 - Zip 已被儲存到:[內部儲存空間]%1$1 + Zip 已被儲存到:[內部儲存空間]%1$s 處裡失敗 下載