Skip to content

Commit

Permalink
Add update notification with automatic download & install option
Browse files Browse the repository at this point in the history
  • Loading branch information
fm-sys committed Oct 14, 2020
1 parent 31aa750 commit ef85fae
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
# but have a common checkstyle configuration
!.idea/checkstyle-idea.xml
*.iml
*.lnk
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'com.squareup.okhttp:okhttp:2.5.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
Expand Down
20 changes: 0 additions & 20 deletions app/release/output-metadata.json

This file was deleted.

Binary file modified app/release/snapdrop_v1.1.apk
Binary file not shown.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<application
android:allowBackup="true"
Expand Down
34 changes: 34 additions & 0 deletions app/src/main/java/com/fmsys/snapdrop/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
Expand All @@ -30,6 +31,7 @@
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.content.ContextCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
Expand Down Expand Up @@ -119,6 +121,7 @@ protected void onCreate(final Bundle savedInstanceState) {
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(receiver, intentFilter);

new UpdateChecker().execute("");
}

private void refreshWebsite() {
Expand Down Expand Up @@ -278,4 +281,35 @@ public void run() {

}

private class UpdateChecker extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(final String... params) {
try {
return UpdateUtils.checkUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(final String result) {
try {
if (result == null) {
return;
}

final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogTheme)
.setTitle(R.string.app_update)
.setMessage(R.string.app_update_summary)
.setPositiveButton(R.string.app_update_install, (dialog, id) -> UpdateUtils.runUpdate(MainActivity.this, result))
.setNegativeButton(R.string.app_update_show_details, (dialog, id) -> UpdateUtils.showUpdatesInBrowserIntent(MainActivity.this));
builder.create().show();

} catch (Exception e) {
e.printStackTrace();
}
}
}

}
112 changes: 112 additions & 0 deletions app/src/main/java/com/fmsys/snapdrop/UpdateUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.fmsys.snapdrop;

import android.app.Activity;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;

import androidx.core.content.FileProvider;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;

import org.json.JSONException;
import org.json.JSONObject;


public final class UpdateUtils {

private UpdateUtils() {
// utility class
}

public static String checkUpdate() throws JSONException, IOException {

final OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder()
.url("https://fm-sys.github.io/snapdrop-android/output-metadata.json")
.build();

final Response response = client.newCall(request).execute();
final JSONObject obj = new JSONObject(response.body().string());
final JSONObject recentApp = obj.getJSONArray("elements").getJSONObject(0);
final int versionCode = recentApp.getInt("versionCode");

if (BuildConfig.VERSION_CODE < versionCode) {
return recentApp.getString("outputFile");
}

return null;
}

public static void runUpdate(final Activity context, final String fileName) {

final String downloadLink = "https://github.com/fm-sys/snapdrop-android/releases/latest/download/" + fileName;

final File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
if (file.exists()) {
launchInstallIntent(context, file);
return;
}

final ProgressDialog progressdialog = new ProgressDialog(context, R.style.AlertDialogTheme);
progressdialog.setMessage(context.getString(R.string.app_update_download_text));
progressdialog.setTitle(R.string.app_update_download_info);
progressdialog.setCancelable(false);
progressdialog.show();

//set downloadManager
final DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(downloadLink))
.setDescription(context.getString(R.string.app_update_download_info))
.setTitle(fileName)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
.setDestinationUri(Uri.fromFile(file));

// get download service and enqueue file
final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(downloadRequest);

//set BroadcastReceiver to install app when .apk is downloaded
final BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(final Context cntxt, final Intent intent) {
progressdialog.dismiss();
context.unregisterReceiver(this);
launchInstallIntent(context, file);
}
};
//register receiver for when .apk download is compete
context.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));


}

private static void launchInstallIntent(final Activity context, final File file) {

final Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
install.setData(FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file));
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
install.setData(Uri.fromFile(file));
}
context.startActivity(install);
}

public static void showUpdatesInBrowserIntent(final Activity context) {
final Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://github.com/fm-sys/snapdrop-android/releases/latest"));
context.startActivity(i);
}

}
10 changes: 10 additions & 0 deletions app/src/main/res/values-de-rDE/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Snapdrop</string>
<string name="app_update">Update verfügbar</string>
<string name="app_update_summary">Updates enthalten in der Regel wichtige Fehlerbehebungen und tolle neue Funktionen. Die Installation wird empfohlen…</string>
<string name="app_update_install">Installieren</string>
<string name="app_update_show_details">Weitere Informationen</string>
<string name="app_update_download_info">Update wird heruntergeladen</string>
<string name="app_update_download_text">Dies sollte nur wenige Sekunden in Anspruch nehmen…</string>
</resources>
7 changes: 7 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
<resources>
<string name="app_name">Snapdrop</string>

<string name="app_update">Update available</string>
<string name="app_update_summary">Updates usually contain important bug fixes and great new features. Installation is recommended…</string>
<string name="app_update_install">Install</string>
<string name="app_update_show_details">More details</string>
<string name="app_update_download_info">Downloading update</string>
<string name="app_update_download_text">This should only take a few seconds…</string>
</resources>
5 changes: 5 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@
<item name="colorPrimary">@color/colorPrimary</item>
</style>

<style name="AlertDialogTheme" parent="Theme.MaterialComponents.Light.Dialog.Alert">
<item name="colorPrimary">@color/colorAccent</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

</resources>

0 comments on commit ef85fae

Please sign in to comment.