B4A Library In-App Update Library

flexible_flow.png


Keeping your app up-to-date on your users’ devices enables them to try new features, as well as benefit from performance improvements and bug fixes. Although some users enable background updates when their device is connected to an unmetered connection, other users may need to be reminded to update. In-app updates is a Play Core library feature that introduces a new request flow to prompt active users to update your app.

This is a B4A wrapper for Google In-App Update. https://developer.android.com/guide/playcore/in-app-updates
Before you begin, please read google documentation. You can also read from CapTech https://www.captechconsulting.com/blogs/upgrading-your-app-with-in-app-updates and Medium article.


Requirements:
  • In-app updates works only with devices running Android 5.0 (API level 21) or higher, and requires you to use Play Core library 1.5.0 or higher. To install Play Core library start SDK Manager and in search field type: com.google.android.play:core and install it.
  • In-app updates are available only to user accounts that own the app. So, make sure the account you’re using has downloaded your app from Google Play at least once before using the account to test in-app updates.
  • Make sure that the app that you are testing in-app updates with has the same application ID(Package Name) and is signed with the same signing key as the one available from Google Play.
  • Because Google Play can only update an app to a higher version code, make sure the app you are testing as a lower version code than the update version code.
  • When testing, make sure the Google Play cache is up to date by closing the Play Store App and then going back to the My Apps & Games tab before testing updates.

HowToUse:
Note: This is an example of ImmediateUpdate which handle all tasks by itself.

If you want to use this library with B4XPages then follow instructions here(https://www.b4x.com/android/forum/threads/in-app-update-library.126305/post-809707)

- Add this line to your manifest.
B4X:
CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)

- Add this line in Project Attributes of your Main activity.
B4X:
#AdditionalJar: com.google.android.gms:play-services-base

- Define a variable as InAppUpdate library.
B4X:
Private Sub Globals
  Private InAppUpdate As InAppUpdate
End Sub

- Copy this codes to your main activity without change.
B4X:
Private Sub CheckUpdate
    InAppUpdate.initialize(False)
    InAppUpdate.GetAppUpdateInfo

    #IF JAVA
      public void _onactivityresult(int requestCode,int resultCode){
        com.khaan.iau.InAppUpdate.onActivityResult(activityBA,requestCode,resultCode);
      }
    #END IF
End Sub

Private Sub InAppUpdate_onAppUpdateInfoReceived(success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
    Log($"InAppUpdate_onAppUpdateInfoReceived, Success: ${success}"$)

    If success Then
      If inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS Or inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_AVAILABLE Then
        InAppUpdate.startImmediateUpdateFlow
      End If
    End If
End Sub

- And finaly call CheckUpdate everywhere you want. for example in Activity_Resume
B4X:
Private Sub Activity_Resume
    CheckUpdate
End Sub


If you want to use FlexibleUpdate then you should implement methods and handle events and states manually.
When you start a flexible update, a dialog first appears to the user to request consent. If the user consents, the download starts in the background and you can Show your custom progressbar to user when update is downloading, and the user may continue to interact with the app.
After the update is downloaded, show a notification and request user confirmation to install update and restart the app.

for more information please read documents.




InAppUpdate
Version:
1.1
  • InAppUpdate
    Events:
    • InAppUpdate_onAppUpdateInfoReceived (success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
    • InAppUpdate_onUserAcceptUpdate (accepted As Boolean)
    • InAppUpdate_onStateUpdate (installStatus As Int, arg1 As Long, arg2 As Long)
  • Fields:
    • INSTALL_STATUS_REQUIRES_UI_INTENT As int
    • INSTALL_STATUS_CANCELED As int
    • INSTALL_STATUS_PENDING As int
    • INSTALL_STATUS_DOWNLOADED As int
    • INSTALL_STATUS_INSTALLING As int
    • INSTALL_STATUS_DOWNLOADING As int
    • INSTALL_STATUS_FAILED As int
    • INSTALL_STATUS_INSTALLED As int
    • INSTALL_STATUS_UNKNOWN As int
  • Methods:
    • fake_UserRejectsUpdate As void
      Simulates that a user has declined an update from the update confirmation dialog.
      This method call works only if isConfirmationDialogVisible() or isImmediateFlowVisible() is true.
    • fake_UpdateDownloaded As void
      Simulates that update downloaded.
    • isTestMode As java.lang.Boolean
      Retuen whether test mode is enabled or not.
    • fake_UpdateDownloading As void
      Simulates that update downloading.
    • StartImmediateUpdateFlow As void
      Trigger the immediate update flow.
    • fake_UserCancelsDownload As void
      Simulates the user canceling the download via the Play UI.
      This method call works only if the download of an update is pending or downloading.
    • installFlexibleUpdate As void
      Once we detect that the InstallStatus represents the DOWNLOADED state,
      We are required to restart the app so that the update can be installed.
      Whilst the immediate update method handles this for you, in the case of the flexible update
      We need to manually trigger this. In order to manually trigger this update we need to make use of the installFlexibleUpdate method.
      When this is called, a full-screen UI will be displayed from the play core library and the app will be restarted in the background so that the update can be installed.
      The app will then be restarted with the update applied.
    • Initialize (ba As anywheresoftware.b4a.BA, testMode As boolean) As com.khaan.iau.InAppUpdate
      Initializes the In-App update.
    • fake_UserAcceptsUpdate As void
      Simulates that a user has accepted an flexible update from the update confirmation dialog.
      The download is enqueued in PENDING status.
    • StartFlexibleUpdateFlow As void
      Trigger the flexible update flow.
    • fake_CustomState (status As int) As void
      Simulates custom state.
    • fake_UpdateFailed As void
      Simulates that update is failed.
    • GetAppUpdateInfo As void
      Checking whether there is an update that is available from the play store.
  • InAppUpdateInfo
    Fields:
    • UPDATE_AVAILABILITY_DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS As int
    • UPDATE_AVAILABILITY_AVAILABLE As int
    • UPDATE_AVAILABILITY_UNKNOWN As int
    • UPDATE_AVAILABILITY_NOT_AVAILABLE As int
  • Methods:
    • totalBytesToDownload As long
    • updateAvailability As int
    • isImmediateUpdateAllowed As boolean
    • bytesDownloaded As long
    • clientVersionStalenessDays As java.lang.Integer
    • installStatus As int
    • updatePriority As int
    • availableVersionCode As int
    • isFlexibleUpdateAllowed As boolean
 

Attachments

  • InAppUpdate.xml
    7.9 KB · Views: 671
  • InAppUpdate.jar
    7 KB · Views: 703
Last edited:

scsjc

Well-Known Member
Licensed User
Longtime User
Hi, great library :)
I have tried using it and it gives me this error:

B4X:
   Error occurred on line: 4530 (Main)
   java.lang.NullPointerException: Attempt to read from field 'anywheresoftware.b4a.BA com.xxxxxxxxx.main.activityBA' on a null object reference
   at com.xxxxxxxxxxxx.main._inappupdate_onappupdateinforeceived(main.java:16761)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at com.khaan.iau.InAppUpdate.onAppUpdateInfoReceived(InAppUpdate.java:96)
    at com.khaan.iau.InAppUpdate.access$200(InAppUpdate.java:30)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:89)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:85)
    at com.google.android.play.core.tasks.e.run(Unknown Source:36)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
indicates error in this line:
B4X:
   Private Sub InAppUpdate_onAppUpdateInfoReceived(success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
this is the full report error:
B4X:
CctBackendFactory.java:29)
~e:    at com.google.android.datatransport.runtime.backends.MetadataBackendRegistry.get(MetadataBackendRegistry.java:80)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.lambda$schedule$1(DefaultScheduler.java:70)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler$$Lambda$1.run(Unknown Source:13)
~e:    at com.google.android.datatransport.runtime.SafeLoggingExecutor$SafeLoggingRunnable.run(SafeLoggingExecutor.java:47)
~e:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
~e:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
~e:    at java.lang.Thread.run(Thread.java:764)
~e:Caused by: java.lang.NoSuchMethodError: No static method of(Ljava/lang/String;)Lcom/google/firebase/encoders/FieldDescriptor; in class Lcom/google/firebase/encoders/FieldDescriptor; or its super classes (declaration of 'com.google.firebase.encoders.FieldDescriptor' appears in /data/app/com.oficinadirecta-7SYFKHw8m4EY8w6eSb_ZyA=base.apk!classes2.dex)
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder.<clinit>(AutoBatchedLogRequestEncoder.java:38)
~e:    ... 13 more
~e:java.lang.NoClassDefFoundError: com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder.configure(AutoBatchedLogRequestEncoder.java:21)
~e:    at com.google.firebase.encoders.json.JsonDataEncoderBuilder.configureWith(JsonDataEncoderBuilder.java:103)
~e:    at com.google.android.datatransport.cct.internal.BatchedLogRequest.createDataEncoder(BatchedLogRequest.java:39)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:100)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:129)
~e:    at com.google.android.datatransport.cct.CctBackendFactory.create(CctBackendFactory.java:29)
~e:    at com.google.android.datatransport.runtime.backends.MetadataBackendRegistry.get(MetadataBackendRegistry.java:80)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.lambda$schedule$1(DefaultScheduler.java:70)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler$$Lambda$1.run(Unknown Source:13)
~e:    at com.google.android.datatransport.runtime.SafeLoggingExecutor$SafeLoggingRunnable.run(SafeLoggingExecutor.java:47)
~e:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
~e:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
~e:    at java.lang.Thread.run(Thread.java:764)
~e:Caused by: java.lang.NoSuchMethodError: No static method of(Ljava/lang/String;)Lcom/google/firebase/encoders/FieldDescriptor; in class Lcom/google/firebase/encoders/FieldDescriptor; or its super classes (declaration of 'com.google.firebase.encoders.FieldDescriptor' appears in /data/app/com.oficinadirecta-7SYFKHw8m4EY8w6eSb_ZyA=base.apk!classes2.dex)
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder.<clinit>(AutoBatchedLogRequestEncoder.java:38)
~e:    ... 13 more
~e:java.lang.NoClassDefFoundError: com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder.configure(AutoBatchedLogRequestEncoder.java:21)
~e:    at com.google.firebase.encoders.json.JsonDataEncoderBuilder.configureWith(JsonDataEncoderBuilder.java:103)
~e:    at com.google.android.datatransport.cct.internal.BatchedLogRequest.createDataEncoder(BatchedLogRequest.java:39)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:100)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:129)
~e:    at com.google.android.datatransport.cct.CctBackendFactoryjava.lang.NullPointerException: Attempt to read from field 'com.oficinadirecta.codigo com.oficinadirecta.main._vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv7' on a null object reference
    at com.oficinadirecta.main._inappupdate_onappupdateinforeceived(main.java:13047)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at com.khaan.iau.InAppUpdate.onAppUpdateInfoReceived(InAppUpdate.java:96)
    at com.khaan.iau.InAppUpdate.access$200(InAppUpdate.java:30)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:89)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:85)
    at com.google.android.play.core.tasks.e.run(Unknown Source:27)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 
Last edited:

ArminKh1993

Active Member
Hi, great library :)
I have tried using it and it gives me this error:

B4X:
   Error occurred on line: 4530 (Main)
   java.lang.NullPointerException: Attempt to read from field 'anywheresoftware.b4a.BA com.xxxxxxxxx.main.activityBA' on a null object reference
   at com.xxxxxxxxxxxx.main._inappupdate_onappupdateinforeceived(main.java:16761)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at com.khaan.iau.InAppUpdate.onAppUpdateInfoReceived(InAppUpdate.java:96)
    at com.khaan.iau.InAppUpdate.access$200(InAppUpdate.java:30)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:89)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:85)
    at com.google.android.play.core.tasks.e.run(Unknown Source:36)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
indicates error in this line:
B4X:
   Private Sub InAppUpdate_onAppUpdateInfoReceived(success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
this is the full report error:
B4X:
CctBackendFactory.java:29)
~e:    at com.google.android.datatransport.runtime.backends.MetadataBackendRegistry.get(MetadataBackendRegistry.java:80)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.lambda$schedule$1(DefaultScheduler.java:70)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler$$Lambda$1.run(Unknown Source:13)
~e:    at com.google.android.datatransport.runtime.SafeLoggingExecutor$SafeLoggingRunnable.run(SafeLoggingExecutor.java:47)
~e:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
~e:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
~e:    at java.lang.Thread.run(Thread.java:764)
~e:Caused by: java.lang.NoSuchMethodError: No static method of(Ljava/lang/String;)Lcom/google/firebase/encoders/FieldDescriptor; in class Lcom/google/firebase/encoders/FieldDescriptor; or its super classes (declaration of 'com.google.firebase.encoders.FieldDescriptor' appears in /data/app/com.oficinadirecta-7SYFKHw8m4EY8w6eSb_ZyA=base.apk!classes2.dex)
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder.<clinit>(AutoBatchedLogRequestEncoder.java:38)
~e:    ... 13 more
~e:java.lang.NoClassDefFoundError: com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder.configure(AutoBatchedLogRequestEncoder.java:21)
~e:    at com.google.firebase.encoders.json.JsonDataEncoderBuilder.configureWith(JsonDataEncoderBuilder.java:103)
~e:    at com.google.android.datatransport.cct.internal.BatchedLogRequest.createDataEncoder(BatchedLogRequest.java:39)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:100)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:129)
~e:    at com.google.android.datatransport.cct.CctBackendFactory.create(CctBackendFactory.java:29)
~e:    at com.google.android.datatransport.runtime.backends.MetadataBackendRegistry.get(MetadataBackendRegistry.java:80)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.lambda$schedule$1(DefaultScheduler.java:70)
~e:    at com.google.android.datatransport.runtime.scheduling.DefaultScheduler$$Lambda$1.run(Unknown Source:13)
~e:    at com.google.android.datatransport.runtime.SafeLoggingExecutor$SafeLoggingRunnable.run(SafeLoggingExecutor.java:47)
~e:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
~e:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
~e:    at java.lang.Thread.run(Thread.java:764)
~e:Caused by: java.lang.NoSuchMethodError: No static method of(Ljava/lang/String;)Lcom/google/firebase/encoders/FieldDescriptor; in class Lcom/google/firebase/encoders/FieldDescriptor; or its super classes (declaration of 'com.google.firebase.encoders.FieldDescriptor' appears in /data/app/com.oficinadirecta-7SYFKHw8m4EY8w6eSb_ZyA=base.apk!classes2.dex)
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder.<clinit>(AutoBatchedLogRequestEncoder.java:38)
~e:    ... 13 more
~e:java.lang.NoClassDefFoundError: com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder$BatchedLogRequestEncoder
~e:    at com.google.android.datatransport.cct.internal.AutoBatchedLogRequestEncoder.configure(AutoBatchedLogRequestEncoder.java:21)
~e:    at com.google.firebase.encoders.json.JsonDataEncoderBuilder.configureWith(JsonDataEncoderBuilder.java:103)
~e:    at com.google.android.datatransport.cct.internal.BatchedLogRequest.createDataEncoder(BatchedLogRequest.java:39)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:100)
~e:    at com.google.android.datatransport.cct.CctTransportBackend.<init>(CctTransportBackend.java:129)
~e:    at com.google.android.datatransport.cct.CctBackendFactoryjava.lang.NullPointerException: Attempt to read from field 'com.oficinadirecta.codigo com.oficinadirecta.main._vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv7' on a null object reference
    at com.oficinadirecta.main._inappupdate_onappupdateinforeceived(main.java:13047)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at com.khaan.iau.InAppUpdate.onAppUpdateInfoReceived(InAppUpdate.java:96)
    at com.khaan.iau.InAppUpdate.access$200(InAppUpdate.java:30)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:89)
    at com.khaan.iau.InAppUpdate$1.onSuccess(InAppUpdate.java:85)
    at com.google.android.play.core.tasks.e.run(Unknown Source:27)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
I just tested it and it had no problem and it worked well
use b4a latest version
and please update your sdk
 

scsjc

Well-Known Member
Licensed User
Longtime User
I test it right now and it's ok
use b4a latest version
and please update your sdk
thanks :)

b4aversion: 10.50
android.jar : C:\android-sdk\platforms\android-30
manifest : <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="29"/>
com.google.android.play:core: 1.9.0
 

fredo

Well-Known Member
Licensed User
Longtime User
... for example in Activity_Resume ...


Thanks for the lib.

It is easy to implement and worked flawlessly in the first test with a classic B4A project structure.
B4X:
Sub Activity_Resume
    CheckUpdate   
End Sub

2021-01-08_15-22-01.png 2021-01-08_15-22-14.png 2021-01-08_15-22-17.png


Strangely, it did not work with another app constructed with B4XPagesManager.
B4X:
Sub Activity_Resume
    CheckUpdate   
    B4XPages.Delegate.Activity_Resume 
End Sub


The sub CheckUpdate was called, but no message appeared.
 

ArminKh1993

Active Member
Thanks for the lib.

It is easy to implement and worked flawlessly in the first test with a classic B4A project structure.
B4X:
Sub Activity_Resume
    CheckUpdate 
End Sub

View attachment 105737 View attachment 105736 View attachment 105735


Strangely, it did not work with another app constructed with B4XPagesManager.
B4X:
Sub Activity_Resume
    CheckUpdate 
    B4XPages.Delegate.Activity_Resume
End Sub


The sub CheckUpdate was called, but no message appeared.
I did not test this with b4xPages but it is probably due to the onActivityResult callback
I will check this as soon as possible, but unfortunately I do not have time to coordinate this with b4x pages.
maybe erel can help
i dont know what is the b4xpages alternative fo inline onActivityResult
if you know replace this part of code by your self
B4X:
    #IF JAVA
      public void _onactivityresult(int requestCode,int resultCode){
        com.khaan.iau.InAppUpdate.onActivityResult(activityBA,requestCode,resultCode);
      }
    #END IF
 
Last edited:

scsjc

Well-Known Member
Licensed User
Longtime User
I think i know problem... is a AppCompat 4.0 library ...
B4X:
#Extends: android.support.v7.app.AppCompatActivity

1610123463277.png
 

Attachments

  • test.zip
    9.4 KB · Views: 356

ArminKh1993

Active Member
I think i know problem... is a AppCompat 4.0 library ...
B4X:
#Extends: android.support.v7.app.AppCompatActivity

View attachment 105744

this is not related to appcompat.
in-app update is using google core library

sorry it's not possible to test your project without real packagename and signKey as i said at first post
if you want you can send me in pv and i will check it.
 

scsjc

Well-Known Member
Licensed User
Longtime User
this is not related to appcompat.
in-app update is using google core library

sorry it's not possible to test your project without real packagename and signKey as i said at first post
if you want you can send me in pv and i will check it.


You're absolutely right, ... the ruling in my case was simpler.

When I launch the application for the first time, if the user is not logged in, I launch a new activity called "login" and close the main activity with Activity.finish

This causes the InAppUpdate to be running and returns to "Sub InAppUpdate_onAppUpdateInfoReceived" but the activity has already been completed, and at this point it gives that error.

I have solved it by putting an "If IsPaused (Me) Then Return" inside the "Sub InAppUpdate_onAppUpdateInfoReceived" so that it is not executed if it is paused, and it solves the problem



B4X:
Private Sub InAppUpdate_onAppUpdateInfoReceived(success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
    If IsPaused(Me) Then Return
    Log($"InAppUpdate_onAppUpdateInfoReceived, Success: ${success}"$)
  
    If success Then
        If inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS Or inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_AVAILABLE Then
            InAppUpdate.startImmediateUpdateFlow
        End If
    End If
End Sub
 

ArminKh1993

Active Member
You're absolutely right, ... the ruling in my case was simpler.

When I launch the application for the first time, if the user is not logged in, I launch a new activity called "login" and close the main activity with Activity.finish

This causes the InAppUpdate to be running and returns to "Sub InAppUpdate_onAppUpdateInfoReceived" but the activity has already been completed, and at this point it gives that error.

I have solved it by putting an "If IsPaused (Me) Then Return" inside the "Sub InAppUpdate_onAppUpdateInfoReceived" so that it is not executed if it is paused, and it solves the problem



B4X:
Private Sub InAppUpdate_onAppUpdateInfoReceived(success As Boolean, inAppUpdateInfo As InAppUpdateInfo)
    If IsPaused(Me) Then Return
    Log($"InAppUpdate_onAppUpdateInfoReceived, Success: ${success}"$)

    If success Then
        If inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS Or inAppUpdateInfo.updateAvailability = inAppUpdateInfo.UPDATE_AVAILABILITY_AVAILABLE Then
            InAppUpdate.startImmediateUpdateFlow
        End If
    End If
End Sub
Thanks for sharing your experience
I will fix this problem internally in the next update of the library.
I think using raiseEventFromDifferentThread instead of raiseEvent will fix it.
 
Top