When Users downloads the app via Flexible app update
appUpdateManager?.startUpdateFlowForResult(it, AppUpdateType.FLEXIBLE, activity, REQUEST_CODE_FLEXI_UPDATE)
but forgets or accidentally skips to click the restart app button which does following:
appUpdateManager?.completeUpdate()
Then app update is not available. Even I tried with clear app data, it doesn't work. Looks like once app is downloaded via inappupdate and skips installation, you're stuck, it doesn't ask again.
appUpdateManager?.appUpdateInfo?.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
updateAvailable.value = true
}
}
Is there a solution to this? Other things are working and it's live on playstore just looking for solution of such use-case.
Also how to get progress value of app being downloaded, couldn't find it in documentation. In my case, onActivityResult keeps calling but which key gives progress value?
Also facing another issue with different use case: java.lang.reflect.InvocationTargetException while inappupdate android if retries
You should check for appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED on app restart and call completeUpdate() at some point as per the documentation.
Related
I'm facing an interesting situation which I don't know how to resolve. When a user is signing into my app for the first time as an Android for Work user, I am obliged to make sure that the app is registered as a device manager. I check whether this is the case by calling DevicePolicyManager#isAdminActive, and if this returns false, then I launch an Intent with action=DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN, in order to launch the Android control which will enable device management. Once this has happened, when my app is launched again (or when it returns from the device management flow), the value of DevicePolicyManager#isAdminActive is checked again. If the user enabled device management, then everything is fine, and the app continues on its way.
Interestingly, this works exactly as expected the first time the user goes through our flow. Unfortunately, after a reboot, when the user starts up my app, it checks to make sure device management is still on, via DevicePolicyManager#isAdminActive, and here it gets interesting. DevicePolicyManager#isAdminActive will report false, which is verified by looking at the device security settings. Even worse, however, attempting to enable device management will result in the following exception:
W/DeviceAdminAdd: Exception trying to activate
admin ComponentInfo{com.mysoft.myapp/com.mysoft.core.receivers.MyAppAdminReceiver}
java.lang.IllegalArgumentException: Admin is already added
at android.os.Parcel.readException(Parcel.java:1550)
at android.os.Parcel.readException(Parcel.java:1499)
at android.app.enterprise.IEnterpriseDeviceManager$Stub$Proxy.setActiveAdmin(IEnterpriseDeviceManager.java:867)
at android.app.enterprise.EnterpriseDeviceManager.setActiveAdmin(EnterpriseDeviceManager.java:720)
at com.android.settings.DeviceAdminAdd.addAndFinish(DeviceAdminAdd.java:346)
at com.android.settings.DeviceAdminAdd$3.onClick(DeviceAdminAdd.java:313)
at android.view.View.performClick(View.java:5242)
at android.widget.TextView.performClick(TextView.java:10571)
at android.view.View$PerformClick.run(View.java:21196)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at ...
This exact exception appears on my logcat console even when I attempt to manually enable device management via the system security settings page, so I don't think the original Intent is malformed.
So, here's my problem: One call to the Android device management API tells me that my device administrator is not activated, but another call to the same API tells me that it is. I believe that the 2nd one is, in fact, in error, but without being able to activate the administration, my user is stuck in a loop and unable to use my app.
Has anyone else encountered this error, and if so, how do you code around it?
I have analyzed AOSP source of DevicePolicyManagerService.java. The function
which is failing in this case is called setActiveAdmin(), and it is throwing an
exception because it claims that our application has already been added as a device
administrator. This exception is being thrown from setActiveAdmin after a call
to getActiveAdminUncheckedLocked() returns a valid object, indicating that the
requested device administrator is active:
final ActiveAdmin existingAdmin
= getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (!refreshing && existingAdmin != null) {
throw new IllegalArgumentException("Admin is already added");
}
if (policy.mRemovingAdmins.contains(adminReceiver)) {
throw new IllegalArgumentException(
"Trying to set an admin which is being removed");
}
However, before this, we have already called DevicePolicyManager.isAdminActive,
which contains this logic:
return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
This is fine; this is exactly what we want. However, this is AOSP code. I theorized that there might be a different implementation on affected
devices, in which there is an error in the logic of
DevicePolicyManager#isAdminActive(), so that the call is returning false when it
should be returning true.
After deploying instrumentation to catch this condition in production, I have verified that this hypothesis is correct. Inferring from my metrics, implementations exist in the Android device population such that the value returned by isAdminActive(X) will return false, even though X will be found in the list of enumerated active administrators returned by getActiveAdmins(). This is, fortunately, not a common case, but it does exist. I would advise any coders who rely upon these calls to harden their code against this scenario.
I'm currently create an application that have the possibility to updated from own code thanks to a downloaded .apk from a server.
I would like to know if the update/Install of the app is successfull. Because currently the update working fine but i don't know if the installation/update is ok or not, if the installation face a problem or if the user cancel install or somethings else. So i need to have a callback "installFinish(boolean isOk)".
i search for a day but i don't find solution for my problem.
I read lot of things, particulary this :
How to find out when an installation is completed
or this :
Android - Install Application programmatically with result
but is not what i seach.
This is my code for update my app
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file.getAbsoluteFile()), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
((Activity) context).startActivity(intent);
EDIT
I tried this https://stackoverflow.com/questions/29175722/how-to-get-onactivityresult-called-from-action-view-intent
but it's not working for me for two reason i think:
I don't know whether the user pressed Cancel
onActivityResult is never call after updated the same app, maybe because it's the same app which updated the app who launch the intent is kill. ?
Maybe the last reason it's the same reason why i don't receive broadcastevent such as listening for ACTION_PACKAGE_ADDED in the app who launch the update.
Maybe i can call the method when the first time the application is launch, it's like install is successfully because the app is started.
Heres a work around which we use:
Implement a dummy provider and override onUpgrade().onUpgrade is called whenever database is upgraded.U will need maintain one to one mapping between database version and app version.
I think I need some help understanding how Bundles are handled on Destroy. I have an issue with my App where a bundle becomes null when its closed overnight or over several hours etc. But i cannot replicate this for debugging purposes. No matter what I do, the bundle remains intact after supposed forced destroys etc
To replicate the issue I've tried two different things:
Using the option under Developer options IIRC - Settings>Developer Options > Don't Keep activities.
Using the "STOP" button under eclipse DDMS.
Neither of these seem to remove the Bundle. Am I missing something, how is the bundle retained after a supposed full destroy?
I'm using a Nexus 5, android 4.4.2
I have a check in my "preferences" class, which firstly checks if Bundle variables are available from a logical previous/parent Activity, if not it reads from Android SharedPreferences. The problem is I must have an issue when I check the bundle is not null. So I need to debug this as its allowing null values to be set from the bundle to my "session" ID's
Am I missing something? Surely the bundle should be destroyed along with my App, but when using option 1) above, the Bundle still exists so i can't debug my IF statement. Option 2) is not useful because the stop button seems just to close the active Activity - my app steps backwards through the hierarchy of screens as I click stop. Again not destroying the entire application from memory. I must be missing something fundamental!
Cheers for any help.
BTW, I've search for all solutions on SO I could, everything just seems to be using the optoins above with no issues, is something possibly different with a my Android OS/Phone?
Edit: This article by Google shows the functionality I need but i assume this is an outdated article and its referring to what I try in option 1)? -
See "Immediately destroy activities" - developer.android.com/tools/debugging/debugging-devtools.html
Edit2: see the comments below I mistakenly thought the above Google doc was referring to removing an entire application from memory rather than just an Activity. Anyway for now I'll try something like this to check the bundle value
Long val = bundle.getLong(Navigator.INTENT_KEY_CHANNEL_ID, 0);
if (val != 0 && val != null) {
}
1- Launch your application
2- Press Home Button
3- Launch DDMS in Android Studio or Eclipse
4- Select your app and click stop
5- Choose your app launched app history
Thanks,
So in the documentation here
http://developer.android.com/google/play-services/setup.html
it says to check the status of play services with isGooglePlayServicesAvailable() and then display the error dialog if it's not okay.
This seems to be working fine for me, the dialog showing it's not installed with a button that opens up the play store all seems okay. My question is specifically about the returned results in onActivityResult().
We have to pass a requestCode to getErrorDialog() and I get that back in onActivityResult just fine, but im more concerned with the resultCode returned. So far with all my testing I've gotten 0 (RESULT_CANCELLED). I was wondering if there was any way to know if the play services were installed successfully?
For now I'm handling it by just assuming that RESULT_CANCELLED means that they at least got to the play store and started downloading, and display another dialog that says "please restart this app once the play services complete installation" followed by a finish().
Is this the best way to handle it? or is there a case that I'm missing where it will return RESULT_OK and I can just continue onward with my app working without restarting it?
I must say that today I tried it, and I never got onActivityResult() called.
When dialog is cancelled, my OnCancelListener (getErrorDialog() parameter) is called, and when returning from PlayStore, whether installing Google Play Services or not, my app is destroyed.
Even more, when installing Google Play Services, onDestroy() is called when installation starts.
I think maybe this is an updated behaviour, and I think is consequent, because you can return from Play Store before background installation ends.
Nonetheless, I found a couple of links with sample code that may confirm in case onActivityResult() is called with RESULT_OK, it means that you can continue:
http://developer.android.com/training/location/activity-recognition.html
http://developer.android.com/training/location/retrieve-current.html
Hope it helps
Consider that user has my app with version 1 and auto update option is disabled/off. I have an upgrade in the market for my app(say version 2).
User gets a notification saying, "updates available" and updates my app.
Now based on some requirement I need my app not be be upgraded to version 2.
Can this be done?
That's a very odd question...
It can't be done, since the application WILL be updated to the new one when the user UPDATES the application as this is the concept of updating the app...
You can, however, do these differentiations in the code, where if you don't want the new updated code to occur, just call the old one... Then you'll have 2 sets of logics inside your code and you will run the correct code based on your decision