@capawesome/capacitor-live-update 8.1.1 → 8.2.1-dev.70823ec8.1778138208
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/CapawesomeCapacitorLiveUpdate.podspec +15 -0
- package/Package.swift +21 -5
- package/README.md +147 -3
- package/android/build.gradle +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +104 -2
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateHttpClient.java +12 -1
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +39 -1
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/api/GetChannelsResponseItem.java +28 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/FetchChannelsOptions.java +38 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/FetchLatestBundleOptions.java +15 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/ChannelResult.java +28 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/FetchChannelsResult.java +28 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/FetchLatestBundleResult.java +30 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/providers/ionic/LiveUpdateIonicManager.java +232 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/providers/ionic/LiveUpdateIonicProvider.java +41 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/providers/ionic/LiveUpdateIonicProviderRegistration.java +46 -0
- package/dist/docs.json +151 -3
- package/dist/esm/definitions.d.ts +85 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +2 -1
- package/dist/esm/web.js +3 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +3 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Classes/Options/FetchChannelsOptions.swift +26 -0
- package/ios/Plugin/Classes/Options/FetchLatestBundleOptions.swift +12 -0
- package/ios/Plugin/Classes/Results/ChannelResult.swift +19 -0
- package/ios/Plugin/Classes/Results/FetchChannelsResult.swift +16 -0
- package/ios/Plugin/Classes/Results/FetchLatestBundleResult.swift +24 -0
- package/ios/Plugin/Enums/CustomError.swift +12 -0
- package/ios/Plugin/LiveUpdate.swift +55 -1
- package/ios/Plugin/LiveUpdateHttpClient.swift +11 -0
- package/ios/Plugin/LiveUpdatePlugin.swift +40 -1
- package/ios/Plugin/Protocols/Api/GetChannelsResponseItem.swift +4 -0
- package/ios/Plugin/Providers/Ionic/LiveUpdateIonicManager.swift +118 -0
- package/ios/Plugin/Providers/Ionic/LiveUpdateIonicProvider.swift +25 -0
- package/package.json +1 -3
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.classes.api;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import org.json.JSONObject;
|
|
5
|
+
|
|
6
|
+
public class GetChannelsResponseItem {
|
|
7
|
+
|
|
8
|
+
@NonNull
|
|
9
|
+
private final String id;
|
|
10
|
+
|
|
11
|
+
@NonNull
|
|
12
|
+
private final String name;
|
|
13
|
+
|
|
14
|
+
public GetChannelsResponseItem(@NonNull JSONObject responseJson) {
|
|
15
|
+
this.id = responseJson.optString("id");
|
|
16
|
+
this.name = responseJson.optString("name");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@NonNull
|
|
20
|
+
public String getId() {
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@NonNull
|
|
25
|
+
public String getName() {
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.classes.options;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.PluginCall;
|
|
6
|
+
|
|
7
|
+
public class FetchChannelsOptions {
|
|
8
|
+
|
|
9
|
+
@Nullable
|
|
10
|
+
private final Integer limit;
|
|
11
|
+
|
|
12
|
+
@Nullable
|
|
13
|
+
private final Integer offset;
|
|
14
|
+
|
|
15
|
+
@Nullable
|
|
16
|
+
private final String query;
|
|
17
|
+
|
|
18
|
+
public FetchChannelsOptions(@NonNull PluginCall call) {
|
|
19
|
+
this.limit = call.getInt("limit");
|
|
20
|
+
this.offset = call.getInt("offset");
|
|
21
|
+
this.query = call.getString("query");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Nullable
|
|
25
|
+
public Integer getLimit() {
|
|
26
|
+
return limit;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Nullable
|
|
30
|
+
public Integer getOffset() {
|
|
31
|
+
return offset;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Nullable
|
|
35
|
+
public String getQuery() {
|
|
36
|
+
return query;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -6,17 +6,32 @@ import com.getcapacitor.PluginCall;
|
|
|
6
6
|
|
|
7
7
|
public class FetchLatestBundleOptions {
|
|
8
8
|
|
|
9
|
+
@Nullable
|
|
10
|
+
private final String appId;
|
|
11
|
+
|
|
9
12
|
@Nullable
|
|
10
13
|
private final String channel;
|
|
11
14
|
|
|
12
15
|
public FetchLatestBundleOptions(@NonNull PluginCall call) {
|
|
16
|
+
this.appId = null;
|
|
13
17
|
this.channel = call.getString("channel", null);
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
public FetchLatestBundleOptions(@Nullable String channel) {
|
|
21
|
+
this.appId = null;
|
|
22
|
+
this.channel = channel;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public FetchLatestBundleOptions(@Nullable String appId, @Nullable String channel) {
|
|
26
|
+
this.appId = appId;
|
|
17
27
|
this.channel = channel;
|
|
18
28
|
}
|
|
19
29
|
|
|
30
|
+
@Nullable
|
|
31
|
+
public String getAppId() {
|
|
32
|
+
return appId;
|
|
33
|
+
}
|
|
34
|
+
|
|
20
35
|
@Nullable
|
|
21
36
|
public String getChannel() {
|
|
22
37
|
return channel;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
6
|
+
|
|
7
|
+
public class ChannelResult implements Result {
|
|
8
|
+
|
|
9
|
+
@NonNull
|
|
10
|
+
private final String id;
|
|
11
|
+
|
|
12
|
+
@NonNull
|
|
13
|
+
private final String name;
|
|
14
|
+
|
|
15
|
+
public ChannelResult(@NonNull String id, @NonNull String name) {
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.name = name;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@NonNull
|
|
21
|
+
@Override
|
|
22
|
+
public JSObject toJSObject() {
|
|
23
|
+
JSObject result = new JSObject();
|
|
24
|
+
result.put("id", id);
|
|
25
|
+
result.put("name", name);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.JSArray;
|
|
5
|
+
import com.getcapacitor.JSObject;
|
|
6
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
7
|
+
|
|
8
|
+
public class FetchChannelsResult implements Result {
|
|
9
|
+
|
|
10
|
+
@NonNull
|
|
11
|
+
private final ChannelResult[] channels;
|
|
12
|
+
|
|
13
|
+
public FetchChannelsResult(@NonNull ChannelResult[] channels) {
|
|
14
|
+
this.channels = channels;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@NonNull
|
|
18
|
+
@Override
|
|
19
|
+
public JSObject toJSObject() {
|
|
20
|
+
JSObject result = new JSObject();
|
|
21
|
+
JSArray channelsArray = new JSArray();
|
|
22
|
+
for (ChannelResult channel : channels) {
|
|
23
|
+
channelsArray.put(channel.toJSObject());
|
|
24
|
+
}
|
|
25
|
+
result.put("channels", channelsArray);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -43,6 +43,36 @@ public class FetchLatestBundleResult implements Result {
|
|
|
43
43
|
this.signature = signature;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
@Nullable
|
|
47
|
+
public ArtifactType getArtifactType() {
|
|
48
|
+
return artifactType;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Nullable
|
|
52
|
+
public String getBundleId() {
|
|
53
|
+
return bundleId;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Nullable
|
|
57
|
+
public String getChecksum() {
|
|
58
|
+
return checksum;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Nullable
|
|
62
|
+
public JSONObject getCustomProperties() {
|
|
63
|
+
return customProperties;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@Nullable
|
|
67
|
+
public String getDownloadUrl() {
|
|
68
|
+
return downloadUrl;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@Nullable
|
|
72
|
+
public String getSignature() {
|
|
73
|
+
return signature;
|
|
74
|
+
}
|
|
75
|
+
|
|
46
76
|
@NonNull
|
|
47
77
|
public JSObject toJSObject() {
|
|
48
78
|
JSObject result = new JSObject();
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.providers.ionic;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.content.SharedPreferences;
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
import com.getcapacitor.Logger;
|
|
8
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdate;
|
|
9
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdatePlugin;
|
|
10
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.DownloadBundleOptions;
|
|
11
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.FetchLatestBundleOptions;
|
|
12
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.FetchLatestBundleResult;
|
|
13
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.enums.ArtifactType;
|
|
14
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.EmptyCallback;
|
|
15
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.NonEmptyCallback;
|
|
16
|
+
import io.ionic.liveupdateprovider.FederatedCapacitorSyncResult;
|
|
17
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderError;
|
|
18
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderManager;
|
|
19
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderSyncCallback;
|
|
20
|
+
import java.io.File;
|
|
21
|
+
import java.util.HashMap;
|
|
22
|
+
import java.util.Iterator;
|
|
23
|
+
import java.util.Map;
|
|
24
|
+
import org.json.JSONObject;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Ionic Live Update Provider manager backed by the Capawesome live update plugin.
|
|
28
|
+
*
|
|
29
|
+
* Each manager instance is scoped by a {@code managerKey} so that multiple shells (Portals or
|
|
30
|
+
* Federated Capacitor apps) can persist their own active bundle without colliding with each
|
|
31
|
+
* other or with the standalone plugin's {@code currentBundleId} / {@code nextBundleId} state.
|
|
32
|
+
*
|
|
33
|
+
* Provider config keys (V1):
|
|
34
|
+
* <ul>
|
|
35
|
+
* <li>{@code managerKey} (required) — scopes per-manager persisted state</li>
|
|
36
|
+
* <li>{@code appId} (optional) — Capawesome Cloud app UUID; falls back to plugin config</li>
|
|
37
|
+
* <li>{@code channel} (optional) — channel to sync; falls back to plugin config</li>
|
|
38
|
+
* </ul>
|
|
39
|
+
*/
|
|
40
|
+
public class LiveUpdateIonicManager implements LiveUpdateProviderManager {
|
|
41
|
+
|
|
42
|
+
public static final String SHARED_PREFERENCES_NAME = "CapawesomeLiveUpdateIonicProvider";
|
|
43
|
+
public static final String PREF_PREFIX_LAST_SYNCED_BUNDLE_ID = "lastSyncedBundleId.";
|
|
44
|
+
|
|
45
|
+
@Nullable
|
|
46
|
+
private final String appId;
|
|
47
|
+
|
|
48
|
+
@Nullable
|
|
49
|
+
private final String channel;
|
|
50
|
+
|
|
51
|
+
@Nullable
|
|
52
|
+
private File latestAppDirectory;
|
|
53
|
+
|
|
54
|
+
@NonNull
|
|
55
|
+
private final LiveUpdate liveUpdate;
|
|
56
|
+
|
|
57
|
+
@NonNull
|
|
58
|
+
private final String managerKey;
|
|
59
|
+
|
|
60
|
+
@NonNull
|
|
61
|
+
private final SharedPreferences sharedPreferences;
|
|
62
|
+
|
|
63
|
+
public LiveUpdateIonicManager(@NonNull Context context, @NonNull Map<String, ?> config, @NonNull LiveUpdate liveUpdate)
|
|
64
|
+
throws LiveUpdateProviderError.InvalidConfiguration {
|
|
65
|
+
Object managerKeyValue = config.get("managerKey");
|
|
66
|
+
if (!(managerKeyValue instanceof String) || ((String) managerKeyValue).isEmpty()) {
|
|
67
|
+
throw new LiveUpdateProviderError.InvalidConfiguration(LiveUpdatePlugin.ERROR_MANAGER_KEY_MISSING, null);
|
|
68
|
+
}
|
|
69
|
+
this.managerKey = (String) managerKeyValue;
|
|
70
|
+
|
|
71
|
+
Object appIdValue = config.get("appId");
|
|
72
|
+
this.appId = appIdValue instanceof String ? (String) appIdValue : null;
|
|
73
|
+
|
|
74
|
+
Object channelValue = config.get("channel");
|
|
75
|
+
this.channel = channelValue instanceof String ? (String) channelValue : null;
|
|
76
|
+
|
|
77
|
+
this.liveUpdate = liveUpdate;
|
|
78
|
+
this.sharedPreferences = context.getApplicationContext().getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
79
|
+
|
|
80
|
+
// Restore the last synced bundle directory, if any.
|
|
81
|
+
String persistedBundleId = sharedPreferences.getString(getLastSyncedBundleIdKey(), null);
|
|
82
|
+
if (persistedBundleId != null) {
|
|
83
|
+
this.latestAppDirectory = liveUpdate.getBundleDirectory(persistedBundleId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Nullable
|
|
88
|
+
@Override
|
|
89
|
+
public File getLatestAppDirectory() {
|
|
90
|
+
return latestAppDirectory;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Override
|
|
94
|
+
public void sync(@Nullable LiveUpdateProviderSyncCallback callback) {
|
|
95
|
+
try {
|
|
96
|
+
FetchLatestBundleOptions fetchOptions = new FetchLatestBundleOptions(appId, channel);
|
|
97
|
+
liveUpdate.fetchLatestBundle(
|
|
98
|
+
fetchOptions,
|
|
99
|
+
new NonEmptyCallback<FetchLatestBundleResult>() {
|
|
100
|
+
@Override
|
|
101
|
+
public void success(@NonNull FetchLatestBundleResult result) {
|
|
102
|
+
handleFetchLatestBundleSuccess(result, callback);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@Override
|
|
106
|
+
public void error(@NonNull Exception exception) {
|
|
107
|
+
notifyFailure(callback, exception);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
} catch (Exception exception) {
|
|
112
|
+
notifyFailure(callback, exception);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void handleFetchLatestBundleSuccess(
|
|
117
|
+
@NonNull FetchLatestBundleResult result,
|
|
118
|
+
@Nullable LiveUpdateProviderSyncCallback callback
|
|
119
|
+
) {
|
|
120
|
+
try {
|
|
121
|
+
String bundleId = result.getBundleId();
|
|
122
|
+
if (bundleId == null) {
|
|
123
|
+
// No update available; report success without changing state.
|
|
124
|
+
notifySuccess(callback, null, null);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Bundle already on disk — just point latestAppDirectory at it and persist.
|
|
129
|
+
File existingDirectory = liveUpdate.getBundleDirectory(bundleId);
|
|
130
|
+
if (existingDirectory != null) {
|
|
131
|
+
applySyncedBundle(bundleId, existingDirectory);
|
|
132
|
+
notifySuccess(callback, bundleId, result.getCustomProperties());
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Otherwise, download and then apply.
|
|
137
|
+
String downloadUrl = result.getDownloadUrl();
|
|
138
|
+
if (downloadUrl == null || downloadUrl.isEmpty()) {
|
|
139
|
+
notifyFailure(callback, new Exception(LiveUpdatePlugin.ERROR_DOWNLOAD_URL_MISSING));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
ArtifactType artifactType = result.getArtifactType() == null ? ArtifactType.ZIP : result.getArtifactType();
|
|
143
|
+
String artifactTypeString = artifactType == ArtifactType.MANIFEST ? "manifest" : "zip";
|
|
144
|
+
DownloadBundleOptions downloadOptions = new DownloadBundleOptions(
|
|
145
|
+
artifactTypeString,
|
|
146
|
+
bundleId,
|
|
147
|
+
result.getChecksum(),
|
|
148
|
+
result.getSignature(),
|
|
149
|
+
downloadUrl
|
|
150
|
+
);
|
|
151
|
+
liveUpdate.downloadBundle(
|
|
152
|
+
downloadOptions,
|
|
153
|
+
new EmptyCallback() {
|
|
154
|
+
@Override
|
|
155
|
+
public void success() {
|
|
156
|
+
File downloadedDirectory = liveUpdate.getBundleDirectory(bundleId);
|
|
157
|
+
if (downloadedDirectory == null) {
|
|
158
|
+
notifyFailure(callback, new Exception(LiveUpdatePlugin.ERROR_BUNDLE_DIRECTORY_NOT_FOUND));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
applySyncedBundle(bundleId, downloadedDirectory);
|
|
162
|
+
notifySuccess(callback, bundleId, result.getCustomProperties());
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@Override
|
|
166
|
+
public void error(@NonNull Exception exception) {
|
|
167
|
+
notifyFailure(callback, exception);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
} catch (Exception exception) {
|
|
172
|
+
notifyFailure(callback, exception);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private void applySyncedBundle(@NonNull String bundleId, @NonNull File directory) {
|
|
177
|
+
latestAppDirectory = directory;
|
|
178
|
+
sharedPreferences.edit().putString(getLastSyncedBundleIdKey(), bundleId).apply();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private void notifySuccess(
|
|
182
|
+
@Nullable LiveUpdateProviderSyncCallback callback,
|
|
183
|
+
@Nullable String bundleId,
|
|
184
|
+
@Nullable JSONObject customProperties
|
|
185
|
+
) {
|
|
186
|
+
if (callback == null) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
Map<String, Object> metadata = new HashMap<>();
|
|
190
|
+
if (bundleId != null) {
|
|
191
|
+
metadata.put("bundleId", bundleId);
|
|
192
|
+
}
|
|
193
|
+
if (channel != null) {
|
|
194
|
+
metadata.put("channel", channel);
|
|
195
|
+
}
|
|
196
|
+
if (customProperties != null) {
|
|
197
|
+
Map<String, Object> customPropertiesMap = jsonObjectToMap(customProperties);
|
|
198
|
+
if (!customPropertiesMap.isEmpty()) {
|
|
199
|
+
metadata.put("customProperties", customPropertiesMap);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
callback.onSuccess(new FederatedCapacitorSyncResult(metadata));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private void notifyFailure(@Nullable LiveUpdateProviderSyncCallback callback, @NonNull Exception exception) {
|
|
206
|
+
Logger.error(LiveUpdatePlugin.TAG, "Ionic provider sync failed: " + exception.getMessage(), exception);
|
|
207
|
+
if (callback == null) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
String message = exception.getMessage() == null ? LiveUpdatePlugin.ERROR_UNKNOWN_ERROR : exception.getMessage();
|
|
211
|
+
callback.onFailure(new LiveUpdateProviderError.SyncFailed(message, exception));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@NonNull
|
|
215
|
+
private String getLastSyncedBundleIdKey() {
|
|
216
|
+
return PREF_PREFIX_LAST_SYNCED_BUNDLE_ID + managerKey;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@NonNull
|
|
220
|
+
private static Map<String, Object> jsonObjectToMap(@NonNull JSONObject jsonObject) {
|
|
221
|
+
Map<String, Object> map = new HashMap<>();
|
|
222
|
+
Iterator<String> keys = jsonObject.keys();
|
|
223
|
+
while (keys.hasNext()) {
|
|
224
|
+
String key = keys.next();
|
|
225
|
+
Object value = jsonObject.opt(key);
|
|
226
|
+
if (value != null && value != JSONObject.NULL) {
|
|
227
|
+
map.put(key, value);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return map;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.providers.ionic;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import androidx.annotation.NonNull;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdate;
|
|
6
|
+
import io.ionic.liveupdateprovider.LiveUpdateProvider;
|
|
7
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderError;
|
|
8
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderManager;
|
|
9
|
+
import java.util.Map;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Ionic Live Update Provider implementation backed by the Capawesome live update plugin.
|
|
13
|
+
*
|
|
14
|
+
* Registered with {@link io.ionic.liveupdateprovider.LiveUpdateProviderRegistry} when the
|
|
15
|
+
* Capacitor plugin loads, so Federated Capacitor can resolve provider id {@code "capawesome"}
|
|
16
|
+
* and create managers from the per-shell configuration.
|
|
17
|
+
*/
|
|
18
|
+
public class LiveUpdateIonicProvider implements LiveUpdateProvider {
|
|
19
|
+
|
|
20
|
+
public static final String ID = "capawesome";
|
|
21
|
+
|
|
22
|
+
@NonNull
|
|
23
|
+
private final LiveUpdate liveUpdate;
|
|
24
|
+
|
|
25
|
+
public LiveUpdateIonicProvider(@NonNull LiveUpdate liveUpdate) {
|
|
26
|
+
this.liveUpdate = liveUpdate;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@NonNull
|
|
30
|
+
@Override
|
|
31
|
+
public String getId() {
|
|
32
|
+
return ID;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@NonNull
|
|
36
|
+
@Override
|
|
37
|
+
public LiveUpdateProviderManager createManager(@NonNull Context context, @NonNull Map<String, ?> config)
|
|
38
|
+
throws LiveUpdateProviderError.InvalidConfiguration {
|
|
39
|
+
return new LiveUpdateIonicManager(context, config, liveUpdate);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.liveupdate.providers.ionic;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.getcapacitor.Logger;
|
|
5
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdate;
|
|
6
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.LiveUpdatePlugin;
|
|
7
|
+
import io.ionic.liveupdateprovider.LiveUpdateProviderRegistry;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper that registers the Capawesome live update provider with the Ionic
|
|
11
|
+
* {@link LiveUpdateProviderRegistry}, but only when the optional
|
|
12
|
+
* {@code io.ionic:liveupdateprovider} dependency is present at runtime.
|
|
13
|
+
*
|
|
14
|
+
* The Gradle build wires the SDK as either {@code implementation} (when the consumer opts in
|
|
15
|
+
* via {@code capawesomeCapacitorLiveUpdateIncludeIonicProvider = true}) or {@code compileOnly}
|
|
16
|
+
* (the default). When opted out, the SDK classes are stripped from the consumer APK and the
|
|
17
|
+
* reflection check below short-circuits registration.
|
|
18
|
+
*/
|
|
19
|
+
public final class LiveUpdateIonicProviderRegistration {
|
|
20
|
+
|
|
21
|
+
private LiveUpdateIonicProviderRegistration() {
|
|
22
|
+
// Static utility — no instances.
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static boolean isAvailable() {
|
|
26
|
+
try {
|
|
27
|
+
Class.forName("io.ionic.liveupdateprovider.LiveUpdateProviderRegistry");
|
|
28
|
+
return true;
|
|
29
|
+
} catch (ClassNotFoundException exception) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static void tryRegister(@NonNull LiveUpdate liveUpdate) {
|
|
35
|
+
try {
|
|
36
|
+
if (LiveUpdateProviderRegistry.resolve(LiveUpdateIonicProvider.ID) != null) {
|
|
37
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Ionic provider '" + LiveUpdateIonicProvider.ID + "' already registered.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
LiveUpdateProviderRegistry.register(new LiveUpdateIonicProvider(liveUpdate));
|
|
41
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Registered Ionic provider '" + LiveUpdateIonicProvider.ID + "'.");
|
|
42
|
+
} catch (Exception exception) {
|
|
43
|
+
Logger.error(LiveUpdatePlugin.TAG, "Failed to register Ionic provider: " + exception.getMessage(), exception);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|