Android Open Source - HockeySDK-Android Download File Task






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.tasks;
/*  www.ja v a  2  s  . c o  m*/
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import net.hockeyapp.android.Strings;
import net.hockeyapp.android.listeners.DownloadFileListener;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;

/**
 * <h3>Description</h3>
 * 
 * Internal helper class. Downloads an .apk from HockeyApp and stores
 * it on external storage. If the download was successful, the file 
 * is then opened to trigger the installation. 
 * 
 * <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 DownloadFileTask extends AsyncTask<Void, Integer, Long> {
  protected static final int MAX_REDIRECTS = 6;

  protected Context context;
  protected DownloadFileListener notifier;
  protected String urlString;
  protected String filename;
  protected String filePath;
  protected ProgressDialog progressDialog;
  private String downloadErrorMessage;

  public DownloadFileTask(Context context, String urlString, DownloadFileListener notifier) {
    this.context = context;
    this.urlString = urlString;
    this.filename = UUID.randomUUID() + ".apk";
    this.filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download";
    this.notifier = notifier;
    this.downloadErrorMessage = null;
  }

  public void attach(Context context) {
    this.context = context;
  }

  public void detach() {
    context = null;
    progressDialog = null;
  }

  @Override
  protected Long doInBackground(Void... args) {
    try {
      URL url = new URL(getURLString());
      URLConnection connection = createConnection(url, MAX_REDIRECTS);
      connection.connect();

      int lengthOfFile = connection.getContentLength();
      String contentType = connection.getContentType();

      if (contentType != null && contentType.contains("text")) {
        // This is not the expected APK file. Maybe the redirect could not be resolved.
        downloadErrorMessage = "The requested download does not appear to be a file.";
        return 0L;
      }

      File dir = new File(this.filePath);
      boolean result = dir.mkdirs();
      if (!result && !dir.exists()) {
        throw new IOException("Could not create the dir(s):" + dir.getAbsolutePath());
      }
      File file = new File(dir, this.filename);

      InputStream input = new BufferedInputStream(connection.getInputStream());
      OutputStream output = new FileOutputStream(file);

      byte data[] = new byte[1024];
      int count;
      long total = 0;
      while ((count = input.read(data)) != -1) {
        total += count;
        publishProgress(Math.round(total * 100.0f / lengthOfFile));
        output.write(data, 0, count);
      }

      output.flush();
      output.close();
      input.close();

      return total;
    } 
    catch (Exception e) {
      e.printStackTrace();
      return 0L;
    }
  }

  protected void setConnectionProperties(HttpURLConnection connection) {
    connection.addRequestProperty("User-Agent", "HockeySDK/Android");
    connection.setInstanceFollowRedirects(true);

    // connection bug workaround for SDK<=2.x
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD) {
      connection.setRequestProperty("connection", "close");
    }
  }

  /**
   * Recursive method for resolving redirects. Resolves at most MAX_REDIRECTS times.
   * 
   * @param url a URL
   * @param remainingRedirects loop counter
   * @throws IOException if connection fails
   * @return instance of URLConnection
   */
  protected URLConnection createConnection(URL url, int remainingRedirects) throws IOException {
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    setConnectionProperties(connection);

    int code = connection.getResponseCode();
    if (code == HttpURLConnection.HTTP_MOVED_PERM ||
        code == HttpURLConnection.HTTP_MOVED_TEMP ||
        code == HttpURLConnection.HTTP_SEE_OTHER) {

      if (remainingRedirects == 0) {
        // Stop redirecting.
        return connection;
      }

      URL movedUrl = new URL(connection.getHeaderField("Location"));
      if (!url.getProtocol().equals(movedUrl.getProtocol())) {
        // HttpURLConnection doesn't handle redirects across schemes, so handle it manually, see
        // http://code.google.com/p/android/issues/detail?id=41651
        connection.disconnect();
        return createConnection(movedUrl, --remainingRedirects); // Recursion
      }
    }
    return connection;
  }

  @Override
  protected void onProgressUpdate(Integer... args) {
    try {
      if (progressDialog == null) {
        progressDialog = new ProgressDialog(context);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(false);
        progressDialog.show();
      }
      progressDialog.setProgress(args[0]);
    }
    catch (Exception e) {
      // Ignore all exceptions
    }
  }

  @Override
  protected void onPostExecute(Long result) {
    if (progressDialog != null) {
      try {
        progressDialog.dismiss();
      }
      catch (Exception e) {
        // Ignore all exceptions
      }
    }

    if (result > 0L) {
      notifier.downloadSuccessful(this);

      Intent intent = new Intent(Intent.ACTION_VIEW);
      intent.setDataAndType(Uri.fromFile(new File(this.filePath, this.filename)), "application/vnd.android.package-archive");
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context.startActivity(intent);
    }
    else {
      try {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle(Strings.get(notifier, Strings.DOWNLOAD_FAILED_DIALOG_TITLE_ID));

        String message;
        if (downloadErrorMessage == null) {
          message = Strings.get(notifier, Strings.DOWNLOAD_FAILED_DIALOG_MESSAGE_ID);
        }
        else {
          message = downloadErrorMessage;
        }
        builder.setMessage(message);

        builder.setNegativeButton(Strings.get(notifier, Strings.DOWNLOAD_FAILED_DIALOG_NEGATIVE_BUTTON_ID), new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            notifier.downloadFailed(DownloadFileTask.this, false);
          } 
        });

        builder.setPositiveButton(Strings.get(notifier, Strings.DOWNLOAD_FAILED_DIALOG_POSITIVE_BUTTON_ID), new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            notifier.downloadFailed(DownloadFileTask.this, true);
          } 
        });

        builder.create().show();
      }
      catch (Exception e) {
        // Ignore all exceptions
      }
    }
  }

  protected String getURLString() {
    return urlString + "&type=apk";      
  }
}




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