@simplysm/capacitor-plugin-auto-update 13.0.100 → 14.0.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @simplysm/capacitor-plugin-auto-update
2
2
 
3
- Simplysm Package - Capacitor Auto Update Plugin. Provides APK installation and OTA auto-update functionality for Android Capacitor apps.
3
+ Capacitor auto-update plugin for Android APK installation and OTA updates.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,85 +10,105 @@ npm install @simplysm/capacitor-plugin-auto-update
10
10
 
11
11
  ## API Overview
12
12
 
13
- ### APK Installer
13
+ ### APK Installation
14
14
 
15
15
  | API | Type | Description |
16
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 |
17
+ | `VersionInfo` | Interface | App version information |
18
+ | `ApkInstallerPlugin` | Interface | Native plugin interface for APK installation |
19
+ | `ApkInstaller` | Class | Static API for APK installation, permission management, and version info |
20
20
 
21
21
  ### Auto Update
22
22
 
23
23
  | API | Type | Description |
24
24
  |-----|------|-------------|
25
- | `AutoUpdate` | class | OTA auto-update manager (static methods) |
25
+ | `AutoUpdate` | Class | Static API for downloading and installing APK updates from a server or external storage |
26
26
 
27
- ---
27
+ ## Interfaces
28
28
 
29
- ### `VersionInfo`
29
+ ### VersionInfo
30
+
31
+ Holds application version information.
30
32
 
31
33
  | Field | Type | Description |
32
34
  |-------|------|-------------|
33
- | `versionName` | `string` | App version name (e.g., `"1.0.0"`) |
34
- | `versionCode` | `string` | App version code |
35
+ | `versionName` | `string` | Human-readable version name (e.g. `"1.2.3"`) |
36
+ | `versionCode` | `string` | Numeric version code used by the Android system |
37
+
38
+ ### ApkInstallerPlugin
35
39
 
36
- ### `ApkInstallerPlugin`
40
+ Native plugin interface for APK installation.
37
41
 
38
42
  | Method | Signature | Description |
39
43
  |--------|-----------|-------------|
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
+ | `install` | `(options: { uri: string }) => Promise<void>` | Install APK from the given content URI |
45
+ | `checkPermissions` | `() => Promise<{ granted: boolean; manifest: boolean }>` | Check whether install permissions are granted |
46
+ | `requestPermissions` | `() => Promise<void>` | Request the `REQUEST_INSTALL_PACKAGES` permission |
47
+ | `getVersionInfo` | `() => Promise<VersionInfo>` | Retrieve current app version info |
48
+
49
+ ## Classes
44
50
 
45
- ### `ApkInstaller`
51
+ ### ApkInstaller
46
52
 
47
- Abstract class with static methods. Android executes APK install intent; browser shows alert and returns normally.
53
+ APK installation plugin. On Android it runs the APK install intent and manages the `REQUEST_INSTALL_PACKAGES` permission. On the browser it shows a notification and returns normally.
54
+
55
+ All methods are static.
48
56
 
49
57
  | Method | Signature | Description |
50
58
  |--------|-----------|-------------|
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 |
59
+ | `checkPermissions` | `static async checkPermissions(): Promise<{ granted: boolean; manifest: boolean }>` | Check whether install permissions are currently granted |
60
+ | `requestPermissions` | `static async requestPermissions(): Promise<void>` | Request the `REQUEST_INSTALL_PACKAGES` permission from the user |
61
+ | `install` | `static async install(apkUri: string): Promise<void>` | Install an APK from a `content://` URI |
62
+ | `getVersionInfo` | `static async getVersionInfo(): Promise<VersionInfo>` | Get the current app version name and version code |
63
+
64
+ ### AutoUpdate
55
65
 
56
- ### `AutoUpdate`
66
+ Handles the full update flow: download an APK and install it.
57
67
 
58
- Abstract class with static methods for OTA update management.
68
+ All methods are static.
59
69
 
60
70
  | Method | Signature | Description |
61
71
  |--------|-----------|-------------|
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 |
72
+ | `run` | `static async run(opt: { log: (messageHtml: string) => void; serviceClient: ServiceClient }): Promise<void>` | Download the latest APK from a server via `ServiceClient` and install it. Progress is reported through the `log` callback as HTML strings. |
73
+ | `runByExternalStorage` | `static async runByExternalStorage(opt: { log: (messageHtml: string) => void; dirPath: string }): Promise<void>` | Find the latest APK file from an external storage directory and install it. Progress is reported through the `log` callback. |
64
74
 
65
75
  ## Usage Examples
66
76
 
67
- ### Check and install APK
77
+ ### Check permissions and install an APK
68
78
 
69
- ```typescript
79
+ ```ts
70
80
  import { ApkInstaller } from "@simplysm/capacitor-plugin-auto-update";
71
81
 
72
- // Check permissions
73
82
  const perms = await ApkInstaller.checkPermissions();
74
83
  if (!perms.granted) {
75
84
  await ApkInstaller.requestPermissions();
76
85
  }
77
86
 
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();
87
+ await ApkInstaller.install("content://com.example.provider/apk/update.apk");
83
88
  ```
84
89
 
85
- ### Run OTA auto-update
90
+ ### Auto-update from a server
86
91
 
87
- ```typescript
92
+ ```ts
88
93
  import { AutoUpdate } from "@simplysm/capacitor-plugin-auto-update";
89
94
 
90
95
  await AutoUpdate.run({
91
- log: (messageHtml) => { /* display status */ },
96
+ log: (messageHtml) => {
97
+ document.getElementById("status")!.innerHTML = messageHtml;
98
+ },
92
99
  serviceClient: myServiceClient,
93
100
  });
94
101
  ```
102
+
103
+ ### Auto-update from external storage
104
+
105
+ ```ts
106
+ import { AutoUpdate } from "@simplysm/capacitor-plugin-auto-update";
107
+
108
+ await AutoUpdate.runByExternalStorage({
109
+ log: (messageHtml) => {
110
+ document.getElementById("status")!.innerHTML = messageHtml;
111
+ },
112
+ dirPath: "/storage/emulated/0/Download/updates",
113
+ });
114
+ ```
@@ -1,4 +1,5 @@
1
1
  apply plugin: 'com.android.library'
2
+ apply plugin: 'kotlin-android'
2
3
 
3
4
  android {
4
5
  namespace "kr.co.simplysm.capacitor.apkinstaller"
@@ -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
+ }
@@ -1,28 +1,28 @@
1
1
  import type { VersionInfo } from "./ApkInstallerPlugin";
2
2
  /**
3
- * APK installation plugin
4
- * - Android: Executes APK install intent, manages REQUEST_INSTALL_PACKAGES permission
5
- * - Browser: Shows alert message and returns normally
3
+ * APK 설치 플러그인
4
+ * - Android: APK 설치 인텐트를 실행하고, REQUEST_INSTALL_PACKAGES 권한을 관리
5
+ * - Browser: 알림 메시지를 표시하고 정상 반환
6
6
  */
7
7
  export declare abstract class ApkInstaller {
8
8
  /**
9
- * Check permissions (install permission granted + manifest declared)
9
+ * 권한 확인 (설치 권한 승인 여부 + manifest 선언 여부)
10
10
  */
11
11
  static checkPermissions(): Promise<{
12
12
  granted: boolean;
13
13
  manifest: boolean;
14
14
  }>;
15
15
  /**
16
- * Request REQUEST_INSTALL_PACKAGES permission (navigates to settings)
16
+ * REQUEST_INSTALL_PACKAGES 권한 요청 (설정 화면으로 이동)
17
17
  */
18
18
  static requestPermissions(): Promise<void>;
19
19
  /**
20
- * Install APK
20
+ * APK 설치
21
21
  * @param apkUri content:// URI (FileProvider URI)
22
22
  */
23
23
  static install(apkUri: string): Promise<void>;
24
24
  /**
25
- * Get app version info
25
+ * 버전 정보 조회
26
26
  */
27
27
  static getVersionInfo(): Promise<VersionInfo>;
28
28
  }
@@ -1,38 +1,40 @@
1
1
  import { registerPlugin } from "@capacitor/core";
2
2
  const apkInstallerPlugin = registerPlugin("ApkInstaller", {
3
- web: async () => {
4
- const { ApkInstallerWeb } = await import("./web/ApkInstallerWeb");
5
- return new ApkInstallerWeb();
6
- }
3
+ web: async () => {
4
+ const { ApkInstallerWeb } = await import("./web/ApkInstallerWeb.js");
5
+ return new ApkInstallerWeb();
6
+ },
7
7
  });
8
- class ApkInstaller {
9
- /**
10
- * Check permissions (install permission granted + manifest declared)
11
- */
12
- static async checkPermissions() {
13
- return apkInstallerPlugin.checkPermissions();
14
- }
15
- /**
16
- * Request REQUEST_INSTALL_PACKAGES permission (navigates to settings)
17
- */
18
- static async requestPermissions() {
19
- await apkInstallerPlugin.requestPermissions();
20
- }
21
- /**
22
- * Install APK
23
- * @param apkUri content:// URI (FileProvider URI)
24
- */
25
- static async install(apkUri) {
26
- await apkInstallerPlugin.install({ uri: apkUri });
27
- }
28
- /**
29
- * Get app version info
30
- */
31
- static async getVersionInfo() {
32
- return apkInstallerPlugin.getVersionInfo();
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
- export {
36
- ApkInstaller
37
- };
38
- //# sourceMappingURL=ApkInstaller.js.map
40
+ //# sourceMappingURL=ApkInstaller.js.map
@@ -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
- //# sourceMappingURL=ApkInstallerPlugin.js.map
1
+ export {};
2
+ //# sourceMappingURL=ApkInstallerPlugin.js.map
@@ -1,6 +1 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "mappings": "",
5
- "names": []
6
- }
1
+ {"version":3,"file":"ApkInstallerPlugin.js","sourceRoot":"","sources":["..\\src\\ApkInstallerPlugin.ts"],"names":[],"mappings":""}
@@ -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
- static _BUTTON_CSS = `
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
- static _BUTTON_ACTIVE_CSS = `
19
+ static _BUTTON_ACTIVE_CSS = `
20
20
  background: lightgrey;
21
21
  `;
22
- static _throwAboutReinstall(code, targetHref) {
23
- const downloadHtml = targetHref != null ? html`
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} }
@@ -29,157 +30,162 @@ class AutoUpdate {
29
30
  class="_button"
30
31
  href="intent://${targetHref.replace(/^https?:\/\//, "")}#Intent;scheme=http;end"
31
32
  >
32
- Download
33
+ 다운로드
33
34
  </a>
34
- ` : "";
35
- throw new Error(html`
36
- You need to re-download and install the APK file(${code}). ${downloadHtml}
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
- let granted;
44
- try {
45
- const result = await ApkInstaller.checkPermissions();
46
- if (!result.manifest) {
47
- this._throwAboutReinstall(1, targetHref);
48
- }
49
- granted = result.granted;
50
- } catch (err) {
51
- console.error("[AutoUpdate] checkPermissions manifest check failed:", err);
52
- this._throwAboutReinstall(2, targetHref);
53
- return;
54
- }
55
- if (!granted) {
56
- log(html`
57
- Installation permission must be enabled.
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()">Retry</button>
66
+ <button onclick="location.reload()">재시도</button>
63
67
  `);
64
- await ApkInstaller.requestPermissions();
65
- await wait.until(
66
- async () => {
67
- const result = await ApkInstaller.checkPermissions();
68
- return result.granted;
69
- },
70
- 1e3,
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
- static async _installApk(log, apkFilePath) {
76
- log(html`
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()">Retry</button>
83
+ <button onclick="location.reload()">재시도</button>
83
84
  `);
84
- const apkFileUri = await FileSystem.getUri(apkFilePath);
85
- await ApkInstaller.install(apkFileUri);
86
- }
87
- static _getErrorMessage(err) {
88
- return html`
89
- Error occurred during update:
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
- static async _freezeApp() {
95
- await new Promise(() => {
96
- });
97
- }
98
- static async run(opt) {
99
- try {
100
- opt.log(`Checking latest version...`);
101
- const autoUpdateServiceClient = opt.serviceClient.getService("AutoUpdateService");
102
- const serverVersionInfo = await autoUpdateServiceClient.getLastVersion("android");
103
- if (!serverVersionInfo) {
104
- console.log("Failed to get latest version information from server.");
105
- return;
106
- }
107
- opt.log(`Checking permission...`);
108
- await this._checkPermission(
109
- opt.log,
110
- opt.serviceClient.hostUrl + serverVersionInfo.downloadPath
111
- );
112
- const currentVersionInfo = await ApkInstaller.getVersionInfo();
113
- if (semver.valid(currentVersionInfo.versionName) === null || semver.valid(serverVersionInfo.version) === null) {
114
- console.log("Invalid semver version, skipping update check");
115
- return;
116
- }
117
- if (!semver.gt(serverVersionInfo.version, currentVersionInfo.versionName)) {
118
- return;
119
- }
120
- opt.log(`Downloading latest version file...`);
121
- const buffer = await fetchUrlBytes(
122
- opt.serviceClient.hostUrl + serverVersionInfo.downloadPath,
123
- {
124
- onProgress: (progress) => {
125
- const progressText = (progress.receivedLength * 100 / progress.contentLength).toFixed(
126
- 2
127
- );
128
- opt.log(`Downloading latest version file...(${progressText}%)`);
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
- static async runByExternalStorage(opt) {
143
- try {
144
- opt.log(`Checking permission...`);
145
- await this._checkPermission(opt.log);
146
- opt.log(`Checking latest version...`);
147
- const externalPath = await FileSystem.getStoragePath("external");
148
- const fileInfos = await FileSystem.readdir(path.join(externalPath, opt.dirPath));
149
- const versions = fileInfos.filter((fileInfo) => !fileInfo.isDirectory).map((fileInfo) => ({
150
- fileName: fileInfo.name,
151
- version: path.basename(fileInfo.name, path.extname(fileInfo.name)),
152
- extName: path.extname(fileInfo.name)
153
- })).filter((item) => {
154
- return item.extName === ".apk" && /^[0-9.]*$/.test(item.version);
155
- });
156
- if (versions.length === 0) return;
157
- const latestVersion = semver.maxSatisfying(
158
- versions.map((item) => item.version),
159
- "*"
160
- );
161
- if (latestVersion == null) {
162
- console.log("No valid semver version files found.");
163
- return;
164
- }
165
- const currentVersionInfo = await ApkInstaller.getVersionInfo();
166
- if (semver.valid(currentVersionInfo.versionName) === null || semver.valid(latestVersion) === null) {
167
- console.log("Invalid semver version, skipping update check");
168
- return;
169
- }
170
- if (!semver.gt(latestVersion, currentVersionInfo.versionName)) {
171
- return;
172
- }
173
- const apkFilePath = path.join(externalPath, opt.dirPath, latestVersion + ".apk");
174
- await this._installApk(opt.log, apkFilePath);
175
- await this._freezeApp();
176
- } catch (err) {
177
- opt.log(this._getErrorMessage(err));
178
- await this._freezeApp();
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
- export {
183
- AutoUpdate
184
- };
185
- //# sourceMappingURL=AutoUpdate.js.map
191
+ //# sourceMappingURL=AutoUpdate.js.map
@@ -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
@@ -1,4 +1,6 @@
1
+ // APK 설치
1
2
  export * from "./ApkInstaller.js";
2
3
  export * from "./ApkInstallerPlugin.js";
4
+ // 자동 업데이트
3
5
  export * from "./AutoUpdate.js";
4
- //# sourceMappingURL=index.js.map
6
+ //# sourceMappingURL=index.js.map
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
- install(_options) {
4
- alert("[ApkInstaller] APK installation is not supported in web environment.");
5
- return Promise.resolve();
6
- }
7
- checkPermissions() {
8
- return Promise.resolve({ granted: true, manifest: true });
9
- }
10
- async requestPermissions() {
11
- }
12
- getVersionInfo() {
13
- return Promise.resolve({
14
- versionName: import.meta.env.__VER__ ?? "0.0.0",
15
- versionCode: "0"
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
- export {
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": "13.0.100",
4
- "description": "Simplysm Package - Capacitor Auto Update Plugin",
5
- "author": "simplysm",
6
- "license": "MIT",
3
+ "version": "14.0.4",
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/capacitor-plugin-file-system": "13.0.100",
23
- "@simplysm/service-client": "13.0.100",
24
- "@simplysm/core-browser": "13.0.100",
25
- "@simplysm/core-common": "13.0.100",
26
- "@simplysm/service-common": "13.0.100"
22
+ "@simplysm/capacitor-plugin-file-system": "14.0.4",
23
+ "@simplysm/core-browser": "14.0.4",
24
+ "@simplysm/service-client": "14.0.4",
25
+ "@simplysm/core-common": "14.0.4",
26
+ "@simplysm/service-common": "14.0.4"
27
27
  },
28
28
  "devDependencies": {
29
- "@capacitor/core": "^7.6.0",
29
+ "@capacitor/core": "^7.6.1",
30
30
  "@types/semver": "^7.7.1"
31
31
  },
32
32
  "peerDependencies": {
33
- "@capacitor/core": "^7.4.4"
33
+ "@capacitor/core": "^7"
34
34
  },
35
35
  "capacitor": {
36
36
  "android": {
@@ -9,27 +9,27 @@ const apkInstallerPlugin = registerPlugin<ApkInstallerPlugin>("ApkInstaller", {
9
9
  });
10
10
 
11
11
  /**
12
- * APK installation plugin
13
- * - Android: Executes APK install intent, manages REQUEST_INSTALL_PACKAGES permission
14
- * - Browser: Shows alert message and returns normally
12
+ * APK 설치 플러그인
13
+ * - Android: APK 설치 인텐트를 실행하고, REQUEST_INSTALL_PACKAGES 권한을 관리
14
+ * - Browser: 알림 메시지를 표시하고 정상 반환
15
15
  */
16
16
  export abstract class ApkInstaller {
17
17
  /**
18
- * Check permissions (install permission granted + manifest declared)
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
- * Request REQUEST_INSTALL_PACKAGES permission (navigates to settings)
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
- * Install APK
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
- * Get app version info
40
+ * 버전 정보 조회
41
41
  */
42
42
  static async getVersionInfo(): Promise<VersionInfo> {
43
43
  return apkInstallerPlugin.getVersionInfo();
package/src/AutoUpdate.ts CHANGED
@@ -36,19 +36,19 @@ export abstract class AutoUpdate {
36
36
  class="_button"
37
37
  href="intent://${targetHref.replace(/^https?:\/\//, "")}#Intent;scheme=http;end"
38
38
  >
39
- Download
39
+ 다운로드
40
40
  </a>
41
41
  `
42
42
  : "";
43
43
 
44
44
  throw new Error(html`
45
- You need to re-download and install the APK file(${code}). ${downloadHtml}
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("Only Android is supported.");
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 check failed:", err);
63
+ console.error("[AutoUpdate] checkPermissions manifest 확인 실패:", err);
64
64
  this._throwAboutReinstall(2, targetHref);
65
- return; // unreachable — _throwAboutReinstall always throws
65
+ return; // 도달 불가 — _throwAboutReinstall 항상 throw함
66
66
  }
67
67
 
68
68
  if (!granted) {
69
69
  log(html`
70
- Installation permission must be enabled.
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()">Retry</button>
75
+ <button onclick="location.reload()">재시도</button>
76
76
  `);
77
77
  await ApkInstaller.requestPermissions();
78
- // Wait up to 5 minutes (300 seconds) - time for user to grant permission in settings
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
- Please install the latest version and restart.
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()">Retry</button>
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
- Error occurred during update:
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(() => {}); // Wait indefinitely
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(`Checking latest version...`);
120
+ opt.log(`최신 버전 확인 중...`);
121
121
 
122
- // Get version and download link from server
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("Failed to get latest version information from server.");
129
+ console.log("서버에서 최신 버전 정보를 가져오지 못했습니다.");
130
130
  return;
131
131
  }
132
132
 
133
- opt.log(`Checking permission...`);
133
+ opt.log(`권한 확인 중...`);
134
134
  await this._checkPermission(
135
135
  opt.log,
136
136
  opt.serviceClient.hostUrl + serverVersionInfo.downloadPath,
137
137
  );
138
138
 
139
- // Get current app version
139
+ // 현재 버전 조회
140
140
  const currentVersionInfo = await ApkInstaller.getVersionInfo();
141
141
 
142
- // Return if already latest or server version is lower
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("Invalid semver version, skipping update check");
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(`Downloading latest version file...`);
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(`Downloading latest version file...(${progressText}%)`);
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(`Checking permission...`);
181
+ opt.log(`권한 확인 중...`);
182
182
  await this._checkPermission(opt.log);
183
183
 
184
- opt.log(`Checking latest version...`);
184
+ opt.log(`최신 버전 확인 중...`);
185
185
 
186
- // Get versions
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
- // Return if no version files are saved
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
- // Return if no valid semver versions
209
+ // 유효한 semver 버전이 없으면 반환
210
210
  if (latestVersion == null) {
211
211
  // eslint-disable-next-line no-console
212
- console.log("No valid semver version files found.");
212
+ console.log("유효한 semver 버전 파일을 찾을 수 없습니다.");
213
213
  return;
214
214
  }
215
215
 
216
- // Get current app version
216
+ // 현재 버전 조회
217
217
  const currentVersionInfo = await ApkInstaller.getVersionInfo();
218
218
 
219
- // Return if already latest or external storage version is lower
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("Invalid semver version, skipping update check");
225
+ console.log("유효하지 않은 semver 버전이므로 업데이트 확인을 건너뜁니다");
226
226
  return;
227
227
  }
228
228
  if (!semver.gt(latestVersion, currentVersionInfo.versionName)) {
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- // APK Installer
1
+ // APK 설치
2
2
  export * from "./ApkInstaller";
3
3
  export * from "./ApkInstallerPlugin";
4
4
 
5
- // Auto Update
5
+ // 자동 업데이트
6
6
  export * from "./AutoUpdate";
@@ -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] APK installation is not supported in web environment.");
6
+ alert("[ApkInstaller] 환경에서는 APK 설치를 지원하지 않습니다.");
7
7
  return Promise.resolve();
8
8
  }
9
9
 
10
10
  checkPermissions(): Promise<{ granted: boolean; manifest: boolean }> {
11
- // Skip permission check on web
11
+ // 웹에서는 권한 확인 생략
12
12
  return Promise.resolve({ granted: true, manifest: true });
13
13
  }
14
14
 
15
15
  async requestPermissions(): Promise<void> {
16
- // No-op on web
16
+ // 웹에서는 동작 없음
17
17
  }
18
18
 
19
19
  getVersionInfo(): Promise<VersionInfo> {
@@ -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
package/dist/env.d.js.map DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "mappings": "",
5
- "names": []
6
- }