org.aschyiel.nextboat.Downloader.java Source code

Java tutorial

Introduction

Here is the source code for org.aschyiel.nextboat.Downloader.java

Source

  //..Downloader.java, uly, june2013..
  package org.aschyiel.nextboat;
  /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership.  The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */

  import org.aschyiel.nextboat.NextBoat;

  import android.app.Service;
  import android.content.Intent;
  import android.os.IBinder;
  import android.os.Environment;
  import android.content.pm.PackageInfo;
  import android.util.Log;
  import android.net.Uri;
  import android.content.Context;
  import android.content.ContentResolver;
  import android.content.ContentValues;
  import android.os.Process;
  import android.os.Looper;

  import org.apache.http.HttpEntity;
  import org.apache.http.HttpResponse;
  import org.apache.http.StatusLine;
  import org.apache.http.client.HttpClient;
  import org.apache.http.client.methods.HttpGet;
  import org.apache.http.impl.client.DefaultHttpClient;

  import android.content.pm.PackageManager;
  import android.content.pm.PackageManager.NameNotFoundException;

  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileReader;
  import java.io.FileWriter;

  import android.widget.Toast;

  /**
  * The downloader runs in it's own thread, and then tells the main activity to
  * do something when it's done.
  * 
  * @see http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
  * @see WordWidget.java from simpleWiktionary example.
  * @see BooksUpdater.java from Shelves example.
  */
  public class Downloader implements Runnable {
      /**
      * A reference back to the main activity.
      */
      private static NextBoat _context;

      /** The web-page url we want to download stuff from. */
      private String _url;

      /**
      * Our logger tag.
      */
      private static final String TAG = "Downloader";

      /**
      * The callback to execute after a successful download.
      */
      private String _callbackMethodName;

      /**
      * Our downloader thread.
      */
      private Thread _thread;

      /**
      * When true - represents that the thread is currently "stopped".
      */
      private volatile boolean _isStopped;

      //---------------------------------
      //
      // Public Methods.
      //
      //---------------------------------

      /** @constructor */
      public Downloader(NextBoat context, String url, String callbackMethodName) {
          _context = context;
          _url = url;
          _callbackMethodName = callbackMethodName;
      }

      /**
      * @override Thread#start
      */
      public void start() {
          if (null == _thread) {
              _isStopped = false;
              _thread = new Thread(this, "Downloader");
              _thread.start();
          }
      }

      /**
      * @override Thread#stop
      */
      public void stop() {
          if (null != _thread) {
              _isStopped = true;
              _thread.interrupt();
              _thread = null;
          }
      }

      /**
      * @override Thread#run
      */
      public void run() {
          Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
          while (!_isStopped) {
              try {
                  _download();
                  Thread.sleep(1000);
                  _isStopped = true;
              } catch (InterruptedException e) {
                  // Ignore
              }
          }
      }

/**
* Download something, and then execute callbacks
* against the downloaded text-content.
*/
private void _download()
{
  String userAgent = _prepareUserAgent( _context );
  try
  {
    content = getUrlContent( _url, userAgent );
  }
  catch ( DownloaderFail fail )
  {
      Log.e( TAG, "DownloaderFail", fail );
  }

  if ( null != content )
  {
    Method callback = _context.getClass().getMethod( _callbackMethodName,
        new Class[]{ String.class } )
    callback.invoke( _context, content );
  }
}

      //---------------------------------
      //
      // Private Methods.
      //
      //---------------------------------

      /**
      * Make sure the user-agent represents us as an android device.
      */
      private void _prepareUserAgent(Context context) {
          try {
              // Read the package name and version number from the manifest.
              PackageManager manager = context.getPackageManager();
              PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
              sUserAgent = String.format(context.getString(R.string.template_user_agent), info.packageName,
                      info.versionName);
          } catch (NameNotFoundException e) {
              Log.e(TAG, "Couldn't find package information in PackageManager", e);
          }
      }

      /**
      * Returns the web-page text-content for a given web-page url.
      *
      * @private
      * @synchronized
      * @param (String) url is the web-page to download stuff from.
      * @return (String) is the plain-text contained there-in.
      * @throws DownloaderFail
      */
      private synchronized String getUrlContent(String url) throws DownloaderFail {
          //
          // Create client and set our specific user-agent string
          //

          if (null == sUserAgent) {
              throw new DownloaderFail("User-Agent string must be prepared");
          }
          HttpClient client = new DefaultHttpClient();
          HttpGet request = new HttpGet(url);
          request.setHeader("User-Agent", sUserAgent);

          String textContent;
          try {
              HttpResponse response = client.execute(request);

              // Check if server response is valid
              StatusLine status = response.getStatusLine();
              if (200 != status.getStatusCode()) {
                  throw new DownloaderFail("Invalid response from server: " + status.toString());
              }

              // Pull content stream from response
              HttpEntity entity = response.getEntity();
              InputStream inputStream = entity.getContent();
              ByteArrayOutputStream content = new ByteArrayOutputStream();

              // Read response into a buffered stream
              int bytesRead = 0;
              byte[] buffer = new byte[512];
              while (-1 != (bytesRead = inputStream.read(buffer))) {
                  content.write(buffer, 0, bytesRead);
              }

              // Return result from buffered stream
              textContent = new String(content.toByteArray());
          } catch (IOException e) {
              throw new DownloaderFail("Problem communicating with API", e);
          }
          return textContent;
      }

      //---------------------------------
      //
      // Private Inner Classes.
      //
      //---------------------------------

      /**
      * Our very own way of failing.
      * Not exactly sure why it's needed in the first place!
      */
      private class DownloaderFail extends Exception {
          public DownloaderFail(String message) {
              super(message);
          }

          public DownloaderFail(String message, Throwable throwable) {
              super(message, throwable);
          }
      }
  }