Programmatically trigger app update from Google play - android

Once an update to app is submitted in Google play developer console and the app is visible to all users, how much time would it take for any device to pick the update? (Assuming active internet wifi connection is throughout the day and auto-update is on for this app)
Can I programmatically initiate a request to Google play store regarding the update WITHOUT ANY USER PROMPT OR ANY INTERACTION? (Assuming no new permissions are requested while updating). If so, please suggest how.
Other information: My app is designed for digital signage using android boxes. App is launched on startup, occupies the screen. There will not be any sort of user interaction directly with the app during its lifetime.

Usually update is installed within 24 hours, provided the user maintains active connection with internet and sufficient battery. Android boxes do not have any battery, so automatic updates via google play (without any user interaction) are not reliable.
Use this code for issuing auto update without playstore.
Add this permission: <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
Use the following function:
public static void installAPK(String filename) {
File file = new File(filename);
if (file.exists()) {
Runtime.getRuntime().exec("chmod 777 " + filename);
String command;
command = "pm install -r " + filename;
Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", command});
proc.waitFor();
}
}
Note: This would work only if you are not requesting any extra permissions for the app since last install.

It depends on Google's back end replicating your new update, usually within 8-24 hours.
No, that would be a security vulnerability. Apps are not permitted to install or update themselves without user interaction.

I have been through this many times.
1> It usually took me for about 2 - 4hrs to get my app updated on google play.
2> I think you are talking about force update. What I did for this was that
I made an api for checking the version of app. And according to it I redirected to update screen in google play . I hope it helps.
// Here min_supported_version is generated from api
if (min_supported_version <= BuildConfig.VERSION_CODE) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=yourpackagename")));
}

Related

Play Core In-App Review API not showing the Review Activity

I'm trying to utilize the Review API (Play Core library 1.8.0) from Google which was just released yesterday.
See https://developer.android.com/guide/playcore/in-app-review
I followed the troubleshooting section carefully, I made sure the app is downloaded from the internal testing track, my account does not have a review on the app, the app is in the library of that user etc.. I even tried with a completely new account, but every time the com.google.android.finsky.inappreviewdialog.InAppReviewActivity is shown only to immediately disappear.
I'm calling the following code from the onResume() method of my activity:
reviewManager = ReviewManagerFactory.create(AlarmClock.this);
Logger.logInfo("Rating: requestReviewFlow() ");
reviewManager.requestReviewFlow().addOnSuccessListener(new OnSuccessListener<ReviewInfo>() {
#Override
public void onSuccess(ReviewInfo result) {
Logger.logInfo("Rating: launchReviewFlow() ");
reviewManager.launchReviewFlow(AlarmClock.this, result).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void result) {
Logger.logInfo("Rating: launchReviewFlow() success ");
}
});
}
});
Both listeners return success.
Here is the log output:
2020-08-06 16:01:29.317 29618-29618/? I/MyApp: [06Aug 16:01:29.317, main]: Rating: requestReviewFlow()
2020-08-06 16:01:29.318 29618-29618/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : requestInAppReview (com.mypackage)
2020-08-06 16:01:29.320 29618-29774/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : Initiate binding to the service.
2020-08-06 16:01:30.081 29618-29618/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : ServiceConnectionImpl.onServiceConnected(ComponentInfo{com.android.vending/com.google.android.finsky.inappreviewservice.InAppReviewService})
***2020-08-06 16:01:30.082 29618-29774/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : linkToDeath***
2020-08-06 16:01:30.355 29618-29637/? I/PlayCore: UID: [10409] PID: [29618] OnRequestInstallCallback : onGetLaunchReviewFlowInfo
2020-08-06 16:01:30.355 29618-29774/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : Unbind from service.
2020-08-06 17:02:21.590 7478-7478/? I/MyApp: [06Aug 17:02:21.590, main]: Rating: launchReviewFlow()
2020-08-06 17:02:21.630 1511-4316/? I/ActivityTaskManager: START u0 {cmp=com.android.vending/com.google.android.finsky.inappreviewdialog.InAppReviewActivity (has extras)} from uid 10122
2020-08-06 17:02:21.750 7478-7478/? I/MyApp: [06Aug 17:02:21.750, main]: Rating: launchReviewFlow() success
Anyone had success to make this working? Any tips. Big thanks!
Okay, I had exactly the same problem as described by the OP and as is listed on the issue tracker here: https://issuetracker.google.com/issues/167352813 and has still not been resolved as yet by GoogleDev.
Same UI manifestation(s), same log entries (incidentally, the log entries are the same when it works though, complete with the entry that says “ReviewService : linkToDeath”, but let’s not worry about that eh?)
The key thing, you'll no-doubt want to know though, to avoid too much suspense, is that IT WORKS. The in-app review API works! No need for me to repeat the block of code for calling the review flow, it is pretty much exactly the same as in the docs, similar to what the OP has listed, and several others have kindly repeated.
Took me a while, but I got to the bottom of it as follows, in a nutshell:
Your device needs to have the latest Google Play system update
Irrespective of whether your app is published on the Play Store YOU ABSOLUTELY NEED TO DO YOUR TESTING VIA INTERNAL APP TESTING or SHARING (I only did “Internal App Testing”, but I expect the same applies)
To debug your code with Android Studio, you need to have installed your Internal App Testing version on your device AND RUN THE DEBUGGER SUCCESSFULLY WITH YOUR IAT VERSION STILL INSTALLED ON THE DEVICE AT LEAST ONCE
Once you are up and running, when the review dialog pops up, you have to note that, if you submit a review, then you have utilised all your quota. When you try and launch the review flow again it looks like the “problem” has returned. You get “successful” launch but nothing shows. If you have submitted a review (and this is why it absolutely needs to be in IAT), then it is only a “private review” (not seen publicly on your app page), and you need to DELETE THE REVIEW TO GET THE POP UP TO SHOW AGAIN.
You can select “Not Now” instead of "Submit" ad infinitum (well, I tried about two-dozen times) and the pop-up dialog will launch each time you (re)call the flow.
So, step-by-step fix:
Prepare your device by uninstalling your app, then ensure you have the latest Google Play Store update. On my Sony Xperia X1 this is Settings->About Phone->Android version->Google Play system update.
Irrespective of whether the above restarted your device, turn your device off and then back on again (don’t restart - off then on i.e. cold boot).
Now go into Settings->Apps & notifications->Google Play->Storage & Cache, then do both CLEAR CACHE and CLEAR STORAGE. (This should not affect any of your installed apps).
Create a signed release for IAT based on your In-App review code base. You have to do this even if you have a release in production.
Now install your IAT RELEASE on your device - the words, "(Internal Beta)" or words to that effect, should be appended to your app name if you are downloading from the right location (i.e. IAT), (do not run it, just install)
In Android studio Clean, Rebuild and Debug, your app on the device with the IAT version installed. If you get a message saying "The device already has an application with the same package but a different signature." DON'T CLICK OK TO UNINSTALL YOUR IAT VERSION Follow the instructions here: Android: Error - App has same packaged different signature. The accepted answer is the correct one. If you have to do this, please note you should do a Clean and Rebuild->Debug again.
Hopefully, now all should be okay. Once you have done the above steps successfully, you can actually "clean" uninstall the app from the device on subsequent debugging sessions, and it will still work.
To test, and to delete a review note the following. When you submit a review, you will be able to see it in Google Play Console (not under "Reviews", incidentally but) under "Testing Feedback". Also you cannot delete your review under "Testing Feedback" it seems. You need to delete it from your IAT download page on the device. On there, under the heading Your private feedback, select the right-angled ellipsis thingy to the right of your review and simply "Delete".
Your pop-up will now show every time until you submit another review. Voila!
I have raised a issue on google issue tracker regarding this. I also have the same issue.
For more info check this my issue tracking url: https://issuetracker.google.com/issues/167352813
I also saw the same problem, my request review flow works, then the launch review flow works, but nothing displays (I do notice the small line at the center of the bottom of the screen appears briefly, and my audio cuts out briefly as the app is paused and then resumed but no review flow appeared).
I was able to get it to work by adding a user to my device that was not in my list of License Testers (Google developer console) and had not reviewed my app previously. I was able to display the rating popup once, I cancelled the operation so that I could test it again, but it would not reappear afterwards. It appears to be a one shot thing and they are aggressively guarding against annoying the user with review popups.
This feature doesn't seem useful for my case, I have a button on the settings screen to rate my app. Since I have no way of knowing what happened, I can't thank the user, I can't disable the button or display an "you already rated this thank you" message, and the button just appears to do nothing so it looks like a bug. I guess the intended use is to ask the user during gameplay, and if they cancel the dialog accidentally then it's just too bad for you.
Ideally Google should allow License Testing users to display this popup more than once for testing purposes.
I just want to share the code that is working reliably today (2020-09-03). It was essentially copied from the official document
ReviewManager manager = ReviewManagerFactory.create(activity);
Task<ReviewInfo> request = manager.requestReviewFlow();
request.addOnCompleteListener(task -> {
try {
if (task.isSuccessful()) {
// We can get the ReviewInfo object
ReviewInfo reviewInfo = task.getResult();
Task<Void> flow = manager.launchReviewFlow(activity, reviewInfo);
flow.addOnCompleteListener(task2 -> {
// The flow has finished. The API does not indicate whether the user
// reviewed or not, or even whether the review dialog was shown. Thus, no
// matter the result, we continue our app flow.
utility.logMessageAsync(activity, "In-app review returned.");
});
} else {
// There was some problem, continue regardless of the result.
goToAppPage(activity);
}
} catch (Exception ex) {
utility.logExceptionAsync(activity, "Exception from openReview():", ex);
}
});
It was tested with internal app sharing on a Android 10. It never failed to show the review dialog.
I had the same problem and I solved with the next steps:
Adding my APK file to internal testing channel
Adding a tester user with a gmail account ex: email#gmail.com. GSuite mails don't work
With the tester mail, accept the tester privilege
With a physical device signed with the tester user email, go to Play Store and download the app
It works!!
Note: If App is not published yet, you could use Google Console App Sharing
Try uploading your app to Internal App Sharing
I have found that with the exact same apk uploaded to Internal Testing versus Internal App Sharing, the latter is more reliable in displaying the In-App Review Flow every time I try testing it.
You would need to enable Internal app sharing in the Play Store to be able to install your app from the link provided by uploading your apk.
Basically go to the Play Store, go to Settings, scroll down to Play Store version and tap it a bunch of times to "Become a developer", then enable Internal app sharing.
For all the users that needs a working JAVA code, please find my code below:
ReviewInfo reviewInfo;
ReviewManager manager;
OnCreate
manager = ReviewManagerFactory.create(this);
private void Review(){
manager.requestReviewFlow().addOnCompleteListener(new OnCompleteListener<ReviewInfo>() {
#Override
public void onComplete(#NonNull Task<ReviewInfo> task) {
if(task.isSuccessful()){
reviewInfo = task.getResult();
manager.launchReviewFlow(MainActivity.this, reviewInfo).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
Toast.makeText(MainActivity.this, "Rating Failed", Toast.LENGTH_SHORT).show();
}
}).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(MainActivity.this, "Review Completed, Thank You!", Toast.LENGTH_SHORT).show();
}
});
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
Toast.makeText(MainActivity.this, "In-App Request Failed", Toast.LENGTH_SHORT).show();
}
});
}
Make sure the below is implemented:
implementation 'com.google.android.play:core:1.8.0'
And please also note, that the dialog will only display if your app is in production, alpha or internal testing on the Google Play Console Account.
I had same issue, I've followed below steps then working fine
If you mark stars and submit, then need to remove your review from
play store.
Clear data for Play Store.
My working code:
private fun askForReview() {
val manager = ReviewManagerFactory.create(this)
manager.requestReviewFlow().addOnCompleteListener { request ->
if (request.isSuccessful) {
val reviewInfo = request.result
manager.launchReviewFlow(this, reviewInfo).addOnFailureListener {
logWarning("In-app review request failed, reason=$it")
}.addOnCompleteListener { _ ->
logInfo("In-app review finished")
}
} else {
logWarning("In-app review request failed, reason=${request.exception}")
}
}
}
Tested on an app from Internal Test track (there is no quota there).
The documentation says
To provide a great user experience, Google Play enforces a quota on
how often a user can be shown the review dialog. Because of this,
calling a launchReviewFlow method might not always display a dialog.
For example, you should not have a call-to-action option (such as a
button) to trigger a review as a user might have already hit their
quota and the flow won’t be shown, presenting a broken experience to
the user.
So you don't expect it to show the dialog every time and also there's no way to know if the dialog is shown or not nor the user has reviewed your app or not either
I had exactly the same problem, the dialog never appeared to me ...
But even so, I left it implemented in the application and posted it on the Play store.
Then I downloaded and tested the version and everything works perfectly.
Most of the cases are covered in other answers. I want to highlight few more troubleshooting Steps .
Make sure the user account is not protected (like some enterprise accounts) use some personnel G mail ID to test.
Make Sure the version of beta app is greater then the currently Live application
if its not then it will not show up the review dialogue.
In MY case, yes, this will not work if the account that’s being used already left a review.
HOWEVER, deleting the review from the Play Store doesn’t always work. Something lingers.
So, unless you want to be sad, CLEAR THE PLAY STORE APP’S STORAGE EVERY TIME YOU DELETE THE REVIEW THAT’S LEFT. You do not need to also clear the cache as well as others have suggested (clearing the storage will also do this), but clearing the Play Store app’s cache was not enough. Once I did this, I could consistently test this ad nauseum.
Good luck. What a mess this is.
Documentation says that it won't be shown every time you request it since it has quota restrictions:
https://developer.android.com/guide/playcore/in-app-review#quotas
I just included it in my project and it showed the dialog only one time. It is a little inconvenient since we don't have any controls over it.
Also, I noticed that if you try to show the dialog again and again, navigation bar starts blinking (like it wants to show the dialog but it gets dismissed).
My problem was solved by typecasting the context and activity to the required form i.e application context and activity . Although it seems illogical, nothing else worked for me
I joined the beta in the store and it showed. But just show once time.
Just to be clear you are not using com.mypackage right?
2020-08-06 16:01:29.318 29618-29618/? I/PlayCore: UID: [10409] PID: [29618] ReviewService : requestInAppReview (com.mypackage)
Ensure that the appId used is the one that it's "owned" (aka installed by) by the selected account in the Play Store in the device.
I believe the test guide (https://developer.android.com/guide/playcore/in-app-review/test) is clear in terms of how to test it given the different requirements.
My tips:
Use only one account in the device
Ensure that account has installed the app (appears in the app & games > Library section in Play Store)
The account is a GMAIL one, not a GSuit
You can review with the account if you go to the app play listing page.
The account has not reviewed
If you intend to use the Internal Test Track ensure the account has joined the test track.
When switching between different accounts and testing things out, sometimes might be helpful to "Clear Data" from the Play Store app.
Try all the above with different account
PS: You could test also the Internal App Sharing.
Just discovered that the app must be approved from google (i.e. not having the temporary name)
The code is correct no issue
we can follow a few steps
app upload following URL https://play.google.com/console/u/0/internal-app-sharing/
setup google play console your project setup->inter app sharing-> anyone can download select the option -> to save
3 check your mobile internal app sharing to play store app
I know this is an old thread but none of the steps for the solutions provided worked for me. They are all great advice and should be followed. However, if you also can't get the in-app review UI to pop up, you might want to try what I did. (I'm sure there is probably a key step in there that is the actual solution so all these steps may not be necessary.)
Ultimately, the issue was that I initially installed my app using a gmail suite email (same one I used to deploy the app if that makes a difference) and the app remained associated with that user even after switching to other users on my phone.
Bad user is active in Google Play app
Uninstall the app (duh)
Go to bad user's library and remove the app
Stop and delete data/cache for Play Store app
(At this point I removed/re-added my good gmail user account in android settings but probably not necessary)
Start and switch to good gmail account in Play Store app
(If you search for the app, you should see a little note under the name saying the app is associated with the bad user account. This means it will not work right. Don't install it yet!)
This is the important part!
Start Chrome browser, and login with good gmail account
Go to email and CLICK ON THE LINK TO INSTALL THE APP FROM YOUR INVITE to test it (notice that was in all caps so must be important)
The app should now be associated on this device with the good account and you should see the in-app review pop-up UI
For anyone still having this problem:
I used applicationContext and now it is working and displaying just fine.
For some reason, the context and activity don't work, only applicationContext.
Please test using FakeReviewManager :)
ReviewManager manager = new FakeReviewManager(context);
https://developer.android.com/guide/playcore/in-app-review/test

how can I perform any task after uninstalling my apk?

I want to install the apk from internal/external memory after uninstalling the same apk.?(actually i want to update my apk,if i directly(don't uninstall the current apk) install my updated apk then there comes signature issue.)
final Intent installIntent = new Intent(Intent.ACTION_VIEW);
if (isSDPresent) {
installIntent.setDataAndType(Uri.fromFile(new File("/storage/sdcard1/Download/" + "Life.apk")), "application/vnd.android.package-archive");
}else {
installIntent.setDataAndType(Uri.fromFile(new File("/storage/emulated/0/Download/" + "Life.apk")), "application/vnd.android.package-archive");
}
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(installIntent);
The behaviour you are seeing is by design.
Android does not allow any code within an APK to be run once the user chooses to remove it - there are no notifications and no pre-uninstall actions that you can use. It's designed that way to prevent developers from writing Apps that can never be uninstalled by the user.
Having two apps with the same package name but signed with different keys is also not allowed, and can only be resolved by the user manually removing the first app before installing the second. This is to prevent developers from writing Apps to imitate other Apps (like Facebook for example) without the user knowing about it.
You can update your apk using below command that will upgrade application that is exactly same as when you perform Update from google play store.
adb install -r foo.apk

Install a GooglePlay located App from NFC

Working with Lollipop, I have a device-owner app that is installed with NFC at provision time.
What I need now is to handle automatic updates for my App, from Google Play to rely on the standard Android App update system...
So far I can imagine 2 ways to get this done, but don't know how to handle any of them :
in my NFC install constant EXTRA PROVISIONING DEVICE ADMIN PACKAGE
DOWNLOAD LOCATION install the App directly from the Play Store instead of the url on my own dev server. However
this constant need to handle the url of an apk file, and I did not find any
official way to get apk install direct from Play Store ? (as it will
be a production App in the future I'm not interested in hacks)
keep installing the apk from the dev server, but then allow the App
to update itself with its little brother located on the Play Store
with the same package name. To say it an other way: Would this be possible to install a v1 apk from a custom location, then put a v2 on the PlayStore... and let the magic come true ?
I'd be glad to hear if anyone could share experience about such procedures. Thanks for reading!
EDIT after #Stephan Branczyk suggestion I could make some more testing, here is what I did and the results:
1 - In the NFC provisioning I replaced the apk url with
snep://my.app.packagename without luck ; it just gives an error
without much explanation.
2 - I replaced this url by such a PlayStore link :
https://play.google.com/store/apps/details?id=my.app.packagename but
it gives a checksum error whether I use the checksum locally
computed, or the checksum given on the GooglePlay apk details. It looks not so far from the goal but I could not make it work.
3 - Finally I came back on my first solution, a self-hosted apk
versioned 1... but this time I tried to put on the PlayStore a newer
version 2 of the app with the exact same packagename... That led me
to strange things:
At first my App did not appear anywhere in the local PlayStore App,
but when I searched for it in Google Play, it showed up with the green
"installed" badge, and it proposed me to make an update... So did I.
Then, after this first manual update, the App is in v2, nice, and
better: it appears well listed in my PlayStore.
Optimistically, I uploaded a v3 of the App... just to see if my
PlayStore would automatically update my app (as is does for all the
other ones), but sadly no luck : even if my app is still listed in the
playstore, and proposing the "update" button... it never
updates by itself as it should ; I still need to click on it manually.
Isn't it a strange behavior ? If some have ideas about it, I would really need to be able to rely on the Play Store functionalities but so far no luck, and I cannot believe that Device-Owner app distribution is not compatible with PlayStore ?
Just in case, FYI here is the kind of provisioning code I'm using:
try {
Properties p = new Properties();
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
"my.app.packagename");
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
"http://www.example.com/myDeviceOwnerApp.apk");
p.setProperty(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM,
"U55o3fO0cXQtUoQCbQEO9c_gKrs");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStream out = new ObjectOutputStream(bos);
p.store(out, "");
final byte[] bytes = bos.toByteArray();
NdefMessage msg = new NdefMessage(NdefRecord.createMime(
DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, bytes));
return msg;
} catch (Exception e) {
throw new RuntimeException(e);
}
Write your package name as an AAR record in the tag.
To confirm that this functionality works, use this app to write the tag with.
You need to set Base64 encoded SHA1 or SHA256 (from M forward) of the apk in the
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
field when provisioning through NFC otherwise the provisioned device will not accept the URL for download.
Also see this answer for properly encoding the checksum.

Remote update app on multiple devices NOT using Playstore

I'm trying to find a solution to do a remote update of an APK to 80 tablets. This should preferably be as automated as possible and if this can happen completely in the background without any user input that would be great. Basically what the Playstore currently do which I unfortunately can't use.
Is something like this possible without rooting the device? Any suggestion on libraries/ services that does this?
I'm running Android 4.1.1 and they will all be connected to a Wi-Fi.
You can download the new APK file to SD card, then call this to install it:
Intent shareIntent = new Intent(Intent.ACTION_VIEW);
shareIntent.setDataAndType(Uri.fromFile(new File("path-to-APK-file")),
"application/vnd.android.package-archive");
try {
context.startActivity(shareIntent);
} catch (Throwable t) {
// handle the exception here
}
There is only one thing not automatic: the final step. The system will ask the user to confirm installation.
About the MIME type of APK files, here's the wiki page.
No, in the background isn't possible without rooting or having the device's signing key at least as a standard Android APK update. The only semi-reasonable way I can envision something similar to this working is for your app to always check for/download code to run which you load using a class loader. This would be a significant amount of work and not easy.
However, if you're willing to live with some user interaction, it really shouldn't be that hard (though it'll still take some building of infrastructure). Keep a web service that returns the latest version number, compare with the current version number and download the new APK as necessary. Installing an APK programmatically has been covered in many SO questions.

Auto-Update for (private) Android apps

I'm developing a non-public Android app, i.e. the app won't be available in the global Android Market. The app will be installed on a limited number of clients, e.g. by using an apk file.
How can I enable an auto-update functionality in this app?
I see different potential options (I do not know if those are technically hard or even impossible to implement or if there are any existing functionalities that can be reused):
On each launch the app tests if a new version exists (by requesting a server), if so downloads the new apk and replaces itself with the new version.
Use (or develop?) a separated app or service that undertakes the update-check and replacement-process.
Use (or develop?) a private market app which has an auto-update option. This option is similar to the second one, but more generic: The market app would be connected to a repository, i.e. it would handle an arbitrary number of (private) apps.
I would prefer option one since the auto-update functionality is included in the app which needs less development efforts.
janjonas, in the company I work we had a similar problem with Windows Mobile 6.x, and we use pretty much the same solution pointed by EboMike:
The main app check if it's updated, against a WebService. It receives the current version & the URL from where download the new version, if necessary. The main app then start the Updater app, passing the URL, and quit.
The Updater do the download of the new program, via HTTP, showing to the user the % downloaded. The user can cancel the download anytime, in a controlled way, and the Updater can registry this cancellation.
Since the new app is downloaded, the Updater run the new app, and quit.
I think option one is the least amount of work for you, and actually the cleanest one too since it will go through the proper channel of using Android's built-in package installer which includes user notification and the option for the user to abort the installation if desired.
You already have it all outlined - check for a new version on a server (would be nice to give the user the option to turn that off), and if there is a new version, you could either just link to the URL with the APK (which will, IIRC, use the browser's download manager to download it), or you could download it with your app and then point the intent to your local file. Using the HTTP link is technically less work and cleaner - the more you let the operating system do, the better - unless there's a reason not to.
Enabling "Install non-market app" is still needed for any application outside the Google Play. If it not enabled, the installation process is going to ask for it and redirect the user to the Application Settings, and after that, the user can install the app.
Depending on your needs, you can delegate to a third part lib.
Some of the permissions we'll use to get this done are the following:
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Let me explain a bit... The last, WRITE_EXTERNAL_STORAGE, is self-explanatory. With ACCESS_SUPERUSER we'll tell the system that we intend to use root privileges. READ_EXTERNAL_STORAGE will be needed in the future in order for your app to read files on SD card.
Assuming that you have downloaded the file and that all those devices can be rooted (limited number of clients, not on Play, etc.), you could do this:
String filePath = Environment.getExternalStorageDirectory().toString() + "/your_app_directory/your_app_filename.apk";
Process installProcess = null;
int installResult = -1337;
try {
installProcess = Runtime.getRuntime().exec("su -c pm install -r " + filePath);
} catch (IOException e) {
// Handle IOException the way you like.
}
if (installProcess != null) {
try {
installResult = installProcess.waitFor();
} catch(InterruptedException e) {
// Handle InterruptedException the way you like.
}
if (installResult == 0) {
// Success!
} else {
// Failure. :-/
}
} else {
// Failure 2. :-(
}
Here might be a very lame method but for some companies, if you believe its applicable, this might be very easy to implement.
Create an password screen (passwordActivity) that asks a password to access the application.
Once the password is entered, raise a flag (set a boolean value from false to true using sharedpreferences)
Place the .apk file on Google Store.
Change the password once everyone installs the app, and release a new update on Google Play Store.
Since the software is going to cache the flag value, the password screen won`t show up even the password is change. It will only show up for new installations so might need to repeat the process.
Note: This method might better fit if there is not hundreds of users using the application. And don`t forget this method is also not secure. To sum up, if you are looking a way to keep the application private and have no security concerns, this is what I recommend.
Update app
Make sure that you already have your new apk download on location
void installNewVersion(String location) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}

Categories

Resources