html2apk 0.1.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 +472 -0
- package/bin/html2apk-desktop.js +23 -0
- package/bin/html2apk.js +19 -0
- package/examples/minimal/app.json +27 -0
- package/examples/minimal/dist/MeuApp-1.0.0-debug.apk +0 -0
- package/examples/minimal/index.html +41 -0
- package/html2apk.png +0 -0
- package/index.js +3 -0
- package/package.json +76 -0
- package/src/android/README.md +7 -0
- package/src/bridge/install-bridge.js +16 -0
- package/src/cli/index.js +163 -0
- package/src/cordova/apk-finder.js +45 -0
- package/src/cordova/config-xml.js +110 -0
- package/src/cordova/project.js +56 -0
- package/src/core/build-apk.js +189 -0
- package/src/core/config.js +99 -0
- package/src/core/defaults.js +37 -0
- package/src/core/validation.js +58 -0
- package/src/desktop/main.js +522 -0
- package/src/desktop/preload.js +30 -0
- package/src/desktop/renderer/index.html +323 -0
- package/src/desktop/renderer/renderer.js +1074 -0
- package/src/desktop/renderer/styles.css +1208 -0
- package/src/index.js +12 -0
- package/src/runtime-manager/doctor.js +164 -0
- package/src/runtime-manager/index.js +190 -0
- package/src/templates/cordova-plugin-html2apk-bridge/package.json +16 -0
- package/src/templates/cordova-plugin-html2apk-bridge/plugin.xml +39 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/BootReceiver.java +20 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/Html2ApkBridge.java +375 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/NotificationReceiver.java +112 -0
- package/src/templates/cordova-plugin-html2apk-bridge/src/android/NotificationStore.java +91 -0
- package/src/templates/cordova-plugin-html2apk-bridge/www/html2apk-bridge.js +129 -0
- package/src/utils/command-runner.js +124 -0
- package/src/utils/fs-extra.js +111 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { buildApk } = require("./core/build-apk");
|
|
4
|
+
const { loadProjectConfig, resolveBuildOptions } = require("./core/config");
|
|
5
|
+
const { runDoctor } = require("./runtime-manager/doctor");
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
buildApk,
|
|
9
|
+
loadProjectConfig,
|
|
10
|
+
resolveBuildOptions,
|
|
11
|
+
runDoctor
|
|
12
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs/promises");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { createCommandRunner } = require("../utils/command-runner");
|
|
7
|
+
const {
|
|
8
|
+
REQUIRED_ANDROID_BUILD_TOOLS,
|
|
9
|
+
REQUIRED_ANDROID_PLATFORM,
|
|
10
|
+
getRuntimeEnvironment
|
|
11
|
+
} = require("./index");
|
|
12
|
+
|
|
13
|
+
async function pathExists(targetPath) {
|
|
14
|
+
if (!targetPath) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(targetPath);
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function checkWritableDirectory(targetPath) {
|
|
27
|
+
try {
|
|
28
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
29
|
+
const probe = path.join(targetPath, `.html2apk-doctor-${Date.now()}.tmp`);
|
|
30
|
+
await fs.writeFile(probe, "ok");
|
|
31
|
+
await fs.rm(probe, { force: true });
|
|
32
|
+
return true;
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function checkCommand(name, args, env) {
|
|
39
|
+
const logs = [];
|
|
40
|
+
const runner = createCommandRunner({ logs, env });
|
|
41
|
+
try {
|
|
42
|
+
const result = await runner.run(name, args);
|
|
43
|
+
return {
|
|
44
|
+
name,
|
|
45
|
+
ok: true,
|
|
46
|
+
details: (result.stdout || result.stderr || "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean)[0] || "found"
|
|
47
|
+
};
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const output = [error.stderr, error.stdout]
|
|
50
|
+
.filter(Boolean)
|
|
51
|
+
.join("\n")
|
|
52
|
+
.split(/\r?\n/)
|
|
53
|
+
.map((line) => line.trim())
|
|
54
|
+
.filter(Boolean)[0];
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
name,
|
|
58
|
+
ok: false,
|
|
59
|
+
details: output || error.message
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function runDoctor(options = {}) {
|
|
65
|
+
const runtime = getRuntimeEnvironment();
|
|
66
|
+
const checks = [];
|
|
67
|
+
const env = runtime.env;
|
|
68
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
69
|
+
|
|
70
|
+
checks.push(await checkCommand("java", ["-version"], env));
|
|
71
|
+
checks.push(await checkCommand("javac", ["-version"], env));
|
|
72
|
+
checks.push(await checkCommand("gradle", ["-v"], env));
|
|
73
|
+
checks.push(await checkCommand("cordova", ["--version"], env));
|
|
74
|
+
|
|
75
|
+
const androidSdk = runtime.androidSdk;
|
|
76
|
+
const sdkManager = runtime.cmdlineTools
|
|
77
|
+
? path.join(runtime.cmdlineTools, process.platform === "win32" ? "sdkmanager.bat" : "sdkmanager")
|
|
78
|
+
: null;
|
|
79
|
+
|
|
80
|
+
checks.push({
|
|
81
|
+
name: "ANDROID_HOME or ANDROID_SDK_ROOT",
|
|
82
|
+
ok: Boolean(androidSdk),
|
|
83
|
+
details: androidSdk || "set ANDROID_HOME to your Android SDK directory"
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
checks.push({
|
|
87
|
+
name: "Android platform-tools",
|
|
88
|
+
ok: await pathExists(runtime.platformTools),
|
|
89
|
+
details: runtime.platformTools || "install Android SDK platform-tools"
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
checks.push({
|
|
93
|
+
name: "Android cmdline-tools",
|
|
94
|
+
ok: await pathExists(runtime.cmdlineTools),
|
|
95
|
+
details: runtime.cmdlineTools || "install Android command line tools"
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
checks.push({
|
|
99
|
+
name: "Android sdkmanager",
|
|
100
|
+
ok: await pathExists(sdkManager),
|
|
101
|
+
details: sdkManager || "install Android command line tools"
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
checks.push({
|
|
105
|
+
name: `Android build-tools ${REQUIRED_ANDROID_BUILD_TOOLS}`,
|
|
106
|
+
ok: await pathExists(runtime.requiredBuildTools),
|
|
107
|
+
details: runtime.requiredBuildTools || `install build-tools;${REQUIRED_ANDROID_BUILD_TOOLS} with sdkmanager`
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
checks.push({
|
|
111
|
+
name: `Android platform ${REQUIRED_ANDROID_PLATFORM}`,
|
|
112
|
+
ok: await pathExists(runtime.requiredPlatform),
|
|
113
|
+
details: runtime.requiredPlatform || `install platforms;${REQUIRED_ANDROID_PLATFORM} with sdkmanager`
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
checks.push({
|
|
117
|
+
name: "Project directory writable",
|
|
118
|
+
ok: await checkWritableDirectory(projectRoot),
|
|
119
|
+
details: projectRoot
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
checks.push({
|
|
123
|
+
name: "Temporary directory writable",
|
|
124
|
+
ok: await checkWritableDirectory(os.tmpdir()),
|
|
125
|
+
details: os.tmpdir()
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const ok = checks.every((check) => check.ok);
|
|
129
|
+
return {
|
|
130
|
+
ok,
|
|
131
|
+
checks,
|
|
132
|
+
runtime,
|
|
133
|
+
suggestions: [
|
|
134
|
+
"Install a supported JDK and set JAVA_HOME.",
|
|
135
|
+
"Install Android Studio or Android command line tools.",
|
|
136
|
+
"Set ANDROID_HOME or ANDROID_SDK_ROOT, or install the SDK in the platform default path.",
|
|
137
|
+
"Install Cordova globally with: npm install -g cordova.",
|
|
138
|
+
`Install Android platform/build packages with: sdkmanager "platform-tools" "platforms;${REQUIRED_ANDROID_PLATFORM}" "build-tools;${REQUIRED_ANDROID_BUILD_TOOLS}".`
|
|
139
|
+
]
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function formatDoctorReport(report) {
|
|
144
|
+
const lines = ["html2apk doctor", ""];
|
|
145
|
+
for (const check of report.checks) {
|
|
146
|
+
lines.push(`${check.ok ? "OK " : "ERR"} ${check.name}`);
|
|
147
|
+
lines.push(` ${check.details}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(report.ok ? "Environment looks ready." : "Missing requirements:");
|
|
152
|
+
if (!report.ok) {
|
|
153
|
+
for (const suggestion of report.suggestions) {
|
|
154
|
+
lines.push(`- ${suggestion}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return lines.join("\n");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = {
|
|
162
|
+
runDoctor,
|
|
163
|
+
formatDoctorReport
|
|
164
|
+
};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const REQUIRED_ANDROID_PLATFORM = "android-36";
|
|
8
|
+
const REQUIRED_ANDROID_BUILD_TOOLS = "36.0.0";
|
|
9
|
+
|
|
10
|
+
function pathExists(targetPath) {
|
|
11
|
+
try {
|
|
12
|
+
return Boolean(targetPath) && fs.existsSync(targetPath);
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function unique(items) {
|
|
19
|
+
return Array.from(new Set(items.filter(Boolean)));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function pathDelimiter() {
|
|
23
|
+
return process.platform === "win32" ? ";" : ":";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function defaultAndroidSdkCandidates(env = process.env) {
|
|
27
|
+
const home = os.homedir();
|
|
28
|
+
const candidates = [
|
|
29
|
+
env.ANDROID_HOME,
|
|
30
|
+
env.ANDROID_SDK_ROOT
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
if (process.platform === "win32") {
|
|
34
|
+
candidates.push(
|
|
35
|
+
env.LOCALAPPDATA ? path.join(env.LOCALAPPDATA, "Android", "Sdk") : null,
|
|
36
|
+
home ? path.join(home, "AppData", "Local", "Android", "Sdk") : null
|
|
37
|
+
);
|
|
38
|
+
} else if (process.platform === "darwin") {
|
|
39
|
+
candidates.push(
|
|
40
|
+
home ? path.join(home, "Library", "Android", "sdk") : null,
|
|
41
|
+
"/Library/Android/sdk"
|
|
42
|
+
);
|
|
43
|
+
} else {
|
|
44
|
+
candidates.push(
|
|
45
|
+
home ? path.join(home, "Android", "Sdk") : null,
|
|
46
|
+
"/opt/android-sdk",
|
|
47
|
+
"/usr/local/share/android-sdk"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return unique(candidates);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getAndroidSdkPath(env = process.env) {
|
|
55
|
+
return defaultAndroidSdkCandidates(env).find(pathExists) || env.ANDROID_HOME || env.ANDROID_SDK_ROOT || null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getJavaHome(env = process.env) {
|
|
59
|
+
if (env.JAVA_HOME && pathExists(env.JAVA_HOME)) {
|
|
60
|
+
return env.JAVA_HOME;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const candidates = [];
|
|
64
|
+
if (process.platform === "win32") {
|
|
65
|
+
candidates.push(
|
|
66
|
+
latestSubdir(path.join(process.env.ProgramFiles || "C:\\Program Files", "Eclipse Adoptium")),
|
|
67
|
+
latestSubdir(path.join(process.env.ProgramFiles || "C:\\Program Files", "Java"))
|
|
68
|
+
);
|
|
69
|
+
} else if (process.platform === "darwin") {
|
|
70
|
+
candidates.push(
|
|
71
|
+
latestSubdir("/Library/Java/JavaVirtualMachines")
|
|
72
|
+
);
|
|
73
|
+
} else {
|
|
74
|
+
candidates.push(
|
|
75
|
+
latestSubdir("/usr/lib/jvm"),
|
|
76
|
+
latestSubdir("/usr/java")
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return candidates.find(pathExists) || env.JAVA_HOME || null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function latestSubdir(parent) {
|
|
84
|
+
if (!pathExists(parent)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const entries = fs.readdirSync(parent, { withFileTypes: true })
|
|
89
|
+
.filter((entry) => entry.isDirectory())
|
|
90
|
+
.map((entry) => entry.name)
|
|
91
|
+
.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
|
|
92
|
+
|
|
93
|
+
return entries.length ? path.join(parent, entries[0]) : null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function androidSdkPaths(androidSdk) {
|
|
97
|
+
if (!androidSdk) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return unique([
|
|
102
|
+
path.join(androidSdk, "platform-tools"),
|
|
103
|
+
path.join(androidSdk, "emulator"),
|
|
104
|
+
path.join(androidSdk, "cmdline-tools", "latest", "bin"),
|
|
105
|
+
path.join(androidSdk, "tools", "bin"),
|
|
106
|
+
latestSubdir(path.join(androidSdk, "build-tools"))
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getGradleHome(env = process.env) {
|
|
111
|
+
if (env.GRADLE_HOME && pathExists(env.GRADLE_HOME)) {
|
|
112
|
+
return env.GRADLE_HOME;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const candidates = [];
|
|
116
|
+
if (process.platform === "win32") {
|
|
117
|
+
candidates.push(
|
|
118
|
+
latestSubdir(path.join(env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "html2apk", "gradle")),
|
|
119
|
+
latestSubdir(path.join(process.env.ProgramFiles || "C:\\Program Files", "Gradle"))
|
|
120
|
+
);
|
|
121
|
+
} else {
|
|
122
|
+
candidates.push(
|
|
123
|
+
latestSubdir(path.join(os.homedir(), ".html2apk", "gradle")),
|
|
124
|
+
latestSubdir("/opt/gradle")
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return candidates.find(pathExists) || env.GRADLE_HOME || null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function prependToPath(env, entries) {
|
|
132
|
+
const key = Object.prototype.hasOwnProperty.call(env, "Path") ? "Path" : "PATH";
|
|
133
|
+
const current = env[key] || "";
|
|
134
|
+
env[key] = unique([...entries, ...current.split(pathDelimiter())]).join(pathDelimiter());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getRuntimeEnvironment(env = process.env) {
|
|
138
|
+
const androidSdk = getAndroidSdkPath(env);
|
|
139
|
+
const javaHome = getJavaHome(env);
|
|
140
|
+
const gradleHome = getGradleHome(env);
|
|
141
|
+
const nextEnv = { ...env };
|
|
142
|
+
const pathEntries = [];
|
|
143
|
+
|
|
144
|
+
if (androidSdk) {
|
|
145
|
+
nextEnv.ANDROID_HOME = androidSdk;
|
|
146
|
+
nextEnv.ANDROID_SDK_ROOT = androidSdk;
|
|
147
|
+
pathEntries.push(...androidSdkPaths(androidSdk));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (javaHome) {
|
|
151
|
+
nextEnv.JAVA_HOME = javaHome;
|
|
152
|
+
pathEntries.push(path.join(javaHome, "bin"));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (gradleHome) {
|
|
156
|
+
nextEnv.GRADLE_HOME = gradleHome;
|
|
157
|
+
pathEntries.push(path.join(gradleHome, "bin"));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
prependToPath(nextEnv, pathEntries);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
env: nextEnv,
|
|
164
|
+
javaHome,
|
|
165
|
+
gradleHome,
|
|
166
|
+
androidSdk,
|
|
167
|
+
platformTools: androidSdk ? path.join(androidSdk, "platform-tools") : null,
|
|
168
|
+
cmdlineTools: androidSdk ? path.join(androidSdk, "cmdline-tools", "latest", "bin") : null,
|
|
169
|
+
buildTools: androidSdk ? latestSubdir(path.join(androidSdk, "build-tools")) : null,
|
|
170
|
+
requiredBuildTools: androidSdk ? path.join(androidSdk, "build-tools", REQUIRED_ANDROID_BUILD_TOOLS) : null,
|
|
171
|
+
platforms: androidSdk ? path.join(androidSdk, "platforms") : null,
|
|
172
|
+
requiredPlatform: androidSdk ? path.join(androidSdk, "platforms", REQUIRED_ANDROID_PLATFORM) : null,
|
|
173
|
+
pathEntries
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function prepareBuildEnvironment(env = process.env) {
|
|
178
|
+
return getRuntimeEnvironment(env).env;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = {
|
|
182
|
+
REQUIRED_ANDROID_BUILD_TOOLS,
|
|
183
|
+
REQUIRED_ANDROID_PLATFORM,
|
|
184
|
+
defaultAndroidSdkCandidates,
|
|
185
|
+
getAndroidSdkPath,
|
|
186
|
+
getGradleHome,
|
|
187
|
+
getJavaHome,
|
|
188
|
+
getRuntimeEnvironment,
|
|
189
|
+
prepareBuildEnvironment
|
|
190
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cordova-plugin-html2apk-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Initial native bridge used by html2apk generated apps.",
|
|
5
|
+
"cordova": {
|
|
6
|
+
"id": "cordova-plugin-html2apk-bridge",
|
|
7
|
+
"platforms": [
|
|
8
|
+
"android"
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"cordova",
|
|
13
|
+
"html2apk"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT"
|
|
16
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<plugin id="cordova-plugin-html2apk-bridge" version="0.1.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
+
<name>Html2ApkBridge</name>
|
|
4
|
+
|
|
5
|
+
<js-module src="www/html2apk-bridge.js" name="Html2ApkBridge">
|
|
6
|
+
<clobbers target="Html2ApkNative" />
|
|
7
|
+
</js-module>
|
|
8
|
+
|
|
9
|
+
<platform name="android">
|
|
10
|
+
<config-file target="res/xml/config.xml" parent="/*">
|
|
11
|
+
<feature name="Html2ApkBridge">
|
|
12
|
+
<param name="android-package" value="dev.html2apk.bridge.Html2ApkBridge" />
|
|
13
|
+
</feature>
|
|
14
|
+
</config-file>
|
|
15
|
+
|
|
16
|
+
<config-file target="AndroidManifest.xml" parent="/manifest">
|
|
17
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
18
|
+
<uses-permission android:name="android.permission.VIBRATE" />
|
|
19
|
+
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
|
20
|
+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
21
|
+
</config-file>
|
|
22
|
+
|
|
23
|
+
<config-file target="AndroidManifest.xml" parent="/manifest/application">
|
|
24
|
+
<receiver android:name="dev.html2apk.bridge.NotificationReceiver" android:exported="false" />
|
|
25
|
+
<receiver android:name="dev.html2apk.bridge.BootReceiver" android:enabled="true" android:exported="true">
|
|
26
|
+
<intent-filter>
|
|
27
|
+
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
28
|
+
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
|
29
|
+
</intent-filter>
|
|
30
|
+
</receiver>
|
|
31
|
+
</config-file>
|
|
32
|
+
|
|
33
|
+
<source-file src="src/android/Html2ApkBridge.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
34
|
+
<source-file src="src/android/NotificationReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
35
|
+
<source-file src="src/android/BootReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
36
|
+
<source-file src="src/android/NotificationStore.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
|
|
37
|
+
<framework src="androidx.core:core:1.12.0" />
|
|
38
|
+
</platform>
|
|
39
|
+
</plugin>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package dev.html2apk.bridge;
|
|
2
|
+
|
|
3
|
+
import android.app.AlarmManager;
|
|
4
|
+
import android.content.BroadcastReceiver;
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.content.Intent;
|
|
7
|
+
import android.os.Build;
|
|
8
|
+
|
|
9
|
+
public class BootReceiver extends BroadcastReceiver {
|
|
10
|
+
@Override
|
|
11
|
+
public void onReceive(Context context, Intent intent) {
|
|
12
|
+
boolean exactAllowed = true;
|
|
13
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
14
|
+
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
15
|
+
exactAllowed = alarmManager != null && alarmManager.canScheduleExactAlarms();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
NotificationStore.rescheduleAll(context, exactAllowed);
|
|
19
|
+
}
|
|
20
|
+
}
|