cordova-plugin-in-app-updates 1.0.5

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/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 andreszs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+
2
+ ![License](https://img.shields.io/badge/license-MIT-orange.svg) ![Platform](https://img.shields.io/badge/platform-android-green.svg) [![Donate](https://img.shields.io/badge/donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G33QACCVKYD7U)
3
+
4
+ # cordova-plugin-in-app-update
5
+
6
+ Cordova Android plugin for checking for updates and auto updating app with Google Play Store In-App updates API.
7
+
8
+ # Platforms
9
+
10
+ - Android
11
+ - Browser
12
+
13
+ # Features
14
+
15
+ - AndroidX ready (plugin version 2.0.x)
16
+ - Checks for updates
17
+ - Install flexible updates
18
+ - Install immediate updates
19
+ - Customize snackbar message and button for Flexible updates
20
+ - Customize snackbar button color for Flexible updates
21
+
22
+ # Installation
23
+
24
+ ## Version Requirements
25
+
26
+ | Plugin version | Cordova CLI | Cordova Android | AndroidX support |
27
+ | --- | --- | --- | --- |
28
+ | 1.0.5| 9.0.0 | 8.0.0 | No |
29
+ | 2.0.5 | 10.0.0 | 9.0.0 | Yes |
30
+
31
+ ## Install latest version via CLI
32
+
33
+ ```bash
34
+ cordova plugin add cordova-plugin-in-app-updates
35
+ ```
36
+
37
+ # Methods
38
+
39
+ ## getUpdateAvailability
40
+
41
+ Invokes the AppUpdateManager and return one of the [updateAvailability](https://developer.android.com/reference/com/google/android/play/core/install/model/UpdateAvailability.html) codes as string.
42
+
43
+ ### Return values
44
+
45
+ - **UPDATE_AVAILABLE**
46
+ - **UPDATE_NOT_AVAILABLE**
47
+ - **DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS**
48
+ - **UNKNOWN**
49
+
50
+ When this method returns **UPDATE_AVAILABLE**, your app is ready to use the following methods to prompt the user for update.
51
+
52
+ ### Example
53
+
54
+ ```javascript
55
+ var onSuccess = function (strSuccess) {
56
+ console.log(strSuccess);
57
+ };
58
+ var onFailure = function (strError) {
59
+ console.warn(strError);
60
+ };
61
+ cordova.plugins.InAppUpdate.getUpdateAvailability(onSuccess, onFailure);
62
+ ```
63
+
64
+ ## updateFlexible
65
+
66
+ Starts a [flexible update](https://developer.android.com/guide/playcore/in-app-updates/kotlin-java#flexible "flexible update") process and prompts the user with a dialog to download the new version now or when Wi-Fi is available.
67
+
68
+ :warning: The **successCallback** from this method can be triggered repeatedly according to its status.
69
+
70
+ ### Return values
71
+
72
+ - **UPDATE_NOT_AVAILABLE**: No updates available in Play Store.
73
+ - **DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS**: Either flexible or immadiate update is in progress.
74
+ - **UPDATE_PROMPT**: The user has been presented with the Play Store dialog to download or ignore the flexible update.
75
+ - **RESULT_OK**: User accepted to download flexible update.
76
+ - **RESULT_CANCELED**: User declined the flexible update dialog or update was aborted while in progress.
77
+ - **RESULT_IN_APP_UPDATE_FAILED**: Something went wrong with the update dialog response.
78
+ - **ACTIVITY_RESULT_UNKNOWN**: Unknown result code returned by the dialog.
79
+ - **DOWNLOADING**: An update is currently being downloaded in the background.
80
+ - **DOWNLOADED**: The update was downloaded and the snackbar with RESTART button has been shown.
81
+
82
+ ### Example
83
+
84
+ ```javascript
85
+ var onSuccess = function (strSuccess) {
86
+ console.log(strSuccess);
87
+ };
88
+ var onFailure = function (strError) {
89
+ console.warn(strError);
90
+ };
91
+ cordova.plugins.InAppUpdate.updateFlexible(onSuccess, onFailure);
92
+ ```
93
+
94
+ :warning: Make sure to call **getUpdateAvailability** as often as needed to ensure there are no **flexible** updates downloaded pending install, as they will consume storage space until installed.
95
+
96
+ ## updateImmediate
97
+
98
+ Starts an [immediate update](https://developer.android.com/guide/playcore/in-app-updates/kotlin-java#immediate "immediate update") process and prompts the user with a fullscreen dialog to download now or when Wi-Fi is available. The update is downloaded and installed in the foreground, preventing the user from interacting with your app until the installation succeeds and the app is automatically restarted.
99
+
100
+ :warning: The **successCallback** from this method can be triggered repeatedly according to its status.
101
+
102
+ ### Return values
103
+
104
+ - **UPDATE_NOT_AVAILABLE**: No updates available in Play Store.
105
+ - **DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS**: Either flexible or immadiate update is in progress.
106
+ - **RESULT_OK**: User accepted to download immediate update.
107
+ - **RESULT_CANCELED**: User declined the immediate update dialog.
108
+ - **RESULT_IN_APP_UPDATE_FAILED**: Something went wrong with the update dialog response.
109
+ - **ACTIVITY_RESULT_UNKNOWN**: Unknown result code returned by the dialog.
110
+ - **DOWNLOADING**: An update is currently being downloaded in the foreground.
111
+ - **DOWNLOADED**: The update was downloaded and will be installed immediately.
112
+
113
+ ### Example
114
+
115
+ ```javascript
116
+ var onSuccess = function (strSuccess) {
117
+ console.log(strSuccess);
118
+ };
119
+ var onFailure = function (strError) {
120
+ console.warn(strError);
121
+ };
122
+ cordova.plugins.InAppUpdate.updateImmediate(onSuccess, onFailure);
123
+ ```
124
+
125
+ ## setSnackbarOptions
126
+
127
+ Sets the label and the button text for the snackbar shown after downloading a flexible update. You are free to call this method at any time. You can also call it again to show different snackbar messages after the snackbar was shown.
128
+
129
+ If not called, default messages in English will be shown.
130
+
131
+ ### Example
132
+
133
+ ```javascript
134
+ var onSuccess = function (strSuccess) {
135
+ console.log(strSuccess);
136
+ };
137
+ var onFailure = function (strError) {
138
+ console.warn(strError);
139
+ };
140
+ var snackbarText = "An update has just been downloaded.";
141
+ var snackbarButton = "RESTART";
142
+ var snackbarButtonColor = "#76FF03";
143
+ cordova.plugins.InAppUpdate.setSnackbarOptions(onSuccess, onFailure, snackbarText, snackbarButton, snackbarButtonColor);
144
+ ```
145
+
146
+ ### Default messages when not called
147
+
148
+ - **snackbarText** = "An update has just been downloaded."
149
+ - **snackbarButton** = "RESTART"
150
+ - **snackbarText** = "#76FF03"
151
+
152
+ ### Return values
153
+
154
+ - **onSuccess** = "SUCCESS"
155
+ - **onFail** = *Internal error description.*
156
+
157
+ # Plugin demo app
158
+
159
+ Get the [In-App Update Plugin Demo app](https://www.andreszsogon.com/cordova-in-app-update-plugin-demo-app/ "In-App Update Plugin Demo app") to test the plugin in all possible scenarios. This app is available in the Store, please follow the linked instructions to test the update flow.
160
+
161
+ # Reporting issues
162
+
163
+ Please report any issue with this plugin in GitHub by providing detailed context and sample code.
@@ -0,0 +1,4 @@
1
+ file.reference.cordova-plugin-in-app-update-www=www
2
+ files.encoding=UTF-8
3
+ site.root.folder=${file.reference.cordova-plugin-in-app-update-www}
4
+ source.folder=
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://www.netbeans.org/ns/project/1">
3
+ <type>org.netbeans.modules.web.clientproject</type>
4
+ <configuration>
5
+ <data xmlns="http://www.netbeans.org/ns/clientside-project/1">
6
+ <name>cordova-plugin-in-app-updates</name>
7
+ </data>
8
+ </configuration>
9
+ </project>
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "cordova-plugin-in-app-updates",
3
+ "version": "1.0.5",
4
+ "description": "In-App updates from Play Store for your Apache Cordova app.",
5
+ "cordova": {
6
+ "id": "cordova-plugin-in-app-updates",
7
+ "platforms": [
8
+ "android"
9
+ ]
10
+ },
11
+ "engines": {
12
+ "cordovaDependencies": {
13
+ "1.0.5": {
14
+ "cordova": ">=9.0.0",
15
+ "cordova-android": ">=8.0.0"
16
+ },
17
+ "2.0.5": {
18
+ "cordova": ">=10.0.0",
19
+ "cordova-android": ">=9.0.0"
20
+ }
21
+ }
22
+ },
23
+ "main": "index.js",
24
+ "scripts": {
25
+ "test": "echo \"Error: no test specified\" && exit 1"
26
+ },
27
+ "keywords": [
28
+ "ecosystem:cordova",
29
+ "cordova-android",
30
+ "cordova-browser",
31
+ "cordova",
32
+ "android",
33
+ "playstore",
34
+ "update",
35
+ "autoupdate",
36
+ "in-app update"
37
+ ],
38
+ "author": "Andres Zsogon",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/andreszs/cordova-plugin-in-app-updates.git"
43
+ },
44
+ "homepage": "https://github.com/andreszs/cordova-plugin-in-app-updates#readme",
45
+ "bugs": {
46
+ "url": "https://github.com/andreszs/cordova-plugin-in-app-updates/issues"
47
+ }
48
+ }
package/plugin.xml ADDED
@@ -0,0 +1,50 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+ <plugin id="cordova-plugin-in-app-updates" version="1.0.5" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <name>InAppUpdate</name>
4
+ <description>In-App updates from Play Store for your Apache Cordova app.</description>
5
+ <license>MIT</license>
6
+ <keywords>android,in-app,update</keywords>
7
+
8
+ <engines>
9
+ <engine name="cordova" version=">=9.0.0" />
10
+ <engine name="cordova-android" version=">=8.0.0" />
11
+ </engines>
12
+
13
+ <js-module name="InAppUpdate" src="www/InAppUpdate.js">
14
+ <clobbers target="cordova.plugins.InAppUpdate" />
15
+ </js-module>
16
+
17
+ <platform name="android">
18
+ <preference name="ANDROID_APPCOMPAT_VERSION" default="28.0.0" />
19
+ <framework src="com.android.support:appcompat-v7:$ANDROID_APPCOMPAT_VERSION" />
20
+
21
+ <preference name="ANDROID_PLAY_CORE_VERSION" default="1.7.2" />
22
+ <framework src="com.google.android.play:core:$ANDROID_PLAY_CORE_VERSION" />
23
+
24
+ <preference name="ANDROID_DESIGN_VERSION" default="28.0.0" />
25
+ <framework src="com.android.support:design:$ANDROID_DESIGN_VERSION" />
26
+
27
+ <config-file target="res/xml/config.xml" parent="/*">
28
+ <feature name="InAppUpdate">
29
+ <param name="android-package" value="com.andreszs.inappupdate.InAppUpdate" />
30
+ </feature>
31
+ </config-file>
32
+
33
+ <edit-config file="AndroidManifest.xml" target="/manifest/application/activity[@android:name='MainActivity']" mode="merge">
34
+ <activity android:name="MainActivity" android:theme="@style/Theme.AppCompat.NoActionBar" />
35
+ </edit-config>
36
+
37
+ <source-file src="src/android/InAppUpdate.java" target-dir="src/com/andreszs/inappupdate" />
38
+ </platform>
39
+
40
+ <platform name="browser">
41
+ <config-file target="config.xml" parent="/*">
42
+ <feature name="InAppUpdate">
43
+ <param name="browser-package" value="InAppUpdate" />
44
+ </feature>
45
+ </config-file>
46
+ <js-module src="src/browser/InAppUpdateProxy.js" name="InAppUpdateProxy">
47
+ <runs />
48
+ </js-module>
49
+ </platform>
50
+ </plugin>
@@ -0,0 +1,478 @@
1
+ package com.andreszs.inappupdate;
2
+
3
+ import android.app.Activity;
4
+ import android.content.Intent;
5
+ import android.content.IntentSender;
6
+ import android.graphics.Color;
7
+ import android.support.design.widget.Snackbar;
8
+ import android.util.Log;
9
+ import android.view.View;
10
+ import android.widget.FrameLayout;
11
+ import android.widget.TextView;
12
+
13
+ import com.google.android.play.core.appupdate.AppUpdateInfo;
14
+ import com.google.android.play.core.appupdate.AppUpdateManager;
15
+ import com.google.android.play.core.appupdate.AppUpdateManagerFactory;
16
+ import com.google.android.play.core.install.model.AppUpdateType;
17
+ import com.google.android.play.core.install.model.UpdateAvailability;
18
+
19
+ import com.google.android.play.core.install.model.InstallStatus;
20
+ import com.google.android.play.core.install.InstallState;
21
+ import com.google.android.play.core.install.InstallStateUpdatedListener;
22
+ import com.google.android.play.core.tasks.Task;
23
+
24
+ import org.apache.cordova.CallbackContext;
25
+ import org.apache.cordova.CordovaInterface;
26
+ import org.apache.cordova.CordovaPlugin;
27
+ import org.apache.cordova.CordovaWebView;
28
+ import org.apache.cordova.PluginResult;
29
+
30
+ import org.json.JSONArray;
31
+ import org.json.JSONException;
32
+ import org.json.JSONObject;
33
+
34
+ import static android.app.Activity.RESULT_CANCELED;
35
+ import static android.app.Activity.RESULT_OK;
36
+ import static com.google.android.play.core.install.model.ActivityResult.RESULT_IN_APP_UPDATE_FAILED;
37
+
38
+ /**
39
+ * @author https://github.com/andreszs/cordova-plugin-in-app-update
40
+ */
41
+ public class InAppUpdate extends CordovaPlugin {
42
+
43
+ private static String LOG_TAG;
44
+ private static boolean PROMPTED = false;
45
+ private static int currentUpdateType;
46
+ private static AppUpdateManager appUpdateManager;
47
+
48
+ private final int activityResultRequestCode = 777;
49
+ private CordovaPlugin activityResultCallback;
50
+ private FrameLayout layout;
51
+ private Snackbar snackbar;
52
+ private CallbackContext callbackContext;
53
+
54
+ private String snackbarText = "An update has just been downloaded.";
55
+ private String snackbarButton = "RESTART";
56
+ private String snackbarButtonColor = "#76FF03";
57
+
58
+ public InAppUpdate() {
59
+ this.LOG_TAG = InAppUpdate.class.getSimpleName();
60
+ Log.i(LOG_TAG, "Constructed");
61
+ }
62
+
63
+ @Override
64
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
65
+ super.initialize(cordova, webView);
66
+ layout = (FrameLayout) webView.getView().getParent();
67
+ }
68
+
69
+ @Override
70
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
71
+ this.callbackContext = callbackContext;
72
+ this.PROMPTED = false;
73
+
74
+ Log.i(LOG_TAG, String.format("Executing the %s action started", action));
75
+ if (action.equals("getUpdateAvailability")) {
76
+ getUpdateAvailability(callbackContext);
77
+ return true;
78
+ } else if (action.equals("updateFlexible")) {
79
+ updateFlexible();
80
+ return true;
81
+ } else if (action.equals("updateImmediate")) {
82
+ updateImmediate();
83
+ return true;
84
+ } else if (action.equals("setSnackbarOptions")) {
85
+ setSnackbarOptions(args);
86
+ return true;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ private void getUpdateAvailability(CallbackContext callbackContext) {
93
+
94
+ cordova.getThreadPool().execute(new Runnable() {
95
+ public void run() {
96
+
97
+ // Creates instance of the manager.
98
+ appUpdateManager = AppUpdateManagerFactory.create(cordova.getContext());
99
+
100
+ // Returns an intent object that you use to check for an update.
101
+ Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
102
+
103
+ appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
104
+ Log.i(LOG_TAG, String.format("appUpdateInfo.updateAvailability = %s", String.valueOf(appUpdateInfo.updateAvailability())));
105
+ PluginResult result;
106
+ switch (appUpdateInfo.updateAvailability()) {
107
+ case UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS:
108
+ result = new PluginResult(PluginResult.Status.OK, "DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS");
109
+ callbackContext.sendPluginResult(result);
110
+ break;
111
+
112
+ case UpdateAvailability.UPDATE_AVAILABLE:
113
+ result = new PluginResult(PluginResult.Status.OK, "UPDATE_AVAILABLE");
114
+ callbackContext.sendPluginResult(result);
115
+ break;
116
+
117
+ case UpdateAvailability.UPDATE_NOT_AVAILABLE:
118
+ result = new PluginResult(PluginResult.Status.OK, "UPDATE_NOT_AVAILABLE");
119
+ callbackContext.sendPluginResult(result);
120
+ break;
121
+
122
+ default:
123
+ result = new PluginResult(PluginResult.Status.OK, "UNKNOWN");
124
+ callbackContext.sendPluginResult(result);
125
+ }
126
+
127
+ }).addOnFailureListener(e -> {
128
+ // Returns "com.google.android.play.core.internal.al: Failed to bind to the service." whenever the Play Store is not available.
129
+ e.printStackTrace();
130
+ Log.e(LOG_TAG, e.toString());
131
+ callbackContext.error(e.toString());
132
+
133
+ });
134
+
135
+ }
136
+ });
137
+
138
+ }
139
+
140
+ public void setActivityResultCallback(CordovaPlugin plugin) {
141
+ Log.i(LOG_TAG, "setActivityResultCallback");
142
+
143
+ // Cancel any previously pending activity.
144
+ if (this.activityResultCallback != null) {
145
+ this.activityResultCallback.onActivityResult(this.activityResultRequestCode, Activity.RESULT_CANCELED, null);
146
+ }
147
+ this.activityResultCallback = plugin;
148
+ }
149
+
150
+ private void popupSnackbarForCompleteUpdate() {
151
+ Log.i(LOG_TAG, "popupSnackbarForCompleteUpdate");
152
+ this.PROMPTED = true;
153
+
154
+ cordova.getActivity().runOnUiThread(new Runnable() {
155
+ public void run() {
156
+ try {
157
+ snackbar = Snackbar.make(layout, snackbarText, Snackbar.LENGTH_INDEFINITE);
158
+ snackbar.setAction(snackbarButton, new View.OnClickListener() {
159
+ public void onClick(View view) {
160
+ appUpdateManager.completeUpdate();
161
+ }
162
+ });
163
+ snackbar.setActionTextColor(Color.parseColor(snackbarButtonColor));
164
+ snackbar.show();
165
+ } catch (Exception e) {
166
+ e.printStackTrace();
167
+ Log.e(LOG_TAG, e.getMessage());
168
+ }
169
+ }
170
+ });
171
+
172
+ }
173
+
174
+ private void setSnackbarOptions(JSONArray args) {
175
+
176
+ PluginResult result;
177
+ Log.i(LOG_TAG, "setSnackbarOptions");
178
+
179
+ try {
180
+
181
+ JSONObject arg_object = args.getJSONObject(0);
182
+ this.snackbarText = arg_object.getString("strText");
183
+ this.snackbarButton = arg_object.getString("strButton");
184
+ String colorHex = arg_object.getString("strButtonColor");
185
+ if (colorHex != null && colorHex.length() == 7) {
186
+ this.snackbarButtonColor = colorHex;
187
+ result = new PluginResult(PluginResult.Status.OK, "SUCCESS");
188
+ } else {
189
+ result = new PluginResult(PluginResult.Status.OK, "SUCCESS (Invalid HEX color specified; ignored)");
190
+ }
191
+ this.callbackContext.sendPluginResult(result);
192
+
193
+ } catch (Exception e) {
194
+
195
+ Log.e(LOG_TAG, e.getMessage());
196
+ result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
197
+ this.callbackContext.sendPluginResult(result);
198
+
199
+ }
200
+
201
+ }
202
+
203
+ private void updateFlexible() {
204
+
205
+ currentUpdateType = AppUpdateType.FLEXIBLE;
206
+ cordova.setActivityResultCallback(this);
207
+
208
+ cordova.getThreadPool().execute(new Runnable() {
209
+ //@Override
210
+ InstallStateUpdatedListener installStateUpdatedListener;
211
+
212
+ public void run() {
213
+
214
+ // Creates instance of the manager.
215
+ appUpdateManager = AppUpdateManagerFactory.create(cordova.getContext());
216
+
217
+ // Returns an intent object that you use to check for an update.
218
+ Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
219
+
220
+ // Create a listener to track request state updates.
221
+ installStateUpdatedListener = new InstallStateUpdatedListener() {
222
+ @Override
223
+ public void onStateUpdate(InstallState state) {
224
+ if (state.installStatus() == InstallStatus.DOWNLOADED) {
225
+ // Update downloaded.
226
+ Log.i(LOG_TAG, "InstallStateUpdatedListener: InstallStatus.DOWNLOADED");
227
+
228
+ // Unregister listener
229
+ appUpdateManager.unregisterListener(installStateUpdatedListener);
230
+
231
+ // Prevent multiple consecutive prompts of this event
232
+ if (!PROMPTED) {
233
+ popupSnackbarForCompleteUpdate();
234
+ PluginResult result = new PluginResult(PluginResult.Status.OK, "DOWNLOADED");
235
+ callbackContext.sendPluginResult(result);
236
+ }
237
+ } else if (state.installStatus() == InstallStatus.INSTALLED) {
238
+ // Update installed.
239
+ Log.i(LOG_TAG, "InstallStateUpdatedListener: InstallStatus.INSTALLED");
240
+ if (appUpdateManager != null) {
241
+ // Unregister listener.
242
+ appUpdateManager.unregisterListener(installStateUpdatedListener);
243
+ }
244
+ } else if (state.installStatus() == InstallStatus.DOWNLOADING) {
245
+ // Now downloading...
246
+ Log.i(LOG_TAG, "InstallStateUpdatedListener: InstallStatus.DOWNLOADING");
247
+ PluginResult result = new PluginResult(PluginResult.Status.OK, "DOWNLOADING");
248
+ result.setKeepCallback(true);
249
+ callbackContext.sendPluginResult(result);
250
+ } else {
251
+ // Other status.
252
+ Log.i(LOG_TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
253
+ }
254
+ }
255
+ };
256
+
257
+ // Before starting an update, register a listener for updates.
258
+ appUpdateManager.registerListener(installStateUpdatedListener);
259
+
260
+ // Start an update.
261
+ appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
262
+ Log.i(LOG_TAG, "Updated success listener called");
263
+
264
+ if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
265
+ // If the update is downloaded but not installed, notify the user to complete the update.
266
+ Log.i(LOG_TAG, "InstallStatus.DOWNLOADED");
267
+
268
+ // When status updates are no longer needed, unregister the listener.
269
+ appUpdateManager.unregisterListener(installStateUpdatedListener);
270
+
271
+ popupSnackbarForCompleteUpdate();
272
+ PluginResult result = new PluginResult(PluginResult.Status.OK, "DOWNLOADED");
273
+ callbackContext.sendPluginResult(result);
274
+
275
+ } else {
276
+ // Check for update availability.
277
+ switch (appUpdateInfo.updateAvailability()) {
278
+ case UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS:
279
+ // An update has been triggered by the developer and is in progress.
280
+ Log.i(LOG_TAG, "DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS");
281
+ callbackContext.success("DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS");
282
+ break;
283
+
284
+ case UpdateAvailability.UPDATE_AVAILABLE:
285
+ // Update is available.
286
+ Log.i(LOG_TAG, "UPDATE_AVAILABLE");
287
+ if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
288
+ // Request the update.
289
+ startUpdate(AppUpdateType.FLEXIBLE, appUpdateInfo);
290
+
291
+ } else {
292
+ // Update type not allowed.
293
+ Log.e(LOG_TAG, "Flexible update type not allowed");
294
+ callbackContext.error("UPDATE_TYPE_NOT_ALLOWED");
295
+ }
296
+ break;
297
+
298
+ case UpdateAvailability.UPDATE_NOT_AVAILABLE:
299
+ // Update not available.
300
+ Log.i(LOG_TAG, "UPDATE_NOT_AVAILABLE");
301
+ callbackContext.success("UPDATE_NOT_AVAILABLE");
302
+ break;
303
+
304
+ default:
305
+ // Unknown update status.
306
+ Log.i(LOG_TAG, "UNKNOWN");
307
+ callbackContext.success("UNKNOWN");
308
+ }
309
+ }
310
+
311
+ }).addOnFailureListener(e -> {
312
+ // Returns "com.google.android.play.core.internal.al: Failed to bind to the service." whenever the Play Store is not available.
313
+ e.printStackTrace();
314
+ Log.e(LOG_TAG, e.toString());
315
+ callbackContext.error(e.toString());
316
+
317
+ });
318
+
319
+ }
320
+ });
321
+ }
322
+
323
+ private void updateImmediate() {
324
+
325
+ currentUpdateType = AppUpdateType.IMMEDIATE;
326
+ cordova.setActivityResultCallback(this);
327
+ cordova.getThreadPool().execute(new Runnable() {
328
+ @Override
329
+ public void run() {
330
+
331
+ // Creates instance of the manager.
332
+ appUpdateManager = AppUpdateManagerFactory.create(cordova.getContext());
333
+
334
+ // Returns an intent object that you use to check for an update.
335
+ Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
336
+
337
+ appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
338
+ Log.i(LOG_TAG, "Updated success listener called");
339
+
340
+ if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
341
+ // If the update is downloaded but not installed, complete the update now.
342
+ startUpdate(AppUpdateType.IMMEDIATE, appUpdateInfo);
343
+
344
+ } else {
345
+ // Check for update availability.
346
+ switch (appUpdateInfo.updateAvailability()) {
347
+ case UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS:
348
+ // An update has been triggered by the developer and is in progress.
349
+ Log.i(LOG_TAG, "DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS");
350
+ callbackContext.success("DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS");
351
+ break;
352
+
353
+ case UpdateAvailability.UPDATE_AVAILABLE:
354
+ // Update is available.
355
+ Log.i(LOG_TAG, "UPDATE_AVAILABLE");
356
+ if (appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
357
+ // Request the update.
358
+ startUpdate(AppUpdateType.IMMEDIATE, appUpdateInfo);
359
+ } else {
360
+ // Update type not allowed.
361
+ Log.e(LOG_TAG, "Flexible update type not allowed");
362
+ callbackContext.error("Flexible update type not allowed");
363
+ }
364
+ break;
365
+
366
+ case UpdateAvailability.UPDATE_NOT_AVAILABLE:
367
+ // Update not available.
368
+ Log.i(LOG_TAG, "UPDATE_NOT_AVAILABLE");
369
+ callbackContext.success("UPDATE_NOT_AVAILABLE");
370
+ break;
371
+
372
+ default:
373
+ // Unknown update status.
374
+ Log.i(LOG_TAG, "UNKNOWN");
375
+ callbackContext.success("UNKNOWN");
376
+ }
377
+ }
378
+
379
+ }).addOnFailureListener(e -> {
380
+ // Returns "com.google.android.play.core.internal.al: Failed to bind to the service." whenever the Play Store is not available.
381
+ Log.e(LOG_TAG, e.toString());
382
+ e.printStackTrace();
383
+ callbackContext.error(e.toString());
384
+
385
+ });
386
+
387
+ }
388
+ });
389
+
390
+ }
391
+
392
+ @Override
393
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
394
+
395
+ PluginResult result;
396
+ Log.i(LOG_TAG, "onActivityResult");
397
+
398
+ if (requestCode == this.activityResultRequestCode && this.callbackContext != null) {
399
+ switch (resultCode) {
400
+ case RESULT_OK:
401
+ // User accepted the update.
402
+ Log.i(LOG_TAG, "RESULT_OK");
403
+ result = new PluginResult(PluginResult.Status.OK, "RESULT_OK");
404
+ result.setKeepCallback(true);
405
+ this.callbackContext.sendPluginResult(result);
406
+ break;
407
+
408
+ case RESULT_CANCELED:
409
+ // User cancelled the update.
410
+ Log.i(LOG_TAG, "RESULT_CANCELED");
411
+ result = new PluginResult(PluginResult.Status.OK, "RESULT_CANCELED");
412
+ this.callbackContext.sendPluginResult(result);
413
+ break;
414
+
415
+ case RESULT_IN_APP_UPDATE_FAILED:
416
+ // Update failured.
417
+ Log.e(LOG_TAG, "RESULT_IN_APP_UPDATE_FAILED");
418
+ result = new PluginResult(PluginResult.Status.ERROR, "RESULT_IN_APP_UPDATE_FAILED");
419
+ this.callbackContext.sendPluginResult(result);
420
+ break;
421
+
422
+ default:
423
+ // Unknown activity result.
424
+ Log.e(LOG_TAG, "ACTIVITY_RESULT_UNKNOWN");
425
+ result = new PluginResult(PluginResult.Status.ERROR, "ACTIVITY_RESULT_UNKNOWN");
426
+ this.callbackContext.sendPluginResult(result);
427
+ }
428
+ }
429
+ super.onActivityResult(requestCode, resultCode, intent);
430
+
431
+ }
432
+
433
+ @Override
434
+ public void onResume(final boolean multitasking) {
435
+
436
+ //Log.i(LOG_TAG, String.format("onResume: currentUpdateType = %s", String.valueOf(currentUpdateType)));
437
+ appUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
438
+ if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
439
+ // If the update is downloaded but not installed, notify the user to complete the update.
440
+ if (currentUpdateType == AppUpdateType.FLEXIBLE) {
441
+ Log.i(LOG_TAG, "onResume: popupSnackbarForCompleteUpdate");
442
+ popupSnackbarForCompleteUpdate();
443
+ } else {
444
+ Log.i(LOG_TAG, "onResume: startUpdate");
445
+ try {
446
+ startUpdate(AppUpdateType.IMMEDIATE, appUpdateInfo);
447
+ } catch (Exception e) {
448
+ e.printStackTrace();
449
+ }
450
+ }
451
+ }
452
+ });
453
+
454
+ super.onResume(multitasking);
455
+
456
+ }
457
+
458
+ public void startUpdate(final int updateType, final AppUpdateInfo appUpdateInfo) {
459
+
460
+ PluginResult result;
461
+ Log.i(LOG_TAG, "startUpdate");
462
+
463
+ try {
464
+ appUpdateManager.startUpdateFlowForResult(appUpdateInfo, updateType, cordova.getActivity(), this.activityResultRequestCode);
465
+ result = new PluginResult(PluginResult.Status.OK, "UPDATE_PROMPT");
466
+ result.setKeepCallback(true);
467
+ this.callbackContext.sendPluginResult(result);
468
+
469
+ } catch (Exception e) {
470
+ Log.e(LOG_TAG, e.getMessage());
471
+ result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
472
+ this.callbackContext.sendPluginResult(result);
473
+
474
+ }
475
+
476
+ }
477
+
478
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var InAppUpdate = {
4
+ getUpdateAvailability: function (successCallback, failureCallback) {
5
+ successCallback('UPDATE_NOT_AVAILABLE');
6
+ },
7
+ setSnackbarOptions: function (successCallback, failureCallback, snackbarText, snackbarButton, snackbarButtonColor) {
8
+ successCallback('SUCCESS');
9
+ },
10
+ updateFlexible: function (successCallback, failureCallback) {
11
+ successCallback('UPDATE_NOT_AVAILABLE');
12
+ },
13
+ updateImmediate: function (successCallback, failureCallback) {
14
+ successCallback('UPDATE_NOT_AVAILABLE');
15
+ }
16
+ };
17
+
18
+ module.exports = InAppUpdate;
19
+
20
+ require("cordova/exec/proxy").add("InAppUpdate", module.exports);
@@ -0,0 +1,25 @@
1
+ var exec = require('cordova/exec');
2
+
3
+ var InAppUpdate = {
4
+ getUpdateAvailability: function (successCallback, failureCallback) {
5
+ exec(successCallback, failureCallback, 'InAppUpdate', 'getUpdateAvailability');
6
+ },
7
+ setSnackbarOptions: function (successCallback, failureCallback, snackbarText, snackbarButton, snackbarButtonColor) {
8
+ snackbarText = (typeof (snackbarText) == 'undefined' || snackbarText.length == 0) ? 'An update has just been downloaded.' : snackbarText;
9
+ snackbarButton = (typeof (snackbarButton) == 'undefined' || snackbarButton.length == 0) ? 'RESTART' : snackbarButton;
10
+ snackbarButtonColor = (typeof (snackbarButtonColor) == 'undefined' || snackbarButtonColor.length == 0) ? '#76FF03' : snackbarButtonColor;
11
+ exec(successCallback, failureCallback, 'InAppUpdate', 'setSnackbarOptions', [
12
+ {strText: snackbarText, strButton: snackbarButton, strButtonColor: snackbarButtonColor}
13
+ ]);
14
+ },
15
+ updateFlexible: function (successCallback, failureCallback) {
16
+ exec(successCallback, failureCallback, 'InAppUpdate', 'updateFlexible');
17
+ },
18
+ updateImmediate: function (successCallback, failureCallback) {
19
+ exec(successCallback, failureCallback, 'InAppUpdate', 'updateImmediate');
20
+ }
21
+
22
+ };
23
+
24
+ module.exports = InAppUpdate;
25
+