From ed8836ca6d0d88489013dee37763ea610feb1345 Mon Sep 17 00:00:00 2001
From: NekoInverter <42698724+NekoInverter@users.noreply.github.com>
Date: Thu, 5 Mar 2020 17:33:14 +0800
Subject: [PATCH] Remove storage permission
---
app/src/main/AndroidManifest.xml | 4 +-
.../android/xposed/installer/XposedApp.java | 1 +
.../edxposed/manager/BaseActivity.java | 14 --
.../manager/BaseAdvancedInstaller.java | 70 ++-----
.../edxposed/manager/BlackListActivity.java | 8 +-
.../edxposed/manager/CompatListActivity.java | 8 +-
.../edxposed/manager/DownloadActivity.java | 4 +-
.../manager/DownloadDetailsFragment.java | 2 +
.../DownloadDetailsSettingsFragment.java | 2 +-
.../DownloadDetailsVersionsFragment.java | 40 +++-
.../edxposed/manager/EdDownloadActivity.java | 10 +-
.../edxposed/manager/LogsActivity.java | 82 +++-----
.../edxposed/manager/MainActivity.java | 6 +-
.../edxposed/manager/ModulesActivity.java | 196 ++++++++----------
.../manager/StatusInstallerFragment.java | 148 ++++++-------
.../meowcat/edxposed/manager/XposedApp.java | 48 +++--
.../edxposed/manager/util/DownloadsUtil.java | 167 ++-------------
.../edxposed/manager/widget/DownloadView.java | 59 ++----
app/src/main/res/layout/download_view.xml | 10 -
app/src/main/res/values-zh-rCN/strings.xml | 4 -
app/src/main/res/values-zh-rHK/strings.xml | 4 -
app/src/main/res/values-zh-rTW/strings.xml | 4 -
app/src/main/res/values/strings.xml | 5 -
app/src/main/res/xml/file_paths.xml | 5 +-
24 files changed, 299 insertions(+), 602 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 512c456b..f253cdf7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,8 +4,6 @@
package="org.meowcat.edxposed.manager">
-
-
@@ -98,7 +96,7 @@
= Build.VERSION_CODES.M) {
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, XposedApp.WRITE_EXTERNAL_PERMISSION);
- }
- return true;
- }
- return false;
- }
-
void reboot(String mode) {
if (!Shell.rootAccess()) {
showAlert(getString(R.string.root_failed));
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/BaseAdvancedInstaller.java b/app/src/main/java/org/meowcat/edxposed/manager/BaseAdvancedInstaller.java
index 4c4b4de6..f762dfd0 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/BaseAdvancedInstaller.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/BaseAdvancedInstaller.java
@@ -1,13 +1,9 @@
package org.meowcat.edxposed.manager;
-import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
@@ -20,11 +16,9 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.google.android.material.snackbar.Snackbar;
import org.meowcat.edxposed.manager.util.NavUtil;
import org.meowcat.edxposed.manager.util.json.XposedTab;
@@ -33,8 +27,6 @@ import org.meowcat.edxposed.manager.util.json.XposedZip;
import java.util.List;
import java.util.Objects;
-import static org.meowcat.edxposed.manager.XposedApp.WRITE_EXTERNAL_PERMISSION;
-
public class BaseAdvancedInstaller extends Fragment {
private View mClickedButton;
@@ -88,16 +80,6 @@ public class BaseAdvancedInstaller extends Fragment {
return Objects.requireNonNull(tab).description;
}
- private boolean checkPermissions() {
- if (Build.VERSION.SDK_INT < 23) return false;
-
- if (ActivityCompat.checkSelfPermission(Objects.requireNonNull(getActivity()), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_PERMISSION);
- return true;
- }
- return false;
- }
-
@Override
public void onDestroy() {
super.onDestroy();
@@ -143,31 +125,21 @@ public class BaseAdvancedInstaller extends Fragment {
.setMessage(s).setPositiveButton(android.R.string.ok, null).show();
});
- btnInstall.setOnClickListener(v -> {
- mClickedButton = v;
- if (checkPermissions()) return;
+ btnInstall.setOnClickListener(v -> areYouSure(R.string.warningArchitecture,
+ (dialog, which) -> {
+ XposedZip selectedInstaller = (XposedZip) chooserInstallers.getSelectedItem();
+ Uri uri = Uri.parse(selectedInstaller.link);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ startActivity(intent);
+ }));
- areYouSure(R.string.warningArchitecture,
- (dialog, which) -> {
- XposedZip selectedInstaller = (XposedZip) chooserInstallers.getSelectedItem();
- Uri uri = Uri.parse(selectedInstaller.link);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- startActivity(intent);
- });
- });
-
- btnUninstall.setOnClickListener(v -> {
- mClickedButton = v;
- if (checkPermissions()) return;
-
- areYouSure(R.string.warningArchitecture,
- (dialog, which) -> {
- XposedZip selectedUninstaller = (XposedZip) chooserUninstallers.getSelectedItem();
- Uri uri = Uri.parse(selectedUninstaller.link);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- startActivity(intent);
- });
- });
+ btnUninstall.setOnClickListener(v -> areYouSure(R.string.warningArchitecture,
+ (dialog, which) -> {
+ XposedZip selectedUninstaller = (XposedZip) chooserUninstallers.getSelectedItem();
+ Uri uri = Uri.parse(selectedUninstaller.link);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ startActivity(intent);
+ }));
noticeTv.setText(Html.fromHtml(notice()));
author.setText(getString(R.string.download_author, author()));
@@ -198,20 +170,6 @@ public class BaseAdvancedInstaller extends Fragment {
return view;
}
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (requestCode == WRITE_EXTERNAL_PERMISSION) {
- if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (mClickedButton != null) {
- new Handler().postDelayed(() -> mClickedButton.performClick(), 500);
- }
- } else {
- Snackbar.make(getActivity().findViewById(R.id.snackbar), R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
- }
- }
- }
-
@SuppressWarnings("SameParameterValue")
private void areYouSure(int contentTextId, DialogInterface.OnClickListener listener) {
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java
index bdeb92ba..96481189 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java
@@ -11,7 +11,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -73,7 +72,7 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_app_list, menu);
- mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_search));
+ mSearchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
mSearchView.setOnQueryTextListener(mSearchListener);
return super.onCreateOptionsMenu(menu);
}
@@ -126,11 +125,6 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
AppHelper.showMenu(this, getSupportFragmentManager(), v, info);
}
- @Override
- public void onPointerCaptureChanged(boolean hasCapture) {
-
- }
-
@Override
public void onBackPressed() {
if (mSearchView.isIconified()) {
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java
index c94f411b..83b99db2 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java
@@ -10,7 +10,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -68,15 +67,10 @@ public class CompatListActivity extends BaseActivity implements AppAdapter.Callb
};
}
- @Override
- public void onResume() {
- super.onResume();
- }
-
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_app_list, menu);
- mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_search));
+ mSearchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
mSearchView.setOnQueryTextListener(mSearchListener);
return super.onCreateOptionsMenu(menu);
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/DownloadActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/DownloadActivity.java
index 60afee70..1e638dd6 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/DownloadActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/DownloadActivity.java
@@ -23,7 +23,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -153,8 +152,7 @@ public class DownloadActivity extends BaseActivity implements RepoLoader.RepoLis
getMenuInflater().inflate(R.menu.menu_download, menu);
// Setup search button
- final MenuItem searchItem = menu.findItem(R.id.menu_search);
- mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
+ mSearchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
mSearchView.setIconifiedByDefault(true);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsFragment.java
index 1d511950..17a3f7f2 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsFragment.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsFragment.java
@@ -1,5 +1,6 @@
package org.meowcat.edxposed.manager;
+import android.annotation.SuppressLint;
import android.net.Uri;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
@@ -20,6 +21,7 @@ import org.meowcat.edxposed.manager.util.chrome.LinkTransformationMethod;
public class DownloadDetailsFragment extends Fragment {
+ @SuppressLint("SetTextI18n")
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
DownloadDetailsActivity mActivity = (DownloadDetailsActivity) getActivity();
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsSettingsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsSettingsFragment.java
index bb06d323..7c464bb0 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsSettingsFragment.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsSettingsFragment.java
@@ -40,7 +40,7 @@ public class DownloadDetailsSettingsFragment extends PreferenceFragmentCompat {
if (prefs.getBoolean("no_global", true)) {
for (Map.Entry k : prefs.getAll().entrySet()) {
- if (prefs.getString(k.getKey(), "").equals("global")) {
+ if (("global").equals(prefs.getString(k.getKey(), ""))) {
editor.putString(k.getKey(), "").apply();
}
}
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 616358d1..999fdb7f 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/DownloadDetailsVersionsFragment.java
@@ -1,12 +1,16 @@
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.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -35,11 +39,11 @@ 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;
-import static org.meowcat.edxposed.manager.XposedApp.WRITE_EXTERNAL_PERMISSION;
-
public class DownloadDetailsVersionsFragment extends ListFragment {
private static View rootView;
private DownloadDetailsActivity mActivity;
@@ -93,13 +97,31 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (requestCode == WRITE_EXTERNAL_PERMISSION) {
- if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- DownloadView.mClickedButton.performClick();
- } else {
- Snackbar.make(rootView, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
+ 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 = mActivity.getContentResolver().openOutputStream(uri);
+ if (os != null) {
+ FileInputStream in = new FileInputStream(new File(DownloadView.mInfo.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();
+ }
+ }
}
}
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/EdDownloadActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/EdDownloadActivity.java
index a4457c2d..4365ff97 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/EdDownloadActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/EdDownloadActivity.java
@@ -83,10 +83,6 @@ public class EdDownloadActivity extends BaseActivity {
@SuppressLint("StaticFieldLeak")
private class JSONParser extends AsyncTask {
- private String newApkVersion = null;
- private String newApkLink = null;
- private String newApkChangelog = null;
-
@Override
protected String doInBackground(Void... params) {
try {
@@ -115,9 +111,9 @@ public class EdDownloadActivity extends BaseActivity {
tabsAdapter.notifyDataSetChanged();
}
- newApkVersion = xposedJson.apk.version;
- newApkLink = xposedJson.apk.link;
- newApkChangelog = xposedJson.apk.changelog;
+ String newApkVersion = xposedJson.apk.version;
+ String newApkLink = xposedJson.apk.link;
+ String newApkChangelog = xposedJson.apk.changelog;
if (newApkVersion == null) {
return;
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/LogsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/LogsActivity.java
index b23c1b68..abb8f01a 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/LogsActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/LogsActivity.java
@@ -1,15 +1,11 @@
package org.meowcat.edxposed.manager;
-import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -23,7 +19,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -36,6 +31,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -48,7 +44,6 @@ public class LogsActivity extends BaseActivity {
XposedApp.BASE_DIR + "log/error.log.old");
private File mFileAllLog = new File(XposedApp.BASE_DIR + "log/all.log");
private File mFileAllLogOld = new File(XposedApp.BASE_DIR + "log/all.log.old");
- private MenuItem mClickedMenuItem = null;
private LogsAdapter mAdapter;
private RecyclerView mListView;
private Handler handler = new Handler();
@@ -124,7 +119,6 @@ public class LogsActivity extends BaseActivity {
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- mClickedMenuItem = item;
switch (item.getItemId()) {
case R.id.menu_scroll_top:
scrollTop();
@@ -138,7 +132,8 @@ public class LogsActivity extends BaseActivity {
case R.id.menu_send:
try {
send();
- } catch (NullPointerException ignored) {
+ } catch (Exception e) {
+ Snackbar.make(findViewById(R.id.snackbar), e.getLocalizedMessage(), Snackbar.LENGTH_LONG).show();
}
return true;
case R.id.menu_save:
@@ -186,34 +181,8 @@ public class LogsActivity extends BaseActivity {
startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.menuSend)));
}
- @Override
- public void onRequestPermissionsResult(int requestCode,
- @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions,
- grantResults);
- if (requestCode == XposedApp.WRITE_EXTERNAL_PERMISSION) {
- if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (mClickedMenuItem != null) {
- new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500);
- }
- } else {
- Snackbar.make(findViewById(R.id.snackbar), R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
- }
- }
- }
-
@SuppressLint("DefaultLocale")
private void save() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, XposedApp.WRITE_EXTERNAL_PERMISSION);
- return;
- }
-
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- Snackbar.make(findViewById(R.id.snackbar), R.string.sdcard_not_writable, Snackbar.LENGTH_LONG).show();
- return;
- }
-
Calendar now = Calendar.getInstance();
String filename = String.format(
"EdXposed_Verbose_%04d%02d%02d_%02d%02d%02d.log",
@@ -221,22 +190,39 @@ public class LogsActivity extends BaseActivity {
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
- File targetFile = new File(XposedApp.createFolder(), filename);
+ Intent exportIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ exportIntent.addCategory(Intent.CATEGORY_OPENABLE);
+ exportIntent.setType("text/*");
+ exportIntent.putExtra(Intent.EXTRA_TITLE, filename);
+ startActivityForResult(exportIntent, 42);
+ }
- try {
- FileInputStream in = new FileInputStream(allLog ? mFileAllLog : mFileErrorLog);
- FileOutputStream out = new FileOutputStream(targetFile);
- byte[] buffer = new byte[1024];
- int len;
- while ((len = in.read(buffer)) > 0) {
- out.write(buffer, 0, len);
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+ if (requestCode == 42) {
+ if (data != null) {
+ Uri uri = data.getData();
+ if (uri != null) {
+ try {
+ OutputStream os = getContentResolver().openOutputStream(uri);
+ if (os != null) {
+ FileInputStream in = new FileInputStream(allLog ? mFileAllLog : mFileErrorLog);
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) > 0) {
+ os.write(buffer, 0, len);
+ }
+ os.close();
+ }
+ } catch (Exception e) {
+ Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
+ }
+ }
}
- in.close();
- out.close();
-
- Snackbar.make(findViewById(R.id.snackbar), targetFile.toString(), Snackbar.LENGTH_LONG).show();
- } catch (IOException e) {
- Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
}
}
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/MainActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/MainActivity.java
index c3a681e1..171bfeb6 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/MainActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/MainActivity.java
@@ -9,8 +9,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.appcompat.view.menu.MenuBuilder;
-import androidx.appcompat.view.menu.MenuPopupHelper;
import androidx.appcompat.widget.PopupMenu;
import com.google.android.material.card.MaterialCardView;
@@ -70,9 +68,7 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene
PopupMenu appMenu = new PopupMenu(MainActivity.this, menu);
appMenu.inflate(R.menu.menu_installer);
appMenu.setOnMenuItemClickListener(this::onOptionsItemSelected);
- MenuPopupHelper menuHelper = new MenuPopupHelper(MainActivity.this, (MenuBuilder) appMenu.getMenu(), menu);
- menuHelper.setForceShowIcon(true);
- menuHelper.show();
+ appMenu.show();
});
String installedXposedVersion;
try {
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 1f4fd114..ff8d869b 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java
@@ -1,15 +1,11 @@
package org.meowcat.edxposed.manager;
-import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
import android.text.TextUtils;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -24,7 +20,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -43,15 +38,11 @@ import org.meowcat.edxposed.manager.util.NavUtil;
import org.meowcat.edxposed.manager.util.RepoLoader;
import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -77,7 +68,6 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
private DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
private ModuleUtil mModuleUtil;
private ModuleAdapter mAdapter = null;
- private MenuItem mClickedMenuItem = null;
private RecyclerView mListView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private Runnable reloadModules = new Runnable() {
@@ -162,152 +152,140 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_modules, menu);
- mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_search));
+ mSearchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
mSearchView.setOnQueryTextListener(mSearchListener);
return super.onCreateOptionsMenu(menu);
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions,
- grantResults);
- if (requestCode == XposedApp.WRITE_EXTERNAL_PERMISSION) {
- if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (mClickedMenuItem != null) {
- new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500);
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+ if (requestCode == 42) {
+ File listModules = new File(XposedApp.ENABLED_MODULES_LIST_FILE);
+ if (data != null) {
+ Uri uri = data.getData();
+ if (uri != null) {
+ try {
+ OutputStream os = getContentResolver().openOutputStream(uri);
+ if (os != null) {
+ FileInputStream in = new FileInputStream(listModules);
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) > 0) {
+ os.write(buffer, 0, len);
+ }
+ os.close();
+ }
+ } catch (Exception e) {
+ Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
+ }
+ }
+ }
+ } else if (requestCode == 43) {
+ if (data != null) {
+ Uri uri = data.getData();
+ if (uri != null) {
+ try {
+ OutputStream os = getContentResolver().openOutputStream(uri);
+ if (os != null) {
+ PrintWriter fileOut = new PrintWriter(os);
+
+ Set keys = ModuleUtil.getInstance().getModules().keySet();
+ for (String key1 : keys) {
+ fileOut.println(key1);
+ }
+ fileOut.close();
+ os.close();
+ }
+ } catch (Exception e) {
+ Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
+ }
+ }
+ }
+ } else if (requestCode == 44) {
+ if (data != null) {
+ Uri uri = data.getData();
+ if (uri != null) {
+ try {
+ importModules(uri);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
- } else {
- Snackbar.make(findViewById(R.id.snackbar), R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
}
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- File enabledModulesPath = new File(XposedApp.createFolder(), "enabled_modules.list");
- File installedModulesPath = new File(XposedApp.createFolder(), "installed_modules.list");
- File listModules = new File(XposedApp.ENABLED_MODULES_LIST_FILE);
-
- mClickedMenuItem = item;
-
- if (checkPermissions())
- return false;
-
+ Intent intent;
switch (item.getItemId()) {
case R.id.export_enabled_modules:
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- return false;
- }
-
if (ModuleUtil.getInstance().getEnabledModules().isEmpty()) {
Snackbar.make(findViewById(R.id.snackbar), R.string.no_enabled_modules, Snackbar.LENGTH_SHORT).show();
return false;
}
-
- try {
- XposedApp.createFolder();
-
- FileInputStream in = new FileInputStream(listModules);
- FileOutputStream out = new FileOutputStream(enabledModulesPath);
-
- byte[] buffer = new byte[1024];
- int len;
- while ((len = in.read(buffer)) > 0) {
- out.write(buffer, 0, len);
- }
- in.close();
- out.close();
- } catch (IOException e) {
- Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
- return false;
- }
-
- Snackbar.make(findViewById(R.id.snackbar), enabledModulesPath.toString(), Snackbar.LENGTH_LONG).show();
+ intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("text/*");
+ intent.putExtra(Intent.EXTRA_TITLE, "enabled_modules.list");
+ startActivityForResult(intent, 42);
return true;
case R.id.export_installed_modules:
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- Snackbar.make(findViewById(R.id.snackbar), R.string.sdcard_not_writable, Snackbar.LENGTH_LONG).show();
- return false;
- }
Map installedModules = ModuleUtil.getInstance().getModules();
if (installedModules.isEmpty()) {
Snackbar.make(findViewById(R.id.snackbar), R.string.no_installed_modules, Snackbar.LENGTH_SHORT).show();
return false;
}
-
- try {
- XposedApp.createFolder();
-
- FileWriter fw = new FileWriter(installedModulesPath);
- BufferedWriter bw = new BufferedWriter(fw);
- PrintWriter fileOut = new PrintWriter(bw);
-
- Set keys = installedModules.keySet();
- for (String key1 : keys) {
- fileOut.println(key1);
- }
-
- fileOut.close();
- } catch (IOException e) {
- Snackbar.make(findViewById(R.id.snackbar), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
- return false;
- }
-
- Snackbar.make(findViewById(R.id.snackbar), installedModulesPath.toString(), Snackbar.LENGTH_LONG).show();
+ intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("text/*");
+ intent.putExtra(Intent.EXTRA_TITLE, "installed_modules.list");
+ startActivityForResult(intent, 43);
return true;
case R.id.import_installed_modules:
- return importModules(installedModulesPath);
case R.id.import_enabled_modules:
- return importModules(enabledModulesPath);
+ intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ startActivityForResult(intent, 44);
+ return true;
}
return super.onOptionsItemSelected(item);
}
- private boolean importModules(File path) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- Snackbar.make(findViewById(R.id.snackbar), R.string.sdcard_not_writable, Snackbar.LENGTH_LONG).show();
- return false;
- }
- InputStream ips = null;
+ private void importModules(Uri uri) {
RepoLoader repoLoader = RepoLoader.getInstance();
List list = new ArrayList<>();
- if (!path.exists()) {
- Snackbar.make(findViewById(R.id.snackbar), R.string.no_backup_found, Snackbar.LENGTH_LONG).show();
- return false;
- }
- try {
- ips = new FileInputStream(path);
- } catch (FileNotFoundException e) {
- Log.e(XposedApp.TAG, "ModulesFragment -> " + e.getMessage());
- }
-
- if (path.length() == 0) {
- Snackbar.make(findViewById(R.id.snackbar), R.string.file_is_empty, Snackbar.LENGTH_LONG).show();
- return false;
- }
try {
- assert ips != null;
- InputStreamReader ipsr = new InputStreamReader(ips);
- BufferedReader br = new BufferedReader(ipsr);
+ InputStream inputStream = getContentResolver().openInputStream(uri);
+ InputStreamReader isr = new InputStreamReader(inputStream);
+ BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
Module m = repoLoader.getModule(line);
if (m == null) {
- Snackbar.make(findViewById(R.id.snackbar), getString(R.string.download_details_not_found,
- line), Snackbar.LENGTH_SHORT).show();
+ Snackbar.make(findViewById(R.id.snackbar), getString(R.string.download_details_not_found, line), Snackbar.LENGTH_SHORT).show();
} else {
list.add(m);
}
}
br.close();
- } catch (ActivityNotFoundException | IOException e) {
- Snackbar.make(findViewById(R.id.snackbar), e.toString(), Snackbar.LENGTH_SHORT).show();
+ } catch (Exception e) {
+ e.printStackTrace();
+ Snackbar.make(findViewById(R.id.snackbar), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
}
for (final Module m : list) {
+ if (mModuleUtil.getModule(m.packageName) != null) {
+ continue;
+ }
ModuleVersion mv = null;
for (int i = 0; i < m.versions.size(); i++) {
ModuleVersion mvTemp = m.versions.get(i);
@@ -319,13 +297,11 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
}
if (mv != null) {
- DownloadsUtil.addModule(this, m.name, mv.downloadLink, false, (context, info) -> new InstallApkUtil(this, info).execute());
+ DownloadsUtil.addModule(this, m.name, mv.downloadLink, (context, info) -> new InstallApkUtil(this, info).execute());
}
}
ModuleUtil.getInstance().reloadInstalledModules();
-
- return true;
}
@Override
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/StatusInstallerFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/StatusInstallerFragment.java
index edf1959d..3dcddcca 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/StatusInstallerFragment.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/StatusInstallerFragment.java
@@ -3,13 +3,9 @@ package org.meowcat.edxposed.manager;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.FileUtils;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
@@ -28,13 +24,10 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Objects;
@SuppressLint("StaticFieldLeak")
public class StatusInstallerFragment extends Fragment {
- public static final File DISABLE_FILE = new File(XposedApp.BASE_DIR + "conf/disabled");
private static AppCompatActivity sActivity;
private static String mUpdateLink;
private static View mUpdateView;
@@ -98,20 +91,6 @@ public class StatusInstallerFragment extends Fragment {
}
}
- @SuppressWarnings("SameParameterValue")
- @SuppressLint({"WorldReadableFiles", "WorldWriteableFiles"})
- private static void setFilePermissionsFromMode(String name, int mode) {
- int perms = FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IWGRP;
- if ((mode & Context.MODE_WORLD_READABLE) != 0) {
- perms |= FileUtils.S_IROTH;
- }
- if ((mode & Context.MODE_WORLD_WRITEABLE) != 0) {
- perms |= FileUtils.S_IWOTH;
- }
- FileUtils.setPermissions(name, perms, -1, -1);
- }
-
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -119,7 +98,6 @@ public class StatusInstallerFragment extends Fragment {
}
@SuppressLint("WorldReadableFiles")
- @SuppressWarnings("ResultOfMethodCallIgnored")
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.status_installer, container, false);
@@ -156,8 +134,6 @@ public class StatusInstallerFragment extends Fragment {
cpu.setText(getCompleteArch());
determineVerifiedBootState(v);
-
- refreshKnownIssue();
return v;
}
@@ -191,57 +167,58 @@ public class StatusInstallerFragment extends Fragment {
}
}
- @SuppressWarnings("SameParameterValue")
- private boolean checkAppInstalled(Context context, String pkgName) {
- if (pkgName == null || pkgName.isEmpty()) {
- return false;
- }
- final PackageManager packageManager = context.getPackageManager();
- List info = packageManager.getInstalledPackages(0);
- if (info == null || info.isEmpty()) {
- return false;
- }
- for (int i = 0; i < info.size(); i++) {
- if (pkgName.equals(info.get(i).packageName)) {
- return true;
+ /*
+ @SuppressWarnings("SameParameterValue")
+ private boolean checkAppInstalled(Context context, String pkgName) {
+ if (pkgName == null || pkgName.isEmpty()) {
+ return false;
}
- }
- return false;
- }
-
- @SuppressLint("StringFormatInvalid")
- private void refreshKnownIssue() {
- String issueName = null;
- String issueLink = null;
- final ApplicationInfo appInfo = Objects.requireNonNull(getActivity()).getApplicationInfo();
- final File baseDir = new File(XposedApp.BASE_DIR);
- final File baseDirCanonical = getCanonicalFile(baseDir);
- final File baseDirActual = new File(Build.VERSION.SDK_INT >= 24 ? appInfo.deviceProtectedDataDir : appInfo.dataDir);
- final File baseDirActualCanonical = getCanonicalFile(baseDirActual);
-
- if (new File("/system/framework/core.jar.jex").exists()) {
- issueName = "Aliyun OS";
- issueLink = "https://forum.xda-developers.com/showpost.php?p=52289793&postcount=5";
-// } else if (Build.VERSION.SDK_INT < 24 && (new File("/data/miui/DexspyInstaller.jar").exists() || checkClassExists("miui.dexspy.DexspyInstaller"))) {
-// issueName = "MIUI/Dexspy";
-// issueLink = "https://forum.xda-developers.com/showpost.php?p=52291098&postcount=6";
-// } else if (Build.VERSION.SDK_INT < 24 && new File("/system/framework/twframework.jar").exists()) {
-// issueName = "Samsung TouchWiz ROM";
-// issueLink = "https://forum.xda-developers.com/showthread.php?t=3034811";
- } else if (!baseDirCanonical.equals(baseDirActualCanonical)) {
- Log.e(XposedApp.TAG, "Base directory: " + getPathWithCanonicalPath(baseDir, baseDirCanonical));
- Log.e(XposedApp.TAG, "Expected: " + getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
- issueName = getString(R.string.known_issue_wrong_base_directory, getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
- } else if (!baseDir.exists()) {
- issueName = getString(R.string.known_issue_missing_base_directory);
- issueLink = "https://github.com/rovo89/XposedInstaller/issues/393";
- } else if (checkAppInstalled(getContext(), "com.solohsu.android.edxp.manager")) {
- issueName = getString(R.string.edxp_installer_installed);
- issueLink = getString(R.string.about_support);
+ final PackageManager packageManager = context.getPackageManager();
+ List info = packageManager.getInstalledPackages(0);
+ if (info == null || info.isEmpty()) {
+ return false;
+ }
+ for (int i = 0; i < info.size(); i++) {
+ if (pkgName.equals(info.get(i).packageName)) {
+ return true;
+ }
+ }
+ return false;
}
- }
+ @SuppressLint("StringFormatInvalid")
+ private void refreshKnownIssue() {
+ String issueName = null;
+ String issueLink = null;
+ final ApplicationInfo appInfo = Objects.requireNonNull(getActivity()).getApplicationInfo();
+ final File baseDir = new File(XposedApp.BASE_DIR);
+ final File baseDirCanonical = getCanonicalFile(baseDir);
+ final File baseDirActual = new File(Build.VERSION.SDK_INT >= 24 ? appInfo.deviceProtectedDataDir : appInfo.dataDir);
+ final File baseDirActualCanonical = getCanonicalFile(baseDirActual);
+ if (new File("/system/framework/core.jar.jex").exists()) {
+ issueName = "Aliyun OS";
+ issueLink = "https://forum.xda-developers.com/showpost.php?p=52289793&postcount=5";
+ // } else if (Build.VERSION.SDK_INT < 24 && (new File("/data/miui/DexspyInstaller.jar").exists() || checkClassExists("miui.dexspy.DexspyInstaller"))) {
+ // issueName = "MIUI/Dexspy";
+ // issueLink = "https://forum.xda-developers.com/showpost.php?p=52291098&postcount=6";
+ // } else if (Build.VERSION.SDK_INT < 24 && new File("/system/framework/twframework.jar").exists()) {
+ // issueName = "Samsung TouchWiz ROM";
+ // issueLink = "https://forum.xda-developers.com/showthread.php?t=3034811";
+ } else if (!baseDirCanonical.equals(baseDirActualCanonical)) {
+ Log.e(XposedApp.TAG, "Base directory: " + getPathWithCanonicalPath(baseDir, baseDirCanonical));
+ Log.e(XposedApp.TAG, "Expected: " + getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
+ issueName = getString(R.string.known_issue_wrong_base_directory, getPathWithCanonicalPath(baseDirActual, baseDirActualCanonical));
+ } else if (!baseDir.exists()) {
+ issueName = getString(R.string.known_issue_missing_base_directory);
+ issueLink = "https://github.com/rovo89/XposedInstaller/issues/393";
+ } else if (checkAppInstalled(getContext(), "com.solohsu.android.edxp.manager")) {
+ issueName = getString(R.string.edxp_installer_installed);
+ issueLink = getString(R.string.about_support);
+ }
+
+ }
+ */
private String getAndroidVersion() {
switch (Build.VERSION.SDK_INT) {
// case 16:
@@ -296,23 +273,24 @@ public class StatusInstallerFragment extends Fragment {
return manufacturer;
}
- private File getCanonicalFile(File file) {
- try {
- return file.getCanonicalFile();
- } catch (IOException e) {
- Log.e(XposedApp.TAG, "Failed to get canonical file for " + file.getAbsolutePath(), e);
- return file;
+ /*
+ private File getCanonicalFile(File file) {
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ Log.e(XposedApp.TAG, "Failed to get canonical file for " + file.getAbsolutePath(), e);
+ return file;
+ }
}
- }
- private String getPathWithCanonicalPath(File file, File canonical) {
- if (file.equals(canonical)) {
- return file.getAbsolutePath();
- } else {
- return file.getAbsolutePath() + " \u2192 " + canonical.getAbsolutePath();
+ private String getPathWithCanonicalPath(File file, File canonical) {
+ if (file.equals(canonical)) {
+ return file.getAbsolutePath();
+ } else {
+ return file.getAbsolutePath() + " \u2192 " + canonical.getAbsolutePath();
+ }
}
- }
-
+ */
private int extractIntPart(String str) {
int result = 0, length = str.length();
for (int offset = 0; offset < length; offset++) {
diff --git a/app/src/main/java/org/meowcat/edxposed/manager/XposedApp.java b/app/src/main/java/org/meowcat/edxposed/manager/XposedApp.java
index 8adff14c..82ff254f 100644
--- a/app/src/main/java/org/meowcat/edxposed/manager/XposedApp.java
+++ b/app/src/main/java/org/meowcat/edxposed/manager/XposedApp.java
@@ -105,31 +105,35 @@ public class XposedApp extends de.robv.android.xposed.installer.XposedApp implem
public void onCreate() {
super.onCreate();
- try {
- Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
+ if (!BuildConfig.DEBUG) {
+ try {
+ Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- throwable.printStackTrace(pw);
- String stackTraceString = sw.toString();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ throwable.printStackTrace(pw);
+ String stackTraceString = sw.toString();
- //Reduce data to 128KB so we don't get a TransactionTooLargeException when sending the intent.
- //The limit is 1MB on Android but some devices seem to have it lower.
- //See: http://developer.android.com/reference/android/os/TransactionTooLargeException.html
- //And: http://stackoverflow.com/questions/11451393/what-to-do-on-transactiontoolargeexception#comment46697371_12809171
- if (stackTraceString.length() > 131071) {
- String disclaimer = " [stack trace too large]";
- stackTraceString = stackTraceString.substring(0, 131071 - disclaimer.length()) + disclaimer;
- }
- Intent intent = new Intent(XposedApp.this, CrashReportActivity.class);
- intent.putExtra(BuildConfig.APPLICATION_ID + ".EXTRA_STACK_TRACE", stackTraceString);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- XposedApp.this.startActivity(intent);
- android.os.Process.killProcess(android.os.Process.myPid());
- System.exit(10);
- });
- } catch (Throwable t) {
+ //Reduce data to 128KB so we don't get a TransactionTooLargeException when sending the intent.
+ //The limit is 1MB on Android but some devices seem to have it lower.
+ //See: http://developer.android.com/reference/android/os/TransactionTooLargeException.html
+ //And: http://stackoverflow.com/questions/11451393/what-to-do-on-transactiontoolargeexception#comment46697371_12809171
+ if (stackTraceString.length() > 131071) {
+ String disclaimer = " [stack trace too large]";
+ stackTraceString = stackTraceString.substring(0, 131071 - disclaimer.length()) + disclaimer;
+ }
+ Intent intent = new Intent(XposedApp.this, CrashReportActivity.class);
+ intent.putExtra(BuildConfig.APPLICATION_ID + ".EXTRA_STACK_TRACE", stackTraceString);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ XposedApp.this.startActivity(intent);
+ android.os.Process.killProcess(android.os.Process.myPid());
+ System.exit(10);
+ });
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
}
+
mInstance = this;
mUiThread = Thread.currentThread();
mMainHandler = new Handler();
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 12a83ee0..5cd6e744 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
@@ -4,26 +4,17 @@ import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
-import android.app.ProgressDialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Environment;
import android.provider.MediaStore;
-import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import androidx.core.os.EnvironmentCompat;
import org.meowcat.edxposed.manager.R;
import org.meowcat.edxposed.manager.XposedApp;
-import org.meowcat.edxposed.manager.repo.Module;
-import org.meowcat.edxposed.manager.repo.ModuleVersion;
-import org.meowcat.edxposed.manager.repo.ReleaseType;
import java.io.File;
import java.io.FileOutputStream;
@@ -40,7 +31,7 @@ import java.util.Map;
import java.util.Objects;
public class DownloadsUtil {
- static final String MIME_TYPE_APK = "application/vnd.android.package-archive";
+ public static final String MIME_TYPE_APK = "application/vnd.android.package-archive";
//private static final String MIME_TYPE_ZIP = "application/zip";
private static final Map mCallbacks = new HashMap<>();
@SuppressLint("StaticFieldLeak")
@@ -48,152 +39,55 @@ public class DownloadsUtil {
private static final SharedPreferences mPref = mApp
.getSharedPreferences("download_cache", Context.MODE_PRIVATE);
- private static String DOWNLOAD_MODULES = "modules";
-
private static DownloadInfo add(Builder b) {
Context context = b.mContext;
removeAllForUrl(context, b.mUrl);
- if (!b.mDialog) {
- synchronized (mCallbacks) {
- mCallbacks.put(b.mUrl, b.mCallback);
- }
- }
-
- String savePath = "Download/EdXposedManager";
- if (b.mModule) {
- savePath += "/modules";
+ synchronized (mCallbacks) {
+ mCallbacks.put(b.mUrl, b.mCallback);
}
Request request = new Request(Uri.parse(b.mUrl));
request.setTitle(b.mTitle);
request.setMimeType(b.mMimeType.toString());
- if (b.mSave) {
+ /*if (b.mSave) {
try {
request.setDestinationInExternalPublicDir(savePath, b.mTitle + b.mMimeType.getExtension());
} catch (IllegalStateException e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
}
- } else if (b.mDestination != null) {
- //noinspection ResultOfMethodCallIgnored
- b.mDestination.getParentFile().mkdirs();
- removeAllForLocalFile(context, b.mDestination);
- request.setDestinationUri(Uri.fromFile(b.mDestination));
- }
-
+ } else */
+ File destination = new File(context.getExternalCacheDir(), "/downloads/" + b.mTitle + b.mMimeType.getExtension());
+ request.setDestinationUri(Uri.fromFile(destination));
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE);
-
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
long id = dm.enqueue(request);
- if (b.mDialog) {
- showDownloadDialog(b, id);
- }
-
return getById(context, id);
}
- private static File[] getDownloadDirs(String subDir) {
- Context context = XposedApp.getInstance();
- ArrayList dirs = new ArrayList<>(2);
- for (File dir : ContextCompat.getExternalCacheDirs(context)) {
- if (dir != null && EnvironmentCompat.getStorageState(dir).equals(Environment.MEDIA_MOUNTED)) {
- dirs.add(new File(new File(dir, "downloads"), subDir));
- }
- }
- dirs.add(new File(new File(context.getCacheDir(), "downloads"), subDir));
- return dirs.toArray(new File[0]);
- }
-
- private static File getDownloadTarget(String subDir, String filename) {
- return new File(getDownloadDirs(subDir)[0], filename);
- }
-
- private static File getDownloadTargetForUrl(String subDir, String url) {
- return getDownloadTarget(subDir, Uri.parse(url).getLastPathSegment());
- }
-
- public static DownloadInfo addModule(Context context, String title, String url, boolean save, DownloadFinishedCallback callback) {
+ public static DownloadInfo addModule(Context context, String title, String url, DownloadFinishedCallback callback) {
return new Builder(context)
.setTitle(title)
.setUrl(url)
- .setDestinationFromUrl(DownloadsUtil.DOWNLOAD_MODULES)
.setCallback(callback)
- .setSave(save)
.setModule(true)
.setMimeType(MIME_TYPES.APK)
.download();
}
- private static void showDownloadDialog(final Builder b, final long id) {
- final Context context = b.mContext;
- final ProgressDialog dialog = new ProgressDialog(context);
- dialog.setTitle(b.mTitle);
- dialog.setMessage(context.getString(R.string.download_view_waiting));
- dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.download_view_cancel), (dialog1, which) -> dialog1.cancel());
- dialog.setOnCancelListener(dialog12 -> removeById(context, id));
+ /*
+ public static ModuleVersion getStableVersion(Module m) {
+ for (int i = 0; i < m.versions.size(); i++) {
+ ModuleVersion mvTemp = m.versions.get(i);
- dialog.setProgress(0);
- dialog.setCanceledOnTouchOutside(false);
- dialog.setProgressNumberFormat(context.getString(R.string.download_progress));
- dialog.show();
-
- new Thread("DownloadDialog") {
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- return;
- }
-
- final DownloadInfo info = getById(context, id);
- if (info == null) {
- dialog.cancel();
- return;
- } else if (info.status == DownloadManager.STATUS_FAILED) {
- dialog.cancel();
- XposedApp.runOnUiThread(() -> Toast.makeText(context,
- context.getString(R.string.download_view_failed, info.reason),
- Toast.LENGTH_LONG).show());
- return;
- } else if (info.status == DownloadManager.STATUS_SUCCESSFUL) {
- dialog.dismiss();
- // Hack to reset stat information.
- //noinspection ResultOfMethodCallIgnored
- new File(info.localFilename).setExecutable(false);
- if (b.mCallback != null) {
- b.mCallback.onDownloadFinished(context, info);
- }
- return;
- }
-
- XposedApp.runOnUiThread(() -> {
- if (info.totalSize <= 0 || info.status != DownloadManager.STATUS_RUNNING) {
- dialog.setMessage(context.getString(R.string.download_view_waiting));
- } else {
- dialog.setMessage(context.getString(R.string.download_running));
- dialog.setProgress(info.bytesDownloaded / 1024);
- dialog.setMax(info.totalSize / 1024);
- }
- });
+ if (mvTemp.relType == ReleaseType.STABLE) {
+ return mvTemp;
}
}
- }.start();
- }
-
- 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;
}
- 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));
@@ -317,7 +211,7 @@ public class DownloadsUtil {
dm.remove(ids);
}
-
+/*
private static void removeAllForLocalFile(Context context, File file) {
//noinspection ResultOfMethodCallIgnored
file.delete();
@@ -367,7 +261,7 @@ public class DownloadsUtil {
ids[i] = idsList.get(i);
dm.remove(ids);
- }
+ }*/
// public static void removeOutdated(Context context, long cutoff) {
// DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
@@ -563,9 +457,6 @@ public class DownloadsUtil {
private String mUrl = null;
private DownloadFinishedCallback mCallback = null;
private MIME_TYPES mMimeType = MIME_TYPES.APK;
- private File mDestination = null;
- private boolean mDialog = false;
- private boolean mSave = false;
public Builder(Context context) {
mContext = context;
@@ -591,33 +482,11 @@ public class DownloadsUtil {
return this;
}
- Builder setDestination(File file) {
- mDestination = file;
- return this;
- }
-
- Builder setDestinationFromUrl(String subDir) {
- if (mUrl == null) {
- throw new IllegalStateException("URL must be set first");
- }
- return setDestination(getDownloadTargetForUrl(subDir, mUrl));
- }
-
- public Builder setSave(boolean save) {
- this.mSave = save;
- return this;
- }
-
public Builder setModule(boolean module) {
this.mModule = module;
return this;
}
- public Builder setDialog(boolean dialog) {
- mDialog = dialog;
- return this;
- }
-
public DownloadInfo download() {
return add(this);
}
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 142a10e4..c3cdb76b 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,10 +1,8 @@
package org.meowcat.edxposed.manager.widget;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.Context;
-import android.content.pm.PackageManager;
+import android.content.Intent;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -12,9 +10,7 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
-import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import org.meowcat.edxposed.manager.R;
@@ -23,20 +19,15 @@ import org.meowcat.edxposed.manager.util.DownloadsUtil.DownloadFinishedCallback;
import java.util.Objects;
-import static org.meowcat.edxposed.manager.XposedApp.WRITE_EXTERNAL_PERMISSION;
-
public class DownloadView extends LinearLayout {
- @SuppressLint("StaticFieldLeak")
- public static Button mClickedButton;
+ public static DownloadsUtil.DownloadInfo mInfo = null;
private final Button btnDownload;
private final Button btnDownloadCancel;
private final Button btnInstall;
- private final Button btnRemove;
private final Button btnSave;
private final ProgressBar progressBar;
private final TextView txtInfo;
public Fragment fragment;
- private DownloadsUtil.DownloadInfo mInfo = null;
private String mUrl = null;
private final Runnable refreshViewRunnable = new Runnable() {
@Override
@@ -45,7 +36,6 @@ public class DownloadView extends LinearLayout {
btnDownload.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
btnDownloadCancel.setVisibility(View.GONE);
- btnRemove.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
@@ -54,7 +44,6 @@ public class DownloadView extends LinearLayout {
btnDownload.setVisibility(View.VISIBLE);
btnSave.setVisibility(View.VISIBLE);
btnDownloadCancel.setVisibility(View.GONE);
- btnRemove.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.GONE);
@@ -66,7 +55,6 @@ public class DownloadView extends LinearLayout {
btnDownload.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
btnDownloadCancel.setVisibility(View.VISIBLE);
- btnRemove.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
txtInfo.setVisibility(View.VISIBLE);
@@ -88,7 +76,6 @@ public class DownloadView extends LinearLayout {
btnDownload.setVisibility(View.VISIBLE);
btnSave.setVisibility(View.VISIBLE);
btnDownloadCancel.setVisibility(View.GONE);
- btnRemove.setVisibility(View.GONE);
btnInstall.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
@@ -98,9 +85,8 @@ public class DownloadView extends LinearLayout {
case DownloadManager.STATUS_SUCCESSFUL:
btnDownload.setVisibility(View.GONE);
- btnSave.setVisibility(View.GONE);
+ btnSave.setVisibility(View.VISIBLE);
btnDownloadCancel.setVisibility(View.GONE);
- btnRemove.setVisibility(View.VISIBLE);
btnInstall.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
txtInfo.setVisibility(View.VISIBLE);
@@ -123,27 +109,27 @@ public class DownloadView extends LinearLayout {
btnDownload = findViewById(R.id.btnDownload);
btnDownloadCancel = findViewById(R.id.btnDownloadCancel);
- btnRemove = findViewById(R.id.btnRemove);
btnInstall = findViewById(R.id.btnInstall);
btnSave = findViewById(R.id.save);
btnDownload.setOnClickListener(v -> {
- mClickedButton = btnDownload;
-
- mInfo = DownloadsUtil.addModule(getContext(), mTitle, mUrl, false, mCallback);
+ mInfo = DownloadsUtil.addModule(getContext(), mTitle, mUrl, mCallback);
refreshViewFromUiThread();
-
if (mInfo != null)
new DownloadMonitor().start();
});
btnSave.setOnClickListener(v -> {
- mClickedButton = btnSave;
-
- if (checkPermissions())
- return;
-
- mInfo = DownloadsUtil.addModule(getContext(), mTitle, mUrl, true, (context1, info) -> Toast.makeText(context1, context1.getString(R.string.module_saved, info.localFilename), Toast.LENGTH_SHORT).show());
+ 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();
});
btnDownloadCancel.setOnClickListener(v -> {
@@ -154,14 +140,6 @@ public class DownloadView extends LinearLayout {
// UI update will happen automatically by the DownloadMonitor
});
- btnRemove.setOnClickListener(v -> {
- if (mInfo == null)
- return;
-
- DownloadsUtil.removeById(getContext(), mInfo.id);
- // UI update will happen automatically by the DownloadMonitor
- });
-
btnInstall.setOnClickListener(v -> {
if (mCallback == null)
return;
@@ -175,15 +153,6 @@ public class DownloadView extends LinearLayout {
refreshViewFromUiThread();
}
- private boolean checkPermissions() {
- if (ActivityCompat.checkSelfPermission(this.getContext(),
- Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- fragment.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_PERMISSION);
- return true;
- }
- return false;
- }
-
private void refreshViewFromUiThread() {
refreshViewRunnable.run();
}
diff --git a/app/src/main/res/layout/download_view.xml b/app/src/main/res/layout/download_view.xml
index e50bf8ef..163b5d6f 100644
--- a/app/src/main/res/layout/download_view.xml
+++ b/app/src/main/res/layout/download_view.xml
@@ -42,16 +42,6 @@
android:visibility="gone"
tools:ignore="ButtonOrder" />
-
-
无法将日志写入 SD 卡:
- 无法找到 SD 卡或不可写入
立即清理日志
日志清理成功
无法清理日志:
@@ -156,7 +155,6 @@
无法读取下载的文件: %s
下载的文件并非有效的 APK (或存在兼容性问题)
文件包名不正确(下载: %1$s, 预期: %2$s)
- 正在下载
下载 %1$s 失败: %2$d(%3$s)
@@ -173,7 +171,6 @@
没有任何已安装的模块
启用浮动通知
对新安装或已更新的模块启用浮动通知
- 找不到备份
没有任何已启用的模块
分享
@@ -195,7 +192,6 @@
更新日志
滚动到顶部
- 文件为空
静默安装(root)
勾选后在 EdXposed Manager 内安装模块时将不再显示安装提示
模块已保存至 %1$s
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 8caefe74..01e3441c 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -126,7 +126,6 @@
無法將日誌寫入 SD 卡:
- 無法找到 SD 卡或不可寫入
立即清理日誌
日誌清理成功
無法清理日誌:
@@ -156,7 +155,6 @@
無法讀取下載的文件: %s
下載的文件並非有效的 APK (或存在兼容性問題)
文件包名不正確(下載: %1$s, 預期: %2$s)
- 正在下載
下載 %1$s 失敗: %2$d(%3$s)
@@ -173,7 +171,6 @@
沒有任何已安裝的模塊
啟用浮動通知
對新安裝或已更新的模塊啟用浮動通知
- 找不到備份
沒有任何已啟用的模塊
分享
@@ -195,7 +192,6 @@
更新日誌
滾動到頂部
- 文件為空
靜默安裝(root)
勾選後在 EdXposed Manager 內安裝模塊時將不再顯示安裝提示
模塊已保存至 %1$s
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 49be36d8..7b40bbb2 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -126,7 +126,6 @@
無法將日誌寫入 SD 卡:
- 無法找到 SD 卡或不可寫入
立即清理日誌
日誌清理成功
無法清理日誌:
@@ -156,7 +155,6 @@
無法讀取下載的檔案: %s
下載的檔案並非有效的 APK (或存在相容性問題)
檔案包名不正確(下載: %1$s, 預期: %2$s)
- 正在下載
下載 %1$s 失敗: %2$d(%3$s)
@@ -173,7 +171,6 @@
沒有任何已安裝的模組
啟用浮動通知
對新安裝或已更新的模組啟用浮動通知
- 找不到備份
沒有任何已啟用的模組
分享
@@ -195,7 +192,6 @@
更新日誌
滾動到頂部
- 檔案為空
靜默安裝(root)
勾選後在 EdXposed Manager 內安裝模組時將不再顯示安裝提示
模組已儲存至 %1$s
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 47afed7f..e8a69644 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -128,7 +128,6 @@
Could not write log to SD card:
- SD card not found or not writable
Clear log now
Log successfully cleared.
Could not clear the log:
@@ -158,8 +157,6 @@
Could not read downloaded file: %s
Downloaded file is not a valid APK (or incompatible)
Package name is incorrect (downloaded: %1$s, expected: %2$s)
- Download is running
- %1$,d / %2$,d kB
Downloading %1$s failed: %2$d (%3$s)
@@ -176,7 +173,6 @@
There are no installed modules!
Enable Heads-Up notification
This option enables heads up notification on new/updated module
- No backup found
There are no modules enabled
Share with…
@@ -198,7 +194,6 @@
Changelog
Scroll to top
- File is empty
Silent installation (root)
If checked EdXposed Manager will install modules without a prompt
Module saved at %1$s
diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml
index a132791b..1f1be923 100644
--- a/app/src/main/res/xml/file_paths.xml
+++ b/app/src/main/res/xml/file_paths.xml
@@ -2,10 +2,7 @@
-
+ path="/downloads" />