Recently I am going to work on a project in which the requirement is little weird. I am asked to develop a app which will not be uploaded to any marketplace like playstore or any other android app stores. It will be simply uploaded in cloud to distribute the APK among users.
After the app is being installed on user device, when a new version will be released, the user will be notified (notified not to download the new version and re-install, but to grant permission and update). After the user grant permission, the app will be updated. What's the best way to do this without the marketplace help?
My idea:
- Use GCM (Google Cloud Messaging) to notify user and give a new version link.
- User will click on the link and a new version will be downloaded and replaced the previous one (android by-default version replacement)
Is there any smarter way to do what I want to achieve actually?
The best way to do this I have found, was to host the apk and a text file with the latest version #.
Opon opening the app, check the current v # against the one hosted on the server, if they dont match, grab the new one.
No need for pushing anything unless your app works as a background service and you need to ensure that whether the user is on the latest version whether they use it or not.
If that is the case, you can have a service that does it once a day or something like that.
EDIT - after downloaded, to install the apk, use the following code.
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse("file:///path/to/your.apk"),
"application/vnd.android.package-archive");
startActivity(promptInstall);
Install Application programmatically on Android
Here is some of the code I use for this purpose. You will have to adjust some as I am too lazy to strip it down atm. (sorry).
So, in onCreate of my Activity I have:
new FetchLatestVersion().execute();
And the code to check for and fetch latest version (+launch installer).
private class FetchLatestVersion extends AsyncTask<Void, Void, Integer> {
@Override
protected Integer doInBackground(Void... param) {
String inputLine = "-1";
BufferedReader in = null;
try {
URL update_url = new URL(UPDATE_VERSIONCHECK_URL);
in = new BufferedReader(new InputStreamReader(
update_url.openStream()));
while ((inputLine = in.readLine()) != null) {
return Integer.parseInt(inputLine);
}
} catch (IOException e) {
Log.e(TAG, inputLine, e);
} catch (NumberFormatException e) {
Log.e(TAG, inputLine, e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
}
}
return -1;
}
@Override
protected void onPostExecute(Integer result) {
if (result > device.getVersionCode()) {
// Toast.makeText(
// getApplicationContext(),
// "current version: " + device.getVersionCode() + "\n"
// + "new version: " + result, Toast.LENGTH_SHORT)
// .show();
// pref.putBoolean(PREF_HAS_UPDATE, true);
showDownloadOption();
}
}
}
private void showDownloadOption() {
findViewById(R.id.new_update).setVisibility(View.VISIBLE);
}
@OnClick(R.id.button_download)
public void update(Button button) {
if (mDownloadTask != null
&& mDownloadTask.getStatus() == Status.RUNNING) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadUpdate();
mDownloadTask.execute();
}
private class DownloadUpdate extends AsyncTask<Void, Void, File> {
public ProgressDialog working_dialog;
private String toastMsg = "";
@Override
protected void onPreExecute() {
working_dialog = ProgressDialog.show(context, "",
context.getString(R.string.working), true);
}
@Override
protected File doInBackground(Void... param) {
String filename = "YOURAPP.apk";
HttpURLConnection c = null;
try {
URL url = new URL(UPDATE_DOWNLOAD_URL);
c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
} catch (IOException e1) {
toastMsg = context
.getString(R.string.could_not_connect_to_server);
return null;
}
File myFilesDir = new File(Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/Download");
File file = new File(myFilesDir, filename);
if (file.exists()) {
file.delete();
}
if ((myFilesDir.mkdirs() || myFilesDir.isDirectory())) {
try {
InputStream is = c.getInputStream();
FileOutputStream fos = new FileOutputStream(myFilesDir
+ "/" + filename);
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
} catch (Exception e) {
toastMsg = context
.getString(R.string.missing_internet_connection);
}
}
return file;
}
@Override
protected void onPostExecute(File file) {
if (!toastMsg.isEmpty()) {
Toast.makeText(context, toastMsg, Toast.LENGTH_LONG).show();
} else {
launchInstaller(file);
}
removeWorkingDialog();
}
private void removeWorkingDialog() {
if (working_dialog != null && working_dialog.isShowing()) {
working_dialog.dismiss();
working_dialog = null;
}
}
}
public void launchInstaller(File apkFile) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(apkFile),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, 0);
}
I did a small amount of digging and found a library that does exactly this.
I have not used it, but it popped up in some other related SO questions.
https://github.com/RaghavSood/AppaholicsUpdateChecker