diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3e9c1018..6088baa1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -77,14 +77,6 @@
-
-
-
-
-
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java
index fcf79037..c17bbe3e 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java
@@ -1,13 +1,8 @@
package org.meowcat.edxposed.manager;
import android.annotation.SuppressLint;
-import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.net.Uri;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
@@ -24,23 +19,15 @@ import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.ListFragment;
-import com.google.android.material.snackbar.Snackbar;
-
import org.meowcat.edxposed.manager.repo.Module;
import org.meowcat.edxposed.manager.repo.ModuleVersion;
import org.meowcat.edxposed.manager.repo.ReleaseType;
import org.meowcat.edxposed.manager.repo.RepoParser;
-import org.meowcat.edxposed.manager.util.DownloadsUtil;
-import org.meowcat.edxposed.manager.util.HashUtil;
-import org.meowcat.edxposed.manager.util.InstallApkUtil;
import org.meowcat.edxposed.manager.util.ModuleUtil.InstalledModule;
import org.meowcat.edxposed.manager.util.RepoLoader;
import org.meowcat.edxposed.manager.util.chrome.LinkTransformationMethod;
import org.meowcat.edxposed.manager.widget.DownloadView;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.OutputStream;
import java.text.DateFormat;
import java.util.Date;
@@ -72,7 +59,7 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
getListView().addHeaderView(txtHeader);
}
- VersionsAdapter sAdapter = new VersionsAdapter(activity, activity.getInstalledModule(), activity.findViewById(R.id.snackbar));
+ VersionsAdapter sAdapter = new VersionsAdapter(activity, activity.getInstalledModule()/*, activity.findViewById(R.id.snackbar)*/);
for (ModuleVersion version : module.versions) {
if (repoLoader.isVersionShown(version))
sAdapter.add(version);
@@ -104,36 +91,6 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
setListAdapter(null);
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (resultCode != Activity.RESULT_OK) {
- return;
- }
- if (requestCode == 42) {
- if (data != null) {
- Uri uri = data.getData();
- if (uri != null) {
- try {
- OutputStream os = activity.getContentResolver().openOutputStream(uri);
- if (os != null) {
- FileInputStream in = new FileInputStream(new File(DownloadView.lastInfo.localFilename));
- byte[] buffer = new byte[1024];
- int len;
- while ((len = in.read(buffer)) > 0) {
- os.write(buffer, 0, len);
- }
- os.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- //Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
- }
- }
- }
- }
- }
-
static class ViewHolder {
TextView txtStatus;
TextView txtVersion;
@@ -144,55 +101,6 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
TextView txtChanges;
}
- public static class DownloadModuleCallback implements DownloadsUtil.DownloadFinishedCallback {
- private final ModuleVersion moduleVersion;
- private View snackbar;
-
- DownloadModuleCallback(ModuleVersion moduleVersion, View snackbar) {
- this.moduleVersion = moduleVersion;
- this.snackbar = snackbar;
- }
-
- @Override
- public void onDownloadFinished(Context context, DownloadsUtil.DownloadInfo info) {
- File localFile = new File(info.localFilename);
- if (!localFile.isFile())
- return;
-
- if (moduleVersion.md5sum != null && !moduleVersion.md5sum.isEmpty()) {
- try {
- String actualMd5Sum = HashUtil.md5(localFile);
- if (!moduleVersion.md5sum.equals(actualMd5Sum)) {
- Snackbar.make(snackbar, context.getString(R.string.download_md5sum_incorrect, actualMd5Sum, moduleVersion.md5sum), Snackbar.LENGTH_LONG).show();
- DownloadsUtil.removeById(context, info.id);
- return;
- }
- } catch (Exception e) {
- Snackbar.make(snackbar, context.getString(R.string.download_could_not_read_file, e.getMessage()), Snackbar.LENGTH_LONG).show();
- DownloadsUtil.removeById(context, info.id);
- return;
- }
- }
-
- PackageManager pm = context.getPackageManager();
- PackageInfo packageInfo = pm.getPackageArchiveInfo(info.localFilename, 0);
-
- if (packageInfo == null) {
- Snackbar.make(snackbar, R.string.download_no_valid_apk, Snackbar.LENGTH_LONG).show();
- DownloadsUtil.removeById(context, info.id);
- return;
- }
-
- if (!packageInfo.packageName.equals(moduleVersion.module.packageName)) {
- Snackbar.make(snackbar, context.getString(R.string.download_incorrect_package_name, packageInfo.packageName, moduleVersion.module.packageName), Snackbar.LENGTH_LONG).show();
- DownloadsUtil.removeById(context, info.id);
- return;
- }
-
- new InstallApkUtil(context, info).execute();
- }
- }
-
private class VersionsAdapter extends ArrayAdapter {
private final DateFormat dateFormatter = DateFormat
.getDateInstance(DateFormat.SHORT);
@@ -203,9 +111,9 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
private final String textInstalled;
private final String textUpdateAvailable;
private final long installedVersionCode;
- private View snackbar;
+ //private View snackbar;
- VersionsAdapter(Context context, InstalledModule installed, View snackbar) {
+ VersionsAdapter(Context context, InstalledModule installed/*, View snackbar*/) {
super(context, R.layout.item_version);
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
@@ -218,7 +126,7 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
textInstalled = getString(R.string.download_section_installed) + ":";
textUpdateAvailable = getString(R.string.download_section_update_available) + ":";
installedVersionCode = (installed != null) ? installed.versionCode : -1;
- this.snackbar = snackbar;
+ //this.snackbar = snackbar;
}
@SuppressLint("InflateParams")
@@ -274,7 +182,7 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
holder.downloadView.setUrl(item.downloadLink);
holder.downloadView.setTitle(activity.getModule().name);
- holder.downloadView.setDownloadFinishedCallback(new DownloadModuleCallback(item, snackbar));
+ //holder.downloadView.setDownloadFinishedCallback(new DownloadModuleCallback(item, snackbar));
if (item.changelog != null && !item.changelog.isEmpty()) {
holder.txtChangesTitle.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java
index e2a2a902..b1292dde 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java
@@ -32,7 +32,6 @@ import org.meowcat.edxposed.manager.repo.Module;
import org.meowcat.edxposed.manager.repo.ModuleVersion;
import org.meowcat.edxposed.manager.repo.ReleaseType;
import org.meowcat.edxposed.manager.repo.RepoDb;
-import org.meowcat.edxposed.manager.util.DownloadsUtil;
import org.meowcat.edxposed.manager.util.InstallApkUtil;
import org.meowcat.edxposed.manager.util.ModuleUtil;
import org.meowcat.edxposed.manager.util.NavUtil;
@@ -369,7 +368,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
}
if (mv != null) {
- DownloadsUtil.addModule(this, m.name, mv.downloadLink, (context, info) -> new InstallApkUtil(this, info).execute());
+ NavUtil.startURL(this, mv.downloadLink);
}
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java b/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java
index 3b6ee46c..c6764728 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java
@@ -3,27 +3,28 @@ package org.meowcat.edxposed.manager.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.AsyncTask;
-import android.util.Log;
import org.json.JSONObject;
import org.meowcat.edxposed.manager.BuildConfig;
-import org.meowcat.edxposed.manager.XposedApp;
import org.meowcat.edxposed.manager.util.NotificationUtil;
+import org.meowcat.edxposed.manager.util.TaskRunner;
import org.meowcat.edxposed.manager.util.json.JSONUtils;
+import java.util.concurrent.Callable;
+
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
- new android.os.Handler().postDelayed(() -> new CheckUpdates().execute(), 60 * 60 * 1000 /*60 min*/);
+ new TaskRunner().executeAsync(new LongRunningTask());
}
- private static class CheckUpdates extends AsyncTask {
+ private static class LongRunningTask implements Callable {
@Override
- protected Void doInBackground(Void... params) {
+ public Void call() {
try {
+ Thread.sleep(60 * 60 * 1000);
String jsonString = JSONUtils.getFileContent(JSONUtils.JSON_LINK).replace("%XPOSED_ZIP%", "");
String newApkVersion = new JSONObject(jsonString).getJSONObject("apk").getString("version");
@@ -35,11 +36,9 @@ public class BootReceiver extends BroadcastReceiver {
NotificationUtil.showInstallerUpdateNotification();
}
} catch (Exception e) {
- //noinspection ConstantConditions
- Log.d(XposedApp.TAG, e.getMessage());
+ e.printStackTrace();
}
return null;
}
-
}
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/receivers/DownloadReceiver.java b/app/src/main/java/org/meowcat/edxposed/manager/receivers/DownloadReceiver.java
deleted file mode 100644
index b24ca571..00000000
--- a/app/src/main/java/org/meowcat/edxposed/manager/receivers/DownloadReceiver.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.meowcat.edxposed.manager.receivers;
-
-import android.app.DownloadManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.widget.Toast;
-
-import org.meowcat.edxposed.manager.util.DownloadsUtil;
-
-public class DownloadReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- try {
- String action = intent.getAction();
- if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
- long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
- DownloadsUtil.triggerDownloadFinishedCallback(context, downloadId);
- }
- } catch (Exception e) {//Flyme
- e.printStackTrace();
- Toast.makeText(context, "shit flyme boom", Toast.LENGTH_LONG).show();
- }
-
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java
index 68d05c61..dd251424 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java
@@ -1,17 +1,7 @@
package org.meowcat.edxposed.manager.util;
-import android.app.DownloadManager;
-import android.app.DownloadManager.Query;
-import android.app.DownloadManager.Request;
import android.content.Context;
import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
import org.meowcat.edxposed.manager.R;
import org.meowcat.edxposed.manager.XposedApp;
@@ -23,303 +13,10 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
public class DownloadsUtil {
- public static final String MIME_TYPE_APK = "application/vnd.android.package-archive";
- private static final Map callbacks = new HashMap<>();
private static final SharedPreferences pref = XposedApp.getInstance().getSharedPreferences("download_cache", Context.MODE_PRIVATE);
- private static DownloadInfo add(Builder b) {
- Context context = b.context;
- removeAllForUrl(context, b.url);
-
- synchronized (callbacks) {
- callbacks.put(b.url, b.callback);
- }
-
- Request request = new Request(Uri.parse(b.url));
- request.setTitle(b.title);
- request.setMimeType(b.mimeType.toString());
- request.setNotificationVisibility(Request.VISIBILITY_VISIBLE);
- File path = new File(context.getExternalCacheDir(), "downloads");
- try {
- if (!path.mkdirs()) return null;
- }catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- File destination = new File(path, b.title + b.mimeType.getExtension());
- removeAllForLocalFile(context, destination);
- request.setDestinationUri(Uri.fromFile(destination));
- DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- long id = dm.enqueue(request);
- return getById(context, id);
- }
-
- public static DownloadInfo addModule(Context context, String title, String url, DownloadFinishedCallback callback) {
- return new Builder(context)
- .setTitle(title)
- .setUrl(url)
- .setCallback(callback)
- .setModule(true)
- .setMimeType(MIME_TYPES.APK)
- .download();
- }
-
- /*
- public static ModuleVersion getStableVersion(Module m) {
- for (int i = 0; i < m.versions.size(); i++) {
- ModuleVersion mvTemp = m.versions.get(i);
-
- if (mvTemp.relType == ReleaseType.STABLE) {
- return mvTemp;
- }
- }
- return null;
- }
- */
- public static DownloadInfo getById(Context context, long id) {
- DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = dm.query(new Query().setFilterById(id));
- if (!c.moveToFirst()) {
- c.close();
- return null;
- }
-
- int columnUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_URI);
- int columnTitle = c.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE);
- int columnLastMod = c.getColumnIndexOrThrow(
- DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP);
- int columnLocalUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI);
- int columnStatus = c.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS);
- int columnTotalSize = c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
- int columnBytesDownloaded = c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
- int columnReason = c.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON);
-
- int status = c.getInt(columnStatus);
- String localFilename;
- try {
- localFilename = getFilenameFromUri(c.getString(columnLocalUri));
- } catch (UnsupportedOperationException e) {
- Toast.makeText(context, "An error occurred. Restart app and try again.\n" + e.getMessage(), Toast.LENGTH_SHORT).show();
- return null;
- }
- if (status == DownloadManager.STATUS_SUCCESSFUL && !new File(localFilename).isFile()) {
- dm.remove(id);
- c.close();
- return null;
- }
-
- DownloadInfo info = new DownloadInfo(id, c.getString(columnUri),
- c.getString(columnTitle), c.getLong(columnLastMod),
- localFilename, status,
- c.getInt(columnTotalSize), c.getInt(columnBytesDownloaded),
- c.getInt(columnReason));
- c.close();
- return info;
- }
-
- public static DownloadInfo getLatestForUrl(Context context, String url) {
- List all;
- try {
- all = getAllForUrl(context, url);
- } catch (Throwable throwable) {
- return null;
- }
- return Objects.requireNonNull(all).isEmpty() ? null : all.get(0);
- }
-
- private static List getAllForUrl(Context context, String url) {
- DownloadManager dm = (DownloadManager) context
- .getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = dm.query(new Query());
- int columnId = c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
- int columnUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_URI);
- int columnTitle = c.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE);
- int columnLastMod = c.getColumnIndexOrThrow(
- DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP);
- int columnLocalUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI);
- int columnStatus = c.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS);
- int columnTotalSize = c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
- int columnBytesDownloaded = c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
- int columnReason = c.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON);
-
- List downloads = new ArrayList<>();
- while (c.moveToNext()) {
- if (!url.equals(c.getString(columnUri)))
- continue;
-
- int status = c.getInt(columnStatus);
- String localFilename;
- try {
- localFilename = getFilenameFromUri(c.getString(columnLocalUri));
- } catch (UnsupportedOperationException e) {
- Toast.makeText(context, "An error occurred. Restart app and try again.\n" + e.getMessage(), Toast.LENGTH_SHORT).show();
- return null;
- }
- if (status == DownloadManager.STATUS_SUCCESSFUL && !new File(localFilename).isFile()) {
- dm.remove(c.getLong(columnId));
- continue;
- }
-
- downloads.add(new DownloadInfo(c.getLong(columnId),
- c.getString(columnUri), c.getString(columnTitle),
- c.getLong(columnLastMod), localFilename,
- status, c.getInt(columnTotalSize),
- c.getInt(columnBytesDownloaded), c.getInt(columnReason)));
- }
- c.close();
-
- Collections.sort(downloads);
- return downloads;
- }
-
- public static void removeById(Context context, long id) {
- DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- dm.remove(id);
- }
-
- private static void removeAllForUrl(Context context, String url) {
- DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = dm.query(new Query());
- int columnId = c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
- int columnUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_URI);
-
- List idsList = new ArrayList<>(1);
- while (c.moveToNext()) {
- if (url.equals(c.getString(columnUri)))
- idsList.add(c.getLong(columnId));
- }
- c.close();
-
- if (idsList.isEmpty())
- return;
-
- long[] ids = new long[idsList.size()];
- for (int i = 0; i < ids.length; i++)
- ids[i] = idsList.get(i);
-
- dm.remove(ids);
- }
-
- private static void removeAllForLocalFile(Context context, File file) {
- //noinspection ResultOfMethodCallIgnored
- file.delete();
-
- String filename;
- try {
- filename = file.getCanonicalPath();
- } catch (IOException e) {
- Log.w(XposedApp.TAG, "Could not resolve path for " + file.getAbsolutePath(), e);
- return;
- }
-
- DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- Cursor c = dm.query(new Query());
- int columnId = c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
- int columnLocalUri = c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI);
-
- List idsList = new ArrayList<>(1);
- while (c.moveToNext()) {
- String itemFilename;
- try {
- itemFilename = getFilenameFromUri(c.getString(columnLocalUri));
- } catch (UnsupportedOperationException e) {
- Toast.makeText(context, "An error occurred. Restart app and try again.\n" + e.getMessage(), Toast.LENGTH_SHORT).show();
- itemFilename = null;
- }
- if (itemFilename != null) {
- if (filename.equals(itemFilename)) {
- idsList.add(c.getLong(columnId));
- } else {
- try {
- if (filename.equals(new File(itemFilename).getCanonicalPath())) {
- idsList.add(c.getLong(columnId));
- }
- } catch (IOException ignored) {
- }
- }
- }
- }
- c.close();
-
- if (idsList.isEmpty())
- return;
-
- long[] ids = new long[idsList.size()];
- for (int i = 0; i < ids.length; i++)
- ids[i] = idsList.get(i);
-
- dm.remove(ids);
- }
-
-// public static void removeOutdated(Context context, long cutoff) {
-// DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
-// Cursor c = dm.query(new Query());
-// int columnId = c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
-// int columnLastMod = c.getColumnIndexOrThrow(
-// DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP);
-//
-// List idsList = new ArrayList<>();
-// while (c.moveToNext()) {
-// if (c.getLong(columnLastMod) < cutoff)
-// idsList.add(c.getLong(columnId));
-// }
-// c.close();
-//
-// if (idsList.isEmpty())
-// return;
-//
-// long[] ids = new long[idsList.size()];
-// for (int i = 0; i < ids.length; i++)
-// ids[i] = idsList.get(0);
-//
-// dm.remove(ids);
-// }
-
- public static void triggerDownloadFinishedCallback(Context context, long id) {
- DownloadInfo info = getById(context, id);
- if (info == null || info.status != DownloadManager.STATUS_SUCCESSFUL)
- return;
-
- DownloadFinishedCallback callback;
- synchronized (callbacks) {
- callback = callbacks.get(info.url);
- }
-
- if (callback == null)
- return;
-
- // Hack to reset stat information.
- //noinspection ResultOfMethodCallIgnored
- new File(info.localFilename).setExecutable(false);
- callback.onDownloadFinished(context, info);
- }
-
- private static String getFilenameFromUri(String uriString) {
- if (uriString == null) {
- return null;
- }
- Uri uri = Uri.parse(uriString);
- if (Objects.requireNonNull(uri.getScheme()).equals("file")) {
- return uri.getPath();
- } else if (uri.getScheme().equals("content")) {
- Context context = XposedApp.getInstance();
- try (Cursor c = context.getContentResolver().query(uri, new String[]{MediaStore.Files.FileColumns.DATA}, null, null, null)) {
- Objects.requireNonNull(c).moveToFirst();
- return c.getString(c.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA));
- }
- } else {
- throw new UnsupportedOperationException("Unexpected URI: " + uriString);
- }
- }
-
static SyncDownloadInfo downloadSynchronously(String url, File target) {
final boolean useNotModifiedTags = target.exists();
@@ -416,111 +113,6 @@ public class DownloadsUtil {
}
}
- public enum MIME_TYPES {
- APK {
- @NonNull
- public String toString() {
- return MIME_TYPE_APK;
- }
-
- public String getExtension() {
- return ".apk";
- }
- };
-// ZIP {
-// public String toString() {
-// return MIME_TYPE_ZIP;
-// }
-//
-// public String getExtension() {
-// return ".zip";
-// }
-// };
-
- public String getExtension() {
- return null;
- }
- }
-
- public interface DownloadFinishedCallback {
- void onDownloadFinished(Context context, DownloadInfo info);
- }
-
- public static class Builder {
- private final Context context;
- boolean module = false;
- private String title = null;
- private String url = null;
- private DownloadFinishedCallback callback = null;
- private MIME_TYPES mimeType = MIME_TYPES.APK;
-
- public Builder(Context context) {
- this.context = context;
- }
-
- public Builder setTitle(String title) {
- this.title = title;
- return this;
- }
-
- public Builder setUrl(String url) {
- this.url = url;
- return this;
- }
-
- public Builder setCallback(DownloadFinishedCallback callback) {
- this.callback = callback;
- return this;
- }
-
- Builder setMimeType(MIME_TYPES mimeType) {
- this.mimeType = mimeType;
- return this;
- }
-
- public Builder setModule(boolean module) {
- this.module = module;
- return this;
- }
-
- public DownloadInfo download() {
- return add(this);
- }
- }
-
- public static class DownloadInfo implements Comparable {
- public final long id;
- public final String url;
- public final String title;
- public final String localFilename;
- public final int status;
- public final int totalSize;
- public final int bytesDownloaded;
- public final int reason;
- final long lastModification;
-
- private DownloadInfo(long id, String url, String title, long lastModification, String localFilename, int status, int totalSize, int bytesDownloaded, int reason) {
- this.id = id;
- this.url = url;
- this.title = title;
- this.lastModification = lastModification;
- this.localFilename = localFilename;
- this.status = status;
- this.totalSize = totalSize;
- this.bytesDownloaded = bytesDownloaded;
- this.reason = reason;
- }
-
- @Override
- public int compareTo(@NonNull DownloadInfo another) {
- int compare = (int) (another.lastModification
- - this.lastModification);
- if (compare != 0)
- return compare;
- return this.url.compareTo(another.url);
- }
- }
-
public static class SyncDownloadInfo {
static final int STATUS_SUCCESS = 0;
static final int STATUS_NOT_MODIFIED = 1;
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java
index c59b436e..8a05b6f2 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java
@@ -1,41 +1,10 @@
package org.meowcat.edxposed.manager.util;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.net.Uri;
-import android.os.AsyncTask;
-import androidx.core.content.FileProvider;
-
-import com.topjohnwu.superuser.Shell;
-
-import org.meowcat.edxposed.manager.BuildConfig;
-import org.meowcat.edxposed.manager.R;
-import org.meowcat.edxposed.manager.XposedApp;
-
-import java.io.File;
-import java.util.LinkedList;
-import java.util.List;
-
-public class InstallApkUtil extends AsyncTask {
-
- private static final int ERROR_ROOT_NOT_GRANTED = -99;
-
- private final DownloadsUtil.DownloadInfo info;
- @SuppressLint("StaticFieldLeak")
- private final Context context;
- private boolean isApkRootInstallOn;
- private List output = new LinkedList<>();
-
- public InstallApkUtil(Context context, DownloadsUtil.DownloadInfo info) {
- this.context = context;
- this.info = info;
- }
+public class InstallApkUtil {
public static String getAppLabel(ApplicationInfo info, PackageManager pm) {
try {
@@ -47,74 +16,4 @@ public class InstallApkUtil extends AsyncTask {
}
return info.loadLabel(pm).toString();
}
-
- static void installApkNormally(Context context, String localFilename) {
- Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
- installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", new File(localFilename));
- installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- installIntent.setDataAndType(uri, DownloadsUtil.MIME_TYPE_APK);
- installIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, context.getApplicationInfo().packageName);
- context.startActivity(installIntent);
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
-
- SharedPreferences prefs = XposedApp.getPreferences();
- isApkRootInstallOn = prefs.getBoolean("install_with_su", false);
-
- if (isApkRootInstallOn) {
- NotificationUtil.showModuleInstallingNotification(info.title);
- }
- }
-
- @Override
- protected Integer doInBackground(Void... params) {
- int returnCode = 0;
- if (isApkRootInstallOn) {
- try {
- String path = "/data/local/tmp/";
- String fileName = new File(info.localFilename).getName();
- Shell.su("cat \"" + info.localFilename + "\">" + path + fileName).exec();
- Shell.Result result = Shell.su("pm install -r -f \"" + path + fileName + "\"").exec();
- returnCode = result.getCode();
- output = result.getOut();
- Shell.su("rm -f " + path + fileName).exec();
- } catch (IllegalStateException e) {
- returnCode = ERROR_ROOT_NOT_GRANTED;
- }
- }
- return returnCode;
- }
-
- @Override
- protected void onPostExecute(Integer result) {
- super.onPostExecute(result);
-
- if (isApkRootInstallOn) {
- NotificationUtil.cancel(NotificationUtil.NOTIFICATION_MODULE_INSTALLING);
-
- if (result.equals(ERROR_ROOT_NOT_GRANTED)) {
- NotificationUtil.showModuleInstallNotification(R.string.installation_error, R.string.root_failed, info.localFilename);
- return;
- }
-
- StringBuilder out = new StringBuilder();
- for (String o : output) {
- out.append(o);
- out.append("\n");
- }
-
- if (result.equals(0)) {
- NotificationUtil.showModuleInstallNotification(R.string.installation_successful, R.string.installation_successful_message, info.localFilename, info.title);
- } else {
- NotificationUtil.showModuleInstallNotification(R.string.installation_error, R.string.installation_error_message, info.localFilename, info.title, out);
- installApkNormally(context, info.localFilename);
- }
- } else {
- installApkNormally(context, info.localFilename);
- }
- }
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java
index e7ea200b..c08df26b 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java
@@ -12,7 +12,6 @@ import android.os.Build;
import android.util.Log;
import android.widget.Toast;
-import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
@@ -25,17 +24,14 @@ import org.meowcat.edxposed.manager.XposedApp;
public final class NotificationUtil {
public static final int NOTIFICATION_MODULE_NOT_ACTIVATED_YET = 0;
- public static final int NOTIFICATION_MODULE_INSTALLING = 4;
private static final int NOTIFICATION_MODULES_UPDATED = 1;
private static final int NOTIFICATION_INSTALLER_UPDATE = 2;
- private static final int NOTIFICATION_MODULE_INSTALLATION = 3;
private static final int PENDING_INTENT_OPEN_MODULES = 0;
private static final int PENDING_INTENT_OPEN_INSTALL = 1;
private static final int PENDING_INTENT_SOFT_REBOOT = 2;
private static final int PENDING_INTENT_REBOOT = 3;
private static final int PENDING_INTENT_ACTIVATE_MODULE_AND_REBOOT = 4;
private static final int PENDING_INTENT_ACTIVATE_MODULE = 5;
- private static final int PENDING_INTENT_INSTALL_APK = 6;
private static final String HEADS_UP = "heads_up";
private static final String FRAGMENT_ID = "fragment";
@@ -65,10 +61,6 @@ public final class NotificationUtil {
}
}
- public static void cancel(int id) {
- notificationManager.cancel(id);
- }
-
public static void cancel(String tag, int id) {
notificationManager.cancel(tag, id);
}
@@ -145,48 +137,6 @@ public final class NotificationUtil {
notificationManager.notify(null, NOTIFICATION_MODULES_UPDATED, builder.build());
}
- static void showModuleInstallNotification(@StringRes int title, @StringRes int message, String path, Object... args) {
- showModuleInstallNotification(context.getString(title), context.getString(message, args), path, title == R.string.installation_error);
- }
-
- private static void showModuleInstallNotification(String title, String message, String path, boolean error) {
- NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_MODULES_CHANNEL);
-
- if (error) {
- Intent iInstallApk = new Intent(context, ApkReceiver.class);
- iInstallApk.putExtra(ApkReceiver.EXTRA_APK_PATH, path);
- PendingIntent pInstallApk = PendingIntent.getBroadcast(context, PENDING_INTENT_INSTALL_APK, iInstallApk, PendingIntent.FLAG_UPDATE_CURRENT);
-
- builder.addAction(new NotificationCompat.Action.Builder(0, context.getString(R.string.installation_apk_normal), pInstallApk).build());
- }
-
- if (prefs.getBoolean(HEADS_UP, true)) {
- builder.setPriority(2);
- }
- NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
- notiStyle.setBigContentTitle(title);
- notiStyle.bigText(message);
- builder.setStyle(notiStyle);
-
- notificationManager.notify(null, NOTIFICATION_MODULE_INSTALLATION, builder.build());
-
- new android.os.Handler().postDelayed(() -> cancel(NOTIFICATION_MODULE_INSTALLATION), 10 * 1000);
- }
-
- public static void showModuleInstallingNotification(String appName) {
- String title = context.getString(R.string.install_load);
- String message = context.getString(R.string.install_load_apk, appName);
- NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_MODULES_CHANNEL)
- .setProgress(0, 0, true)
- .setOngoing(true);
- NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
- notiStyle.setBigContentTitle(title);
- notiStyle.bigText(message);
- builder.setStyle(notiStyle);
-
- notificationManager.notify(null, NOTIFICATION_MODULE_INSTALLING, builder.build());
- }
-
public static void showInstallerUpdateNotification() {
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -264,26 +214,4 @@ public final class NotificationUtil {
}
}
}
-
- public static class ApkReceiver extends BroadcastReceiver {
- public static final String EXTRA_APK_PATH = "path";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- /*
- * Close the notification bar in order to see the toast that module
- * was enabled successfully. Furthermore, if SU permissions haven't
- * been granted yet, the SU dialog will be prompted behind the
- * expanded notification panel and is therefore not visible to the
- * user.
- */
- context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-
- if (intent.hasExtra(EXTRA_APK_PATH)) {
- String path = intent.getStringExtra(EXTRA_APK_PATH);
- InstallApkUtil.installApkNormally(context, path);
- }
- NotificationUtil.cancel(NotificationUtil.NOTIFICATION_MODULE_INSTALLATION);
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java b/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java
new file mode 100644
index 00000000..fbdbe1ac
--- /dev/null
+++ b/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java
@@ -0,0 +1,19 @@
+package org.meowcat.edxposed.manager.util;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+public class TaskRunner {
+ private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements
+
+ public void executeAsync(Callable callable) {
+ executor.execute(() -> {
+ try {
+ callable.call();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/widget/DownloadView.java b/app/src/main/java/org/meowcat/edxposed/manager/widget/DownloadView.java
index a9bf8ae3..ffdbc3a0 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/widget/DownloadView.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/widget/DownloadView.java
@@ -1,8 +1,6 @@
package org.meowcat.edxposed.manager.widget;
-import android.app.DownloadManager;
import android.content.Context;
-import android.content.Intent;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -10,86 +8,16 @@ import android.widget.LinearLayout;
import androidx.fragment.app.Fragment;
+import org.meowcat.edxposed.manager.BaseActivity;
import org.meowcat.edxposed.manager.R;
import org.meowcat.edxposed.manager.databinding.DownloadViewBinding;
-import org.meowcat.edxposed.manager.util.DownloadsUtil;
-import org.meowcat.edxposed.manager.util.DownloadsUtil.DownloadFinishedCallback;
+import org.meowcat.edxposed.manager.util.NavUtil;
public class DownloadView extends LinearLayout {
- public static DownloadsUtil.DownloadInfo lastInfo = null;
public Fragment fragment;
- private DownloadsUtil.DownloadInfo mInfo = null;
private String mUrl = null;
private String mTitle = null;
- private DownloadFinishedCallback mCallback = null;
private DownloadViewBinding binding;
- private final Runnable refreshViewRunnable = new Runnable() {
- @Override
- public void run() {
- if (mUrl == null) {
- binding.btnDownload.setVisibility(View.GONE);
- binding.btnSave.setVisibility(View.GONE);
- binding.btnDownloadCancel.setVisibility(View.GONE);
- binding.btnInstall.setVisibility(View.GONE);
- binding.progress.setVisibility(View.GONE);
- binding.txtInfo.setVisibility(View.VISIBLE);
- binding.txtInfo.setText(R.string.download_view_no_url);
- } else if (mInfo == null) {
- binding.btnDownload.setVisibility(View.VISIBLE);
- binding.btnSave.setVisibility(View.VISIBLE);
- binding.btnDownloadCancel.setVisibility(View.GONE);
- binding.btnInstall.setVisibility(View.GONE);
- binding.progress.setVisibility(View.GONE);
- binding.txtInfo.setVisibility(View.GONE);
- } else {
- switch (mInfo.status) {
- case DownloadManager.STATUS_PENDING:
- case DownloadManager.STATUS_PAUSED:
- case DownloadManager.STATUS_RUNNING:
- binding.btnDownload.setVisibility(View.GONE);
- binding.btnSave.setVisibility(View.GONE);
- binding.btnDownloadCancel.setVisibility(View.VISIBLE);
- binding.btnInstall.setVisibility(View.GONE);
- binding.progress.setVisibility(View.VISIBLE);
- binding.txtInfo.setVisibility(View.VISIBLE);
- if (mInfo.totalSize <= 0 || mInfo.status != DownloadManager.STATUS_RUNNING) {
- binding.progress.setIndeterminate(true);
- binding.txtInfo.setText(R.string.download_view_waiting);
- } else {
- binding.progress.setIndeterminate(false);
- binding.progress.setMax(mInfo.totalSize);
- binding.progress.setProgress(mInfo.bytesDownloaded);
- binding.txtInfo.setText(getContext().getString(
- R.string.download_view_running,
- mInfo.bytesDownloaded / 1024,
- mInfo.totalSize / 1024));
- }
- break;
-
- case DownloadManager.STATUS_FAILED:
- binding.btnDownload.setVisibility(View.VISIBLE);
- binding.btnSave.setVisibility(View.VISIBLE);
- binding.btnDownloadCancel.setVisibility(View.GONE);
- binding.btnInstall.setVisibility(View.GONE);
- binding.progress.setVisibility(View.GONE);
- binding.txtInfo.setVisibility(View.VISIBLE);
- binding.txtInfo.setText(getContext().getString(
- R.string.download_view_failed, mInfo.reason));
- break;
-
- case DownloadManager.STATUS_SUCCESSFUL:
- binding.btnDownload.setVisibility(View.GONE);
- binding.btnSave.setVisibility(View.VISIBLE);
- binding.btnDownloadCancel.setVisibility(View.GONE);
- binding.btnInstall.setVisibility(View.VISIBLE);
- binding.progress.setVisibility(View.GONE);
- binding.txtInfo.setVisibility(View.VISIBLE);
- binding.txtInfo.setText(R.string.download_view_successful);
- break;
- }
- }
- }
- };
public DownloadView(Context context, final AttributeSet attrs) {
super(context, attrs);
@@ -98,51 +26,7 @@ public class DownloadView extends LinearLayout {
binding = DownloadViewBinding.inflate(LayoutInflater.from(context), this);
- binding.btnDownload.setOnClickListener(v -> {
- mInfo = DownloadsUtil.addModule(getContext(), mTitle, mUrl, mCallback);
- refreshViewFromUiThread();
- if (mInfo != null)
- new DownloadMonitor().start();
- });
-
- binding.btnSave.setOnClickListener(v -> {
- lastInfo = mInfo;
- mInfo = DownloadsUtil.addModule(getContext(), mTitle, mUrl, (context1, info) -> {
- Intent exportIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- exportIntent.addCategory(Intent.CATEGORY_OPENABLE);
- exportIntent.setType(DownloadsUtil.MIME_TYPE_APK);
- exportIntent.putExtra(Intent.EXTRA_TITLE, mTitle + ".apk");
- fragment.startActivityForResult(exportIntent, 42);
- });
- refreshViewFromUiThread();
- if (mInfo != null)
- new DownloadMonitor().start();
- });
-
- binding.btnDownloadCancel.setOnClickListener(v -> {
- if (mInfo == null)
- return;
-
- DownloadsUtil.removeById(getContext(), mInfo.id);
- // UI update will happen automatically by the DownloadMonitor
- });
-
- binding.btnInstall.setOnClickListener(v -> {
- if (mCallback == null)
- return;
-
- mCallback.onDownloadFinished(getContext(), mInfo);
- });
-
- refreshViewFromUiThread();
- }
-
- private void refreshViewFromUiThread() {
- refreshViewRunnable.run();
- }
-
- private void refreshView() {
- post(refreshViewRunnable);
+ binding.btnDownload.setOnClickListener(v -> NavUtil.startURL((BaseActivity) context, mUrl));
}
public String getUrl() {
@@ -151,13 +35,14 @@ public class DownloadView extends LinearLayout {
public void setUrl(String url) {
mUrl = url;
-
- if (mUrl != null)
- mInfo = DownloadsUtil.getLatestForUrl(getContext(), mUrl);
- else
- mInfo = null;
-
- refreshView();
+ if (mUrl != null) {
+ binding.btnDownload.setVisibility(View.VISIBLE);
+ binding.txtInfo.setVisibility(View.GONE);
+ }else {
+ binding.btnDownload.setVisibility(View.GONE);
+ binding.txtInfo.setVisibility(View.VISIBLE);
+ binding.txtInfo.setText(R.string.download_view_no_url);
+ }
}
public String getTitle() {
@@ -167,44 +52,4 @@ public class DownloadView extends LinearLayout {
public void setTitle(String title) {
this.mTitle = title;
}
-
- @SuppressWarnings("unused")
- public DownloadFinishedCallback getDownloadFinishedCallback() {
- return mCallback;
- }
-
- public void setDownloadFinishedCallback(DownloadFinishedCallback downloadFinishedCallback) {
- this.mCallback = downloadFinishedCallback;
- }
-
- private class DownloadMonitor extends Thread {
- DownloadMonitor() {
- super("DownloadMonitor");
- }
-
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- return;
- }
-
- try {
- mInfo = DownloadsUtil.getById(getContext(), mInfo.id);
- } catch (NullPointerException ignored) {
- }
-
- refreshView();
- if (mInfo == null)
- return;
-
- if (mInfo.status != DownloadManager.STATUS_PENDING
- && mInfo.status != DownloadManager.STATUS_PAUSED
- && mInfo.status != DownloadManager.STATUS_RUNNING)
- return;
- }
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/download_view.xml b/app/src/main/res/layout/download_view.xml
index 6c49b174..a4b7fd6d 100644
--- a/app/src/main/res/layout/download_view.xml
+++ b/app/src/main/res/layout/download_view.xml
@@ -1,5 +1,4 @@
-
+
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 6d1defb0..825c5193 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -139,7 +139,7 @@
使用的库
- 下载并安装
+ 下载
安装
取消
无可用的下载链接
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 5bd48679..5813b89b 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -139,7 +139,7 @@
使用的庫
- 下載並安裝
+ 下載
安裝
取消
無可用的下載鏈接
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 19bbb077..4cd5ac88 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -139,7 +139,7 @@
使用的庫
- 下載並安裝
+ 下載
安裝
取消
無可用的下載連結
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1ee41c95..0d95b6ae 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -141,7 +141,7 @@
Used libraries
- Download and Install
+ Download
Install
Cancel
No download URL available