B4A Library AppUpdating - automate apps updating from a webserver

Status
Not open for further replies.
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
 

Attachments

  • AppUpdating_126_ex.zip
    28.3 KB · Views: 1,167
  • AppUpdating_126.zip
    11.3 KB · Views: 1,222
  • AppUpdating_126_src.zip
    10.8 KB · Views: 981
  • AppUpdating_130.zip
    11.4 KB · Views: 1,204
  • AppUpdating_130_src.zip
    15.7 KB · Views: 1,113
  • AppUpdating_130_ex.zip
    33.4 KB · Views: 1,318
Last edited:

udg

Expert
Licensed User
Longtime 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:
B4X:
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
B4X:
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
B4X:
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
B4X:
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:

udg

Expert
Licensed User
Longtime 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:

JakeBullet70

Well-Known Member
Licensed User
Longtime 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. :)
 

krzyszp

Member
Licensed User
Longtime 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:

udg

Expert
Licensed User
Longtime 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
 

DonManfred

Expert
Licensed User
Longtime User
you simply uncheck this last library reference in your app since it's already checked and used in AppUpdating; right?

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.
 

udg

Expert
Licensed User
Longtime 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
 

udg

Expert
Licensed User
Longtime 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
 

udg

Expert
Licensed User
Longtime 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
 

DonManfred

Expert
Licensed User
Longtime User
maybe the struct of the file should be changed somehow...

b4a.example.appupdater,1.20,nameofapk.apk
b4a.example.otherapp,2.70,subfolder/nameofotherappapk.apk
b4a.example.thebest,4.70,/thebest/nameofthebestapk.apk

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.
 

DonManfred

Expert
Licensed User
Longtime 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

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...
 

Steve Miller

Active Member
Licensed User
Longtime 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.

B4X:
** 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: (Intent) Intent { 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
 

Steve Miller

Active Member
Licensed User
Longtime 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
 
Status
Not open for further replies.
Top