@simplysm/capacitor-plugin-auto-update 13.0.99 → 14.0.1
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/android/build.gradle +1 -0
- package/android/src/main/java/kr/co/simplysm/capacitor/apkinstaller/ApkInstallerPlugin.kt +114 -0
- package/dist/ApkInstaller.d.ts +7 -7
- package/dist/ApkInstaller.js +36 -34
- package/dist/ApkInstaller.js.map +1 -6
- package/dist/ApkInstallerPlugin.js +2 -1
- package/dist/ApkInstallerPlugin.js.map +1 -6
- package/dist/AutoUpdate.js +143 -137
- package/dist/AutoUpdate.js.map +1 -6
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -6
- package/dist/web/ApkInstallerWeb.js +19 -20
- package/dist/web/ApkInstallerWeb.js.map +1 -6
- package/package.json +10 -10
- package/src/ApkInstaller.ts +7 -7
- package/src/AutoUpdate.ts +29 -29
- package/src/index.ts +2 -2
- package/src/web/ApkInstallerWeb.ts +3 -3
- package/README.md +0 -94
- package/android/src/main/java/kr/co/simplysm/capacitor/apkinstaller/ApkInstallerPlugin.java +0 -118
- package/dist/env.d.js +0 -1
- package/dist/env.d.js.map +0 -6
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package kr.co.simplysm.capacitor.apkinstaller
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import android.content.pm.PackageManager
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.provider.Settings
|
|
8
|
+
import android.util.Log
|
|
9
|
+
|
|
10
|
+
import com.getcapacitor.JSObject
|
|
11
|
+
import com.getcapacitor.Plugin
|
|
12
|
+
import com.getcapacitor.PluginCall
|
|
13
|
+
import com.getcapacitor.PluginMethod
|
|
14
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
15
|
+
|
|
16
|
+
@CapacitorPlugin(name = "ApkInstaller")
|
|
17
|
+
class ApkInstallerPlugin : Plugin() {
|
|
18
|
+
|
|
19
|
+
companion object {
|
|
20
|
+
private const val TAG = "ApkInstallerPlugin"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@PluginMethod
|
|
24
|
+
fun install(call: PluginCall) {
|
|
25
|
+
val uriStr = call.getString("uri")
|
|
26
|
+
if (uriStr == null) {
|
|
27
|
+
call.reject("uri is required")
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
val apkUri = Uri.parse(uriStr)
|
|
33
|
+
|
|
34
|
+
val intent = Intent(Intent.ACTION_VIEW)
|
|
35
|
+
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
|
|
36
|
+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
37
|
+
|
|
38
|
+
context.startActivity(intent)
|
|
39
|
+
call.resolve()
|
|
40
|
+
} catch (e: Exception) {
|
|
41
|
+
Log.e(TAG, "install failed", e)
|
|
42
|
+
call.reject("Install failed: " + e.message)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@PluginMethod
|
|
47
|
+
fun checkPermissions(call: PluginCall) {
|
|
48
|
+
// Check granted
|
|
49
|
+
val granted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
50
|
+
context.packageManager.canRequestPackageInstalls()
|
|
51
|
+
} else {
|
|
52
|
+
true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check manifest
|
|
56
|
+
var manifest = false
|
|
57
|
+
try {
|
|
58
|
+
val targetPermission = "android.permission.REQUEST_INSTALL_PACKAGES"
|
|
59
|
+
val requestedPermissions = context.packageManager
|
|
60
|
+
.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
|
|
61
|
+
.requestedPermissions
|
|
62
|
+
if (requestedPermissions != null) {
|
|
63
|
+
for (perm in requestedPermissions) {
|
|
64
|
+
if (targetPermission == perm) {
|
|
65
|
+
manifest = true
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} catch (e: Exception) {
|
|
71
|
+
Log.e(TAG, "checkPermissions manifest check failed", e)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
val ret = JSObject()
|
|
75
|
+
ret.put("granted", granted)
|
|
76
|
+
ret.put("manifest", manifest)
|
|
77
|
+
call.resolve(ret)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@PluginMethod
|
|
81
|
+
fun requestPermissions(call: PluginCall) {
|
|
82
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
83
|
+
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
|
|
84
|
+
intent.data = Uri.parse("package:" + context.packageName)
|
|
85
|
+
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
86
|
+
context.startActivity(intent)
|
|
87
|
+
}
|
|
88
|
+
call.resolve()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@PluginMethod
|
|
92
|
+
fun getVersionInfo(call: PluginCall) {
|
|
93
|
+
try {
|
|
94
|
+
val pm = context.packageManager
|
|
95
|
+
val info = pm.getPackageInfo(context.packageName, 0)
|
|
96
|
+
|
|
97
|
+
val versionName = info.versionName
|
|
98
|
+
val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
99
|
+
info.longVersionCode
|
|
100
|
+
} else {
|
|
101
|
+
@Suppress("DEPRECATION")
|
|
102
|
+
info.versionCode.toLong()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
val ret = JSObject()
|
|
106
|
+
ret.put("versionName", versionName)
|
|
107
|
+
ret.put("versionCode", versionCode.toString())
|
|
108
|
+
call.resolve(ret)
|
|
109
|
+
} catch (e: Exception) {
|
|
110
|
+
Log.e(TAG, "getVersionInfo failed", e)
|
|
111
|
+
call.reject("getVersionInfo failed: " + e.message)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
package/dist/ApkInstaller.d.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import type { VersionInfo } from "./ApkInstallerPlugin";
|
|
2
2
|
/**
|
|
3
|
-
* APK
|
|
4
|
-
* - Android:
|
|
5
|
-
* - Browser:
|
|
3
|
+
* APK 설치 플러그인
|
|
4
|
+
* - Android: APK 설치 인텐트를 실행하고, REQUEST_INSTALL_PACKAGES 권한을 관리
|
|
5
|
+
* - Browser: 알림 메시지를 표시하고 정상 반환
|
|
6
6
|
*/
|
|
7
7
|
export declare abstract class ApkInstaller {
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* 권한 확인 (설치 권한 승인 여부 + manifest 선언 여부)
|
|
10
10
|
*/
|
|
11
11
|
static checkPermissions(): Promise<{
|
|
12
12
|
granted: boolean;
|
|
13
13
|
manifest: boolean;
|
|
14
14
|
}>;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* REQUEST_INSTALL_PACKAGES 권한 요청 (설정 화면으로 이동)
|
|
17
17
|
*/
|
|
18
18
|
static requestPermissions(): Promise<void>;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* APK 설치
|
|
21
21
|
* @param apkUri content:// URI (FileProvider URI)
|
|
22
22
|
*/
|
|
23
23
|
static install(apkUri: string): Promise<void>;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* 앱 버전 정보 조회
|
|
26
26
|
*/
|
|
27
27
|
static getVersionInfo(): Promise<VersionInfo>;
|
|
28
28
|
}
|
package/dist/ApkInstaller.js
CHANGED
|
@@ -1,38 +1,40 @@
|
|
|
1
1
|
import { registerPlugin } from "@capacitor/core";
|
|
2
2
|
const apkInstallerPlugin = registerPlugin("ApkInstaller", {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
web: async () => {
|
|
4
|
+
const { ApkInstallerWeb } = await import("./web/ApkInstallerWeb.js");
|
|
5
|
+
return new ApkInstallerWeb();
|
|
6
|
+
},
|
|
7
7
|
});
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
8
|
+
/**
|
|
9
|
+
* APK 설치 플러그인
|
|
10
|
+
* - Android: APK 설치 인텐트를 실행하고, REQUEST_INSTALL_PACKAGES 권한을 관리
|
|
11
|
+
* - Browser: 알림 메시지를 표시하고 정상 반환
|
|
12
|
+
*/
|
|
13
|
+
export class ApkInstaller {
|
|
14
|
+
/**
|
|
15
|
+
* 권한 확인 (설치 권한 승인 여부 + manifest 선언 여부)
|
|
16
|
+
*/
|
|
17
|
+
static async checkPermissions() {
|
|
18
|
+
return apkInstallerPlugin.checkPermissions();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* REQUEST_INSTALL_PACKAGES 권한 요청 (설정 화면으로 이동)
|
|
22
|
+
*/
|
|
23
|
+
static async requestPermissions() {
|
|
24
|
+
await apkInstallerPlugin.requestPermissions();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* APK 설치
|
|
28
|
+
* @param apkUri content:// URI (FileProvider URI)
|
|
29
|
+
*/
|
|
30
|
+
static async install(apkUri) {
|
|
31
|
+
await apkInstallerPlugin.install({ uri: apkUri });
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 앱 버전 정보 조회
|
|
35
|
+
*/
|
|
36
|
+
static async getVersionInfo() {
|
|
37
|
+
return apkInstallerPlugin.getVersionInfo();
|
|
38
|
+
}
|
|
34
39
|
}
|
|
35
|
-
|
|
36
|
-
ApkInstaller
|
|
37
|
-
};
|
|
38
|
-
//# sourceMappingURL=ApkInstaller.js.map
|
|
40
|
+
//# sourceMappingURL=ApkInstaller.js.map
|
package/dist/ApkInstaller.js.map
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/ApkInstaller.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAG/B,MAAM,qBAAqB,eAAmC,gBAAgB;AAAA,EAC5E,KAAK,YAAY;AACf,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,uBAAuB;AAChE,WAAO,IAAI,gBAAgB;AAAA,EAC7B;AACF,CAAC;AAOM,MAAe,aAAa;AAAA;AAAA;AAAA;AAAA,EAIjC,aAAa,mBAAqE;AAChF,WAAO,mBAAmB,iBAAiB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,qBAAoC;AAC/C,UAAM,mBAAmB,mBAAmB;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,QAAQ,QAA+B;AAClD,UAAM,mBAAmB,QAAQ,EAAE,KAAK,OAAO,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,iBAAuC;AAClD,WAAO,mBAAmB,eAAe;AAAA,EAC3C;AACF;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"ApkInstaller.js","sourceRoot":"","sources":["..\\src\\ApkInstaller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,kBAAkB,GAAG,cAAc,CAAqB,cAAc,EAAE;IAC5E,GAAG,EAAE,KAAK,IAAI,EAAE;QACd,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClE,OAAO,IAAI,eAAe,EAAE,CAAC;IAC/B,CAAC;CACF,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,OAAgB,YAAY;IAChC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,gBAAgB;QAC3B,OAAO,kBAAkB,CAAC,gBAAgB,EAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,kBAAkB;QAC7B,MAAM,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAc;QACjC,MAAM,kBAAkB,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc;QACzB,OAAO,kBAAkB,CAAC,cAAc,EAAE,CAAC;IAC7C,CAAC;CACF"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
|
+
//# sourceMappingURL=ApkInstallerPlugin.js.map
|
package/dist/AutoUpdate.js
CHANGED
|
@@ -3,8 +3,8 @@ import { html, wait, path } from "@simplysm/core-common";
|
|
|
3
3
|
import { fetchUrlBytes } from "@simplysm/core-browser";
|
|
4
4
|
import semver from "semver";
|
|
5
5
|
import { ApkInstaller } from "./ApkInstaller.js";
|
|
6
|
-
class AutoUpdate {
|
|
7
|
-
|
|
6
|
+
export class AutoUpdate {
|
|
7
|
+
static _BUTTON_CSS = `
|
|
8
8
|
all: unset;
|
|
9
9
|
color: blue;
|
|
10
10
|
width: 100%;
|
|
@@ -16,11 +16,12 @@ class AutoUpdate {
|
|
|
16
16
|
left: 0;
|
|
17
17
|
border-top: 1px solid lightgrey;
|
|
18
18
|
`;
|
|
19
|
-
|
|
19
|
+
static _BUTTON_ACTIVE_CSS = `
|
|
20
20
|
background: lightgrey;
|
|
21
21
|
`;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
static _throwAboutReinstall(code, targetHref) {
|
|
23
|
+
const downloadHtml = targetHref != null
|
|
24
|
+
? html `
|
|
24
25
|
<style>
|
|
25
26
|
._button { ${this._BUTTON_CSS} }
|
|
26
27
|
._button:active { ${this._BUTTON_ACTIVE_CSS} }
|
|
@@ -31,155 +32,160 @@ class AutoUpdate {
|
|
|
31
32
|
>
|
|
32
33
|
Download
|
|
33
34
|
</a>
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
`
|
|
36
|
+
: "";
|
|
37
|
+
throw new Error(html `
|
|
38
|
+
APK 파일을 다시 다운로드하여 설치해야 합니다(${code}). ${downloadHtml}
|
|
37
39
|
`);
|
|
38
|
-
}
|
|
39
|
-
static async _checkPermission(log, targetHref) {
|
|
40
|
-
if (!navigator.userAgent.toLowerCase().includes("android")) {
|
|
41
|
-
throw new Error("Only Android is supported.");
|
|
42
40
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
41
|
+
static async _checkPermission(log, targetHref) {
|
|
42
|
+
if (!navigator.userAgent.toLowerCase().includes("android")) {
|
|
43
|
+
throw new Error("Android만 지원됩니다.");
|
|
44
|
+
}
|
|
45
|
+
let granted;
|
|
46
|
+
try {
|
|
47
|
+
const result = await ApkInstaller.checkPermissions();
|
|
48
|
+
if (!result.manifest) {
|
|
49
|
+
this._throwAboutReinstall(1, targetHref);
|
|
50
|
+
}
|
|
51
|
+
granted = result.granted;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.error("[AutoUpdate] checkPermissions manifest 확인 실패:", err);
|
|
56
|
+
this._throwAboutReinstall(2, targetHref);
|
|
57
|
+
return; // 도달 불가 — _throwAboutReinstall은 항상 throw함
|
|
58
|
+
}
|
|
59
|
+
if (!granted) {
|
|
60
|
+
log(html `
|
|
61
|
+
설치 권한을 활성화해야 합니다.
|
|
58
62
|
<style>
|
|
59
63
|
button { ${this._BUTTON_CSS} }
|
|
60
64
|
button:active { ${this._BUTTON_ACTIVE_CSS} }
|
|
61
65
|
</style>
|
|
62
|
-
<button onclick="location.reload()"
|
|
66
|
+
<button onclick="location.reload()">재시도</button>
|
|
63
67
|
`);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
300
|
|
72
|
-
);
|
|
68
|
+
await ApkInstaller.requestPermissions();
|
|
69
|
+
// 최대 5분(300초) 대기 - 사용자가 설정에서 권한을 부여할 시간
|
|
70
|
+
await wait.until(async () => {
|
|
71
|
+
const result = await ApkInstaller.checkPermissions();
|
|
72
|
+
return result.granted;
|
|
73
|
+
}, 1000, 300);
|
|
74
|
+
}
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Please install the latest version and restart.
|
|
76
|
+
static async _installApk(log, apkFilePath) {
|
|
77
|
+
log(html `
|
|
78
|
+
최신 버전을 설치하고 재시작해 주세요.
|
|
78
79
|
<style>
|
|
79
80
|
button { ${this._BUTTON_CSS} }
|
|
80
81
|
button:active { ${this._BUTTON_ACTIVE_CSS} }
|
|
81
82
|
</style>
|
|
82
|
-
<button onclick="location.reload()"
|
|
83
|
+
<button onclick="location.reload()">재시도</button>
|
|
83
84
|
`);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
const apkFileUri = await FileSystem.getUri(apkFilePath);
|
|
86
|
+
await ApkInstaller.install(apkFileUri);
|
|
87
|
+
}
|
|
88
|
+
static _getErrorMessage(err) {
|
|
89
|
+
return html `
|
|
90
|
+
업데이트 중 오류가 발생했습니다:
|
|
90
91
|
<br />
|
|
91
92
|
${err instanceof Error ? err.message : String(err)}
|
|
92
93
|
`;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
94
|
+
}
|
|
95
|
+
static async _freezeApp() {
|
|
96
|
+
await new Promise(() => { }); // 무한 대기
|
|
97
|
+
}
|
|
98
|
+
static async run(opt) {
|
|
99
|
+
try {
|
|
100
|
+
opt.log(`최신 버전 확인 중...`);
|
|
101
|
+
// 서버에서 버전 및 다운로드 링크 조회
|
|
102
|
+
const autoUpdateServiceClient = opt.serviceClient.getService("AutoUpdateService");
|
|
103
|
+
const serverVersionInfo = await autoUpdateServiceClient.getLastVersion("android");
|
|
104
|
+
if (!serverVersionInfo) {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
106
|
+
console.log("서버에서 최신 버전 정보를 가져오지 못했습니다.");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
opt.log(`권한 확인 중...`);
|
|
110
|
+
await this._checkPermission(opt.log, opt.serviceClient.hostUrl + serverVersionInfo.downloadPath);
|
|
111
|
+
// 현재 앱 버전 조회
|
|
112
|
+
const currentVersionInfo = await ApkInstaller.getVersionInfo();
|
|
113
|
+
// 이미 최신이거나 서버 버전이 낮으면 반환
|
|
114
|
+
if (semver.valid(currentVersionInfo.versionName) === null ||
|
|
115
|
+
semver.valid(serverVersionInfo.version) === null) {
|
|
116
|
+
// eslint-disable-next-line no-console
|
|
117
|
+
console.log("유효하지 않은 semver 버전이므로 업데이트 확인을 건너뜁니다");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!semver.gt(serverVersionInfo.version, currentVersionInfo.versionName)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
opt.log(`최신 버전 파일 다운로드 중...`);
|
|
124
|
+
const buffer = await fetchUrlBytes(opt.serviceClient.hostUrl + serverVersionInfo.downloadPath, {
|
|
125
|
+
onProgress: (progress) => {
|
|
126
|
+
const progressText = ((progress.receivedLength * 100) / progress.contentLength).toFixed(2);
|
|
127
|
+
opt.log(`최신 버전 파일 다운로드 중...(${progressText}%)`);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
const storagePath = await FileSystem.getStoragePath("appCache");
|
|
131
|
+
const apkFilePath = path.join(storagePath, `latest.apk`);
|
|
132
|
+
await FileSystem.writeFile(apkFilePath, buffer);
|
|
133
|
+
await this._installApk(opt.log, apkFilePath);
|
|
134
|
+
await this._freezeApp();
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
opt.log(this._getErrorMessage(err));
|
|
138
|
+
await this._freezeApp();
|
|
130
139
|
}
|
|
131
|
-
);
|
|
132
|
-
const storagePath = await FileSystem.getStoragePath("appCache");
|
|
133
|
-
const apkFilePath = path.join(storagePath, `latest.apk`);
|
|
134
|
-
await FileSystem.writeFile(apkFilePath, buffer);
|
|
135
|
-
await this._installApk(opt.log, apkFilePath);
|
|
136
|
-
await this._freezeApp();
|
|
137
|
-
} catch (err) {
|
|
138
|
-
opt.log(this._getErrorMessage(err));
|
|
139
|
-
await this._freezeApp();
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
141
|
+
static async runByExternalStorage(opt) {
|
|
142
|
+
try {
|
|
143
|
+
opt.log(`권한 확인 중...`);
|
|
144
|
+
await this._checkPermission(opt.log);
|
|
145
|
+
opt.log(`최신 버전 확인 중...`);
|
|
146
|
+
// 버전 목록 조회
|
|
147
|
+
const externalPath = await FileSystem.getStoragePath("external");
|
|
148
|
+
const fileInfos = await FileSystem.readdir(path.join(externalPath, opt.dirPath));
|
|
149
|
+
const versions = fileInfos
|
|
150
|
+
.filter((fileInfo) => !fileInfo.isDirectory)
|
|
151
|
+
.map((fileInfo) => ({
|
|
152
|
+
fileName: fileInfo.name,
|
|
153
|
+
version: path.basename(fileInfo.name, path.extname(fileInfo.name)),
|
|
154
|
+
extName: path.extname(fileInfo.name),
|
|
155
|
+
}))
|
|
156
|
+
.filter((item) => {
|
|
157
|
+
return item.extName === ".apk" && /^[0-9.]*$/.test(item.version);
|
|
158
|
+
});
|
|
159
|
+
// 버전 파일이 없으면 반환
|
|
160
|
+
if (versions.length === 0)
|
|
161
|
+
return;
|
|
162
|
+
const latestVersion = semver.maxSatisfying(versions.map((item) => item.version), "*");
|
|
163
|
+
// 유효한 semver 버전이 없으면 반환
|
|
164
|
+
if (latestVersion == null) {
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.log("유효한 semver 버전 파일을 찾을 수 없습니다.");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// 현재 앱 버전 조회
|
|
170
|
+
const currentVersionInfo = await ApkInstaller.getVersionInfo();
|
|
171
|
+
// 이미 최신이거나 외부 저장소 버전이 낮으면 반환
|
|
172
|
+
if (semver.valid(currentVersionInfo.versionName) === null ||
|
|
173
|
+
semver.valid(latestVersion) === null) {
|
|
174
|
+
// eslint-disable-next-line no-console
|
|
175
|
+
console.log("유효하지 않은 semver 버전이므로 업데이트 확인을 건너뜁니다");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!semver.gt(latestVersion, currentVersionInfo.versionName)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const apkFilePath = path.join(externalPath, opt.dirPath, latestVersion + ".apk");
|
|
182
|
+
await this._installApk(opt.log, apkFilePath);
|
|
183
|
+
await this._freezeApp();
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
opt.log(this._getErrorMessage(err));
|
|
187
|
+
await this._freezeApp();
|
|
188
|
+
}
|
|
179
189
|
}
|
|
180
|
-
}
|
|
181
190
|
}
|
|
182
|
-
|
|
183
|
-
AutoUpdate
|
|
184
|
-
};
|
|
185
|
-
//# sourceMappingURL=AutoUpdate.js.map
|
|
191
|
+
//# sourceMappingURL=AutoUpdate.js.map
|
package/dist/AutoUpdate.js.map
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/AutoUpdate.ts"],
|
|
4
|
-
"mappings": "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",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"AutoUpdate.js","sourceRoot":"","sources":["..\\src\\AutoUpdate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts"],
|
|
4
|
-
"mappings": "AACA,cAAc;AACd,cAAc;AAGd,cAAc;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["..\\src\\index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AAErC,UAAU;AACV,cAAc,cAAc,CAAC"}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { WebPlugin } from "@capacitor/core";
|
|
2
|
-
class ApkInstallerWeb extends WebPlugin {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
export class ApkInstallerWeb extends WebPlugin {
|
|
3
|
+
install(_options) {
|
|
4
|
+
alert("[ApkInstaller] 웹 환경에서는 APK 설치를 지원하지 않습니다.");
|
|
5
|
+
return Promise.resolve();
|
|
6
|
+
}
|
|
7
|
+
checkPermissions() {
|
|
8
|
+
// 웹에서는 권한 확인 생략
|
|
9
|
+
return Promise.resolve({ granted: true, manifest: true });
|
|
10
|
+
}
|
|
11
|
+
async requestPermissions() {
|
|
12
|
+
// 웹에서는 동작 없음
|
|
13
|
+
}
|
|
14
|
+
getVersionInfo() {
|
|
15
|
+
return Promise.resolve({
|
|
16
|
+
versionName: import.meta.env.__VER__ ?? "0.0.0",
|
|
17
|
+
versionCode: "0",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
ApkInstallerWeb
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=ApkInstallerWeb.js.map
|
|
21
|
+
//# sourceMappingURL=ApkInstallerWeb.js.map
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/web/ApkInstallerWeb.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,wBAAwB,UAAwC;AAAA,EAC3E,QAAQ,UAA0C;AAChD,UAAM,sEAAsE;AAC5E,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,mBAAqE;AAEnE,WAAO,QAAQ,QAAQ,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAM,qBAAoC;AAAA,EAE1C;AAAA,EAEA,iBAAuC;AACrC,WAAO,QAAQ,QAAQ;AAAA,MACrB,aACE,YAAY,IAAI,WAAW;AAAA,MAC7B,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AACF;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"ApkInstallerWeb.js","sourceRoot":"","sources":["..\\..\\src\\web\\ApkInstallerWeb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC5C,OAAO,CAAC,QAAyB;QAC/B,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACnD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,gBAAgB;QACd,gBAAgB;QAChB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,aAAa;IACf,CAAC;IAED,cAAc;QACZ,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,WAAW,EACT,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO;YACpC,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/capacitor-plugin-auto-update",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"author": "
|
|
6
|
-
"license": "
|
|
3
|
+
"version": "14.0.1",
|
|
4
|
+
"description": "심플리즘 패키지 - Capacitor 자동 업데이트 플러그인",
|
|
5
|
+
"author": "심플리즘",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/kslhunter/simplysm.git",
|
|
@@ -19,18 +19,18 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"semver": "^7.7.4",
|
|
22
|
-
"@simplysm/
|
|
23
|
-
"@simplysm/service-
|
|
24
|
-
"@simplysm/
|
|
25
|
-
"@simplysm/
|
|
26
|
-
"@simplysm/
|
|
22
|
+
"@simplysm/core-browser": "14.0.1",
|
|
23
|
+
"@simplysm/service-client": "14.0.1",
|
|
24
|
+
"@simplysm/service-common": "14.0.1",
|
|
25
|
+
"@simplysm/core-common": "14.0.1",
|
|
26
|
+
"@simplysm/capacitor-plugin-file-system": "14.0.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@capacitor/core": "^7.6.0",
|
|
30
30
|
"@types/semver": "^7.7.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@capacitor/core": "^7
|
|
33
|
+
"@capacitor/core": "^7"
|
|
34
34
|
},
|
|
35
35
|
"capacitor": {
|
|
36
36
|
"android": {
|
package/src/ApkInstaller.ts
CHANGED
|
@@ -9,27 +9,27 @@ const apkInstallerPlugin = registerPlugin<ApkInstallerPlugin>("ApkInstaller", {
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* APK
|
|
13
|
-
* - Android:
|
|
14
|
-
* - Browser:
|
|
12
|
+
* APK 설치 플러그인
|
|
13
|
+
* - Android: APK 설치 인텐트를 실행하고, REQUEST_INSTALL_PACKAGES 권한을 관리
|
|
14
|
+
* - Browser: 알림 메시지를 표시하고 정상 반환
|
|
15
15
|
*/
|
|
16
16
|
export abstract class ApkInstaller {
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* 권한 확인 (설치 권한 승인 여부 + manifest 선언 여부)
|
|
19
19
|
*/
|
|
20
20
|
static async checkPermissions(): Promise<{ granted: boolean; manifest: boolean }> {
|
|
21
21
|
return apkInstallerPlugin.checkPermissions();
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* REQUEST_INSTALL_PACKAGES 권한 요청 (설정 화면으로 이동)
|
|
26
26
|
*/
|
|
27
27
|
static async requestPermissions(): Promise<void> {
|
|
28
28
|
await apkInstallerPlugin.requestPermissions();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* APK 설치
|
|
33
33
|
* @param apkUri content:// URI (FileProvider URI)
|
|
34
34
|
*/
|
|
35
35
|
static async install(apkUri: string): Promise<void> {
|
|
@@ -37,7 +37,7 @@ export abstract class ApkInstaller {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* 앱 버전 정보 조회
|
|
41
41
|
*/
|
|
42
42
|
static async getVersionInfo(): Promise<VersionInfo> {
|
|
43
43
|
return apkInstallerPlugin.getVersionInfo();
|
package/src/AutoUpdate.ts
CHANGED
|
@@ -42,13 +42,13 @@ export abstract class AutoUpdate {
|
|
|
42
42
|
: "";
|
|
43
43
|
|
|
44
44
|
throw new Error(html`
|
|
45
|
-
|
|
45
|
+
APK 파일을 다시 다운로드하여 설치해야 합니다(${code}). ${downloadHtml}
|
|
46
46
|
`);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
private static async _checkPermission(log: (messageHtml: string) => void, targetHref?: string) {
|
|
50
50
|
if (!navigator.userAgent.toLowerCase().includes("android")) {
|
|
51
|
-
throw new Error("
|
|
51
|
+
throw new Error("Android만 지원됩니다.");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
let granted: boolean;
|
|
@@ -60,22 +60,22 @@ export abstract class AutoUpdate {
|
|
|
60
60
|
granted = result.granted;
|
|
61
61
|
} catch (err) {
|
|
62
62
|
// eslint-disable-next-line no-console
|
|
63
|
-
console.error("[AutoUpdate] checkPermissions manifest
|
|
63
|
+
console.error("[AutoUpdate] checkPermissions manifest 확인 실패:", err);
|
|
64
64
|
this._throwAboutReinstall(2, targetHref);
|
|
65
|
-
return; //
|
|
65
|
+
return; // 도달 불가 — _throwAboutReinstall은 항상 throw함
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
if (!granted) {
|
|
69
69
|
log(html`
|
|
70
|
-
|
|
70
|
+
설치 권한을 활성화해야 합니다.
|
|
71
71
|
<style>
|
|
72
72
|
button { ${this._BUTTON_CSS} }
|
|
73
73
|
button:active { ${this._BUTTON_ACTIVE_CSS} }
|
|
74
74
|
</style>
|
|
75
|
-
<button onclick="location.reload()"
|
|
75
|
+
<button onclick="location.reload()">재시도</button>
|
|
76
76
|
`);
|
|
77
77
|
await ApkInstaller.requestPermissions();
|
|
78
|
-
//
|
|
78
|
+
// 최대 5분(300초) 대기 - 사용자가 설정에서 권한을 부여할 시간
|
|
79
79
|
await wait.until(
|
|
80
80
|
async () => {
|
|
81
81
|
const result = await ApkInstaller.checkPermissions();
|
|
@@ -92,12 +92,12 @@ export abstract class AutoUpdate {
|
|
|
92
92
|
apkFilePath: string,
|
|
93
93
|
): Promise<void> {
|
|
94
94
|
log(html`
|
|
95
|
-
|
|
95
|
+
최신 버전을 설치하고 재시작해 주세요.
|
|
96
96
|
<style>
|
|
97
97
|
button { ${this._BUTTON_CSS} }
|
|
98
98
|
button:active { ${this._BUTTON_ACTIVE_CSS} }
|
|
99
99
|
</style>
|
|
100
|
-
<button onclick="location.reload()"
|
|
100
|
+
<button onclick="location.reload()">재시도</button>
|
|
101
101
|
`);
|
|
102
102
|
const apkFileUri = await FileSystem.getUri(apkFilePath);
|
|
103
103
|
await ApkInstaller.install(apkFileUri);
|
|
@@ -105,54 +105,54 @@ export abstract class AutoUpdate {
|
|
|
105
105
|
|
|
106
106
|
private static _getErrorMessage(err: unknown) {
|
|
107
107
|
return html`
|
|
108
|
-
|
|
108
|
+
업데이트 중 오류가 발생했습니다:
|
|
109
109
|
<br />
|
|
110
110
|
${err instanceof Error ? err.message : String(err)}
|
|
111
111
|
`;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
private static async _freezeApp() {
|
|
115
|
-
await new Promise(() => {}); //
|
|
115
|
+
await new Promise(() => {}); // 무한 대기
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
static async run(opt: { log: (messageHtml: string) => void; serviceClient: ServiceClient }) {
|
|
119
119
|
try {
|
|
120
|
-
opt.log(
|
|
120
|
+
opt.log(`최신 버전 확인 중...`);
|
|
121
121
|
|
|
122
|
-
//
|
|
122
|
+
// 서버에서 버전 및 다운로드 링크 조회
|
|
123
123
|
const autoUpdateServiceClient =
|
|
124
124
|
opt.serviceClient.getService<AutoUpdateService>("AutoUpdateService");
|
|
125
125
|
|
|
126
126
|
const serverVersionInfo = await autoUpdateServiceClient.getLastVersion("android");
|
|
127
127
|
if (!serverVersionInfo) {
|
|
128
128
|
// eslint-disable-next-line no-console
|
|
129
|
-
console.log("
|
|
129
|
+
console.log("서버에서 최신 버전 정보를 가져오지 못했습니다.");
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
opt.log(
|
|
133
|
+
opt.log(`권한 확인 중...`);
|
|
134
134
|
await this._checkPermission(
|
|
135
135
|
opt.log,
|
|
136
136
|
opt.serviceClient.hostUrl + serverVersionInfo.downloadPath,
|
|
137
137
|
);
|
|
138
138
|
|
|
139
|
-
//
|
|
139
|
+
// 현재 앱 버전 조회
|
|
140
140
|
const currentVersionInfo = await ApkInstaller.getVersionInfo();
|
|
141
141
|
|
|
142
|
-
//
|
|
142
|
+
// 이미 최신이거나 서버 버전이 낮으면 반환
|
|
143
143
|
if (
|
|
144
144
|
semver.valid(currentVersionInfo.versionName) === null ||
|
|
145
145
|
semver.valid(serverVersionInfo.version) === null
|
|
146
146
|
) {
|
|
147
147
|
// eslint-disable-next-line no-console
|
|
148
|
-
console.log("
|
|
148
|
+
console.log("유효하지 않은 semver 버전이므로 업데이트 확인을 건너뜁니다");
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
151
|
if (!semver.gt(serverVersionInfo.version, currentVersionInfo.versionName)) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
opt.log(
|
|
155
|
+
opt.log(`최신 버전 파일 다운로드 중...`);
|
|
156
156
|
const buffer = await fetchUrlBytes(
|
|
157
157
|
opt.serviceClient.hostUrl + serverVersionInfo.downloadPath,
|
|
158
158
|
{
|
|
@@ -160,7 +160,7 @@ export abstract class AutoUpdate {
|
|
|
160
160
|
const progressText = ((progress.receivedLength * 100) / progress.contentLength).toFixed(
|
|
161
161
|
2,
|
|
162
162
|
);
|
|
163
|
-
opt.log(
|
|
163
|
+
opt.log(`최신 버전 파일 다운로드 중...(${progressText}%)`);
|
|
164
164
|
},
|
|
165
165
|
},
|
|
166
166
|
);
|
|
@@ -178,12 +178,12 @@ export abstract class AutoUpdate {
|
|
|
178
178
|
|
|
179
179
|
static async runByExternalStorage(opt: { log: (messageHtml: string) => void; dirPath: string }) {
|
|
180
180
|
try {
|
|
181
|
-
opt.log(
|
|
181
|
+
opt.log(`권한 확인 중...`);
|
|
182
182
|
await this._checkPermission(opt.log);
|
|
183
183
|
|
|
184
|
-
opt.log(
|
|
184
|
+
opt.log(`최신 버전 확인 중...`);
|
|
185
185
|
|
|
186
|
-
//
|
|
186
|
+
// 버전 목록 조회
|
|
187
187
|
const externalPath = await FileSystem.getStoragePath("external");
|
|
188
188
|
const fileInfos = await FileSystem.readdir(path.join(externalPath, opt.dirPath));
|
|
189
189
|
|
|
@@ -198,7 +198,7 @@ export abstract class AutoUpdate {
|
|
|
198
198
|
return item.extName === ".apk" && /^[0-9.]*$/.test(item.version);
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
//
|
|
201
|
+
// 버전 파일이 없으면 반환
|
|
202
202
|
if (versions.length === 0) return;
|
|
203
203
|
|
|
204
204
|
const latestVersion = semver.maxSatisfying(
|
|
@@ -206,23 +206,23 @@ export abstract class AutoUpdate {
|
|
|
206
206
|
"*",
|
|
207
207
|
);
|
|
208
208
|
|
|
209
|
-
//
|
|
209
|
+
// 유효한 semver 버전이 없으면 반환
|
|
210
210
|
if (latestVersion == null) {
|
|
211
211
|
// eslint-disable-next-line no-console
|
|
212
|
-
console.log("
|
|
212
|
+
console.log("유효한 semver 버전 파일을 찾을 수 없습니다.");
|
|
213
213
|
return;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
//
|
|
216
|
+
// 현재 앱 버전 조회
|
|
217
217
|
const currentVersionInfo = await ApkInstaller.getVersionInfo();
|
|
218
218
|
|
|
219
|
-
//
|
|
219
|
+
// 이미 최신이거나 외부 저장소 버전이 낮으면 반환
|
|
220
220
|
if (
|
|
221
221
|
semver.valid(currentVersionInfo.versionName) === null ||
|
|
222
222
|
semver.valid(latestVersion) === null
|
|
223
223
|
) {
|
|
224
224
|
// eslint-disable-next-line no-console
|
|
225
|
-
console.log("
|
|
225
|
+
console.log("유효하지 않은 semver 버전이므로 업데이트 확인을 건너뜁니다");
|
|
226
226
|
return;
|
|
227
227
|
}
|
|
228
228
|
if (!semver.gt(latestVersion, currentVersionInfo.versionName)) {
|
package/src/index.ts
CHANGED
|
@@ -3,17 +3,17 @@ import type { ApkInstallerPlugin, VersionInfo } from "../ApkInstallerPlugin";
|
|
|
3
3
|
|
|
4
4
|
export class ApkInstallerWeb extends WebPlugin implements ApkInstallerPlugin {
|
|
5
5
|
install(_options: { uri: string }): Promise<void> {
|
|
6
|
-
alert("[ApkInstaller]
|
|
6
|
+
alert("[ApkInstaller] 웹 환경에서는 APK 설치를 지원하지 않습니다.");
|
|
7
7
|
return Promise.resolve();
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
checkPermissions(): Promise<{ granted: boolean; manifest: boolean }> {
|
|
11
|
-
//
|
|
11
|
+
// 웹에서는 권한 확인 생략
|
|
12
12
|
return Promise.resolve({ granted: true, manifest: true });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
async requestPermissions(): Promise<void> {
|
|
16
|
-
//
|
|
16
|
+
// 웹에서는 동작 없음
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
getVersionInfo(): Promise<VersionInfo> {
|
package/README.md
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# @simplysm/capacitor-plugin-auto-update
|
|
2
|
-
|
|
3
|
-
Simplysm Package - Capacitor Auto Update Plugin. Provides APK installation and OTA auto-update functionality for Android Capacitor apps.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/capacitor-plugin-auto-update
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## API Overview
|
|
12
|
-
|
|
13
|
-
### APK Installer
|
|
14
|
-
|
|
15
|
-
| API | Type | Description |
|
|
16
|
-
|-----|------|-------------|
|
|
17
|
-
| `ApkInstaller` | class | APK installation plugin (static methods) |
|
|
18
|
-
| `ApkInstallerPlugin` | interface | Low-level Capacitor plugin interface for APK installation |
|
|
19
|
-
| `VersionInfo` | interface | App version information |
|
|
20
|
-
|
|
21
|
-
### Auto Update
|
|
22
|
-
|
|
23
|
-
| API | Type | Description |
|
|
24
|
-
|-----|------|-------------|
|
|
25
|
-
| `AutoUpdate` | class | OTA auto-update manager (static methods) |
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
### `VersionInfo`
|
|
30
|
-
|
|
31
|
-
| Field | Type | Description |
|
|
32
|
-
|-------|------|-------------|
|
|
33
|
-
| `versionName` | `string` | App version name (e.g., `"1.0.0"`) |
|
|
34
|
-
| `versionCode` | `string` | App version code |
|
|
35
|
-
|
|
36
|
-
### `ApkInstallerPlugin`
|
|
37
|
-
|
|
38
|
-
| Method | Signature | Description |
|
|
39
|
-
|--------|-----------|-------------|
|
|
40
|
-
| `install` | `(options: { uri: string }) => Promise<void>` | Install APK from URI |
|
|
41
|
-
| `checkPermissions` | `() => Promise<{ granted: boolean; manifest: boolean }>` | Check install permissions |
|
|
42
|
-
| `requestPermissions` | `() => Promise<void>` | Request install permissions |
|
|
43
|
-
| `getVersionInfo` | `() => Promise<VersionInfo>` | Get app version info |
|
|
44
|
-
|
|
45
|
-
### `ApkInstaller`
|
|
46
|
-
|
|
47
|
-
Abstract class with static methods. Android executes APK install intent; browser shows alert and returns normally.
|
|
48
|
-
|
|
49
|
-
| Method | Signature | Description |
|
|
50
|
-
|--------|-----------|-------------|
|
|
51
|
-
| `checkPermissions` | `() => Promise<{ granted: boolean; manifest: boolean }>` | Check install permission (granted + manifest declared) |
|
|
52
|
-
| `requestPermissions` | `() => Promise<void>` | Request REQUEST_INSTALL_PACKAGES permission (navigates to settings) |
|
|
53
|
-
| `install` | `(apkUri: string) => Promise<void>` | Install APK from a `content://` URI (FileProvider URI) |
|
|
54
|
-
| `getVersionInfo` | `() => Promise<VersionInfo>` | Get app version info |
|
|
55
|
-
|
|
56
|
-
### `AutoUpdate`
|
|
57
|
-
|
|
58
|
-
Abstract class with static methods for OTA update management.
|
|
59
|
-
|
|
60
|
-
| Method | Signature | Description |
|
|
61
|
-
|--------|-----------|-------------|
|
|
62
|
-
| `run` | `(opt: { log: (messageHtml: string) => void; serviceClient: ServiceClient }) => Promise<void>` | Run auto-update via server (checks version, downloads APK, installs) |
|
|
63
|
-
| `runByExternalStorage` | `(opt: { log: (messageHtml: string) => void; dirPath: string }) => Promise<void>` | Run auto-update from external storage directory |
|
|
64
|
-
|
|
65
|
-
## Usage Examples
|
|
66
|
-
|
|
67
|
-
### Check and install APK
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { ApkInstaller } from "@simplysm/capacitor-plugin-auto-update";
|
|
71
|
-
|
|
72
|
-
// Check permissions
|
|
73
|
-
const perms = await ApkInstaller.checkPermissions();
|
|
74
|
-
if (!perms.granted) {
|
|
75
|
-
await ApkInstaller.requestPermissions();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Install APK
|
|
79
|
-
await ApkInstaller.install("content://com.example.fileprovider/apk/update.apk");
|
|
80
|
-
|
|
81
|
-
// Get version info
|
|
82
|
-
const version = await ApkInstaller.getVersionInfo();
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Run OTA auto-update
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
import { AutoUpdate } from "@simplysm/capacitor-plugin-auto-update";
|
|
89
|
-
|
|
90
|
-
await AutoUpdate.run({
|
|
91
|
-
log: (messageHtml) => { /* display status */ },
|
|
92
|
-
serviceClient: myServiceClient,
|
|
93
|
-
});
|
|
94
|
-
```
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
package kr.co.simplysm.capacitor.apkinstaller;
|
|
2
|
-
|
|
3
|
-
import android.content.Context;
|
|
4
|
-
import android.content.Intent;
|
|
5
|
-
import android.content.pm.PackageInfo;
|
|
6
|
-
import android.content.pm.PackageManager;
|
|
7
|
-
import android.net.Uri;
|
|
8
|
-
import android.os.Build;
|
|
9
|
-
import android.provider.Settings;
|
|
10
|
-
import android.util.Log;
|
|
11
|
-
|
|
12
|
-
import com.getcapacitor.JSObject;
|
|
13
|
-
import com.getcapacitor.Plugin;
|
|
14
|
-
import com.getcapacitor.PluginCall;
|
|
15
|
-
import com.getcapacitor.PluginMethod;
|
|
16
|
-
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
17
|
-
|
|
18
|
-
@CapacitorPlugin(name = "ApkInstaller")
|
|
19
|
-
public class ApkInstallerPlugin extends Plugin {
|
|
20
|
-
|
|
21
|
-
private static final String TAG = "ApkInstallerPlugin";
|
|
22
|
-
|
|
23
|
-
@PluginMethod
|
|
24
|
-
public void install(PluginCall call) {
|
|
25
|
-
String uriStr = call.getString("uri");
|
|
26
|
-
if (uriStr == null) {
|
|
27
|
-
call.reject("uri is required");
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
Uri apkUri = Uri.parse(uriStr);
|
|
33
|
-
|
|
34
|
-
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
35
|
-
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
|
|
36
|
-
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
37
|
-
|
|
38
|
-
getContext().startActivity(intent);
|
|
39
|
-
call.resolve();
|
|
40
|
-
} catch (Exception e) {
|
|
41
|
-
Log.e(TAG, "install failed", e);
|
|
42
|
-
call.reject("Install failed: " + e.getMessage());
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@PluginMethod
|
|
47
|
-
public void checkPermissions(PluginCall call) {
|
|
48
|
-
// Check granted
|
|
49
|
-
boolean granted;
|
|
50
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
51
|
-
granted = getContext().getPackageManager().canRequestPackageInstalls();
|
|
52
|
-
} else {
|
|
53
|
-
granted = true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Check manifest
|
|
57
|
-
boolean manifest = false;
|
|
58
|
-
try {
|
|
59
|
-
Context context = getContext();
|
|
60
|
-
String targetPermission = "android.permission.REQUEST_INSTALL_PACKAGES";
|
|
61
|
-
String[] requestedPermissions = context.getPackageManager()
|
|
62
|
-
.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS)
|
|
63
|
-
.requestedPermissions;
|
|
64
|
-
if (requestedPermissions != null) {
|
|
65
|
-
for (String perm : requestedPermissions) {
|
|
66
|
-
if (targetPermission.equals(perm)) {
|
|
67
|
-
manifest = true;
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
} catch (Exception e) {
|
|
73
|
-
Log.e(TAG, "checkPermissions manifest check failed", e);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
JSObject ret = new JSObject();
|
|
77
|
-
ret.put("granted", granted);
|
|
78
|
-
ret.put("manifest", manifest);
|
|
79
|
-
call.resolve(ret);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@PluginMethod
|
|
83
|
-
public void requestPermissions(PluginCall call) {
|
|
84
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
85
|
-
Context context = getContext();
|
|
86
|
-
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
|
|
87
|
-
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
|
88
|
-
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
89
|
-
context.startActivity(intent);
|
|
90
|
-
}
|
|
91
|
-
call.resolve();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@PluginMethod
|
|
95
|
-
public void getVersionInfo(PluginCall call) {
|
|
96
|
-
try {
|
|
97
|
-
Context context = getContext();
|
|
98
|
-
PackageManager pm = context.getPackageManager();
|
|
99
|
-
PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
|
|
100
|
-
|
|
101
|
-
String versionName = info.versionName;
|
|
102
|
-
long versionCode;
|
|
103
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
104
|
-
versionCode = info.getLongVersionCode();
|
|
105
|
-
} else {
|
|
106
|
-
versionCode = info.versionCode;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
JSObject ret = new JSObject();
|
|
110
|
-
ret.put("versionName", versionName);
|
|
111
|
-
ret.put("versionCode", String.valueOf(versionCode));
|
|
112
|
-
call.resolve(ret);
|
|
113
|
-
} catch (Exception e) {
|
|
114
|
-
Log.e(TAG, "getVersionInfo failed", e);
|
|
115
|
-
call.reject("getVersionInfo failed: " + e.getMessage());
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
package/dist/env.d.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=env.d.js.map
|