Android Question Relaunch an updated app

udg

Expert
Licensed User
Longtime User
Hi all,

I'd like to add a final feature to my AppUpdating lib: automatic relaunch when a newer version was installed.
So far I simply reached the point where through an intent the user is asked whether to install the newly downloaded version of the executing app.

I don't know if it is the right way to do it, but I would add a service to that lib and look for a system message about "installation done" for my package. If and when this message is intercepted then the executing app simply starts "itself" (the newer version) again.

Is it feasible? Is this the way B4A-Bridge works?

And, more important, have you any suggestions or, better, some working code? TIA

Umberto
 

udg

Expert
Licensed User
Longtime User
Thanks Erel.

More stuff to study..just what I needed for the weekend :)

I'll be back here with more questions once my attempts will fail for at least the n-th time!

Thank you again.

Umberto
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Erel,

I read the thread you suggested, but I'm not sure I fully understand it.
So far I modified the library manifest tis way:
B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
  android:normalScreens="true"
  android:smallScreens="true"
  android:anyDensity="true"/>)
AddReceiverText(newinst,
  <intent-filter>
  <action android:name="android.intent.action.PACKAGE_REPLACED" />
  <data android:scheme="package" />
  </intent-filter>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

Where newinst is the name of the service module added to the lib.
Then in Service_Start I have
B4X:
If StartingIntent.Action = "PACKAGE_REPLACED" Then
    cbk = StartingIntent.GetExtra("Mykey")
     pkg = StartingIntent.GetExtra("Mypkg")
    MyAppReload
   End If
where MyAppReload, local to the service, should operate to effectively reload the newly installed app.

Now, if I don't start the service from main activity in the app using the lib, newinst is never activated.
The problem here is that main app never knows whether the user effectively installed the newer version so there's no point where it can start the service.
I exepected the operating system to propagate a PACKAGE_REPLACED message and the newinst service, listening in the background, to intercept that message and command app reload (only if the app to which the message refers is the current one).

Can you help some more? TIA

Umberto
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Erel,

I replaced the wrong line with
B4X:
If StartingIntent.Action = "android.intent.action.PACKAGE_REPLACED" Then

but the service is never called anyway.
Using logs I can follow my lib to the point where the following code is executed
B4X:
'intent to install
  Dim i As Intent
  i.Initialize(i.ACTION_VIEW, "file://" & File.Combine(File.DirDefaultExternal, "temp.apk"))
  i.SetType("application/vnd.android.package-archive")
  StartActivity(i)
  sStatusCode = 6 ' user asked to install this newer version
then the lib passes control to the callback function in the app's main (where I corretly read status code) and the OS shows the "do you want to install a newer version of this app" dialog. If I go with installation I'm returned to the 4A-Bridge screen (on the device) and message "PackageAdded: .." is shown in the log.

I suspect the "problem" has something to do with the intent for app installation.

Umberto
 
Upvote 0

udg

Expert
Licensed User
Longtime User
SOLVED!

I simply used CleanMaster to clean my device's cache and tried again..now it works!

Thanks for your help.

Umberto
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Erel,

I need your help again on this reloading stuff.
As said in my prev message, everything worked as expected, BUT yesterday I downloaded a couple of apps from the Google Play store and when I executed the installation.. my app unexpectedly loaded and put itself on the foreground!
Note that I previously didn't launch it at any time during the day, so this seems a case of "auto-loading" due to some intercepted intent o something similar.

Here is my code so far:

Manifest
B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
  android:normalScreens="true"
  android:smallScreens="true"
  android:anyDensity="true"/>)
AddReceiverText(newinst,
  <intent-filter>
    <action android:name="android.intent.action.PACKAGE_REPLACED" />
    <data android:scheme="package" />
  </intent-filter>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

Service in the lib (newinst) used to check for eventual newer version of my app, download it, wait for user installation and then reload the app
B4X:
Sub Service_Start (StartingIntent As Intent)
   If StartingIntent.Action = "android.intent.action.PACKAGE_REPLACED" Then
   pkg = StartingIntent.GetData
   pkg = pkg.SubString(8)           'discarding "package:"
    MyappReload
   End If
End Sub

Could it be the unlucky choice for the name of the service (newinst)?

Umberto
 
Upvote 0

qsrtech

Active Member
Licensed User
Longtime User
Service in the lib (newinst) used to check for eventual newer version of my app, download it, wait for user installation and then reload the app
Code:
Sub Service_Start (StartingIntent AsIntent)If StartingIntent.Action = "android.intent.action.PACKAGE_REPLACED"Then
pkg = StartingIntent.GetData
pkg = pkg.SubString(8) 'discarding "package:" MyappReloadEndIfEnd Sub

You need to test if the "package" is your package something like:
B4X:
Sub GetPackageName As String
    Dim r As Reflector
    Return r.GetStaticField("anywheresoftware.b4a.BA", "packageName")
End Sub

Sub Service_Start (StartingIntent AsIntent)
    If StartingIntent.Action = "android.intent.action.PACKAGE_REPLACED" Then       
        If StartingIntent.GetData="package:" & GetPackageName Then
             MyappReload
        End If
    End If
End Sub
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi qsrtech,

thanks for your help. BTW, I'm following your threads about your efforts to deliver a push updating service in a library and I'm glad to see you're next to be ready..

Since I never used a reflector before, please specify whether I'm expected to copy the above function as is or should I substitute my data in it?
Actually I have this library named appupdating made up of a class named AppUpdating and a service named newinst.
Class AppUpdating has a property named sPackageName.
So, should I change your example code to:
B4X:
Sub GetPackageName As String
  Dim r As Reflector
     Return r.GetStaticField("eu.dgconsulting.AppUpdating", "sPackageName")
End Sub
To take in account both lib name and class name, probabily its first parameter should be:
eu.dgconsulting.appupdating.AppUpdating
but here I absolutely don't know what I'm doing... sigh!

Umberto
 
Upvote 0

qsrtech

Active Member
Licensed User
Longtime User
I don't think you want to use the package name of your library. It's the final app that us e's your library that will be updated (replaced) so I think you just use my code as is. Seems to work for me as I use almost identical code, except the name of the sub to call.
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi qrstech,

thanks again for your support. Currently I'm experiencing an odd behaviour: my service (again, see post #6 above) is never called.
I put a log command both on service_create and service_start and none of this appear on the log panel, so there's somenthing in my device's config that stops messages/intents propagation, I think.
This time, using CleanMaster did't help.

Umberto
 
Upvote 0

qsrtech

Active Member
Licensed User
Longtime User
Hmm. I think i know your issue. If you're using the "service" in a library, you'll need to use the manifest code in the app that uses you're library. As well, you'll need to add you're library's package name "eu.dgconsulting.AppUpdating"

B4X:
AddReceiverText(eu.dgconsulting.appupdating.newinst,
  <intent-filter>
    <action android:name="android.intent.action.PACKAGE_REPLACED" />
    <data android:scheme="package" />
  </intent-filter>)

note: that goes in any app that is going to use your library
 
Upvote 0

qsrtech

Active Member
Licensed User
Longtime User
I would add in your MyAppReload you might want to try something like ispaused(Main) before reloading it cause you might get it double loading.
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Thanks alot, qsrtech!

Adapting the intent filter for the app manifest caused the service in the library to be called. Now, do I have to eliminate the almost identical text in the lib's manifest?

Function GetPackageName returned exactly to your version.

MyAppReload is now called but no reloading is done. Can you suggest how to modify its code?
B4X:
Sub MyAppReload
   Dim In As Intent
   Dim pm As PackageManager
   In = pm.GetApplicationIntent(pkg)
   Log("MyAppReload: main app should reload soon")
  StartActivity(In)
 End Sub
here pkg is a service process-globals var getting its value as "pkg = GetPackageName" in service-start.

My final goal is to have a working lib to publish in the contributed area of the forum along with its source code.
Even better if we could publish our libs together so to offer two distint ways to achieve own's app auto-updating.

Umberto


Umberto
 
Upvote 0

qsrtech

Active Member
Licensed User
Longtime User
Can you try just startactivity(main) vs all the intent stuff?

B4X:
Sub MyAppReload  
    If IsPaused(main) Then
        StartActivity(main)
    End If
End Sub

Now, do I have to eliminate the almost identical text in the lib's manifest?
YES
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
My AppReload is part of the service, so reducing it to StartActivity(Main) gives me the following error while compiling the lib:
"Error description: Cannot access excluded module: main
Occurred on line: 52
StartActivity(Main)"

I then tried with StartActivity("main") since an error in log showed that this last parameter is concatenated to my package name.
I removed the intent-filter stuff from my lib's Manifest.
Please find here the whole service, as it is now:
B4X:
#Region  Service Attributes
   #StartAtBoot: False
#End Region

Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim pkg As String
End Sub

Sub Service_Create
  Log("Service newinst create")
   pkg = ""
End Sub

Sub Service_Start (StartingIntent As Intent)
   Log("Service newinst: enter service_start")
   Log("intent: " & StartingIntent)
   Log("action: " & StartingIntent.Action)
   Log("extra: " & StartingIntent.ExtrasToString)
   Log("Data: " & StartingIntent.GetData)
   If StartingIntent.Action = "android.intent.action.PACKAGE_REPLACED" Then
     Log("pack replaced")
     pkg = GetPackageName
     If StartingIntent.GetData="package:" & pkg Then
       MyAppReload
    End If
  End If
End Sub

Sub Service_Destroy
End Sub

Sub GetPackageName As String
  Dim r As Reflector
  Return r.GetStaticField("anywheresoftware.b4a.BA", "packageName")
End Sub

Sub MyAppReload
  Log("MyAppReload: ")
  StartActivity("main")
End Sub

Umberto
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Erel,
it seems that this old thread was truncated somehow. I doubt that after post #17 by me (Jan 2014) it follows post #18 from you today.
My intention here is to alert about a possible developing corruption in the Forum.

udg
 
Upvote 0
Top