From 69e5bcd57d8009c229e9e8f058dd0a30b8fd43f0 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 7 Jun 2017 02:19:23 +0800 Subject: [PATCH] Simple OTA implementation --- app/src/main/AndroidManifest.xml | 5 +- .../com/topjohnwu/magisk/MagiskManager.java | 5 +- .../com/topjohnwu/magisk/SplashActivity.java | 4 +- .../magisk/adapters/ReposAdapter.java | 3 + .../topjohnwu/magisk/asyncs/CheckUpdates.java | 40 +++++-------- .../magisk/receivers/DownloadReceiver.java | 5 +- .../magisk/receivers/ManagerUpdate.java | 43 ++++++++++++++ .../com/topjohnwu/magisk/utils/Utils.java | 56 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 + 9 files changed, 124 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f003aa173..6ab4491b8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,8 +52,7 @@ android:taskAffinity="internal.superuser" android:theme="@style/SuRequest" /> - + @@ -69,6 +68,8 @@ + + new DownloadReceiver() { @Override public void onDownloadDone(Uri uri) { + Activity activity = (Activity) mContext; new ProcessRepoZip(activity, uri, true).exec(); } }, @@ -75,6 +77,7 @@ public class ReposAdapter extends RecyclerView.Adapter new DownloadReceiver() { @Override public void onDownloadDone(Uri uri) { + Activity activity = (Activity) mContext; new ProcessRepoZip(activity, uri, false).exec(); } }, 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 8b0f2cc8d..38ffd0028 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java @@ -1,15 +1,8 @@ package com.topjohnwu.magisk.asyncs; -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.MagiskManager; -import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.SplashActivity; +import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebService; @@ -19,7 +12,7 @@ import org.json.JSONObject; public class CheckUpdates extends ParallelTask { private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/magisk_update.json"; - private static final int NOTIFICATION_ID = 1; + private boolean showNotification = false; @@ -42,30 +35,23 @@ public class CheckUpdates extends ParallelTask { magiskManager.remoteMagiskVersionCode = magisk.getInt("versionCode"); magiskManager.magiskLink = magisk.getString("link"); magiskManager.releaseNoteLink = magisk.getString("note"); + JSONObject manager = json.getJSONObject("app"); + magiskManager.remoteManagerVersionString = manager.getString("version"); + magiskManager.remoteManagerVersionCode = manager.getInt("versionCode"); + magiskManager.managerLink = manager.getString("link"); } catch (JSONException ignored) {} return null; } @Override protected void onPostExecute(Void v) { - if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode - && showNotification && magiskManager.updateNotification) { - 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.remoteMagiskVersionString)) - .setVibrate(new long[]{0, 100, 100, 100}) - .setAutoCancel(true); - Intent intent = new Intent(magiskManager, SplashActivity.class); - intent.putExtra(MagiskManager.INTENT_SECTION, "install"); - TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager); - stackBuilder.addParentStack(SplashActivity.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()); + if (showNotification && magiskManager.updateNotification) { + if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode) { + Utils.showMagiskUpdate(magiskManager); + } + if (BuildConfig.VERSION_CODE < magiskManager.remoteManagerVersionCode) { + Utils.showManagerUpdate(magiskManager); + } } magiskManager.updateCheckDone.trigger(); super.onPostExecute(v); diff --git a/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java b/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java index 82253336f..726ce47fb 100644 --- a/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java +++ b/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java @@ -1,6 +1,5 @@ package com.topjohnwu.magisk.receivers; -import android.app.Activity; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -13,7 +12,7 @@ import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Utils; public abstract class DownloadReceiver extends BroadcastReceiver { - public Activity activity; + public Context mContext; public String mFilename; long downloadID; @@ -21,7 +20,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - activity = (Activity) context; + mContext = context; DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); String action = intent.getAction(); if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { diff --git a/app/src/main/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java b/app/src/main/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java new file mode 100644 index 000000000..5ff1ea5e7 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java @@ -0,0 +1,43 @@ +package com.topjohnwu.magisk.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.support.v4.content.FileProvider; + +import com.topjohnwu.magisk.MagiskManager; +import com.topjohnwu.magisk.utils.Utils; + +import java.io.File; + +public class ManagerUpdate extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + MagiskManager magiskManager = Utils.getMagiskManager(context); + Utils.dlAndReceive( + magiskManager, + new DownloadReceiver() { + @Override + public void onDownloadDone(Uri uri) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE); + install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + Uri content = FileProvider.getUriForFile(mContext, + "com.topjohnwu.magisk.provider", new File(uri.getPath())); + install.setData(content); + mContext.startActivity(install); + } else { + Intent install = new Intent(Intent.ACTION_VIEW); + install.setDataAndType(uri, "application/vnd.android.package-archive"); + install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(install); + } + } + }, + magiskManager.managerLink, + Utils.getLegalFilename("MagiskManager-v" + + magiskManager.remoteManagerVersionString + ".apk")); + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index ff37d8d5a..6c04da075 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -3,7 +3,10 @@ package com.topjohnwu.magisk.utils; import android.Manifest; import android.app.Activity; import android.app.DownloadManager; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -16,15 +19,19 @@ import android.provider.OpenableColumns; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.NotificationCompat; import android.text.TextUtils; import android.widget.Toast; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.SplashActivity; import com.topjohnwu.magisk.asyncs.LoadRepos; import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.database.RepoDatabaseHelper; import com.topjohnwu.magisk.receivers.DownloadReceiver; +import com.topjohnwu.magisk.receivers.ManagerUpdate; import java.io.File; import java.util.List; @@ -33,6 +40,9 @@ public class Utils { public static boolean isDownloading = false; + private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1; + private static final int APK_UPDATE_NOTIFICATION_ID = 2; + public static boolean itemExist(String path) { String command = "if [ -e " + path + " ]; then echo true; else echo false; fi"; List ret = Shell.su(command); @@ -70,14 +80,16 @@ public class Utils { if (isDownloading) return; - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); return; } File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename); - if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) || (file.exists() && !file.delete())) { + if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) + || (file.exists() && !file.delete())) { Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); return; } @@ -105,7 +117,9 @@ public class Utils { public static String detectBootImage() { String[] commands = { "for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do", - "BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`", + "BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || " + + "readlink /dev/block/platform/*/by-name/$PARTITION || " + + "readlink /dev/block/platform/*/*/by-name/$PARTITION`", "if [ ! -z \"$BOOTIMAGE\" ]; then break; fi", "done", "echo \"$BOOTIMAGE\"" @@ -194,4 +208,40 @@ public class Utils { } return true; } + + public static void showMagiskUpdate(MagiskManager magiskManager) { + 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.remoteMagiskVersionString)) + .setVibrate(new long[]{0, 100, 100, 100}) + .setAutoCancel(true); + Intent intent = new Intent(magiskManager, SplashActivity.class); + intent.putExtra(MagiskManager.INTENT_SECTION, "install"); + TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager); + stackBuilder.addParentStack(SplashActivity.class); + stackBuilder.addNextIntent(intent); + PendingIntent pendingIntent = stackBuilder.getPendingIntent(MAGISK_UPDATE_NOTIFICATION_ID, + PendingIntent.FLAG_UPDATE_CURRENT); + builder.setContentIntent(pendingIntent); + NotificationManager notificationManager = + (NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(MAGISK_UPDATE_NOTIFICATION_ID, builder.build()); + } + + public static void showManagerUpdate(MagiskManager magiskManager) { + NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager); + builder.setSmallIcon(R.drawable.ic_magisk) + .setContentTitle(magiskManager.getString(R.string.manager_update_title)) + .setContentText(magiskManager.getString(R.string.manager_download_install)) + .setVibrate(new long[]{0, 100, 100, 100}) + .setAutoCancel(true); + Intent intent = new Intent(magiskManager, ManagerUpdate.class); + PendingIntent pendingIntent = PendingIntent.getBroadcast(magiskManager, + APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT); + builder.setContentIntent(pendingIntent); + NotificationManager notificationManager = + (NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(APK_UPDATE_NOTIFICATION_ID, builder.build()); + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 309e99117..e2a8ae82b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -130,6 +130,8 @@ The zip is stored in:\n[Internal Storage]%1$s Processing Please manually select a boot image! + New Magisk Manager Update Available! + Press to download and install General