diff --git a/app/src/full/AndroidManifest.xml b/app/src/full/AndroidManifest.xml
index 58fe76ab0..20dd8c3fd 100644
--- a/app/src/full/AndroidManifest.xml
+++ b/app/src/full/AndroidManifest.xml
@@ -6,7 +6,7 @@
-
+
+
+
- DownloadModule.exec((BaseActivity) context, repo, true))
+ startDownload((BaseActivity) context, repo, true))
.setNeutralButton(R.string.download, (d, i) ->
- DownloadModule.exec((BaseActivity) context, repo, false))
+ startDownload((BaseActivity) context, repo, false))
.setNegativeButton(R.string.no_thanks, null)
.show();
});
}
+ private void startDownload(BaseActivity activity, Repo repo, Boolean install) {
+ activity.runWithExternalRW(() -> {
+ Intent intent = new Intent(activity, ClassMap.get(DownloadModuleService.class))
+ .putExtra("repo", repo).putExtra("install", install);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ activity.startForegroundService(intent);
+ } else {
+ activity.startService(intent);
+ }
+ });
+ }
+
public void notifyDBChanged() {
if (repoCursor != null)
repoCursor.close();
diff --git a/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java b/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java
index 35b91457c..cf35a1948 100644
--- a/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java
+++ b/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java
@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.components;
+import android.app.Notification;
import android.widget.Toast;
import com.topjohnwu.core.App;
@@ -13,6 +14,7 @@ import androidx.core.app.NotificationManagerCompat;
public class ProgressNotification implements DownloadProgressListener {
private NotificationManagerCompat mgr;
private NotificationCompat.Builder builder;
+ private Notification notification;
private long prevTime;
public ProgressNotification(String title) {
@@ -35,12 +37,23 @@ public class ProgressNotification implements DownloadProgressListener {
}
}
- public NotificationCompat.Builder getNotification() {
+ public NotificationCompat.Builder getNotificationBuilder() {
return builder;
}
+ public Notification getNotification() {
+ return notification;
+ }
+
public void update() {
- mgr.notify(hashCode(), builder.build());
+ notification = builder.build();
+ mgr.notify(hashCode(), notification);
+ }
+
+ private void lastUpdate() {
+ notification = builder.build();
+ mgr.cancel(hashCode());
+ mgr.notify(notification.hashCode(), notification);
}
public void dlDone() {
@@ -48,7 +61,7 @@ public class ProgressNotification implements DownloadProgressListener {
.setContentText(App.self.getString(R.string.download_complete))
.setSmallIcon(R.drawable.ic_check_circle)
.setOngoing(false);
- update();
+ lastUpdate();
}
public void dlFail() {
@@ -56,7 +69,7 @@ public class ProgressNotification implements DownloadProgressListener {
.setContentText(App.self.getString(R.string.download_file_error))
.setSmallIcon(R.drawable.ic_cancel)
.setOngoing(false);
- update();
+ lastUpdate();
}
public void dismiss() {
diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/DownloadModule.java b/app/src/full/java/com/topjohnwu/magisk/services/DownloadModuleService.java
similarity index 59%
rename from app/src/full/java/com/topjohnwu/magisk/utils/DownloadModule.java
rename to app/src/full/java/com/topjohnwu/magisk/services/DownloadModuleService.java
index ebf642467..7c7e25b0b 100644
--- a/app/src/full/java/com/topjohnwu/magisk/utils/DownloadModule.java
+++ b/app/src/full/java/com/topjohnwu/magisk/services/DownloadModuleService.java
@@ -1,17 +1,20 @@
-package com.topjohnwu.magisk.utils;
+package com.topjohnwu.magisk.services;
+import android.app.Service;
import android.content.Intent;
import android.net.Uri;
-import android.os.AsyncTask;
+import android.os.IBinder;
+import android.widget.Toast;
-import com.topjohnwu.core.App;
import com.topjohnwu.core.Const;
import com.topjohnwu.core.container.Repo;
+import com.topjohnwu.core.utils.Utils;
import com.topjohnwu.magisk.ClassMap;
import com.topjohnwu.magisk.FlashActivity;
-import com.topjohnwu.magisk.components.BaseActivity;
+import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.ProgressNotification;
import com.topjohnwu.net.Networking;
+import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import java.io.BufferedOutputStream;
@@ -24,16 +27,38 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
-public class DownloadModule {
+import androidx.annotation.Nullable;
- public static void exec(BaseActivity activity, Repo repo, boolean install) {
- activity.runWithExternalRW(() -> AsyncTask.THREAD_POOL_EXECUTOR.execute(
- () -> dlProcessInstall(repo, install)));
+public class DownloadModuleService extends Service {
+
+ private boolean running = false;
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
}
- private static void dlProcessInstall(Repo repo, boolean install) {
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (flags == 0 && running) {
+ Utils.toast(R.string.dl_one_module, Toast.LENGTH_LONG);
+ } else {
+ running = true;
+ Shell.EXECUTOR.execute(() -> {
+ Repo repo = intent.getParcelableExtra("repo");
+ boolean install = intent.getBooleanExtra("install", false);
+ dlProcessInstall(repo, install);
+ stopSelf();
+ });
+ }
+ return START_REDELIVER_INTENT;
+ }
+
+ private void dlProcessInstall(Repo repo, boolean install) {
File output = new File(Const.EXTERNAL_PATH, repo.getDownloadFilename());
ProgressNotification progress = new ProgressNotification(output.getName());
+ startForeground(progress.hashCode(), progress.getNotification());
try {
InputStream in = Networking.get(repo.getZipUrl())
.setDownloadProgressListener(progress)
@@ -41,13 +66,13 @@ public class DownloadModule {
removeTopFolder(in, new BufferedOutputStream(new FileOutputStream(output)));
if (install) {
progress.dismiss();
- Intent intent = new Intent(App.self, ClassMap.get(FlashActivity.class));
+ Intent intent = new Intent(this, ClassMap.get(FlashActivity.class));
intent.setData(Uri.fromFile(output))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
- App.self.startActivity(intent);
+ startActivity(intent);
} else {
- progress.getNotification().setContentTitle(output.getName());
+ progress.getNotificationBuilder().setContentTitle(output.getName());
progress.dlDone();
}
} catch (Exception e) {
@@ -56,7 +81,7 @@ public class DownloadModule {
}
}
- private static void removeTopFolder(InputStream in, OutputStream out) throws IOException {
+ private void removeTopFolder(InputStream in, OutputStream out) throws IOException {
try (ZipInputStream zin = new ZipInputStream(in);
ZipOutputStream zout = new ZipOutputStream(out)) {
ZipEntry entry;
@@ -73,5 +98,4 @@ public class DownloadModule {
}
}
}
-
}
diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/DownloadApp.java b/app/src/full/java/com/topjohnwu/magisk/utils/DownloadApp.java
index 2c8274fde..4aa6cd123 100644
--- a/app/src/full/java/com/topjohnwu/magisk/utils/DownloadApp.java
+++ b/app/src/full/java/com/topjohnwu/magisk/utils/DownloadApp.java
@@ -65,7 +65,7 @@ public class DownloadApp {
File patched = apk;
App app = App.self;
if (!App.self.getPackageName().equals(BuildConfig.APPLICATION_ID)) {
- progress.getNotification()
+ progress.getNotificationBuilder()
.setProgress(0, 0, true)
.setContentTitle(app.getString(R.string.hide_manager_title))
.setContentText("");
@@ -89,7 +89,7 @@ public class DownloadApp {
@Override
public void onDownloadComplete(File apk, ProgressNotification progress) {
App app = App.self;
- progress.getNotification()
+ progress.getNotificationBuilder()
.setProgress(0, 0, true)
.setContentTitle(app.getString(R.string.restore_img_msg))
.setContentText("");
diff --git a/app/src/full/res/values/strings.xml b/app/src/full/res/values/strings.xml
index 9e8492368..ac61e9790 100644
--- a/app/src/full/res/values/strings.xml
+++ b/app/src/full/res/values/strings.xml
@@ -126,6 +126,7 @@
Running environment setup…
Downloading %1$s
This feature will not work without permission to write external storage.
+ Download one module at a time.
General
diff --git a/core/src/main/java/com/topjohnwu/core/container/BaseModule.java b/core/src/main/java/com/topjohnwu/core/container/BaseModule.java
index 167f84447..00ea53fb3 100644
--- a/core/src/main/java/com/topjohnwu/core/container/BaseModule.java
+++ b/core/src/main/java/com/topjohnwu/core/container/BaseModule.java
@@ -2,12 +2,14 @@ package com.topjohnwu.core.container;
import android.content.ContentValues;
import android.database.Cursor;
+import android.os.Parcel;
+import android.os.Parcelable;
import java.util.List;
import androidx.annotation.NonNull;
-public abstract class BaseModule implements Comparable {
+public abstract class BaseModule implements Comparable, Parcelable {
private String mId, mName, mVersion, mAuthor, mDescription;
private int mVersionCode = -1, minMagiskVersion = -1;
@@ -26,6 +28,37 @@ public abstract class BaseModule implements Comparable {
minMagiskVersion = c.getInt(c.getColumnIndex("minMagisk"));
}
+ protected BaseModule(Parcel p) {
+ mId = p.readString();
+ mName = p.readString();
+ mVersion = p.readString();
+ mAuthor = p.readString();
+ mDescription = p.readString();
+ mVersionCode = p.readInt();
+ minMagiskVersion = p.readInt();
+ }
+
+ @Override
+ public int compareTo(@NonNull BaseModule module) {
+ return this.getName().toLowerCase().compareTo(module.getName().toLowerCase());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mId);
+ dest.writeString(mName);
+ dest.writeString(mVersion);
+ dest.writeString(mAuthor);
+ dest.writeString(mDescription);
+ dest.writeInt(mVersionCode);
+ dest.writeInt(minMagiskVersion);
+ }
+
private String nonNull(String s) {
return s == null ? "" : s;
}
@@ -119,9 +152,4 @@ public abstract class BaseModule implements Comparable {
public int getMinMagiskVersion() {
return minMagiskVersion;
}
-
- @Override
- public int compareTo(@NonNull BaseModule module) {
- return this.getName().toLowerCase().compareTo(module.getName().toLowerCase());
- }
}
diff --git a/core/src/main/java/com/topjohnwu/core/container/Module.java b/core/src/main/java/com/topjohnwu/core/container/Module.java
index 48ff50ab4..406f26b72 100644
--- a/core/src/main/java/com/topjohnwu/core/container/Module.java
+++ b/core/src/main/java/com/topjohnwu/core/container/Module.java
@@ -1,5 +1,8 @@
package com.topjohnwu.core.container;
+import android.os.Parcel;
+import android.os.Parcelable;
+
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.io.SuFile;
@@ -32,6 +35,19 @@ public class Module extends BaseModule {
mUpdated = mUpdateFile.exists();
}
+ public static final Parcelable.Creator CREATOR = new Creator() {
+ /* It won't be used at any place */
+ @Override
+ public Module createFromParcel(Parcel source) {
+ return null;
+ }
+
+ @Override
+ public Module[] newArray(int size) {
+ return null;
+ }
+ };
+
public void createDisableFile() {
mEnable = !mDisableFile.createNewFile();
}
diff --git a/core/src/main/java/com/topjohnwu/core/container/Repo.java b/core/src/main/java/com/topjohnwu/core/container/Repo.java
index 8db237a28..3ac31bdab 100644
--- a/core/src/main/java/com/topjohnwu/core/container/Repo.java
+++ b/core/src/main/java/com/topjohnwu/core/container/Repo.java
@@ -2,6 +2,8 @@ package com.topjohnwu.core.container;
import android.content.ContentValues;
import android.database.Cursor;
+import android.os.Parcel;
+import android.os.Parcelable;
import com.topjohnwu.core.Const;
import com.topjohnwu.core.utils.Logger;
@@ -23,6 +25,30 @@ public class Repo extends BaseModule {
mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update")));
}
+ public Repo(Parcel p) {
+ super(p);
+ mLastUpdate = new Date(p.readLong());
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+
+ @Override
+ public Repo createFromParcel(Parcel source) {
+ return new Repo(source);
+ }
+
+ @Override
+ public Repo[] newArray(int size) {
+ return new Repo[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeLong(mLastUpdate.getTime());
+ }
+
public void update() throws IllegalRepoException {
String props[] = Utils.dlString(getPropUrl()).split("\\n");
try {