diff --git a/DEVELOPERS.md b/DEVELOPERS.md
index 0a5cab3..b914807 100644
--- a/DEVELOPERS.md
+++ b/DEVELOPERS.md
@@ -81,6 +81,7 @@ Variables:
- `MMM_EXT_SUPPORT` declared if extensions are supported
- `MMM_USER_LANGUAGE` the current user selected language
- `MMM_APP_VERSION` display version of the app (Ex: `x.y.z`)
+- `MMM_TEXT_WRAP` is set to `1` if text wrapping is enabled
Note:
The current behavior with unknown command is to ignore them,
diff --git a/app/build.gradle b/app/build.gradle
index b1f80a8..e712157 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,8 +10,8 @@ android {
applicationId "com.fox2code.mmm"
minSdk 21
targetSdk 32
- versionCode 19
- versionName "0.2.8"
+ versionCode 20
+ versionName "0.2.9"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/assets/module_installer_test.sh b/app/src/main/assets/module_installer_test.sh
new file mode 100644
index 0000000..c3dbddb
--- /dev/null
+++ b/app/src/main/assets/module_installer_test.sh
@@ -0,0 +1,24 @@
+#!/sbin/sh
+# This script is only used to test debug builds
+
+umask 022
+
+API=$(getprop ro.build.version.sdk)
+OUTFD=$2
+ZIPFILE=$3
+MODPATH="${ZIPFILE%/*}"
+
+ui_print() { echo "$1"; }
+abort() {
+ ui_print "$1"
+ [ -f $MODPATH/customize.sh ] && rm -f $MODPATH/customize.sh
+ exit 1
+}
+
+ui_print "! Using rootless installer test script"
+
+unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2
+
+[ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh
+
+ui_print "- Done"
diff --git a/app/src/main/java/com/fox2code/mmm/Constants.java b/app/src/main/java/com/fox2code/mmm/Constants.java
index 4ac56cd..e2d073f 100644
--- a/app/src/main/java/com/fox2code/mmm/Constants.java
+++ b/app/src/main/java/com/fox2code/mmm/Constants.java
@@ -13,6 +13,7 @@ public class Constants {
public static final String EXTRA_INSTALL_CONFIG = "extra_install_config";
public static final String EXTRA_INSTALL_NO_PATCH = "extra_install_no_patch";
public static final String EXTRA_INSTALL_NO_EXTENSIONS = "extra_install_no_extensions";
+ public static final String EXTRA_INSTALL_TEST_ROOTLESS = "extra_install_test_rootless";
public static final String EXTRA_MARKDOWN_URL = "extra_markdown_url";
public static final String EXTRA_MARKDOWN_TITLE = "extra_markdown_title";
public static final String EXTRA_MARKDOWN_CONFIG = "extra_markdown_config";
diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java
index ddff07f..ee251e6 100644
--- a/app/src/main/java/com/fox2code/mmm/MainApplication.java
+++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java
@@ -102,6 +102,10 @@ public class MainApplication extends Application implements CompatActivity.Appli
return getSharedPreferences().getBoolean("pref_force_dark_terminal", false);
}
+ public static boolean isTextWrapEnabled() {
+ return getSharedPreferences().getBoolean("pref_wrap_text", false);
+ }
+
public static boolean isDeveloper() {
return BuildConfig.DEBUG ||
getSharedPreferences().getBoolean("developer", false);
diff --git a/app/src/main/java/com/fox2code/mmm/NotificationType.java b/app/src/main/java/com/fox2code/mmm/NotificationType.java
index 3c0aa28..f0acb20 100644
--- a/app/src/main/java/com/fox2code/mmm/NotificationType.java
+++ b/app/src/main/java/com/fox2code/mmm/NotificationType.java
@@ -21,6 +21,7 @@ import java.util.zip.ZipFile;
interface NotificationTypeCst {
String TAG = "NotificationType";
+ boolean ROOTLESS_TEST = true;
}
public enum NotificationType implements NotificationTypeCst {
@@ -88,7 +89,9 @@ public enum NotificationType implements NotificationTypeCst {
} else {
IntentHelper.openInstaller(compatActivity, d.getAbsolutePath(),
compatActivity.getString(
- R.string.local_install_title), null);
+ R.string.local_install_title), null, false,
+ BuildConfig.DEBUG && // Use debug mode if no root
+ InstallerInitializer.peekMagiskPath() == null);
}
} catch (IOException ignored) {
if (d.exists() && !d.delete())
@@ -99,14 +102,17 @@ public enum NotificationType implements NotificationTypeCst {
} else if (s == IntentHelper.RESPONSE_URL) {
IntentHelper.openInstaller(compatActivity, u.toString(),
compatActivity.getString(
- R.string.remote_install_title), null);
+ R.string.remote_install_title), null, false,
+ BuildConfig.DEBUG && // Use debug mode if no root
+ InstallerInitializer.peekMagiskPath() == null);
}
});
}, true) {
@Override
public boolean shouldRemove() {
- return MainApplication.isShowcaseMode() ||
- InstallerInitializer.peekMagiskPath() == null;
+ return (!(ROOTLESS_TEST && BuildConfig.DEBUG)) &&
+ (MainApplication.isShowcaseMode() ||
+ InstallerInitializer.peekMagiskPath() == null);
}
};
diff --git a/app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java b/app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java
index 7338c0c..03cc408 100644
--- a/app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java
+++ b/app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java
@@ -12,6 +12,8 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.fox2code.mmm.ActionButtonType;
import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.Constants;
@@ -39,6 +41,7 @@ public class InstallerActivity extends CompatActivity {
public InstallerTerminal installerTerminal;
private File moduleCache;
private File toDelete;
+ private boolean textWrap;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -53,6 +56,7 @@ public class InstallerActivity extends CompatActivity {
final String name;
final boolean noPatch;
final boolean noExtensions;
+ final boolean rootless;
// Should we allow 3rd part app to install modules?
if (Constants.INTENT_INSTALL_INTERNAL.equals(intent.getAction())) {
if (!MainApplication.checkSecret(intent)) {
@@ -65,6 +69,8 @@ public class InstallerActivity extends CompatActivity {
noPatch = intent.getBooleanExtra(Constants.EXTRA_INSTALL_NO_PATCH, false);
noExtensions = intent.getBooleanExtra(// Allow intent to disable extensions
Constants.EXTRA_INSTALL_NO_EXTENSIONS, false);
+ rootless = intent.getBooleanExtra(// For debug only
+ Constants.EXTRA_INSTALL_TEST_ROOTLESS, false);
} else {
Toast.makeText(this, "Unknown intent!", Toast.LENGTH_SHORT).show();
this.forceBackPressed();
@@ -74,7 +80,9 @@ public class InstallerActivity extends CompatActivity {
boolean urlMode = target.startsWith("http://") || target.startsWith("https://");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setTitle(name);
- setContentView(R.layout.installer);
+ setContentView((this.textWrap =
+ MainApplication.isTextWrapEnabled()) ?
+ R.layout.installer_wrap :R.layout.installer);
int background;
int foreground;
if (MainApplication.getINSTANCE().isLightTheme() &&
@@ -85,11 +93,13 @@ public class InstallerActivity extends CompatActivity {
background = Color.BLACK;
foreground = Color.WHITE;
}
- findViewById(R.id.install_horizontal_scroller)
- .setBackground(new ColorDrawable(background));
+ View horizontalScroller = findViewById(R.id.install_horizontal_scroller);
+ RecyclerView installTerminal;
this.progressIndicator = findViewById(R.id.progress_bar);
this.installerTerminal = new InstallerTerminal(
- findViewById(R.id.install_terminal), foreground);
+ installTerminal = findViewById(R.id.install_terminal), foreground);
+ (horizontalScroller != null ? horizontalScroller : installTerminal)
+ .setBackground(new ColorDrawable(background));
this.progressIndicator.setVisibility(View.GONE);
this.progressIndicator.setIndeterminate(true);
if (urlMode) {
@@ -134,7 +144,7 @@ public class InstallerActivity extends CompatActivity {
this.runOnUiThread(() -> {
this.installerTerminal.addLine("- Installing " + name);
});
- this.doInstall(moduleCache, noExtensions);
+ this.doInstall(moduleCache, noExtensions, rootless);
} catch (IOException e) {
Log.e(TAG, "Failed to download module zip", e);
this.setInstallStateFinished(false,
@@ -144,19 +154,32 @@ public class InstallerActivity extends CompatActivity {
} else {
this.installerTerminal.addLine("- Installing " + name);
new Thread(() -> this.doInstall(
- this.toDelete = new File(target), noExtensions),
+ this.toDelete = new File(target), noExtensions, rootless),
"Install Thread").start();
}
}
- private void doInstall(File file,boolean noExtensions) {
+ private void doInstall(File file,boolean noExtensions,boolean rootless) {
Log.i(TAG, "Installing: " + moduleCache.getName());
InstallerController installerController = new InstallerController(
this.progressIndicator, this.installerTerminal,
file.getAbsoluteFile(), noExtensions);
InstallerMonitor installerMonitor;
Shell.Job installJob;
- if (MainApplication.isUsingMagiskCommand() || noExtensions) {
+ if (rootless) { // rootless is only used for debugging
+ File installScript = this.extractInstallScript("module_installer_test.sh");
+ if (installScript == null) {
+ this.setInstallStateFinished(false,
+ "! Failed to extract test install script", "");
+ return;
+ }
+ installerMonitor = new InstallerMonitor(installScript);
+ installJob = Shell.sh("export MMM_EXT_SUPPORT=1",
+ "cd \"" + this.moduleCache.getAbsolutePath() + "\"",
+ "sh \"" + installScript.getAbsolutePath() + "\"" +
+ " /dev/null 1 \"" + file.getAbsolutePath() + "\"")
+ .to(installerController, installerMonitor);
+ } else if (MainApplication.isUsingMagiskCommand() || noExtensions) {
installerMonitor = new InstallerMonitor(new File(InstallerInitializer
.peekMagiskPath().equals("/sbin") ? "/sbin/magisk" : "/system/bin/magisk"));
if (noExtensions) {
@@ -170,12 +193,13 @@ public class InstallerActivity extends CompatActivity {
"en-US" : Resources.getSystem()
.getConfiguration().locale.toLanguageTag()),
"export MMM_APP_VERSION=" + BuildConfig.VERSION_NAME,
+ "export MMM_TEXT_WRAP=" + (this.textWrap ? "1" : "0"),
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
"magisk --install-module \"" + file.getAbsolutePath() + "\"")
.to(installerController, installerMonitor);
}
} else {
- File installScript = this.extractCompatScript();
+ File installScript = this.extractInstallScript("module_installer_compat.sh");
if (installScript == null) {
this.setInstallStateFinished(false,
"! Failed to extract module install script", "");
@@ -187,6 +211,7 @@ public class InstallerActivity extends CompatActivity {
"en-US" : Resources.getSystem()
.getConfiguration().locale.toLanguageTag()),
"export MMM_APP_VERSION=" + BuildConfig.VERSION_NAME,
+ "export MMM_TEXT_WRAP=" + (this.textWrap ? "1" : "0"),
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
"sh \"" + installScript.getAbsolutePath() + "\"" +
" /dev/null 1 \"" + file.getAbsolutePath() + "\"")
@@ -370,16 +395,16 @@ public class InstallerActivity extends CompatActivity {
private static boolean didExtract = false;
- private File extractCompatScript() {
- File compatInstallScript = new File(this.moduleCache, "module_installer_compat.sh");
+ private File extractInstallScript(String script) {
+ File compatInstallScript = new File(this.moduleCache, script);
if (!compatInstallScript.exists() || compatInstallScript.length() == 0 || !didExtract) {
try {
Files.write(compatInstallScript, Files.readAllBytes(
- this.getAssets().open("module_installer_compat.sh")));
+ this.getAssets().open(script)));
didExtract = true;
} catch (IOException e) {
compatInstallScript.delete();
- Log.e(TAG, "Failed to extract module_installer_compat.sh", e);
+ Log.e(TAG, "Failed to extract " + script, e);
return null;
}
}
diff --git a/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java b/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java
index dbde641..1bff216 100644
--- a/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java
+++ b/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java
@@ -16,6 +16,7 @@ import android.widget.Toast;
import androidx.core.app.ActivityOptionsCompat;
+import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.Constants;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
@@ -88,6 +89,11 @@ public class IntentHelper {
}
public static void openInstaller(Context context, String url, String title, String config) {
+ openInstaller(context, url, title, config, false, false);
+ }
+
+ public static void openInstaller(Context context, String url, String title, String config,
+ boolean noPatch,boolean testDebug) {
try {
Intent intent = new Intent(context, InstallerActivity.class);
intent.setAction(Constants.INTENT_INSTALL_INTERNAL);
@@ -96,6 +102,10 @@ public class IntentHelper {
intent.putExtra(Constants.EXTRA_INSTALL_NAME, title);
if (config != null && !config.isEmpty())
intent.putExtra(Constants.EXTRA_INSTALL_CONFIG, config);
+ if (noPatch)
+ intent.putExtra(Constants.EXTRA_INSTALL_NO_PATCH, true);
+ if (testDebug && BuildConfig.DEBUG)
+ intent.putExtra(Constants.EXTRA_INSTALL_TEST_ROOTLESS, true);
startActivity(context, intent, true);
} catch (ActivityNotFoundException e) {
Toast.makeText(context,
@@ -158,6 +168,12 @@ public class IntentHelper {
@SuppressLint("SdCardPath")
public static void openFileTo(CompatActivity compatActivity, File destination,
OnFileReceivedCallback callback) {
+ File destinationFolder;
+ if (destination == null || (destinationFolder = destination.getParentFile()) == null ||
+ (!destinationFolder.isDirectory() && !destinationFolder.mkdirs())) {
+ callback.onReceived(destination, null, RESPONSE_ERROR);
+ return;
+ }
Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("application/zip");
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
diff --git a/app/src/main/res/drawable/ic_baseline_keyboard_return_24.xml b/app/src/main/res/drawable/ic_baseline_keyboard_return_24.xml
new file mode 100644
index 0000000..b3a8cc1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_keyboard_return_24.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/layout/installer_wrap.xml b/app/src/main/res/layout/installer_wrap.xml
new file mode 100644
index 0000000..4601ed4
--- /dev/null
+++ b/app/src/main/res/layout/installer_wrap.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ 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 3714272..0ee54ae 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -75,8 +75,8 @@
禁用 Fox\'s Mmm 扩展, 这可以防止模块使用
终端扩展, 如果模块滥用 Fox\'s Mmm 的扩展, 这会有用
- 文字换行
-
+ 文字换行
+
将文本换行至新行,而不是将所有文本放在同一行
启用仓库
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 53d0a7b..7637527 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -75,9 +75,10 @@
Disable Fox\'s Mmm extensions, this prevent modules from using
terminal extensions, useful if a module misuse Fox\'s Mmm extensions.
- Warp text
-
- Warp text to new line instead of putting all text on the same line
+ Wrap text
+
+ Wrap text to a new line instead of putting
+ all text on the same line when installing a module
Repo enabled
Repo disabled
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index 90d0606..c1eccc0 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -34,6 +34,14 @@
app:summary="@string/showcase_mode_desc"
app:singleLineTitle="false" />
+
+