From 4076947705508da75a2609a4a7893c4348956adf Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Mon, 25 Sep 2017 21:10:49 +0200 Subject: reworked updater --- src/main/java/de/pixart/messenger/Config.java | 2 +- .../messenger/services/CheckAppVersionService.java | 42 --- .../messenger/services/NotificationService.java | 2 + .../pixart/messenger/services/UpdateService.java | 196 +++++++++++ .../messenger/services/UpdaterWebService.java | 99 ------ .../pixart/messenger/ui/ConversationActivity.java | 12 +- .../de/pixart/messenger/ui/UpdaterActivity.java | 381 ++++++++------------- .../java/de/pixart/messenger/ui/XmppActivity.java | 6 +- 8 files changed, 354 insertions(+), 386 deletions(-) delete mode 100644 src/main/java/de/pixart/messenger/services/CheckAppVersionService.java create mode 100644 src/main/java/de/pixart/messenger/services/UpdateService.java delete mode 100644 src/main/java/de/pixart/messenger/services/UpdaterWebService.java (limited to 'src/main/java/de/pixart/messenger') diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java index 21f830a5c..83bea23b1 100644 --- a/src/main/java/de/pixart/messenger/Config.java +++ b/src/main/java/de/pixart/messenger/Config.java @@ -122,7 +122,7 @@ public final class Config { public static final int EXPIRY_INTERVAL = 30 * 60 * 1000; // 30 minutes public static final String UPDATE_URL = BuildConfig.UPDATE_URL; - public static final long UPDATE_CHECK_TIMER = 24 * 60 * 60; // in seconds + public static final long UPDATE_CHECK_TIMER = 24 * 60 * 60; // 24 h in seconds public static final String ISSUE_URL = "xmpp://support@room.pix-art.de?join"; diff --git a/src/main/java/de/pixart/messenger/services/CheckAppVersionService.java b/src/main/java/de/pixart/messenger/services/CheckAppVersionService.java deleted file mode 100644 index e3c4353ed..000000000 --- a/src/main/java/de/pixart/messenger/services/CheckAppVersionService.java +++ /dev/null @@ -1,42 +0,0 @@ -package de.pixart.messenger.services; - -import com.google.gson.JsonObject; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -public class CheckAppVersionService extends HttpServlet { - private static final long serialVersionUID = 1L; - - public CheckAppVersionService() { - super(); - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - doPost(request, response); - } - - protected void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - PrintWriter out = response.getWriter(); - response.setContentType("text/html"); - - //send a JSON response with the app Version and file URI - JsonObject myObj = new JsonObject(); - myObj.addProperty("success", false); - myObj.addProperty("latestVersionCode", 2); - myObj.addProperty("latestVersion", "1.0.0"); - myObj.addProperty("changelog", ""); - myObj.addProperty("filesize", ""); - myObj.addProperty("appURI", ""); - out.println(myObj.toString()); - out.close(); - } -} diff --git a/src/main/java/de/pixart/messenger/services/NotificationService.java b/src/main/java/de/pixart/messenger/services/NotificationService.java index daeba94e3..c1ec963f1 100644 --- a/src/main/java/de/pixart/messenger/services/NotificationService.java +++ b/src/main/java/de/pixart/messenger/services/NotificationService.java @@ -62,6 +62,7 @@ public class NotificationService { public static final int NOTIFICATION_ID = 2 * NOTIFICATION_ID_MULTIPLIER; public static final int FOREGROUND_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 4; public static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; + public static final int UPDATE_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; private Conversation mOpenConversation; private boolean mIsInForeground; private long mLastNotification; @@ -779,4 +780,5 @@ public class NotificationService { notificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification); return notification; } + } diff --git a/src/main/java/de/pixart/messenger/services/UpdateService.java b/src/main/java/de/pixart/messenger/services/UpdateService.java new file mode 100644 index 000000000..bb186063b --- /dev/null +++ b/src/main/java/de/pixart/messenger/services/UpdateService.java @@ -0,0 +1,196 @@ +package de.pixart.messenger.services; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.util.Log; +import android.widget.Toast; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; + +import de.pixart.messenger.BuildConfig; +import de.pixart.messenger.Config; +import de.pixart.messenger.R; +import de.pixart.messenger.ui.UpdaterActivity; + +import static de.pixart.messenger.services.NotificationService.UPDATE_NOTIFICATION_ID; + +public class UpdateService extends AsyncTask { + + private Context context; + + public UpdateService(Context context) { + this.context = context; + } + + public class Wrapper + { + public boolean UpdateAvailable; + public boolean showNoUpdateToast; + } + + @Override + protected Wrapper doInBackground(String... params) { + + boolean showNoUpdateToast = false; + if (params[0].equals("true")) { + showNoUpdateToast = true; + } + + + HttpsURLConnection connection = null; + String jsonString = ""; + boolean UpdateAvailable = false; + + try { + URL url = new URL(Config.UPDATE_URL); + connection = (HttpsURLConnection)url.openConnection(); + connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000); + connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + jsonString += line; + } + + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (connection != null) { + connection.disconnect(); + } + } + + try { + JSONObject json = new JSONObject(jsonString); + if (json.getBoolean("success") && json.has("latestVersion") && json.has("appURI") && json.has("filesize")) { + String version = json.getString("latestVersion"); + String ownVersion = BuildConfig.VERSION_NAME; + String url = json.getString("appURI"); + String filesize = json.getString("filesize"); + String changelog = ""; + if (json.has("changelog")) { + changelog = json.getString("changelog"); + } + if (checkVersion(version, ownVersion) >= 1) { + Log.d(Config.LOGTAG, "AppUpdater: Version " + ownVersion + " should be updated to " + version); + UpdateAvailable = true; + showNotification(url, changelog, version, filesize); + } else { + Log.d(Config.LOGTAG, "AppUpdater: Version " + ownVersion + " is up to date"); + UpdateAvailable = false; + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + Wrapper w = new Wrapper(); + w.UpdateAvailable = UpdateAvailable; + w.showNoUpdateToast = showNoUpdateToast; + return w; + } + + @Override + protected void onPostExecute(Wrapper w) { + super.onPostExecute(w); + if (!w.UpdateAvailable) { + noUpdateMessage(w.showNoUpdateToast); + } + } + + private void noUpdateMessage(boolean show) { + if (!show) { + return; + } + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + + @Override + public void run() { + Toast.makeText(context, context.getString(R.string.no_update_available), Toast.LENGTH_LONG).show(); + } + }); + } + + private void showNotification(String url, String changelog, String version, String filesize) { + Intent intent = new Intent(context, UpdaterActivity.class); + intent.putExtra("update", "PixArtMessenger_UpdateService"); + intent.putExtra("url", url); + intent.putExtra("changelog", changelog); + PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context); + mBuilder.setContentTitle(context.getString(R.string.update_service)); + mBuilder.setContentText(String.format(context.getString(R.string.update_available), version, filesize)); + mBuilder.setSmallIcon(R.drawable.ic_update_notification); + mBuilder.setContentIntent(pi); + Notification notification = mBuilder.build(); + notificationManager.notify(UPDATE_NOTIFICATION_ID, notification); + } + + private int checkVersion(String remoteVersion, String installedVersion) { + // Use this instead of String.compareTo() for a non-lexicographical + // comparison that works for version strings. e.g. "1.10".compareTo("1.6"). + // + // @param str1 a string of ordinal numbers separated by decimal points. + // @param str2 a string of ordinal numbers separated by decimal points. + // @return The result is a negative integer if str1 is _numerically_ less than str2. + // The result is a positive integer if str1 is _numerically_ greater than str2. + // The result is zero if the strings are _numerically_ equal. + // @note It does not work if "1.10" is supposed to be equal to "1.10.0". + + String[] remote = null; + String[] installed = null; + String[] remoteV = null; + String[] installedV = null; + try { + installedV = installedVersion.split(" "); + Log.d(Config.LOGTAG, "AppUpdater: Version installed: " + installedV[0]); + installed = installedV[0].split("\\."); + } catch (Exception e) { + e.printStackTrace(); + } + try { + remoteV = remoteVersion.split(" "); + if (installedV != null && installedV.length > 1) { + if (installedV[1] != null) { + remoteV[0] = remoteV[0] + ".1"; + } + } + Log.d(Config.LOGTAG, "AppUpdater: Version on server: " + remoteV[0]); + remote = remoteV[0].split("\\."); + } catch (Exception e) { + e.printStackTrace(); + } + int i = 0; + // set index to first non-equal ordinal or length of shortest localVersion string + if (remote != null && installed != null) { + while (i < remote.length && i < installed.length && remote[i].equals(installed[i])) { + i++; + } + // compare first non-equal ordinal number + if (i < remote.length && i < installed.length) { + int diff = Integer.valueOf(remote[i]).compareTo(Integer.valueOf(installed[i])); + return Integer.signum(diff); + } + // the strings are equal or one string is a substring of the other + // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" + return Integer.signum(remote.length - installed.length); + } + return 0; + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/services/UpdaterWebService.java b/src/main/java/de/pixart/messenger/services/UpdaterWebService.java deleted file mode 100644 index 4e4a599ad..000000000 --- a/src/main/java/de/pixart/messenger/services/UpdaterWebService.java +++ /dev/null @@ -1,99 +0,0 @@ -package de.pixart.messenger.services; - -import android.app.IntentService; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.util.Log; - -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.params.ConnManagerParams; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import de.pixart.messenger.Config; -import de.pixart.messenger.R; -import de.pixart.messenger.ui.UpdaterActivity.UpdateReceiver; - -public class UpdaterWebService extends IntentService { - public static final String REQUEST_STRING = ""; - public static final String RESPONSE_MESSAGE = ""; - - private String URL = null; - public static final int REGISTRATION_TIMEOUT = Config.SOCKET_TIMEOUT * 1000; - public static final int WAIT_TIMEOUT = Config.CONNECT_TIMEOUT * 1000; - - public UpdaterWebService() { - super("UpdaterWebService"); - } - - @Override - protected void onHandleIntent(Intent intent) { - - String requestString = intent.getStringExtra(REQUEST_STRING); - Log.d(Config.LOGTAG, "AppUpdater: " + requestString); - String responseMessage; - PackageInfo pInfo = null; - try { - pInfo = getPackageManager().getPackageInfo(getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - //get the app version Name for display - final String versionName = pInfo.versionName; - - try { - - URL = requestString; - HttpClient httpclient = new DefaultHttpClient(); - HttpParams params = httpclient.getParams(); - - HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT); - HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT); - ConnManagerParams.setTimeout(params, WAIT_TIMEOUT); - - HttpGet httpGet = new HttpGet(URL); - httpGet.setHeader("User-Agent", getString(R.string.app_name) + " " + versionName); - HttpResponse response = httpclient.execute(httpGet); - - StatusLine statusLine = response.getStatusLine(); - Log.d(Config.LOGTAG, "AppUpdater: HTTP Status Code: " + statusLine.getStatusCode()); - if (statusLine.getStatusCode() == HttpStatus.SC_OK) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - response.getEntity().writeTo(out); - out.close(); - responseMessage = out.toString(); - } else { - Log.e(Config.LOGTAG, "AppUpdater: HTTP1:" + statusLine.getReasonPhrase()); - response.getEntity().getContent().close(); - throw new IOException(statusLine.getReasonPhrase()); - } - - } catch (ClientProtocolException e) { - Log.e(Config.LOGTAG, "AppUpdater: HTTP2:" + e); - responseMessage = ""; - } catch (IOException e) { - Log.e(Config.LOGTAG, "AppUpdater: HTTP3:" + e); - responseMessage = ""; - } catch (Exception e) { - Log.e(Config.LOGTAG, "AppUpdater: HTTP4:" + e); - responseMessage = ""; - } - - Intent broadcastIntent = new Intent(); - broadcastIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - broadcastIntent.setAction(UpdateReceiver.PROCESS_RESPONSE); - broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); - broadcastIntent.putExtra(RESPONSE_MESSAGE, responseMessage); - sendBroadcast(broadcastIntent); - } -} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java index f4c66fbb8..a23daa6c0 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java @@ -71,6 +71,7 @@ import de.pixart.messenger.entities.MucOptions; import de.pixart.messenger.entities.Presence; import de.pixart.messenger.entities.Transferable; import de.pixart.messenger.persistance.FileBackend; +import de.pixart.messenger.services.UpdateService; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.services.XmppConnectionService.OnAccountUpdate; import de.pixart.messenger.services.XmppConnectionService.OnConversationUpdate; @@ -382,16 +383,19 @@ public class ConversationActivity extends XmppActivity String PREFS_NAME = "UpdateTimeStamp"; SharedPreferences UpdateTimeStamp = getApplicationContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); long lastUpdateTime = UpdateTimeStamp.getLong("lastUpdateTime", 0); - Log.d(Config.LOGTAG, "AppUpdater - LastUpdateTime: " + lastUpdateTime); + Log.d(Config.LOGTAG, "AppUpdater: LastUpdateTime: " + lastUpdateTime); if ((lastUpdateTime + (Config.UPDATE_CHECK_TIMER * 1000)) < System.currentTimeMillis()) { lastUpdateTime = System.currentTimeMillis(); SharedPreferences.Editor editor = UpdateTimeStamp.edit(); editor.putLong("lastUpdateTime", lastUpdateTime); editor.commit(); // run AppUpdater - Log.d(Config.LOGTAG, "AppUpdater - CurrentTime: " + lastUpdateTime); - Intent AppUpdater = new Intent(this, UpdaterActivity.class); - startActivity(AppUpdater); + Log.d(Config.LOGTAG, "AppUpdater: CurrentTime: " + lastUpdateTime); + //Intent AppUpdater = new Intent(this, UpdaterActivity.class); + //startActivity(AppUpdater); + + UpdateService task = new UpdateService(this); + task.execute("false"); Log.d(Config.LOGTAG, "AppUpdater started"); } else { Log.d(Config.LOGTAG, "AppUpdater stopped"); diff --git a/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java b/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java index d5a1a04f8..5ab90ca7f 100644 --- a/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java +++ b/src/main/java/de/pixart/messenger/ui/UpdaterActivity.java @@ -3,71 +3,43 @@ package de.pixart.messenger.ui; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; -import android.app.DownloadManager; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.support.v4.app.ActivityCompat; import android.util.Log; -import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; -import org.json.JSONException; -import org.json.JSONObject; +import org.apache.http.util.ByteArrayBuffer; +import java.io.BufferedInputStream; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.persistance.FileBackend; -import de.pixart.messenger.services.UpdaterWebService; public class UpdaterActivity extends Activity { static final private String FileName = "update.apk"; String appURI = ""; - private UpdateReceiver receiver = null; - private int versionCode = 0; - private String localVersion = null; - private DownloadManager downloadManager; - private long downloadReference; - - BroadcastReceiver downloadReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null) { - Toast.makeText(getApplicationContext(), - getText(R.string.failed), - Toast.LENGTH_LONG).show(); - UpdaterActivity.this.finish(); - } - //check if the broadcast message is for our Enqueued download - long referenceId = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID); - if (downloadReference == referenceId) { - File file = new File(FileBackend.getConversationsDirectory("Update", false), FileName); - //start the installation of the latest localVersion - Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); - installIntent.setDataAndType(FileBackend.getUriForFile(UpdaterActivity.this, file), "application/vnd.android.package-archive"); - installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); - installIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); - installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(installIntent); - UpdaterActivity.this.finish(); - } - } - }; + String changelog = ""; + Integer filesize = 0; @Override protected void onCreate(Bundle savedInstanceState) { @@ -77,37 +49,80 @@ public class UpdaterActivity extends Activity { setContentView(R.layout.activity_updater); TextView textView = (TextView) findViewById(R.id.updater); textView.setText(R.string.update_info); + } - //Broadcast receiver for our Web Request - IntentFilter filter = new IntentFilter(UpdateReceiver.PROCESS_RESPONSE); - filter.addCategory(Intent.CATEGORY_DEFAULT); - receiver = new UpdateReceiver(); - registerReceiver(receiver, filter); - - //Broadcast receiver for the download manager (download complete) - registerReceiver(downloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); - - //check of internet is available before making a web service request - if (isNetworkAvailable(this)) { - Intent msgIntent = new Intent(this, UpdaterWebService.class); - msgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - msgIntent.putExtra(UpdaterWebService.REQUEST_STRING, Config.UPDATE_URL); + @Override + protected void onStart() { + super.onStart(); + if (getIntent() != null && getIntent().getStringExtra("update").equals("PixArtMessenger_UpdateService")) { + try { + appURI = getIntent().getStringExtra("url"); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), getText(R.string.failed), Toast.LENGTH_LONG).show(); + UpdaterActivity.this.finish(); + } + try { + changelog = getIntent().getStringExtra("changelog"); + } catch (Exception e) { + Toast.makeText(getApplicationContext(), getText(R.string.failed), Toast.LENGTH_LONG).show(); + UpdaterActivity.this.finish(); + } + //delete old downloaded localVersion files + File dir = new File(FileBackend.getConversationsDirectory("Update", false)); + if (dir.isDirectory()) { + String[] children = dir.list(); + for (String aChildren : children) { + Log.d(Config.LOGTAG, "AppUpdater: delete old update files " + aChildren + " in " + dir); + new File(dir, aChildren).delete(); + } + } - Toast.makeText(getApplicationContext(), - getText(R.string.checking_for_updates), - Toast.LENGTH_SHORT).show(); - startService(msgIntent); + //oh yeah we do need an upgrade, let the user know send an alert message + AlertDialog.Builder builder = new AlertDialog.Builder(UpdaterActivity.this); + builder.setCancelable(false); + builder.setMessage(getString(R.string.install_update)) + .setPositiveButton(R.string.update, new DialogInterface.OnClickListener() { + //if the user agrees to upgrade + public void onClick(DialogInterface dialog, int id) { + Log.d(Config.LOGTAG, "AppUpdater: downloading " + FileName + " from " + appURI); + //ask for permissions on devices >= SDK 23 + if (isStoragePermissionGranted() && isNetworkAvailable(getApplicationContext())) { + //start downloading the file using the download manager + DownloadFromUrl(appURI, FileName); + Toast.makeText(getApplicationContext(), getText(R.string.download_started), Toast.LENGTH_LONG).show(); + } else { + Log.d(Config.LOGTAG, "AppUpdater: failed - has storage permissions " + isStoragePermissionGranted() + " and internet " + isNetworkAvailable(getApplicationContext())); + } + } + }) + .setNeutralButton(R.string.changelog, new DialogInterface.OnClickListener() { + //open link to changelog + public void onClick(DialogInterface dialog, int id) { + Uri uri = Uri.parse("https://github.com/kriztan/Conversations/blob/master/CHANGELOG.md"); // missing 'http://' will cause crashed + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + //restart updater to show dialog again after coming back after opening changelog + recreate(); + } + }) + .setNegativeButton(R.string.remind_later, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + UpdaterActivity.this.finish(); + } + }); + //show the alert message + builder.create().show(); + } else { + Toast.makeText(getApplicationContext(), getText(R.string.failed), Toast.LENGTH_LONG).show(); + UpdaterActivity.this.finish(); } } @Override public void onDestroy() { - //unregister your receivers - this.unregisterReceiver(receiver); - this.unregisterReceiver(downloadReceiver); super.onDestroy(); - //enable touch events - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); } @Override @@ -120,6 +135,70 @@ public class UpdaterActivity extends Activity { super.onRestoreInstanceState(savedInstanceState); } + public void DownloadFromUrl(final String DownloadUrl, final String FileName) { + final Thread thread = new Thread(new Runnable() { + + @Override + public void run() { + try { + File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + FileBackend.getDirectoryName("Update", false)); + + URL url = new URL(DownloadUrl); + File file = new File(dir, FileName); + Log.d(Config.LOGTAG, "AppUpdater: save file to " + file.toString()); + + long startTime = System.currentTimeMillis(); + Log.d(Config.LOGTAG, "AppUpdater: download update from url: " + url + " to file name: " + file.toString()); + + // Open a connection to that URL. + URLConnection connection = url.openConnection(); + + //Define InputStreams to read from the URLConnection. + InputStream is = connection.getInputStream(); + BufferedInputStream bis = new BufferedInputStream(is); + + //Read file size + List values = connection.getHeaderFields().get("content-Length"); + if (values != null && !values.isEmpty()) { + String sLength = (String) values.get(0); + if (sLength != null) { + filesize = Integer.parseInt(sLength); + } + } + //Read bytes to the Buffer until there is nothing more to read(-1). + ByteArrayBuffer baf = new ByteArrayBuffer(5000); + int current = 0; + while ((current = bis.read()) != -1) { + baf.append((byte) current); + } + + // Convert the Bytes read to a String. + FileOutputStream fos = new FileOutputStream(file); + fos.write(baf.toByteArray()); + fos.flush(); + fos.close(); + Log.d(Config.LOGTAG, "AppUpdater: download ready in" + ((System.currentTimeMillis() - startTime) / 1000) + " sec"); + + //start the installation of the latest localVersion + Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); + installIntent.setDataAndType(FileBackend.getUriForFile(UpdaterActivity.this, file), "application/vnd.android.package-archive"); + installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); + installIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); + installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(installIntent); + UpdaterActivity.this.finish(); + + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + Log.d(Config.LOGTAG, "AppUpdater: Error: " + e); + } + } + }); + thread.start(); + } + //check for internet connection private boolean isNetworkAvailable(Context context) { ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -170,180 +249,4 @@ public class UpdaterActivity extends Activity { AlertDialog alert = builder.create(); alert.show(); } - - /** - * Use this instead of String.compareTo() for a non-lexicographical - * comparison that works for version strings. e.g. "1.10".compareTo("1.6"). - * - * @param str1 a string of ordinal numbers separated by decimal points. - * @param str2 a string of ordinal numbers separated by decimal points. - * @return The result is a negative integer if str1 is _numerically_ less than str2. - * The result is a positive integer if str1 is _numerically_ greater than str2. - * The result is zero if the strings are _numerically_ equal. - * @note It does not work if "1.10" is supposed to be equal to "1.10.0". - */ - private int checkVersion(String remoteVersion, String installedVersion) { - String[] remote = null; - String[] installed = null; - String[] remoteV = null; - String[] installedV = null; - try { - installedV = installedVersion.split(" "); - Log.d(Config.LOGTAG, "Updater Version installed: " + installedV[0]); - installed = installedV[0].split("\\."); - } catch (Exception e) { - e.printStackTrace(); - } - try { - remoteV = remoteVersion.split(" "); - if (installedV != null && installedV.length > 1) { - if (installedV[1] != null) { - remoteV[0] = remoteV[0] + ".1"; - } - } - Log.d(Config.LOGTAG, "Updater Version on server: " + remoteV[0]); - remote = remoteV[0].split("\\."); - } catch (Exception e) { - e.printStackTrace(); - } - int i = 0; - // set index to first non-equal ordinal or length of shortest localVersion string - if (remote != null && installed != null) { - while (i < remote.length && i < installed.length && remote[i].equals(installed[i])) { - i++; - } - // compare first non-equal ordinal number - if (i < remote.length && i < installed.length) { - int diff = Integer.valueOf(remote[i]).compareTo(Integer.valueOf(installed[i])); - return Integer.signum(diff); - } - // the strings are equal or one string is a substring of the other - // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" - return Integer.signum(remote.length - installed.length); - } - return 0; - } - - //broadcast receiver to get notification when the web request finishes - public class UpdateReceiver extends BroadcastReceiver { - - public static final String PROCESS_RESPONSE = "de.pixart.messenger.intent.action.PROCESS_RESPONSE"; - - @Override - public void onReceive(Context context, Intent intent) { - - //disable touch events - getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - - String responseMessage = intent.getStringExtra(UpdaterWebService.RESPONSE_MESSAGE); - - if (responseMessage == "" || responseMessage.isEmpty() || responseMessage == null) { - Toast.makeText(getApplicationContext(), - getText(R.string.failed), - Toast.LENGTH_LONG).show(); - UpdaterActivity.this.finish(); - } else { - //parse the JSON reponse - JSONObject reponseObj; - - try { - //if the response was successful check further - reponseObj = new JSONObject(responseMessage); - boolean success = reponseObj.getBoolean("success"); - if (success) { - //Overall information about the contents of a package - //This corresponds to all of the information collected from AndroidManifest.xml. - PackageInfo pInfo = null; - try { - pInfo = getPackageManager().getPackageInfo(getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - //get the app localVersion Name for display - String localVersion = pInfo.versionName; - //get the latest localVersion from the JSON string - int latestVersionCode = reponseObj.getInt("latestVersionCode"); - String remoteVersion = reponseObj.getString("latestVersion"); - String filesize = reponseObj.getString("filesize"); - String changelog = reponseObj.getString("changelog"); - //get the lastest application URI from the JSON string - appURI = reponseObj.getString("appURI"); - //check if we need to upgrade? - if (checkVersion(remoteVersion, localVersion) >= 1) { - //delete old downloaded localVersion files - File dir = new File(FileBackend.getConversationsDirectory("Update", false)); - if (dir.isDirectory()) { - String[] children = dir.list(); - for (String aChildren : children) { - Log.d(Config.LOGTAG, "Updater delete old update files " + aChildren + " in " + dir); - new File(dir, aChildren).delete(); - } - } - //enable touch events - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - - //oh yeah we do need an upgrade, let the user know send an alert message - AlertDialog.Builder builder = new AlertDialog.Builder(UpdaterActivity.this); - builder.setCancelable(false); - String UpdateMessageInfo = getResources().getString(R.string.update_available); - builder.setMessage(String.format(UpdateMessageInfo, remoteVersion, filesize, localVersion, changelog)) - .setPositiveButton(R.string.update, new DialogInterface.OnClickListener() { - //if the user agrees to upgrade - public void onClick(DialogInterface dialog, int id) { - //disable touch events - getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - //ask for permissions on devices >= SDK 23 - if (isStoragePermissionGranted()) { - //start downloading the file using the download manager - downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); - Uri Download_Uri = Uri.parse(appURI); - DownloadManager.Request request = new DownloadManager.Request(Download_Uri); - request.setTitle("Pix-Art Messenger Update"); - request.setDestinationInExternalPublicDir(FileBackend.getDirectoryName("Update", false), FileName); - downloadReference = downloadManager.enqueue(request); - Toast.makeText(getApplicationContext(), - getText(R.string.download_started), - Toast.LENGTH_LONG).show(); - } - } - }) - .setNeutralButton(R.string.changelog, new DialogInterface.OnClickListener() { - //open link to changelog - public void onClick(DialogInterface dialog, int id) { - Uri uri = Uri.parse("https://github.com/kriztan/Conversations/blob/master/CHANGELOG.md"); // missing 'http://' will cause crashed - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - //restart updater to show dialog again after coming back after opening changelog - recreate(); - } - }) - .setNegativeButton(R.string.remind_later, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - // User cancelled the dialog - UpdaterActivity.this.finish(); - } - }); - //show the alert message - builder.create().show(); - } else { - Toast.makeText(getApplicationContext(), - getText(R.string.no_update_available), - Toast.LENGTH_SHORT).show(); - UpdaterActivity.this.finish(); - } - } else { - Toast.makeText(getApplicationContext(), - getText(R.string.failed), - Toast.LENGTH_LONG).show(); - UpdaterActivity.this.finish(); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - } - } } diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java index e5b894322..0fe6e7600 100644 --- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java +++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java @@ -79,6 +79,7 @@ import de.pixart.messenger.entities.Presences; import de.pixart.messenger.http.HttpConnectionManager; import de.pixart.messenger.services.AvatarService; import de.pixart.messenger.services.BarcodeProvider; +import de.pixart.messenger.services.UpdateService; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.services.XmppConnectionService.XmppConnectionBinder; import de.pixart.messenger.utils.CryptoHelper; @@ -376,7 +377,10 @@ public abstract class XmppActivity extends Activity { break; case R.id.action_check_updates: if (xmppConnectionService.hasInternetConnection()) { - startActivity(new Intent(this, UpdaterActivity.class)); + //startActivity(new Intent(this, UpdaterActivity.class)); + + UpdateService task = new UpdateService(this); + task.execute("true"); } else { Toast.makeText(this, R.string.account_status_no_internet, Toast.LENGTH_LONG).show(); } -- cgit v1.2.3