B4A Library AppUpdating - automate apps updating from a webserver

Discussion in 'Additional libraries, classes and official updates' started by udg, Feb 13, 2014.

  1. udg

    udg Expert Licensed User

    Important note: since all the changes made to the Android OS the original code is to be considered outdated. Thanks to @Yayou49 you may find at post#290 a version of the class usable on Android 6+ versions.

    Note: version 1.25 breaks existing code so, please, read changelog in post #60 below.


    Hi all,

    this is my first contributing lib to this great NG.
    How do I dare to publish such a low-grade stuff in an area where generally you may find real masterpieces of programming? Well, to be honest, I hope in your help to upgrade my work to a status of "ready-made solution" for those who prefer to run their own webservers where to publish apps.
    Secondly, I was asked (both privately and publicly) to overcome my legitimate embarassment and go on with the publication. So, here we are: AppUpdating 1.18!

    Note: any valid code fragment comes from some other thread, while all the bad stuff is entirely mine ;-)

    Please find attached both the library as is (yes, it works out of the box) and its source code.

    On a following post I'm gonna describe the lib in greater detail and show how to use it.

    Umberto

    AppUpdating version history

    * version 1.30 (read notes on post #228)
    • compiled with okHttp 1.01 and okHttpUtils 2.20
    • removed files for version 1.25

    * version 1.26 (read notes on post #84)
    • added property WebChangeLog to read optional app's version changelog data
    • better management of versioning in the info file
    • removed files for version 1.18 to avoid confusion (still available on request)
    * version 1.25
    * version 1.18
    • initial release
     

    Attached Files:

    Last edited: Mar 28, 2018
    yiankos1, smallqiang, scsjc and 17 others like this.
  2. udg

    udg Expert Licensed User

    Edit: please refer to post #62 for instructions updated to version 1.25 and up.

    AppUpdating - how to use it

    As usual with any contributed library, download its zip (AppUpdating_118.zip, you need just this one), unzip it and place both files (.xml and .jar) in your additional libraries path (see menu option "Tools/Configure paths" in your B4A installation).

    Now, for any app that you'd like to use this lib with, go to its Manifest editor ("Project/Manifest Editor") and add the following code:
    Code:
    AddReceiverText(eu.dgconsulting.appupdating.newinst2,
      <
    intent-filter>
      <action android:name=
    "android.intent.action.PACKAGE_REPLACED" />
        <data android:scheme=
    "package" />
      </
    intent-filter>)
    In your app's Main you have to:

    0. Put a version number in "#VersionName:" key in Module Attributes. As an example: #VersionName:1.14

    1. dim a variable to access the lib's class; do this in Sub Globals
    Code:
    Sub Globals
      ... 
    'your code here
      Dim apkupdt As cl_appupdate
    End Sub
    2. Add code to Activity_Create to access any desired function in the lib
    Code:
    Sub Activity_Create(FirstTime As Boolean)
       
    If FirstTime Then
         ... 
    'any specific code for your app initialization
       End If
       
    Activity.LoadLayout("Main")
       .... 
    'more stuff
       If FirstTime Then
         apkupdt.Initialize(Me,
    "tab1")                   'tab1 has no meaning; use any name you like
         'this is yor app's package name (see "Project/Package name")
         apkupdt.PackageName = "eu.dgconsulting.tmb"
         
    'this is the complete path to the text file holding the newer version number  
         apkupdt.NewVerTxt = "http://umbetest.web44.net/p_apk/tmb.txt" 
         
    'this is the complete path to your newer apk
         apkupdt.NewVerApk = "http://umbetest.web44.net/p_apk/tmb.apk"
         apkupdt.UserName = 
    "test"         'needed since folder p_apk has access restrictions
         apkupdt.UserPassword = "test"    'as above
         'not needed- just to show use of function GetCurVN
         Log("I am version: " & apkupdt.GetCurVN)
         
    'use only if you like to show a splash screen while update checking goes on
         apkupdt.SetAndStartSplashScreen(Activity,LoadBitmap(File.DirAssets, "tmb0.png"))
         
    'this function starts checking for any newer version of the current app
         apkupdt.LookForNewVersion                                                      
      
    End If
    End Sub
    3. Receive feedback from the lib
    Code:
    Sub tab1_UpdateComplete
       
    If apkupdt.IsDone Then
         
    Log("New Ver available: " & apkupdt.NewVerAvailable)
         
    Log("Status: "  & apkupdt.Status)
         apkupdt.StopSplashScreen
         
    If apkupdt.Status = 6 Then
           
    Log(apkupdt.PackageName)
         
    End If
      
    End If
    End Sub
    Note: sub name above is made up by a first part ("tab1") choosen by you (see apkupdt.Initialize in Activity_Create) and a second mandatory substring ("_UpdateComplete") as coded in the class part of the lib.

    That's all for blindingly using the lib as is (well, that's all for the coding aspect of it..)!

    AppUpdating - set the webserver
    This one is easy.
    On a webserver (even any free shared service would be ok), create a folder (in the example above, I created folder p_apk on webserver umbetest.web44.net) and eventually restrict access to it (I used the .htaccess method).
    Prepare a text file named after your apk (in the example above, you may find tmb.apk and tmb.txt) having one single line of text as follows:
    ver=x.yz
    where x.yz is the newer apk version. Due to my laziness, currently the lib takes for granted that the version number starts on the 5th char..
    Then, using any FTP client, copy both your newer apk's version and its corresponding text file in the folder set before.

    That's all.

    What the lib does is simply to check whether the version written in the text file is greater then the one showed in the running copy of your app.
    If it finds indication of a newer version, it downloads it, then ask the user to install it.
    Since we can't know if the user agrees to update the app, we simply go on with our app, knowing that a service burned in the lib will fire when the OS signals that the user accepted to install the newly downloaded copy of the app. In this latter case, the same service will reload the app when ready.

    Umberto
     
    Last edited: Aug 7, 2016
    Meigionel TS, MhdBoy, Xicu and 5 others like this.
  3. shashkiranr

    shashkiranr Active Member Licensed User

    I liked your app. If you can make the UI more appealing it can definitely be a hit :)
     
  4. JakeBullet70

    JakeBullet70 Well-Known Member Licensed User

    Thanks so much for this! Works great!
     
  5. udg

    udg Expert Licensed User

    @shashkiranr: are you talking about tmb? That's an half-done project and indeed the reason which I wrote AppUpdating for.
    @jake: glad you liked it; I was afraid of more than justified complains about the broken code due to this library version..

    A few easy improvements really needed:
    1. having a single text file for multiple apps
    2. catching a few error conditions like files missing, wrong path..
    3. maybe having the service simply set a status code and wait for Main to call app reloading (I'm not sure whether I prefer an all automated app updating or a few subs to call at will)

    Umberto
     
    Last edited: Feb 13, 2014
  6. JakeBullet70

    JakeBullet70 Well-Known Member Licensed User

    Umberto,

    this is fine for a Version 1.x ... I always ask myself... Does it work?
    In this case its YES, it works!!!

    Thanks for the source code. :)
     
  7. krzyszp

    krzyszp Member Licensed User

    If you use HttpUtils library app doesn't compile and shows error message with your library:
    "HttpUtils2Service is declared twice. You should either remove the library reference or the code module."

    Can you fix this as your library will be VERY usefully, please?

    Update:

    Problem solved - if you need to use thislibrary with HTTP library, you need to remove HttpUtil2Service module from your source code...
     
    Last edited: Feb 21, 2014
  8. udg

    udg Expert Licensed User

    Hi krzyszp,

    unfortunately I read your message too late to be of any help, but I'm glad to hear you solved it.
    So, to use AppUpdating with any app that needs HTTPUtils2, you simply uncheck this last library reference in your app since it's already checked and used in AppUpdating; right?

    Libraries used by AppUpdating: HttpUtils2, Phone, Reflection.

    Umberto
     
  9. krzyszp

    krzyszp Member Licensed User

    Also I had to remove HttpUtils2Service service module from my source code as is already implemented in your library.
     
  10. DonManfred

    DonManfred Expert Licensed User

    No. Putting a reference in libtab to httputils2 and so on is correct and it´s needed.
    BUT the "Module httputils2service" he had to remove from his own project cause he already included it.
    With using your lib there is no need to include the module httputils2service(.bas) in own app cause it is already part of your lib.
     
  11. DonManfred

    DonManfred Expert Licensed User

    For anyone who have problems setting it up. Here is a little example. It updates itself from 1.0 to 1.2 after click on a button.
     

    Attached Files:

    naifnas, jahswani and Theera like this.
  12. udg

    udg Expert Licensed User

    Hi Manfred,

    thank you for your example and explanation about the "module problem".
    I indeed missed the point about the "module" 'cause I was still thinking in terms of libraries, so didn't understand correctly what krzyszp had to leave out of his project.

    I'm considering File.ReadMap / File.ReadList as candidates to read a single text file containing references to multiple app projects in the form of lines such as:
    <project name> = <version number> 'e.g. com.test.myapp = 1.21
    What do you think?
    I'll leave as is the idea of full path to both text and apk files, so you could even store them on different places, but augment the text file in order to have a single check_version.txt file for many apps.

    Regards,

    Umberto
     
  13. DonManfred

    DonManfred Expert Licensed User

    and after reading this new list you will do what?
    Iterate through all packages listet in packatmanager to find out if one or more of the listet apps are installed on this device?
     
  14. udg

    udg Expert Licensed User

    More or less..
    I'd only look for the currently executing project and check its version number.
    In this context, the goal remains the original one, to update the running app.

    But we could even think of something similar to the play store service: something that, reading the webserver list, checks for updates of many device installed apps and then notify the user about the possible upgrade. Don't know, just thinking aloud..

    Regards,
    Umberto
     
  15. udg

    udg Expert Licensed User

    Hi Manfred,

    using your example code as is it shows a warning when I apply for the newer version to be installed: it says that it won't install it due to a conflict related to app signing. I believe it's related to my compiling in release mode so "ver1.00" has my signing while "ver1.20" on your webserver sports your own signing and that causes the warning.
    Should we instruct people to experiment with debug setting instead of release?

    I liked a lot the image you used for the update waiting!
    One thing I'd modify in the example is the usage of PackageManager to retrieve current version, since that could be easily accomplished by using lib function GetCurVN, although we should add something (in the lib) to cover the VersionCode aspect of it.

    If you don't mind I'll use most of your code to build another example code where the user can choose between just discovering if any update exists or going for it all the way down.

    Umberto
     
  16. DonManfred

    DonManfred Expert Licensed User

    maybe the struct of the file should be changed somehow...

    This list can be easily splitted into it parts (regex.split) and you have all needed informations in this line. name of package, versionname and apk-file which have to be downloaded.
     
  17. DonManfred

    DonManfred Expert Licensed User

    Ahh, yes... the file on my server is signed with MY key. You have compiled with YOUR key... I´ll extend the demoexample to a b4a-file for each version to start...
     
  18. Steve Miller

    Steve Miller Active Member Licensed User

    I'm having trouble finding the apk for some reason. It connects to my site, finds there is a new version, but then I get a not found error. I verified the name of my project is correct, and the APK I uploaded to the website is the one found in the Objects folder.

    Code:
    ** Activity (main) Create, isFirst = true **
    ---- GetCurVN
    Current Version: 
    1.00
    ---- GetWebVN
    ** 
    Activity (main) Resume **
    ** 
    Service (newinst2) Create **
    -- AppUpdating.NewInst2: 
    service created
    ** 
    Service (newinst2) Start **
    -- AppUpdating.NewInst2: processing service_start
    intent: (IntentIntent { act=android.intent.action.PACKAGE_REPLACED dat=package:b4a.CustomerTablet flg=0x8000010 cmp=b4a.CustomerTablet/eu.dgconsulting.appupdating.newinst2$newinst2_BR (has extras) }
    action: android.intent.action.PACKAGE_REPLACED
    extra: Bundle[{android.intent.extra.REPLACING=true, android.intent.extra.UID=10152, android.intent.extra.user_handle=0}]
    Data: package:b4a.CustomerTablet
    package REPLACED intent received!
    package: b4a.CustomerTablet
    -- AppUpdating.NewInst2: processing MyAppReload
    ** Service (httputils2service) Create **
    ** Service (httputils2service) Start **
    ----AppUpdating.JobDone --
    JobName = Job3, Success = true
    Read while in job3: ver=1.01
    Web version number: 1.01
    Newer version available. Now I try its downloading
    ---- UpdateApk
    ----AppUpdating.JobDone --
    JobName = Jobapk, Success = false
    Error: Not Found
    Status: -100
    New Ver available: true
    Status: -100
     
  19. DonManfred

    DonManfred Expert Licensed User

    To what you have the following set in your code? Maybe upload your project (Export as zip)

    Code:
    apkupdt.PackageName = ????
    apkupdt.NewVerTxt = ???
    apkupdt.NewVerApk = ???
     
  20. Steve Miller

    Steve Miller Active Member Licensed User

    Hey Don,

    apkupdt.PackageName = b4a.CustomerTablet. This is what it is in Project|Package Name.
    apkupdt.NewVerTxt = "http://www.xxxx.us/CustomerTablet/version.txt"
    apkupdt.NewVerApk = "http://www.xxxx.us/CustomerTablet/CustomerTablet.apk"

    No, this isn't a porn site (denoted by the xxxx in the address). It's a site that I own that I can't give out the address to because it has beta software being tested on it at the moment and is not locked down. Also, can't upload the project either for same reasons.

    Also, I implemented a button do a check also, but that just hangs with the following when clicked:

    ---- GetCurVN
    Current Version: 1.00
    ---- GetWebVN
     
Loading...