Android Question Install new apk version from the apk itself.

vecino

Well-Known Member
Licensed User
Longtime User
Hello, from my apk I download a new version and I run the new apk to install it.
I always get the error: "Application not installed"
Is it possible to install an apk from an apk?
Taking into account that it is the same apk, although a different version.
They have the same name and are running.
I have tried the code of several similar threads, although I do not know if those examples are designed to run another different apk or, what I want to do, is the same apk.
 

vecino

Well-Known Member
Licensed User
Longtime User
Hello, thank you both.
I have a doubt.
It is a project with sdk 15
Does it have to be sdk 26?
 
Upvote 0

udg

Expert
Licensed User
Longtime User
It depends.
API 26 is mandatory when publishing on Google PlayStore. Since your are managing your own update mechanism I guess you're using your proprietary store (webserver) so you should be ok with any API version.
But I find it wise to consider all the new features added to APIs from 15 on. Just have a look at the history changes and evaluate if they are of any interest for your project.
BTW, updating B4A to its latest versions would be highly reccomended.
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Yes, I use the latest version of B4A.
The project is a software for POS that has about a thousand users and works with android 4.4
It has many connected devices and I need them to keep working with sdk 15
 
Upvote 0

udg

Expert
Licensed User
Longtime User
OK. I'm not 100% sure that AppUpdating 2 will work for your current installation (that's because I can't recall what I deeply changed from its predecessor).
Eventually have a look at AppUpdating 1.x available here. Don't use the version from post #290 because it is intended for API 26 as much as AppUpdating 2.00 is.
I planned to release a final version for AU 1, but it will take some time since I'm really that busy these days. Sorry.
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Hi, I am testing the example of your AppUpdating200 library and clicking the "Download apk" button shows the error:


Web version number: 2.11
UpdateComplete - time: 23:43:04
---- AppUpdating.DownloadApk
java.io.FileNotFoundException: /mnt/sdcard/Android/data/b4a.example.appupdate2/files/shared/tmp.apk: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:409)
at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
at anywheresoftware.b4a.objects.streams.File.OpenOutput(File.java:448)
at eu.dgconsulting.appupdating.cl_appupdate$ResumableSub_DownloadApk.resume(cl_appupdate.java:294)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:245)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:185)
at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1154)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
at libcore.io.IoBridge.open(IoBridge.java:393)
... 15 more
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi @vecino ,
I tried myself the AppUpdate Example right now (recently I modified folder structure and permissions on my webserver) and all worked flawlessly.
Please find in the spoiler below the content of the my Log window while executing the step-by-step procedure.
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
---- AppUpdating.ReadCurVN
Current Version: 2.01
UpdateComplete - time: 09:11:54
---- AppUpdating.ReadWebVN
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Webserver's info file content:
ver=2.11
<ChangeLog>
ver 1.01 - initial release
ver 1.87 - added status codes
ver 2.11 - bug fixes
</ChangeLog>
<FileSize>
1042287
</FileSize>
Web version number: 2.11
UpdateComplete - time: 09:11:56
---- AppUpdating.DownloadApk
new apk version downloaded and ready to install
UpdateComplete - time: 09:12:01
---- AppUpdating.InstallApk
user asked to install new apk
UpdateComplete - time: 09:12:05
** Activity (main) Pause, UserClosed = false ** <---Note: this shuts down running 2.01 version in order to start newer 2.11 one
** Receiver (newinst2) OnReceive **
*** Service (starter) Create ***
** Service (starter) Start **
** Service (newinst2) Create **
---- AppUpdating.newinst2: service created
** Service (newinst2) Start **
---- AppUpdating.newinst2: service_started
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
---- AppUpdating.ReadCurVN
Current Version: 2.11
UpdateComplete - time: 09:12:20
---- AppUpdating.ReadWebVN
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Webserver's info file content:
ver=2.11
<ChangeLog>
ver 1.01 - initial release
ver 1.87 - added status codes
ver 2.11 - bug fixes
</ChangeLog>
<FileSize>
1042287
</FileSize>
Web version number: 2.11
UpdateComplete - time: 09:12:22
---- AppUpdating.DownloadApk Note: although current and web versions are the same I ask to download from web again (just to test it)
new apk version downloaded and ready to install
UpdateComplete - time: 09:12:26

An error we should expect is that signature from your compiled AppUpdate Example 2.01 (the one you downlaod from the Forum) and signature from AppUpdate Example 2.11 on my webserver don't match, so installation should fail. To test the whole cycle you should place a copy of AU Example compiled by you on your webserver, prepare the info file accordingly and finally run the "old" copy of AU Example. This way, since both copies are signed by you, the download and installation steps should work.

All the above as a general reply. Your error seems to shows a failure about permissions on a specific path (/mnt/sdcard/Android/data/b4a.example.appupdate2/files/shared/tmp.apk). Let me modify AU lib in order to give feedback about the path used so we'll know more.

Update: on my 4.4.4 device the path is: /storage/emulated/0/Android/data/b4a.example.appupdate2/files/shared/tmp.apk
Keep in mind that AU 2.00 to determine the path to use for its temporary storage uses the code below:
B4X:
Dim p As Phone
   If p.SdkVersion >= 24 Or File.ExternalWritable = False Then
       UseFileProvider = True
       SharedFolder = File.Combine(File.DirInternal, "shared")
       File.MakeDir("", SharedFolder)
   Else
       UseFileProvider = False
       SharedFolder = rp.GetSafeDirDefaultExternal("shared")
   End If
 
Last edited:
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Hi, what is eu.dgconsulting.appupdating.newinst2? With what do I substitute it?

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

udg

Expert
Licensed User
Longtime User
That is the service (inside the lib) that the OS calls when a new package is installed. You should not substitute it, unless you modify the lib's code to derive a proprietary fork of it.
Recently we discussed about substituting android.intent.action.PACKAGE_REPLACED with android.intent.action.MY_PACKAGE_REPLACED, but I hadn't time to test it.
Main benefit will be that the OS will call the service ONLY when there's an update for that specific package. as of today the service is called whenever any package on the device gets updated (and I always found it annoying).
BTW, from Oreo on it seems we should go the "my package" road anyway. As soon as I'm ready I'll publish an update of the lib (AU 2.05), probabily with that substitution only (and a few lines of code in the service itself).
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
I'm going to do a small test project. I'm too confused
I inform you of the result.
Thanks and regards
 
Upvote 0

udg

Expert
Licensed User
Longtime User
No problem. If it doesn't find the module check if the lib is installed (in your Additional libraries folder) and flagged (in your test program).
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Hello, I have created a simple test app.
The app only has a "1" in the version. The app that is on the web has a "2".
It is the only difference.
I have followed the steps you indicate and I always get the same error:
Webserver's info file content:
ver=2
Web version number: 2
Current Version: 1
Newer version available. Now I try its downloading
-- TryApkUpdate
failed download of new apk version
UpdateComplete - time: 20:59:05
** Activity (main) Pause, UserClosed = true **
I attached the test program in case you have time to take a look.
Thank you.
 

Attachments

  • viamos.zip
    30 KB · Views: 266
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi @vecino
I tried your code and it works ok on my phone (the only expected error is raised when I allow the installation of the new apk since the one on the webserver is signed differently from the running one).
Here it is my log:
*** Service (starter) Create ***
** Service (starter) Start **
*** Service (newinst2) Create ***
---- AppUpdating.newinst2: service created
** Service (newinst2) Start **
---- AppUpdating.newinst2: service_started
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
---- AppUpdating.UpdateApk
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Webserver's info file content:
ver=2
Web version number: 2
Current Version: 1
Newer version available. Now I try its downloading
-- TryApkUpdate
new apk version downloaded and ready to install
user asked to install new apk
UpdateComplete - time: 11:11:09
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume ** <-- after failure to install
** Activity (main) Pause, UserClosed = true **

The error you published indicates a failure in sub TryApkUpdate, specifically at the Try..Catch block (rows 256..268) where the chosen path is the "catch" one. That means that File.Copy2 fails and our suspects should go to SharedFolder. Please insert a log there to print out the value for SharedFolder.

Another test you can do is calling tha update methods one after the other (mainly DownloadApk and InstallApk). This way we will know for sure if the probolem is with the downloading (I doubt it) or the writing of the temp file to a protected area (this is my main suspect).
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Oh, I do not understand it :confused:
I have seen that procedure CheckInstallationRequirements returns true.
It only goes through the final "else".

B4X:
Private Sub CheckInstallationRequirements As ResumableSub
    If File.ExternalWritable = False Then
        MsgboxAsync("Storage card not available. Make sure that your device is not connected in USB storage mode.", "")
        Return False
    Else If phone.SdkVersion >= 26 And apkupdt.CanRequestPackageInstalls = False Then
        MsgboxAsync("Please allow me to install applications.", "")
        Wait For Msgbox_Result(Result As Int)
        Dim in As Intent
        in.Initialize("android.settings.MANAGE_UNKNOWN_APP_SOURCES", "package:" & Application.PackageName)
        StartActivity(in)
        Wait For Activity_Resume '<-- wait for Activity_Resume
        Return apkupdt.CanRequestPackageInstalls
    Else If apkupdt.CheckNonMarketAppsEnabled = False Then
        MsgboxAsync("Please enable installation of non-market applications." & CRLF & "Under Settings - Security - Unknown sources" _
            & CRLF & "Or Settings - Applications - Unknown sources", "")
        Return False
    Else 
        Return True   '   <------- It only goes through here. -------------------------
    End If
End Sub

EDIT: Forget this message. I am confused with so many tests.
 
Last edited:
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Wow, the above is correct, the problem is that it does not download the apk file for any reason that I do not know.
 
Upvote 0

vecino

Well-Known Member
Licensed User
Longtime User
Hi, I've tried it on another device and it worked fine, I do not know why it does not work on my usual test device.
Although something strange happens, the update must be executed when I press the button (you have seen the test program), however, the update is executed when I start the program, WITHOUT PRESSING THE BUTTON.
Why can it happen?
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Sorry, but I'm a bit confused now.
You have a device for which the code doesn't work, right?
And a second device that executes the updated code on program start instead of after pressing the "1" button, right?

In post #18, when you say that it doesn't download the apk file, are you talking about the first device? Are you 100% sure that it's the downloading step at failure rather than the writing after the download (httpjob vs. File.Copy2)? Did you insert a few log statements in the cl_appupdate class to clearly spot the problematic step?

As for the retarded upgrading on device #2, what I can say is that the code just send an intent to the OS, which in turn asks the user to allow the installation of the new apk and (on positive) response broadcasts the "android.intent.action.PACKAGE_REPLACED" intent whose action is to wake up any app on the device which has it in the Manifest. Reading the content of the data in this latter intent, service newinst2 (in the library) knows that it's its turn to execute (we're now on the new apk) and launches Main.
Why all that doesn't happen a few seconds after pressing the "1" button but only closing the running app and starting it again, I don't know. Maybe you can try to give the OS more time after pressing the "1" button and see if it completes the loop described above.

ps: let me know if you'd like me to prepare a special version of the lib full of logs in order to better undesrtand the probolem about device #1 or whether you prefer to do it yourself.
 
Upvote 0
Top