Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit f665030

Browse files
committed
Implement downloading files without installing them. (Implement #3)
1 parent ef00997 commit f665030

File tree

11 files changed

+144
-25
lines changed

11 files changed

+144
-25
lines changed

DEVELOPERS.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,21 @@ Note: This doc assume you already read the
66
Note: official repo do not accept new modules anymore, submit
77
[here](https://github.com/Magisk-Modules-Alt-Repo/submission) instead.
88

9-
Index:
9+
Index:
10+
- [Special notes](DEVELOPERS.md#special-notes)
1011
- [Properties](DEVELOPERS.md#properties)
1112
- [Installer commands](DEVELOPERS.md#installer-commands)
1213

14+
## Special notes
15+
16+
MitM: Certificate pinning is only available since Android 7.0,
17+
any issue regarding MitM that can only be performed of
18+
Android versions that doesn't support this feature will be ignored.
19+
20+
App hiding: I don't intent on hiding the app, the package names should always be
21+
`com.fox2code.mmm` or starts with `com.fox2code.mmm.`, however I notice the presence of
22+
my app is causing issues due to it existing, I may add an hiding feature to the app.
23+
1324
## Properties
1425

1526
In addition to the following required magisk properties

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ dependencies {
5151
implementation 'androidx.appcompat:appcompat:1.4.1'
5252
implementation 'androidx.emoji2:emoji2:1.0.1'
5353
implementation 'androidx.emoji2:emoji2-views-helper:1.0.1'
54-
implementation 'androidx.preference:preference:1.1.1'
54+
implementation 'androidx.preference:preference:1.2.0'
5555
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
5656
implementation 'androidx.recyclerview:recyclerview:1.2.1'
5757
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<!-- Supposed to fix bugs with old firmware, only requested on pre Marshmallow -->
1717
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
1818
android:maxSdkVersion="22" />
19+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
20+
android:maxSdkVersion="22" />
1921

2022
<application
2123
android:name=".MainApplication"

app/src/main/java/com/fox2code/mmm/ActionButtonType.java

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package com.fox2code.mmm;
22

3-
import android.app.AlertDialog;
43
import android.content.Context;
54
import android.util.Log;
5+
import android.widget.Button;
66
import android.widget.ImageButton;
77
import android.widget.Toast;
88

99
import androidx.annotation.DrawableRes;
10+
import androidx.appcompat.app.AlertDialog;
1011

1112
import com.fox2code.mmm.compat.CompatActivity;
13+
import com.fox2code.mmm.compat.CompatDisplay;
14+
import com.fox2code.mmm.installer.InstallerInitializer;
15+
import com.fox2code.mmm.manager.LocalModuleInfo;
1216
import com.fox2code.mmm.manager.ModuleInfo;
1317
import com.fox2code.mmm.manager.ModuleManager;
1418
import com.fox2code.mmm.utils.IntentHelper;
19+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
1520

1621
public enum ActionButtonType {
1722
INFO(R.drawable.ic_baseline_info_24) {
@@ -53,15 +58,63 @@ public void doAction(ImageButton button, ModuleHolder moduleHolder) {
5358
if (moduleInfo == null) return;
5459
String updateZipUrl = moduleHolder.getUpdateZipUrl();
5560
if (updateZipUrl == null) return;
61+
// Androidacy manage the selection between download and install
5662
if (updateZipUrl.startsWith("https://www.androidacy.com/")) {
5763
IntentHelper.openUrlAndroidacy(
5864
button.getContext(), updateZipUrl, true,
5965
moduleInfo.name, moduleInfo.config);
6066
return;
6167
}
62-
String updateZipChecksum = moduleHolder.getUpdateZipChecksum();
63-
IntentHelper.openInstaller(button.getContext(), updateZipUrl,
64-
moduleInfo.name, moduleInfo.config, updateZipChecksum);
68+
boolean hasRoot = InstallerInitializer.peekMagiskPath() != null
69+
&& !MainApplication.isShowcaseMode();
70+
MaterialAlertDialogBuilder builder =
71+
new MaterialAlertDialogBuilder(button.getContext());
72+
builder.setTitle(moduleInfo.name).setCancelable(true)
73+
.setIcon(R.drawable.ic_baseline_extension_24);
74+
String desc;
75+
if (moduleInfo instanceof LocalModuleInfo) {
76+
LocalModuleInfo localModuleInfo = (LocalModuleInfo) moduleInfo;
77+
desc = localModuleInfo.updateChangeLog.isEmpty() ?
78+
moduleInfo.description : localModuleInfo.updateChangeLog;
79+
} else {
80+
desc = moduleInfo.description;
81+
}
82+
83+
if (desc == null || desc.isEmpty()) {
84+
builder.setMessage(R.string.no_desc_found);
85+
} else {
86+
if (desc.length() == 1000) {
87+
int lastDot = desc.lastIndexOf('.');
88+
if (lastDot == -1) {
89+
int lastSpace = desc.lastIndexOf(' ');
90+
if (lastSpace == -1)
91+
desc = desc.substring(0, lastSpace);
92+
} else {
93+
desc = desc.substring(0, lastDot + 1);
94+
}
95+
}
96+
builder.setMessage(desc);
97+
}
98+
Log.d("Test", "URL: " + updateZipUrl);
99+
builder.setNegativeButton(R.string.download_module, (x, y) ->
100+
IntentHelper.openUrl(button.getContext(), updateZipUrl, true));
101+
if (hasRoot) {
102+
builder.setPositiveButton(moduleHolder.hasUpdate() ?
103+
R.string.update_module : R.string.install_module, (x, y) -> {
104+
String updateZipChecksum = moduleHolder.getUpdateZipChecksum();
105+
IntentHelper.openInstaller(button.getContext(), updateZipUrl,
106+
moduleInfo.name, moduleInfo.config, updateZipChecksum);
107+
});
108+
}
109+
int dim5dp = CompatDisplay.dpToPixel(5);
110+
builder.setBackgroundInsetStart(dim5dp).setBackgroundInsetEnd(dim5dp);
111+
AlertDialog alertDialog = builder.show();
112+
for (int i = -3; i < 0; i++) {
113+
Button alertButton = alertDialog.getButton(i);
114+
if (alertButton != null && alertButton.getPaddingStart() > dim5dp) {
115+
alertButton.setPadding(dim5dp, dim5dp, dim5dp, dim5dp);
116+
}
117+
}
65118
}
66119
},
67120
UNINSTALL() {

app/src/main/java/com/fox2code/mmm/ModuleHolder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import androidx.annotation.NonNull;
88
import androidx.annotation.StringRes;
99

10-
import com.fox2code.mmm.installer.InstallerInitializer;
1110
import com.fox2code.mmm.manager.LocalModuleInfo;
1211
import com.fox2code.mmm.manager.ModuleInfo;
1312
import com.fox2code.mmm.repo.RepoModule;
@@ -103,6 +102,7 @@ public String getUpdateTimeText() {
103102
return timeStamp <= 0 ? "" :
104103
MainApplication.formatTime(timeStamp);
105104
}
105+
106106
public String getRepoName() {
107107
if (this.repoModule == null) return "";
108108
return this.repoModule.repoName;
@@ -157,8 +157,7 @@ public void getButtons(Context context, List<ActionButtonType> buttonTypeList, b
157157
buttonTypeList.add(ActionButtonType.INFO);
158158
}
159159
if ((this.repoModule != null || (this.moduleInfo != null &&
160-
this.moduleInfo.updateZipUrl != null)) && !showcaseMode &&
161-
InstallerInitializer.peekMagiskPath() != null) {
160+
this.moduleInfo.updateZipUrl != null))) {
162161
buttonTypeList.add(ActionButtonType.UPDATE_INSTALL);
163162
}
164163
String config = this.getMainModuleConfig();

app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public boolean hasRoot() {
6868
*/
6969
@JavascriptInterface
7070
public boolean canInstall() {
71+
// With lockdown mode enabled or lack of root, install should not have any effect
7172
return this.allowInstall && this.hasRoot() &&
7273
!MainApplication.isShowcaseMode();
7374
}
@@ -77,9 +78,7 @@ public boolean canInstall() {
7778
*/
7879
@JavascriptInterface
7980
public void install(String moduleUrl, String installTitle,String checksum) {
80-
if (!this.allowInstall || !this.hasRoot() ||
81-
MainApplication.isShowcaseMode()) {
82-
// With lockdown mode enabled or lack of root, install should not have any effect
81+
if (!this.canInstall()) {
8382
return;
8483
}
8584
Log.d(TAG, "Received install request: " +
@@ -154,7 +153,7 @@ public boolean isAndroidacyModule(String moduleId) {
154153
*/
155154
@JavascriptInterface
156155
public String getAndroidacyModuleFile(String moduleId, String moduleFile) {
157-
if (!this.isAndroidacyModule(moduleId)) return "";
156+
if (moduleFile == null || !this.isAndroidacyModule(moduleId)) return "";
158157
File moduleFolder = new File("/data/adb/modules/" + moduleId);
159158
File absModuleFile = new File(moduleFolder, moduleFile).getAbsoluteFile();
160159
if (!absModuleFile.getPath().startsWith(moduleFolder.getPath())) return "";
@@ -165,4 +164,22 @@ public String getAndroidacyModuleFile(String moduleId, String moduleFile) {
165164
return "";
166165
}
167166
}
167+
168+
/**
169+
* Create an ".androidacy" file with {@param content} as content
170+
* Return true if action succeeded
171+
*/
172+
@JavascriptInterface
173+
public boolean setAndroidacyModuleMeta(String moduleId, String content) {
174+
if (content == null || !this.isAndroidacyModule(moduleId)) return false;
175+
File androidacyMetaFile = new File(
176+
"/data/adb/modules/" + moduleId + "/.andoridacy");
177+
try {
178+
Files.writeSU(androidacyMetaFile,
179+
content.getBytes(StandardCharsets.UTF_8));
180+
return true;
181+
} catch (IOException e) {
182+
return false;
183+
}
184+
}
168185
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.fox2code.mmm.compat;
2+
3+
import android.content.res.Resources;
4+
import android.util.DisplayMetrics;
5+
6+
import androidx.annotation.Dimension;
7+
import androidx.annotation.Px;
8+
9+
public class CompatDisplay {
10+
@Dimension @Px
11+
public static int dpToPixel(@Dimension(unit = Dimension.DP) int dp){
12+
return (int) (dp * ((float) Resources.getSystem().getDisplayMetrics()
13+
.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
14+
}
15+
16+
@Dimension(unit = Dimension.DP)
17+
public static int pixelsToDp(@Dimension @Px int px){
18+
return (int) (px / ((float) Resources.getSystem().getDisplayMetrics()
19+
.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
20+
}
21+
}

app/src/main/java/com/fox2code/mmm/manager/LocalModuleInfo.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class LocalModuleInfo extends ModuleInfo {
1414
public String updateVersion;
1515
public long updateVersionCode = Long.MIN_VALUE;
1616
public String updateZipUrl;
17-
public String updateChangeLog;
17+
public String updateChangeLog = "";
1818
public String updateChecksum;
1919

2020
public LocalModuleInfo(String id) {
@@ -34,11 +34,13 @@ public void checkModuleUpdate() {
3434
if (this.updateZipUrl.isEmpty()) throw FastException.INSTANCE;
3535
this.updateVersion = PropUtils.shortenVersionName(
3636
this.updateVersion.trim(), this.updateVersionCode);
37+
if (this.updateChangeLog.length() > 1000)
38+
this.updateChangeLog = this.updateChangeLog.substring(0, 1000);
3739
} catch (Exception e) {
3840
this.updateVersion = null;
3941
this.updateVersionCode = Long.MIN_VALUE;
4042
this.updateZipUrl = null;
41-
this.updateChangeLog = null;
43+
this.updateChangeLog = "";
4244
this.updateChecksum = null;
4345
Log.w("LocalModuleInfo",
4446
"Failed update checking for module: " + this.id, e);

app/src/main/java/com/fox2code/mmm/manager/ModuleManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private void scanInternal() {
158158
moduleInfo.updateVersion = null;
159159
moduleInfo.updateVersionCode = Long.MIN_VALUE;
160160
moduleInfo.updateZipUrl = null;
161-
moduleInfo.updateChangeLog = null;
161+
moduleInfo.updateChangeLog = "";
162162
}
163163
if (moduleInfo.name == null || (moduleInfo.name.equals(moduleInfo.id))) {
164164
moduleInfo.name = Character.toUpperCase(moduleInfo.id.charAt(0)) +

app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,17 @@
3333

3434
public class IntentHelper {
3535
public static void openUrl(Context context, String url) {
36+
openUrl(context, url, false);
37+
}
38+
39+
public static void openUrl(Context context, String url, boolean forceBrowser) {
3640
try {
3741
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
38-
context.startActivity(myIntent);
42+
myIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
43+
if (forceBrowser) {
44+
myIntent.addCategory(Intent.CATEGORY_BROWSABLE);
45+
}
46+
startActivity(context, myIntent, false);
3947
} catch (ActivityNotFoundException e) {
4048
Toast.makeText(context, "No application can handle this request."
4149
+ " Please install a web-browser", Toast.LENGTH_SHORT).show();
@@ -60,7 +68,7 @@ public static void openUrlAndroidacy(Context context, String url, boolean allowI
6068
if (config != null)
6169
myIntent.putExtra(Constants.EXTRA_ANDROIDACY_ACTIONBAR_CONFIG, config);
6270
MainApplication.addSecret(myIntent);
63-
context.startActivity(myIntent);
71+
startActivity(context, myIntent, true);
6472
} catch (ActivityNotFoundException e) {
6573
Toast.makeText(context, "No application can handle this request."
6674
+ " Please install a web-browser", Toast.LENGTH_SHORT).show();
@@ -155,13 +163,15 @@ public static void startActivity(Context context, Class<? extends Activity> acti
155163

156164
public static void startActivity(Context context, Intent intent,boolean sameApp)
157165
throws ActivityNotFoundException {
158-
int flags = intent.getFlags();
159-
if (sameApp) {
160-
flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
161-
// flags |= Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
162-
} else {
166+
int flags = intent.getFlags() &
167+
~(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
168+
if (!sameApp) {
163169
flags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
164-
flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
170+
if (intent.getData() == null) {
171+
flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
172+
} else {
173+
flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
174+
}
165175
}
166176
intent.setFlags(flags);
167177
Activity activity = getActivity(context);

0 commit comments

Comments
 (0)