Android Open Source - HockeySDK-Android Update Activity






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;
/*w  ww . ja  v a  2  s.  c o m*/
import net.hockeyapp.android.listeners.DownloadFileListener;
import net.hockeyapp.android.objects.ErrorObject;
import net.hockeyapp.android.tasks.DownloadFileTask;
import net.hockeyapp.android.tasks.GetFileSizeTask;
import net.hockeyapp.android.utils.AsyncTaskUtils;
import net.hockeyapp.android.utils.VersionHelper;
import net.hockeyapp.android.views.UpdateView;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;

/**
 * <h3>Description</h3>
 * 
 * Activity to show update information and start the download
 * process if the user taps the corresponding button.
 * 
 * <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 UpdateActivity extends Activity implements UpdateActivityInterface, UpdateInfoListener, OnClickListener {
  private final int DIALOG_ERROR_ID = 0;
  private ErrorObject error;
  private Context context;
  
  /**
   * Task to download the .apk file.
   */
  protected DownloadFileTask downloadTask;
  
  /**
   * Helper for version management.
   */
  protected VersionHelper versionHelper;
  
  /**
   * Called when the activity is starting. Sets the title and content view.
   * Configures the list view adapter. Attaches itself to a previously 
   * started download task.
   * 
   * @param savedInstanceState Data it most recently supplied in 
   *                           onSaveInstanceState(Bundle)
   */
  @SuppressWarnings("deprecation")
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setTitle("App Update");
    setContentView(getLayoutView());

    context = this;
    versionHelper = new VersionHelper(this, getIntent().getStringExtra("json"), this);
    configureView();
    
    downloadTask = (DownloadFileTask)getLastNonConfigurationInstance();
    if (downloadTask != null) {
      downloadTask.attach(this);
    }
  }
  
  /**
   * Configures the content view by setting app name, the current version
   * and the listener for the download button. 
   */
  protected void configureView() {
    TextView nameLabel = (TextView)findViewById(UpdateView.NAME_LABEL_ID);
    nameLabel.setText(getAppName());
    
    final TextView versionLabel = (TextView)findViewById(UpdateView.VERSION_LABEL_ID);
    final String versionString = "Version " + versionHelper.getVersionString();
    final String fileDate = versionHelper.getFileDateString();

    String appSizeString = "Unknown size";
    long appSize = versionHelper.getFileSizeBytes();
    if (appSize >= 0L) {
      appSizeString = String.format("%.2f", appSize / (1024.0f * 1024.0f)) + " MB";
    }
    else {
      GetFileSizeTask task = new GetFileSizeTask(this, getIntent().getStringExtra("url"), new DownloadFileListener() {
        @Override
        public void downloadSuccessful(DownloadFileTask task) {
          if (task instanceof GetFileSizeTask) {
            long appSize = ((GetFileSizeTask)task).getSize();
            String appSizeString = String.format("%.2f", appSize / (1024.0f * 1024.0f)) + " MB";
            versionLabel.setText(versionString + "\n" + fileDate + " - " + appSizeString);
          }
        }
      });
      AsyncTaskUtils.execute(task);
    }
    versionLabel.setText(versionString + "\n" + fileDate + " - " + appSizeString);
    
    Button updateButton = (Button)findViewById(UpdateView.UPDATE_BUTTON_ID);
    updateButton.setOnClickListener(this);
    
    WebView webView = (WebView)findViewById(UpdateView.WEB_VIEW_ID);
    webView.clearCache(true);
    webView.destroyDrawingCache();
    webView.loadDataWithBaseURL(Constants.BASE_URL, getReleaseNotes(), "text/html", "utf-8", null);
  }

  /**
   * Returns the release notes as HTML.
   * 
   * @return String with release notes.
   */
  protected String getReleaseNotes() {
    return versionHelper.getReleaseNotes(false);
  }

  /**
   * Detaches the activity from the download task and returns the task
   * as last instance. This way the task is restored when the activity
   * is immediately re-created.
   * 
   * @return The download task if present.
   */
  @Override
  public Object onRetainNonConfigurationInstance() {
    if (downloadTask != null) {
      downloadTask.detach();
    }
    return downloadTask;
  }
  
  /**
   * Starts the download task for the app and sets the listener 
   * for a successful download, a failed download, and configuration 
   * strings.
   */
  protected void startDownloadTask() {
    String url = getIntent().getStringExtra("url");
    startDownloadTask(url);
  }
  
  /**
   * Starts the download task and sets the listener for a successful
   * download, a failed download, and configuration strings.
   *
   * @param url URL of file that should be downloaded
   */
  protected void startDownloadTask(String url) {
    createDownloadTask(url, new DownloadFileListener() {
      public void downloadSuccessful(DownloadFileTask task) {
        enableUpdateButton();
      }
      
      public void downloadFailed(DownloadFileTask task, Boolean userWantsRetry) {
        if (userWantsRetry) {
          startDownloadTask();
        }
        else {
          enableUpdateButton();
        }
      }
      
      public String getStringForResource(int resourceID) {
        UpdateManagerListener listener = UpdateManager.getLastListener();
        if (listener != null) {
          return listener.getStringForResource(resourceID);
        }
        else {
          return null;
        }
      }
    });
    AsyncTaskUtils.execute(downloadTask);
  }
  
  protected void createDownloadTask(String url, DownloadFileListener listener) {
    downloadTask = new DownloadFileTask(this, url, listener);
  }
  
  /**
   * Enables the download button.
   */
  public void enableUpdateButton() {
    View updateButton = findViewById(UpdateView.UPDATE_BUTTON_ID);
    updateButton.setEnabled(true);
  }
  
  /**
   * Returns the current version of the app.
   * 
   * @return The version code as integer.
   */
  public int getCurrentVersionCode() {
    int currentVersionCode = -1;
    
    try {
      currentVersionCode = getPackageManager().getPackageInfo(this.getPackageName(), PackageManager.GET_META_DATA).versionCode;
    }
    catch (NameNotFoundException e) {
    }
    
    return currentVersionCode;
  }
  
  /**
   * Creates and returns a new instance of UpdateView.
   * 
   * @return Instance of UpdateView
   */
  public ViewGroup getLayoutView() {
    return new UpdateView(this);
  }

  /**
   * Returns the app's name.
   * 
   * @return The app's name as a String.
   */
  public String getAppName() {
    try {
      PackageManager pm = getPackageManager();
      ApplicationInfo applicationInfo = pm.getApplicationInfo(getPackageName(), 0);
      return pm.getApplicationLabel(applicationInfo).toString();
    }
    catch (NameNotFoundException exception) {
      return "";
    }
  }

  /**
   * Checks if WRITE_EXTERNAL_STORAGE permission was added to the {@link Manifest} file
   * @param context
   * @return
   */
  private boolean isWriteExternalStorageSet(Context context) {
    String permission = "android.permission.WRITE_EXTERNAL_STORAGE";
    int res = context.checkCallingOrSelfPermission(permission);
    
    return res == PackageManager.PERMISSION_GRANTED;
  }
  
  /**
   * Checks if Unknown Sources is checked from {@link Settings}
   *
   * @return
   */
  @SuppressWarnings("deprecation")
  private boolean isUnknownSourcesChecked() {
    try {
      if (android.os.Build.VERSION.SDK_INT >= 17 && android.os.Build.VERSION.SDK_INT < 21) {
        return (Settings.Global.getInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS) == 1);
      }
      else {
        return (Settings.Secure.getInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS) == 1);
      }
    } catch (Settings.SettingNotFoundException e) {
      return true;
    }
  }
    
  /**
   * Called when the download button is tapped. Starts the download task and
   * disables the button to avoid multiple taps.
   */
  public void onClick(View v) {
    if (!isWriteExternalStorageSet(context)) {
      error = new ErrorObject();
      error.setMessage("The permission to access the external storage permission is not set. Please contact the developer.");
      
      runOnUiThread(new Runnable() {
        @SuppressWarnings("deprecation")
        @Override
        public void run() {
          showDialog(DIALOG_ERROR_ID);
        }
      });
      
      return;
    }
    
    if (!isUnknownSourcesChecked()) {
      error = new ErrorObject();
      error.setMessage("The installation from unknown sources is not enabled. Please check the device settings.");
      
      runOnUiThread(new Runnable() {
        @SuppressWarnings("deprecation")
        @Override
        public void run() {
          showDialog(DIALOG_ERROR_ID);
        }
      });
      
      return;
    }
    
    startDownloadTask();
    v.setEnabled(false);
  }

  @Override
  protected Dialog onCreateDialog(int id) {
    switch(id) {
      case DIALOG_ERROR_ID:
        return new AlertDialog.Builder(this)
          .setMessage("An error has occured")
          .setCancelable(false)
          .setTitle("Error")
          .setIcon(android.R.drawable.ic_dialog_alert)
          .setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              error = null;
              dialog.cancel();
            }
          }).create();
    }
  
    return null;
  }

  @Override
  protected void onPrepareDialog(int id, Dialog dialog) {
    switch(id) {
      case DIALOG_ERROR_ID:
        AlertDialog messageDialogError = (AlertDialog) dialog;
        if (error != null) {
          /** If the ErrorObject is not null, display the ErrorObject message */
          messageDialogError.setMessage(error.getMessage());
        } 
        else {
          /** If the ErrorObject is null, display the general error message */
          messageDialogError.setMessage("An unknown error has occured.");
        }
  
        break;
    }
  }
}




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