html2apk 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +217 -5
- package/package.json +15 -4
- package/src/desktop/main.js +551 -25
- package/src/desktop/renderer/index.html +1 -1
- package/src/desktop/renderer/renderer.js +517 -35
- package/src/desktop/renderer/styles.css +13 -3
- package/src/runtime-manager/index.js +79 -17
- package/src/templates/cordova-plugin-html2apk-bridge/plugin.xml +33 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/FloatingIconService.java +33 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/Html2ApkBridge.java +5187 -1634
- package/src/templates/cordova-plugin-html2apk-bridge/www/html2apk-bridge.js +485 -12
- package/src/templates/html2apk-early-bridge.js +485 -12
- package/src/templates/html2apk-runtime-console.js +169 -29
- package/examples/minimal/dist/MeuApp-1.0.0-debug.apk +0 -0
- package/examples/minimal/dist/MeuApp-1.0.0-release.aab +0 -0
|
@@ -1027,17 +1027,26 @@ h2 {
|
|
|
1027
1027
|
|
|
1028
1028
|
.log-console {
|
|
1029
1029
|
height: min(620px, calc(100vh - 230px));
|
|
1030
|
+
min-height: 0;
|
|
1031
|
+
box-sizing: border-box;
|
|
1030
1032
|
overflow: auto;
|
|
1031
1033
|
border: 1px solid var(--line);
|
|
1032
1034
|
border-radius: 8px;
|
|
1033
1035
|
background: #0c1117;
|
|
1034
1036
|
color: #d6e4f7;
|
|
1035
|
-
padding: 18px;
|
|
1037
|
+
padding: 18px 18px 34px;
|
|
1038
|
+
scroll-padding-bottom: 34px;
|
|
1036
1039
|
font-family: "Cascadia Mono", Consolas, monospace;
|
|
1037
1040
|
font-size: 13px;
|
|
1038
1041
|
line-height: 1.55;
|
|
1039
1042
|
}
|
|
1040
1043
|
|
|
1044
|
+
.log-console::after {
|
|
1045
|
+
content: "";
|
|
1046
|
+
display: block;
|
|
1047
|
+
height: 12px;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1041
1050
|
.log-line {
|
|
1042
1051
|
padding: 4px 0;
|
|
1043
1052
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
@@ -1407,9 +1416,10 @@ body.logs-visible .bottom-log-bar {
|
|
|
1407
1416
|
}
|
|
1408
1417
|
|
|
1409
1418
|
.bottom-log-console {
|
|
1410
|
-
height:
|
|
1419
|
+
height: 100%;
|
|
1411
1420
|
min-height: 0;
|
|
1412
|
-
padding: 10px 12px;
|
|
1421
|
+
padding: 10px 12px 26px;
|
|
1422
|
+
scroll-padding-bottom: 26px;
|
|
1413
1423
|
font-size: 12px;
|
|
1414
1424
|
line-height: 1.4;
|
|
1415
1425
|
}
|
|
@@ -55,29 +55,74 @@ function getAndroidSdkPath(env = process.env) {
|
|
|
55
55
|
return defaultAndroidSdkCandidates(env).find(pathExists) || env.ANDROID_HOME || env.ANDROID_SDK_ROOT || null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function
|
|
58
|
+
function getValidJavaHome(dir) {
|
|
59
|
+
if (!pathExists(dir)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const javaExe = process.platform === "win32" ? "java.exe" : "java";
|
|
63
|
+
if (pathExists(path.join(dir, "bin", javaExe))) {
|
|
64
|
+
return dir;
|
|
65
|
+
}
|
|
66
|
+
// Support macOS virtual machine package structures
|
|
67
|
+
const macHome = path.join(dir, "Contents", "Home");
|
|
68
|
+
if (pathExists(path.join(macHome, "bin", javaExe))) {
|
|
69
|
+
return macHome;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getJavaHome(env = process.env, parentDirsOverride = null) {
|
|
59
75
|
if (env.JAVA_HOME && pathExists(env.JAVA_HOME)) {
|
|
60
76
|
return env.JAVA_HOME;
|
|
61
77
|
}
|
|
62
78
|
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const parentDirs = parentDirsOverride || [];
|
|
80
|
+
if (!parentDirsOverride) {
|
|
81
|
+
if (process.platform === "win32") {
|
|
82
|
+
parentDirs.push(
|
|
83
|
+
path.join(process.env.ProgramFiles || "C:\\Program Files", "Eclipse Adoptium"),
|
|
84
|
+
path.join(process.env.ProgramFiles || "C:\\Program Files", "Java")
|
|
85
|
+
);
|
|
86
|
+
} else if (process.platform === "darwin") {
|
|
87
|
+
parentDirs.push(
|
|
88
|
+
"/Library/Java/JavaVirtualMachines"
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
parentDirs.push(
|
|
92
|
+
"/usr/lib/jvm",
|
|
93
|
+
"/usr/java"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const parent of parentDirs) {
|
|
99
|
+
if (!pathExists(parent)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const entries = fs.readdirSync(parent)
|
|
104
|
+
.filter((name) => {
|
|
105
|
+
try {
|
|
106
|
+
return fs.statSync(path.join(parent, name)).isDirectory();
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
|
|
112
|
+
|
|
113
|
+
for (const name of entries) {
|
|
114
|
+
const fullPath = path.join(parent, name);
|
|
115
|
+
const valid = getValidJavaHome(fullPath);
|
|
116
|
+
if (valid) {
|
|
117
|
+
return valid;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// Ignore directory read errors and check next parent
|
|
122
|
+
}
|
|
78
123
|
}
|
|
79
124
|
|
|
80
|
-
return
|
|
125
|
+
return env.JAVA_HOME || null;
|
|
81
126
|
}
|
|
82
127
|
|
|
83
128
|
function latestSubdir(parent) {
|
|
@@ -157,6 +202,23 @@ function getRuntimeEnvironment(env = process.env) {
|
|
|
157
202
|
pathEntries.push(path.join(gradleHome, "bin"));
|
|
158
203
|
}
|
|
159
204
|
|
|
205
|
+
// Ensure common system directories are present in PATH, since GUI/desktop
|
|
206
|
+
// launchers on Linux often inherit a minimal PATH that omits /usr/local/bin.
|
|
207
|
+
if (process.platform !== "win32") {
|
|
208
|
+
const systemDirs = [
|
|
209
|
+
"/usr/local/bin",
|
|
210
|
+
"/usr/local/sbin",
|
|
211
|
+
"/usr/bin",
|
|
212
|
+
"/usr/sbin"
|
|
213
|
+
];
|
|
214
|
+
const currentPath = (nextEnv.PATH || "").split(pathDelimiter());
|
|
215
|
+
for (const dir of systemDirs) {
|
|
216
|
+
if (!currentPath.includes(dir) && pathExists(dir)) {
|
|
217
|
+
pathEntries.push(dir);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
160
222
|
prependToPath(nextEnv, pathEntries);
|
|
161
223
|
|
|
162
224
|
return {
|
|
@@ -23,10 +23,21 @@
|
|
|
23
23
|
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
|
24
24
|
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
|
25
25
|
<uses-permission android:name="android.permission.SET_WALLPAPER" />
|
|
26
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
26
27
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
28
|
+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
29
|
+
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
|
30
|
+
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
|
27
31
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
|
32
|
+
<uses-permission android:name="android.permission.NFC" />
|
|
33
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
34
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
35
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
36
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
28
37
|
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
|
29
38
|
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
|
|
39
|
+
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
|
|
40
|
+
<uses-feature android:name="android.hardware.nfc" android:required="false" />
|
|
30
41
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
|
31
42
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
32
43
|
</config-file>
|
|
@@ -52,6 +63,27 @@
|
|
|
52
63
|
</receiver>
|
|
53
64
|
</config-file>
|
|
54
65
|
|
|
66
|
+
<config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
|
|
67
|
+
<intent-filter>
|
|
68
|
+
<action android:name="android.intent.action.SEND" />
|
|
69
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
70
|
+
<data android:mimeType="text/plain" />
|
|
71
|
+
<data android:mimeType="image/*" />
|
|
72
|
+
<data android:mimeType="video/*" />
|
|
73
|
+
<data android:mimeType="application/pdf" />
|
|
74
|
+
<data android:mimeType="*/*" />
|
|
75
|
+
</intent-filter>
|
|
76
|
+
<intent-filter>
|
|
77
|
+
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
78
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
79
|
+
<data android:mimeType="text/plain" />
|
|
80
|
+
<data android:mimeType="image/*" />
|
|
81
|
+
<data android:mimeType="video/*" />
|
|
82
|
+
<data android:mimeType="application/pdf" />
|
|
83
|
+
<data android:mimeType="*/*" />
|
|
84
|
+
</intent-filter>
|
|
85
|
+
</config-file>
|
|
86
|
+
|
|
55
87
|
<source-file src="src/android/Html2ApkBridge.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
56
88
|
<source-file src="src/android/FloatingIconService.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
57
89
|
<source-file src="src/android/NotificationReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
@@ -60,5 +92,6 @@
|
|
|
60
92
|
<source-file src="src/android/NotificationStore.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
61
93
|
<resource-file src="src/android/xml/html2apk_file_paths.xml" target="res/xml/html2apk_file_paths.xml" />
|
|
62
94
|
<framework src="androidx.core:core:1.12.0" />
|
|
95
|
+
<framework src="com.google.mlkit:text-recognition:16.0.1" />
|
|
63
96
|
</platform>
|
|
64
97
|
</plugin>
|
|
@@ -2,6 +2,7 @@ package dev.html2apk.bridge;
|
|
|
2
2
|
|
|
3
3
|
import android.app.Service;
|
|
4
4
|
import android.content.Intent;
|
|
5
|
+
import android.content.SharedPreferences;
|
|
5
6
|
import android.graphics.PixelFormat;
|
|
6
7
|
import android.graphics.drawable.GradientDrawable;
|
|
7
8
|
import android.os.Build;
|
|
@@ -14,9 +15,14 @@ import android.view.WindowManager;
|
|
|
14
15
|
import android.widget.ImageView;
|
|
15
16
|
|
|
16
17
|
public class FloatingIconService extends Service {
|
|
18
|
+
private static final String PREFS_NAME = "html2apk_bridge";
|
|
19
|
+
private static final String OPACITY_KEY = "floating_icon_opacity";
|
|
20
|
+
private static final String EXTRA_OPACITY = "opacity";
|
|
21
|
+
|
|
17
22
|
private WindowManager windowManager;
|
|
18
23
|
private View floatingView;
|
|
19
24
|
private WindowManager.LayoutParams params;
|
|
25
|
+
private float opacity = 1f;
|
|
20
26
|
private int startX;
|
|
21
27
|
private int startY;
|
|
22
28
|
private float touchStartX;
|
|
@@ -29,6 +35,11 @@ public class FloatingIconService extends Service {
|
|
|
29
35
|
|
|
30
36
|
@Override
|
|
31
37
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
38
|
+
applyOptions(intent);
|
|
39
|
+
if (floatingView != null) {
|
|
40
|
+
applyFloatingIconStyle();
|
|
41
|
+
return START_STICKY;
|
|
42
|
+
}
|
|
32
43
|
showFloatingIcon();
|
|
33
44
|
return START_STICKY;
|
|
34
45
|
}
|
|
@@ -60,6 +71,7 @@ public class FloatingIconService extends Service {
|
|
|
60
71
|
int padding = dp(8);
|
|
61
72
|
icon.setImageDrawable(getApplicationInfo().loadIcon(getPackageManager()));
|
|
62
73
|
icon.setPadding(padding, padding, padding, padding);
|
|
74
|
+
icon.setAlpha(opacity);
|
|
63
75
|
|
|
64
76
|
GradientDrawable background = new GradientDrawable();
|
|
65
77
|
background.setShape(GradientDrawable.OVAL);
|
|
@@ -125,6 +137,23 @@ public class FloatingIconService extends Service {
|
|
|
125
137
|
floatingView = null;
|
|
126
138
|
}
|
|
127
139
|
|
|
140
|
+
private void applyOptions(Intent intent) {
|
|
141
|
+
SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
|
142
|
+
float nextOpacity = preferences.getFloat(OPACITY_KEY, 1f);
|
|
143
|
+
if (intent != null && intent.hasExtra(EXTRA_OPACITY)) {
|
|
144
|
+
nextOpacity = intent.getFloatExtra(EXTRA_OPACITY, nextOpacity);
|
|
145
|
+
nextOpacity = clampOpacity(nextOpacity);
|
|
146
|
+
preferences.edit().putFloat(OPACITY_KEY, nextOpacity).apply();
|
|
147
|
+
}
|
|
148
|
+
opacity = clampOpacity(nextOpacity);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private void applyFloatingIconStyle() {
|
|
152
|
+
if (floatingView != null) {
|
|
153
|
+
floatingView.setAlpha(opacity);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
128
157
|
private void openApp() {
|
|
129
158
|
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
|
130
159
|
if (launchIntent == null) {
|
|
@@ -138,4 +167,8 @@ public class FloatingIconService extends Service {
|
|
|
138
167
|
private int dp(int value) {
|
|
139
168
|
return Math.round(value * getResources().getDisplayMetrics().density);
|
|
140
169
|
}
|
|
170
|
+
|
|
171
|
+
private float clampOpacity(float value) {
|
|
172
|
+
return Math.max(0.1f, Math.min(1f, value));
|
|
173
|
+
}
|
|
141
174
|
}
|