html2apk 0.8.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 +340 -4
- package/package.json +15 -4
- package/src/desktop/main.js +902 -0
- package/src/desktop/preload.js +1 -0
- package/src/desktop/renderer/index.html +12 -6
- package/src/desktop/renderer/renderer.js +1164 -59
- package/src/desktop/renderer/styles.css +199 -30
- package/src/runtime-manager/index.js +79 -17
- package/src/templates/cordova-plugin-html2apk-bridge/plugin.xml +50 -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 +5929 -403
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/xml/html2apk_file_paths.xml +6 -0
- package/src/templates/cordova-plugin-html2apk-bridge/www/html2apk-bridge.js +882 -4
- package/src/templates/html2apk-early-bridge.js +879 -4
- package/src/templates/html2apk-runtime-console.js +321 -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
|
@@ -712,7 +712,7 @@ h2 {
|
|
|
712
712
|
|
|
713
713
|
.file-editor-panel {
|
|
714
714
|
display: grid;
|
|
715
|
-
grid-template-rows: auto minmax(
|
|
715
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
716
716
|
overflow: hidden;
|
|
717
717
|
}
|
|
718
718
|
|
|
@@ -745,58 +745,96 @@ h2 {
|
|
|
745
745
|
font-weight: 800;
|
|
746
746
|
}
|
|
747
747
|
|
|
748
|
-
|
|
749
|
-
|
|
748
|
+
.code-editor-shell {
|
|
749
|
+
position: relative;
|
|
750
750
|
min-height: 0;
|
|
751
|
-
|
|
751
|
+
overflow: hidden;
|
|
752
|
+
background: #0c1117;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
#fileEditorInput,
|
|
756
|
+
.file-editor-highlight {
|
|
757
|
+
width: 100%;
|
|
752
758
|
border: 0;
|
|
753
|
-
border-bottom: 1px solid var(--line);
|
|
754
759
|
outline: none;
|
|
755
|
-
padding: 16px;
|
|
756
|
-
|
|
757
|
-
color: var(--text);
|
|
758
|
-
font: 13px/1.55 ui-monospace, SFMono-Regular, Consolas, monospace;
|
|
760
|
+
padding: 16px 18px;
|
|
761
|
+
font: 13px/1.55 "Cascadia Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
|
|
759
762
|
tab-size: 2;
|
|
763
|
+
white-space: pre-wrap;
|
|
764
|
+
overflow-wrap: anywhere;
|
|
760
765
|
}
|
|
761
766
|
|
|
762
|
-
|
|
767
|
+
#fileEditorInput {
|
|
768
|
+
position: relative;
|
|
769
|
+
z-index: 2;
|
|
770
|
+
height: 100%;
|
|
763
771
|
min-height: 0;
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
772
|
+
resize: none;
|
|
773
|
+
background: transparent;
|
|
774
|
+
color: transparent;
|
|
775
|
+
-webkit-text-fill-color: transparent;
|
|
776
|
+
caret-color: #d6e4f7;
|
|
767
777
|
}
|
|
768
778
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
color: var(--muted);
|
|
772
|
-
font-size: 12px;
|
|
779
|
+
#fileEditorInput::selection {
|
|
780
|
+
background: rgba(88, 166, 255, 0.34);
|
|
773
781
|
}
|
|
774
782
|
|
|
775
|
-
.
|
|
783
|
+
.file-editor-highlight {
|
|
784
|
+
position: absolute;
|
|
785
|
+
inset: 0;
|
|
786
|
+
z-index: 1;
|
|
776
787
|
margin: 0;
|
|
777
|
-
|
|
778
|
-
overflow:
|
|
779
|
-
color:
|
|
780
|
-
|
|
788
|
+
min-height: 100%;
|
|
789
|
+
overflow: hidden;
|
|
790
|
+
color: #d6e4f7;
|
|
791
|
+
pointer-events: none;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.file-editor-highlight code {
|
|
795
|
+
display: block;
|
|
796
|
+
min-height: 100%;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
#fileEditorInput:disabled {
|
|
800
|
+
cursor: not-allowed;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
#fileEditorInput:disabled + .file-editor-highlight,
|
|
804
|
+
.code-editor-shell:has(#fileEditorInput:disabled) .file-editor-highlight {
|
|
805
|
+
opacity: .58;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
#fileEditorInput::placeholder {
|
|
809
|
+
color: #64748b;
|
|
810
|
+
-webkit-text-fill-color: #64748b;
|
|
781
811
|
}
|
|
782
812
|
|
|
783
813
|
.syntax-token-tag,
|
|
784
814
|
.syntax-token-keyword {
|
|
785
|
-
color:
|
|
815
|
+
color: #79c0ff;
|
|
786
816
|
font-weight: 800;
|
|
787
817
|
}
|
|
788
818
|
|
|
789
819
|
.syntax-token-string {
|
|
790
|
-
color:
|
|
820
|
+
color: #a5d6a7;
|
|
791
821
|
}
|
|
792
822
|
|
|
793
823
|
.syntax-token-comment {
|
|
794
|
-
color:
|
|
824
|
+
color: #8b949e;
|
|
795
825
|
font-style: italic;
|
|
796
826
|
}
|
|
797
827
|
|
|
798
828
|
.syntax-token-number {
|
|
799
|
-
color:
|
|
829
|
+
color: #f2cc60;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.syntax-token-function {
|
|
833
|
+
color: #d2a8ff;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.syntax-token-operator {
|
|
837
|
+
color: #ffab70;
|
|
800
838
|
}
|
|
801
839
|
|
|
802
840
|
.preference-row {
|
|
@@ -989,17 +1027,26 @@ h2 {
|
|
|
989
1027
|
|
|
990
1028
|
.log-console {
|
|
991
1029
|
height: min(620px, calc(100vh - 230px));
|
|
1030
|
+
min-height: 0;
|
|
1031
|
+
box-sizing: border-box;
|
|
992
1032
|
overflow: auto;
|
|
993
1033
|
border: 1px solid var(--line);
|
|
994
1034
|
border-radius: 8px;
|
|
995
1035
|
background: #0c1117;
|
|
996
1036
|
color: #d6e4f7;
|
|
997
|
-
padding: 18px;
|
|
1037
|
+
padding: 18px 18px 34px;
|
|
1038
|
+
scroll-padding-bottom: 34px;
|
|
998
1039
|
font-family: "Cascadia Mono", Consolas, monospace;
|
|
999
1040
|
font-size: 13px;
|
|
1000
1041
|
line-height: 1.55;
|
|
1001
1042
|
}
|
|
1002
1043
|
|
|
1044
|
+
.log-console::after {
|
|
1045
|
+
content: "";
|
|
1046
|
+
display: block;
|
|
1047
|
+
height: 12px;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1003
1050
|
.log-line {
|
|
1004
1051
|
padding: 4px 0;
|
|
1005
1052
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
@@ -1053,6 +1100,110 @@ h2 {
|
|
|
1053
1100
|
margin-bottom: 18px;
|
|
1054
1101
|
}
|
|
1055
1102
|
|
|
1103
|
+
.code-browser {
|
|
1104
|
+
display: grid;
|
|
1105
|
+
grid-template-columns: minmax(220px, 270px) minmax(0, 1fr);
|
|
1106
|
+
gap: 16px;
|
|
1107
|
+
align-items: start;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.code-categories {
|
|
1111
|
+
position: sticky;
|
|
1112
|
+
top: 0;
|
|
1113
|
+
display: grid;
|
|
1114
|
+
gap: 8px;
|
|
1115
|
+
max-height: calc(100vh - 160px - var(--visible-log-height));
|
|
1116
|
+
overflow: auto;
|
|
1117
|
+
padding-right: 2px;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
.code-category-button {
|
|
1121
|
+
width: 100%;
|
|
1122
|
+
min-height: 58px;
|
|
1123
|
+
border: 1px solid var(--line);
|
|
1124
|
+
border-radius: 8px;
|
|
1125
|
+
background: var(--panel);
|
|
1126
|
+
color: var(--text);
|
|
1127
|
+
padding: 10px 12px;
|
|
1128
|
+
display: grid;
|
|
1129
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
1130
|
+
gap: 4px 10px;
|
|
1131
|
+
align-items: center;
|
|
1132
|
+
text-align: left;
|
|
1133
|
+
box-shadow: 0 14px 34px rgba(49, 86, 130, 0.08);
|
|
1134
|
+
transition: border-color 160ms ease, background 160ms ease, color 160ms ease, transform 160ms ease;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
.code-category-button:hover {
|
|
1138
|
+
border-color: color-mix(in srgb, var(--blue) 42%, var(--line));
|
|
1139
|
+
background: color-mix(in srgb, var(--blue-soft) 56%, var(--panel));
|
|
1140
|
+
transform: translateY(-1px);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
.code-category-button.active {
|
|
1144
|
+
border-color: var(--blue);
|
|
1145
|
+
background: var(--blue-soft);
|
|
1146
|
+
color: var(--blue);
|
|
1147
|
+
box-shadow: inset 4px 0 0 var(--blue), 0 14px 34px rgba(18, 111, 255, 0.12);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.code-category-button strong {
|
|
1151
|
+
min-width: 0;
|
|
1152
|
+
overflow: hidden;
|
|
1153
|
+
text-overflow: ellipsis;
|
|
1154
|
+
white-space: nowrap;
|
|
1155
|
+
font-size: 14px;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
.code-category-button small {
|
|
1159
|
+
grid-column: 1 / -1;
|
|
1160
|
+
color: var(--muted);
|
|
1161
|
+
line-height: 1.35;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
.code-category-count {
|
|
1165
|
+
min-width: 28px;
|
|
1166
|
+
min-height: 24px;
|
|
1167
|
+
border-radius: 999px;
|
|
1168
|
+
display: inline-flex;
|
|
1169
|
+
align-items: center;
|
|
1170
|
+
justify-content: center;
|
|
1171
|
+
background: var(--panel-soft);
|
|
1172
|
+
color: var(--muted);
|
|
1173
|
+
font-size: 12px;
|
|
1174
|
+
font-weight: 900;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
.code-category-button.active .code-category-count {
|
|
1178
|
+
background: var(--panel);
|
|
1179
|
+
color: var(--blue);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
.code-results {
|
|
1183
|
+
min-width: 0;
|
|
1184
|
+
display: grid;
|
|
1185
|
+
gap: 14px;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
.code-summary {
|
|
1189
|
+
border: 1px solid var(--line);
|
|
1190
|
+
border-radius: 8px;
|
|
1191
|
+
background: color-mix(in srgb, var(--panel) 82%, var(--panel-soft));
|
|
1192
|
+
padding: 14px 16px;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.code-summary strong {
|
|
1196
|
+
display: block;
|
|
1197
|
+
color: var(--text);
|
|
1198
|
+
margin-bottom: 4px;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
.code-summary p {
|
|
1202
|
+
margin: 0;
|
|
1203
|
+
color: var(--muted);
|
|
1204
|
+
line-height: 1.45;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1056
1207
|
.code-grid {
|
|
1057
1208
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
1058
1209
|
}
|
|
@@ -1073,11 +1224,14 @@ h2 {
|
|
|
1073
1224
|
}
|
|
1074
1225
|
|
|
1075
1226
|
.code-card-top code {
|
|
1227
|
+
display: block;
|
|
1076
1228
|
overflow-wrap: anywhere;
|
|
1077
1229
|
color: #d6e4f7;
|
|
1078
1230
|
background: #0c1117;
|
|
1079
1231
|
border-radius: 7px;
|
|
1080
1232
|
padding: 10px;
|
|
1233
|
+
font: 12px/1.55 "Cascadia Mono", Consolas, "Courier New", monospace;
|
|
1234
|
+
white-space: pre-wrap;
|
|
1081
1235
|
}
|
|
1082
1236
|
|
|
1083
1237
|
.code-card-top span {
|
|
@@ -1155,7 +1309,7 @@ h2 {
|
|
|
1155
1309
|
display: block;
|
|
1156
1310
|
padding: 12px;
|
|
1157
1311
|
color: #d6e4f7;
|
|
1158
|
-
font: 12px/1.55 Consolas, "Courier New", monospace;
|
|
1312
|
+
font: 12px/1.55 "Cascadia Mono", Consolas, "Courier New", monospace;
|
|
1159
1313
|
white-space: pre;
|
|
1160
1314
|
}
|
|
1161
1315
|
|
|
@@ -1262,9 +1416,10 @@ body.logs-visible .bottom-log-bar {
|
|
|
1262
1416
|
}
|
|
1263
1417
|
|
|
1264
1418
|
.bottom-log-console {
|
|
1265
|
-
height:
|
|
1419
|
+
height: 100%;
|
|
1266
1420
|
min-height: 0;
|
|
1267
|
-
padding: 10px 12px;
|
|
1421
|
+
padding: 10px 12px 26px;
|
|
1422
|
+
scroll-padding-bottom: 26px;
|
|
1268
1423
|
font-size: 12px;
|
|
1269
1424
|
line-height: 1.4;
|
|
1270
1425
|
}
|
|
@@ -1517,6 +1672,20 @@ body.logs-visible .bottom-log-bar {
|
|
|
1517
1672
|
grid-template-columns: 1fr;
|
|
1518
1673
|
}
|
|
1519
1674
|
|
|
1675
|
+
.code-browser {
|
|
1676
|
+
grid-template-columns: 1fr;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
.code-categories {
|
|
1680
|
+
position: static;
|
|
1681
|
+
grid-auto-flow: column;
|
|
1682
|
+
grid-auto-columns: minmax(180px, 220px);
|
|
1683
|
+
overflow-x: auto;
|
|
1684
|
+
overflow-y: hidden;
|
|
1685
|
+
max-height: none;
|
|
1686
|
+
padding: 0 0 4px;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1520
1689
|
.icon-field,
|
|
1521
1690
|
.keystore-field,
|
|
1522
1691
|
.onesignal-field,
|
|
@@ -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 {
|
|
@@ -18,13 +18,40 @@
|
|
|
18
18
|
<uses-permission android:name="android.permission.VIBRATE" />
|
|
19
19
|
<uses-permission android:name="android.permission.CAMERA" />
|
|
20
20
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
21
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
22
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
23
|
+
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
|
24
|
+
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
|
25
|
+
<uses-permission android:name="android.permission.SET_WALLPAPER" />
|
|
26
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
21
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" />
|
|
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" />
|
|
37
|
+
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
|
22
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" />
|
|
23
41
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
|
24
42
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
25
43
|
</config-file>
|
|
26
44
|
|
|
27
45
|
<config-file target="AndroidManifest.xml" parent="/manifest/application">
|
|
46
|
+
<provider
|
|
47
|
+
android:name="androidx.core.content.FileProvider"
|
|
48
|
+
android:authorities="${applicationId}.html2apk.fileprovider"
|
|
49
|
+
android:exported="false"
|
|
50
|
+
android:grantUriPermissions="true">
|
|
51
|
+
<meta-data
|
|
52
|
+
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
53
|
+
android:resource="@xml/html2apk_file_paths" />
|
|
54
|
+
</provider>
|
|
28
55
|
<service android:name="dev.html2apk.bridge.FloatingIconService" android:exported="false" />
|
|
29
56
|
<receiver android:name="dev.html2apk.bridge.NotificationReceiver" android:exported="false" />
|
|
30
57
|
<receiver android:name="dev.html2apk.bridge.NotificationClickReceiver" android:exported="false" />
|
|
@@ -36,12 +63,35 @@
|
|
|
36
63
|
</receiver>
|
|
37
64
|
</config-file>
|
|
38
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
|
+
|
|
39
87
|
<source-file src="src/android/Html2ApkBridge.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
40
88
|
<source-file src="src/android/FloatingIconService.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
41
89
|
<source-file src="src/android/NotificationReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
42
90
|
<source-file src="src/android/NotificationClickReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
43
91
|
<source-file src="src/android/BootReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
44
92
|
<source-file src="src/android/NotificationStore.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
93
|
+
<resource-file src="src/android/xml/html2apk_file_paths.xml" target="res/xml/html2apk_file_paths.xml" />
|
|
45
94
|
<framework src="androidx.core:core:1.12.0" />
|
|
95
|
+
<framework src="com.google.mlkit:text-recognition:16.0.1" />
|
|
46
96
|
</platform>
|
|
47
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
|
}
|