Android Open Source - HockeySDK-Android Version Helper






From Project

Back to project page HockeySDK-Android.

License

The source code is released under:

Apache License

If you think the Android project HockeySDK-Android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package net.hockeyapp.android.utils;
/*ww w  .  j  a v  a  2s .co m*/
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Scanner;

import net.hockeyapp.android.UpdateInfoListener;

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

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

/**
 * <h3>Description</h3>
 * 
 * Internal helper class. Provides helper methods to parse the
 * version JSON and create the release notes as HTML. 
 * 
 * <h3>License</h3>
 * 
 * <pre>
 * Copyright (c) 2011-2014 Bit Stadium GmbH
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * </pre>
 *
 * @author Thomas Dohmke
 **/
public class VersionHelper {
  private ArrayList<JSONObject> sortedVersions;
  private JSONObject newest;
  private UpdateInfoListener listener;
  private int currentVersionCode;
  
  public VersionHelper(Context context, String infoJSON, UpdateInfoListener listener) {
    this.listener = listener;

    loadVersions(context, infoJSON);
    sortVersions();
  }
  
  private void loadVersions(Context context, String infoJSON) {
    this.newest = new JSONObject();
    this.sortedVersions = new ArrayList<JSONObject>();
    this.currentVersionCode = listener.getCurrentVersionCode();

    try {
      JSONArray versions = new JSONArray(infoJSON);
      
      int versionCode = listener.getCurrentVersionCode();
      for (int index = 0; index < versions.length(); index++) {
        JSONObject entry = versions.getJSONObject(index);
        boolean largerVersionCode = (entry.getInt("version") > versionCode);
        boolean newerApkFile = ((entry.getInt("version") == versionCode) && VersionHelper.isNewerThanLastUpdateTime(context, entry.getLong("timestamp")));

        if (largerVersionCode || newerApkFile) {
          newest = entry;
          versionCode = entry.getInt("version");
        }
        sortedVersions.add(entry);
      }
    }
    catch (JSONException je) {
    }
    catch (NullPointerException ne) {
    }
  }

  private void sortVersions() {
    Collections.sort(sortedVersions, new Comparator<JSONObject>() {
      public int compare(JSONObject object1, JSONObject object2) {
        try {
          if (object1.getInt("version") > object2.getInt("version")) {
            return 0;
          }
        }
        catch (JSONException je) {
        }
        catch (NullPointerException ne) {
        }

        return 0;
      }
    });
  }

  public String getVersionString() {
    return failSafeGetStringFromJSON(newest, "shortversion", "") + " (" + failSafeGetStringFromJSON(newest, "version", "") + ")";
  }
  
  public String getFileDateString() {
    long timestamp = failSafeGetLongFromJSON(newest, "timestamp", 0L);
    Date date = new Date(timestamp * 1000L);
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
    return dateFormat.format(date);
  }

  public long getFileSizeBytes() {
    boolean external = Boolean.valueOf(failSafeGetStringFromJSON(newest, "external", "false"));
    long appSize = failSafeGetLongFromJSON(newest, "appsize", 0L);

    // In case of external builds a size of 0 most likely means that the size could not be determined because the URL
    // is not accessible from the HockeyApp servers via the Internet. Return -1 in that case in order to try retrieving
    // the size at runtime from the HTTP header later.
    return (external && appSize == 0L) ? -1L : appSize;
  }

  private static String failSafeGetStringFromJSON(JSONObject json, String name, String defaultValue) {
    try {
      return json.getString(name);
    }
    catch (JSONException e) {
      return defaultValue;
    }
  }
  
  private static long failSafeGetLongFromJSON(JSONObject json, String name, long defaultValue) {
    try {
      return json.getLong(name);
    }
    catch (JSONException e) {
      return defaultValue;
    }
  }

  public String getReleaseNotes(boolean showRestore) {
    StringBuilder result = new StringBuilder();
    result.append("<html>");
    result.append("<body style='padding: 0px 0px 20px 0px'>");
    
    int count = 0;
    for (JSONObject version : sortedVersions) {
      if (count > 0) {
        result.append(getSeparator());
        if (showRestore) { 
          result.append(getRestoreButton(count, version));
        }
      }
      result.append(getVersionLine(count, version));
      result.append(getVersionNotes(count, version));
      count++;
    }

    result.append("</body>");
    result.append("</html>");

    return result.toString();
  }

  private Object getSeparator() {
    return "<hr style='border-top: 1px solid #c8c8c8; border-bottom: 0px; margin: 40px 10px 0px 10px;' />";
  }

  private String getRestoreButton(int count, JSONObject version) {
    StringBuilder result = new StringBuilder();

    String versionID = getVersionID(version);
    if (versionID.length() > 0) {
      result.append("<a href='restore:" + versionID + "'  style='background: #c8c8c8; color: #000; display: block; float: right; padding: 7px; margin: 0px 10px 10px; text-decoration: none;'>Restore</a>");
    }

    return result.toString();
  }

  private String getVersionID(JSONObject version) {
    String versionID = "";
    try { 
      versionID = version.getString("id");
    }
    catch (JSONException e) {
    }
    return versionID;
  }

  private String getVersionLine(int count, JSONObject version) {
    StringBuilder result = new StringBuilder();

    int newestCode = getVersionCode(newest);
    int versionCode = getVersionCode(version);
    String versionName = getVersionName(version);
    
    result.append("<div style='padding: 20px 10px 10px;'><strong>");
    if (count == 0) {
      result.append("Newest version:");
    }
    else {
      result.append("Version " + versionName + " (" + versionCode + "): ");
      if ((versionCode != newestCode) && (versionCode == currentVersionCode)) {
        currentVersionCode = -1;
        result.append("[INSTALLED]");
      }
    }
    result.append("</strong></div>");
    
    return result.toString();
  }
  
  private int getVersionCode(JSONObject version) {
    int versionCode = 0;
    try { 
      versionCode = version.getInt("version");
    }
    catch (JSONException e) {
    }
    return versionCode;
  }
  
  private String getVersionName(JSONObject version) {
    String versionName = "";
    try { 
      versionName = version.getString("shortversion");
    }
    catch (JSONException e) {
    }
    return versionName;
  }

  private String getVersionNotes(int count, JSONObject version) {
    StringBuilder result = new StringBuilder();

    String notes = failSafeGetStringFromJSON(version, "notes", "");
    result.append("<div style='padding: 0px 10px;'>");
    if (notes.trim().length() == 0) {
      result.append("<em>No information.</em>");
    }
    else {
      result.append(notes);
    }
    result.append("</div>");

    return result.toString();
  }
  
  /**
   * Compare two versions strings with each other by splitting at the . 
   * and comparing the integer values. Additional string like "-update1"
   * are ignored, i.e. "2.2" is considered equal to "2.2-update1". 
   * 
   * @param left A version string, e.g. "2.1".
   * @param right A version string, e.g. "4.2.2".
   * @return 0 if the versions are equal. 
   *         1 if the left side is bigger.
   *         -1 if the right side is bigger.
   */
  public static int compareVersionStrings(String left, String right) {
    // If either side is null, we consider the versions equal
    if ((left == null) || (right == null)) {
      return 0;
    }

    try {
      // Strip out any "-update1" stuff, then build a scanner for the strings
      Scanner leftScanner = new Scanner(left.replaceAll("\\-.*", ""));
      Scanner rightScanner = new Scanner(right.replaceAll("\\-.*", ""));
      leftScanner.useDelimiter("\\.");
      rightScanner.useDelimiter("\\.");

      // Compare the parts
      while ((leftScanner.hasNextInt()) && (rightScanner.hasNextInt())) {
        int leftValue = leftScanner.nextInt();
        int rightValue = rightScanner.nextInt();
        if (leftValue < rightValue) {
          return -1;
        } 
        else if (leftValue > rightValue) {
          return 1;
        }
      }

      // Left side has more parts, so consider it bigger
      if (leftScanner.hasNextInt()) {
        return 1;
      } 
      // Right side has more parts, so consider it bigger
      else if (rightScanner.hasNextInt()) {
        return -1;
      } 
      // Ok, they are equal
      else {
        return 0;
      }
    }
    catch (Exception e) {
      // If any exceptions happen, return zero
      return 0;
    }
  }

  /**
   * Returns true of the given timestamp is larger / newer than the last modified timestamp of
   * the APK file of the app.
   *
   * @param context the context to use
   * @param timestamp a Unix-style timestamp
   * @return true if the timestamp is larger / never
   */
  public static boolean isNewerThanLastUpdateTime(Context context, long timestamp) {
    if (context == null) {
      return false;
    }

    try {
      PackageManager pm = context.getPackageManager();
      ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), 0);
      String appFile = appInfo.sourceDir;

      // Get the last modified time stamp and adjust by half an hour
      // to avoid issues with time deviations between client and server
      long lastModified = new File(appFile).lastModified() / 1000 + 1800;

      return timestamp > lastModified;
    }
    catch (PackageManager.NameNotFoundException e) {
      e.printStackTrace();
      return false;
    }
  }

  /**
   * Map internal Google version letter to a semantic version (currently L to 5.0).
   *
   * @param version value of Build.VERSION.RELEASE
   * @return mapped version number
   */
  public static String mapGoogleVersion(String version) {
    if ((version == null) || (version.equalsIgnoreCase("L"))) {
      return "5.0";
    }
    else {
      return version;
    }
  }
}




Java Source Code List

net.hockeyapp.android.Constants.java
net.hockeyapp.android.CrashManagerListener.java
net.hockeyapp.android.CrashManager.java
net.hockeyapp.android.ExceptionHandler.java
net.hockeyapp.android.ExpiryInfoActivity.java
net.hockeyapp.android.FeedbackActivityInterface.java
net.hockeyapp.android.FeedbackActivity.java
net.hockeyapp.android.FeedbackManagerListener.java
net.hockeyapp.android.FeedbackManager.java
net.hockeyapp.android.LocaleManager.java
net.hockeyapp.android.LoginActivity.java
net.hockeyapp.android.LoginManagerListener.java
net.hockeyapp.android.LoginManager.java
net.hockeyapp.android.PaintActivity.java
net.hockeyapp.android.StringListener.java
net.hockeyapp.android.Strings.java
net.hockeyapp.android.Tracking.java
net.hockeyapp.android.UpdateActivityInterface.java
net.hockeyapp.android.UpdateActivity.java
net.hockeyapp.android.UpdateFragment.java
net.hockeyapp.android.UpdateInfoListener.java
net.hockeyapp.android.UpdateManagerListener.java
net.hockeyapp.android.UpdateManager.java
net.hockeyapp.android.adapters.MessagesAdapter.java
net.hockeyapp.android.listeners.DownloadFileListener.java
net.hockeyapp.android.listeners.SendFeedbackListener.java
net.hockeyapp.android.objects.ErrorObject.java
net.hockeyapp.android.objects.FeedbackAttachment.java
net.hockeyapp.android.objects.FeedbackMessage.java
net.hockeyapp.android.objects.FeedbackResponse.java
net.hockeyapp.android.objects.Feedback.java
net.hockeyapp.android.tasks.AttachmentDownloader.java
net.hockeyapp.android.tasks.CheckUpdateTaskWithUI.java
net.hockeyapp.android.tasks.CheckUpdateTask.java
net.hockeyapp.android.tasks.DownloadFileTask.java
net.hockeyapp.android.tasks.GetFileSizeTask.java
net.hockeyapp.android.tasks.LoginTask.java
net.hockeyapp.android.tasks.ParseFeedbackTask.java
net.hockeyapp.android.tasks.SendFeedbackTask.java
net.hockeyapp.android.utils.AsyncTaskUtils.java
net.hockeyapp.android.utils.Base64.java
net.hockeyapp.android.utils.ConnectionManager.java
net.hockeyapp.android.utils.DeviceUtils.java
net.hockeyapp.android.utils.FeedbackParser.java
net.hockeyapp.android.utils.ImageUtils.java
net.hockeyapp.android.utils.PrefsUtil.java
net.hockeyapp.android.utils.SimpleMultipartEntity.java
net.hockeyapp.android.utils.UiThreadUtil.java
net.hockeyapp.android.utils.Util.java
net.hockeyapp.android.utils.VersionCache.java
net.hockeyapp.android.utils.VersionHelper.java
net.hockeyapp.android.utils.ViewHelper.java
net.hockeyapp.android.views.AttachmentListView.java
net.hockeyapp.android.views.AttachmentView.java
net.hockeyapp.android.views.ExpiryInfoView.java
net.hockeyapp.android.views.FeedbackMessageView.java
net.hockeyapp.android.views.FeedbackView.java
net.hockeyapp.android.views.LoginView.java
net.hockeyapp.android.views.PaintView.java
net.hockeyapp.android.views.UpdateView.java