Android Open Source - kirin-for-android Networking Backend






From Project

Back to project page kirin-for-android.

License

The source code is released under:

Apache License

If you think the Android project kirin-for-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

/*
   Copyright 2011 Future Platforms//  www .j  a  v  a 2 s  .com

   Licensed 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.
*/


package com.futureplatforms.kirin.extensions.networking;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.http.client.HttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Environment;
import android.util.Log;

import com.futureplatforms.kirin.C;
import com.futureplatforms.kirin.R;
import com.futureplatforms.kirin.extensions.KirinExtensionAdapter;
import com.futureplatforms.kirin.helpers.IKirinExtensionHelper;
import com.futureplatforms.kirin.internal.JSONUtils;
import com.futureplatforms.kirin.internal.attic.IOUtils;
import com.futureplatforms.kirin.internal.attic.SDCardFileUtils;

public class NetworkingBackend extends KirinExtensionAdapter implements INetworkingBackend {

  private final Context mContext;

  private final SDCardFileUtils mFileUtils;


  private BroadcastReceiver mReceiver;

  private AtomicInteger mDownloadingCount;

  private HttpClient mHttpClient;

  public NetworkingBackend(Context context) {
    this(context, null, null);
  }
  
  public NetworkingBackend(Context context, IKirinExtensionHelper kirinHelper,
      String saveFileLocation) {
    super(context, "Networking", kirinHelper);
    mContext = context;

    
        String packageName = mContext.getPackageName();
        String sdCardPrefix = Environment.getExternalStorageDirectory().getPath();
        String path = sdCardPrefix + MessageFormat.format("/Android/data/{0}/files", packageName);
        if (!path.endsWith("/")) {
            path += "/";
        }
    mFileUtils = new SDCardFileUtils(path);
    
    mDownloadingCount = new AtomicInteger(0);
  }

  protected String downloadString(JSONObject config) throws IOException {
    incrementDownloadCount();
    InputStream in = null;
    ByteArrayOutputStream baos = null;
    HttpClient client = null;
    try {
      client = getClient();
      in = makeConnection(config, client);
      baos = new ByteArrayOutputStream(8 * 1024);
      IOUtils.copy(in, baos);
      return baos.toString("UTF-8");
    } finally {
      IOUtils.close(in);
      IOUtils.close(baos);
      IOUtils.cleanupHttpClient(client);
      decrementDownloadCount();
    }
  }

  private synchronized HttpClient getClient() {
    if (mHttpClient == null) {
      mHttpClient = IOUtils.newHttpClient();
    }
    return mHttpClient;
  }

  private InputStream makeConnection(JSONObject config, HttpClient client)
      throws MalformedURLException, IOException {

    URL url = new URL(config.optString("url"));
    String method = config.optString("method", "GET");
    if (method.equalsIgnoreCase("GET")) {
      return IOUtils.connectTo(mContext, url, client);
    } else {
      return IOUtils.postConnection(mContext, url, method,
          config.optString("params"));
    }
  }

  protected void downloadFile(String urlString, String pathSuffix)
      throws IOException {

    InputStream in = null;
    OutputStream out = null;
    HttpClient client = getClient();
    File file = mFileUtils.readableFile(mContext, pathSuffix);
    if (file.exists()) {
      return;
    }
    try {
      incrementDownloadCount();
      URL url = new URL(urlString);
      in = IOUtils.connectTo(mContext, url, client);
      out = mFileUtils.outputStream(mContext, pathSuffix);

      IOUtils.copy(in, out);

    } finally {
      IOUtils.close(in);
      IOUtils.close(out);
      IOUtils.cleanupHttpClient(client);
      decrementDownloadCount();
    }
  }

  @Override
  public void deleteDownloadedFile_(JSONObject config) {
    String filename = JSONUtils.stringOrNull(config, "filename", null);
    try {
      mFileUtils.deleteFile(mContext, filename);
      mKirinHelper.jsCallback(config, "onFinish");
    } catch (Exception e) {
      Log.e(C.TAG, "Can't delete " + filename);
      reportExceptionToJavascript(config, e);
    } finally {
      cleanup(config, "onFinish", "onError");
    }
  }

  private void reportExceptionToJavascript(JSONObject config, Exception e) {
    Log.e(C.TAG, "Backend reported exception " + e, e);
    mKirinHelper.jsCallback(config, "onError", e.getLocalizedMessage());
  }

  @Override
  public void downloadFile_(JSONObject config) {
    try {
      downloadFile(config.optString("url"), config.optString("filename"));
      mKirinHelper.jsCallback(config, "onFinish");
    } catch (IOException e) {
      reportExceptionToJavascript(config, e);
    } finally {
      cleanup(config, "onFinish", "onError");
    }
  }

  private void incrementDownloadCount() {
    int count = mDownloadingCount.getAndIncrement();
    Log.i(C.TAG, "NetworkingBackend.incrementDownloadCount: " + count);
    if (count == 0) {
      listenForChangeInNetworkStatus();
    }
  }

  private void decrementDownloadCount() {
    int count = mDownloadingCount.decrementAndGet();
    Log.i(C.TAG, "NetworkingBackend.decrementDownloadCount: " + count);
    if (count == 0) {
      zeroCountReached();
    }
  }

  protected void zeroCountReached() {
    Log.i(C.TAG, "NetworkingBackend.zeroCountReached: ");
    if (mReceiver != null) {
      mContext.unregisterReceiver(mReceiver);
    }
    mReceiver = null;

    cleanupHttpClient();
  }

    protected void cleanupHttpClient() {
        HttpClient client = null;
    synchronized (this) {
      if (mHttpClient != null) {
        client = mHttpClient;
        mHttpClient = null;
      }
    }
    IOUtils.closeHttpClient(client);
    }

  public JSONArray isolateArrayFromObject(JSONObject object, JSONArray path) {

    JSONArray list = null;
    JSONObject parent = object;

    for (int i = 0, max = path.length(); i < max; i++) {

      String pathSegment = JSONUtils.stringOrNull(path, i, null);
      if (pathSegment == null) {
        continue;
      }

      Object obj = parent.opt(pathSegment);

      if (obj == null) {
        // not found.
        return null;
      } else if (obj instanceof JSONArray) {
        list = (JSONArray) obj;
        parent.remove(pathSegment);
        break;
      } else if (obj instanceof JSONObject) {
        parent = (JSONObject) obj;
      } else {
        // not found
        return null;
      }
    }

    return list;
  }

  @Override
  public void downloadJSONList_(JSONObject config) {
    String jsonString = null;

    try {
      jsonString = downloadString(config);

      JSONArray array = null;
      JSONObject envelope = null;
      int arraySize = 0;

      String eachCallback = JSONUtils.stringOrNull(config, "each", null);

      Object obj = new JSONTokener(jsonString).nextValue();
      if (obj instanceof JSONArray) {
        array = (JSONArray) obj;
      } else if (obj instanceof JSONObject) {
        envelope = (JSONObject) obj;
        JSONArray path = config.optJSONArray("path");
        if (path != null) {
          array = isolateArrayFromObject(envelope, path);
        }
      }

      if (envelope != null) {
        mKirinHelper.jsCallback(config, "envelope", envelope);
      }
      if (array != null && eachCallback != null) {
        for (int i = 0, max = array.length(); i < max; i++) {
          Object item = array.get(i);
          if (item != null) {
            mKirinHelper.jsCallback(eachCallback, item);
          }
        }
        arraySize = array.length();
      }

      if (array == null && envelope == null) {
        Log.e(C.TAG, "Server provided badly formatted JSON: "
            + jsonString);
        mKirinHelper.jsCallback(config, "onError", "Invalid JSON");
      } else {
        mKirinHelper.jsCallback(config, "onFinish", arraySize);
      }
    } catch (IOException e) {
      Log.e(C.TAG, "Couldn't connect to the server", e);
      reportExceptionToJavascript(config, e);
    } catch (JSONException e) {
      Log.e(C.TAG, "Server provided badly formatted JSON: " + jsonString);
      reportExceptionToJavascript(config, e);
    } finally {
      cleanup(config, "envelope", "each", "onError", "onFinish");
    }
  }

  @Override
  public void downloadJSON_(JSONObject config) {
    try {
      String jsonString = downloadString(config);
      Log.i(C.TAG, "NetworkingBackend.downloadJSON_: downloadJSON_ : "
          + jsonString);
      Object obj = new JSONTokener(jsonString).nextValue();
            if (!(obj instanceof JSONArray) && !(obj instanceof JSONObject)) {
              mKirinHelper.jsCallback(config, "onError", "Invalid JSON response received");
            } else {
              mKirinHelper.jsCallback(config, "payload", new JSONTokener(jsonString).nextValue());
            }
    } catch (IOException e) {
      reportExceptionToJavascript(config, e);
    } catch (JSONException e) {
      reportExceptionToJavascript(config, e);
    } finally {
      cleanup(config, "payload", "onError");
    }
  }

  private void cleanup(JSONObject config, String... callbacks) {
    mKirinHelper.cleanupCallback(config, callbacks);
  }

  private void listenForChangeInNetworkStatus() {
    Log.i(C.TAG, "NetworkingBackend.listenForChangeInNetworkStatus: ");
    mReceiver = new BroadcastReceiver() {

      @Override
      public void onReceive(Context context, Intent intent) {
        if (intent.getBooleanExtra(
            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
          String reason = intent
              .getStringExtra(ConnectivityManager.EXTRA_REASON);
          if (reason == null || reason.trim().length() == 0) {
            reason = mContext
                .getString(R.string.networking_connection_lost);
          }
          cancelAllDownloads(reason);
        }
      }

    };
    mContext.registerReceiver(mReceiver, new IntentFilter(
        ConnectivityManager.CONNECTIVITY_ACTION));

  }

  protected void cancelAllDownloads(String reason) {
    Log.i(C.TAG,
        "NetworkingBackend.cancelAllDownloads: NETWORK CONNECTIVITY LOST, shutting down HttpClient");

    cleanupHttpClient();
  }

}




Java Source Code List

com.futureplatforms.kirin.C.java
com.futureplatforms.kirin.Kirin.java
com.futureplatforms.kirin.TestingApplication.java
com.futureplatforms.kirin.activities.KirinActivity.java
com.futureplatforms.kirin.activities.KirinListActivity.java
com.futureplatforms.kirin.application.IKirinApplication.java
com.futureplatforms.kirin.application.KirinApplication.java
com.futureplatforms.kirin.extensions.IKirinExtensionOnNonDefaultThread.java
com.futureplatforms.kirin.extensions.IKirinExtensionOnUiThread.java
com.futureplatforms.kirin.extensions.IKirinExtension.java
com.futureplatforms.kirin.extensions.IProguardImmunity.java
com.futureplatforms.kirin.extensions.KirinExtensionAdapter.java
com.futureplatforms.kirin.extensions.KirinExtensions.java
com.futureplatforms.kirin.extensions.databases.DBStatement.java
com.futureplatforms.kirin.extensions.databases.DBTransaction.java
com.futureplatforms.kirin.extensions.databases.DatabasesBackend.java
com.futureplatforms.kirin.extensions.databases.IDatabasesBackend.java
com.futureplatforms.kirin.extensions.fs.KirinFilesystemExtensionImpl.java
com.futureplatforms.kirin.extensions.localnotifications.ILocalNotificationsBackend.java
com.futureplatforms.kirin.extensions.localnotifications.LocalNotificationAlarmReceiver.java
com.futureplatforms.kirin.extensions.localnotifications.LocalNotificationsBackend.java
com.futureplatforms.kirin.extensions.networking.INetworkingBackend.java
com.futureplatforms.kirin.extensions.networking.KirinXHRExtensionImpl.java
com.futureplatforms.kirin.extensions.networking.NetworkingBackend.java
com.futureplatforms.kirin.extensions.settings.ISettingsBackend.java
com.futureplatforms.kirin.extensions.settings.PreferencesBackendImpl.java
com.futureplatforms.kirin.extensions.settings.SettingsBackend.java
com.futureplatforms.kirin.generated.fs.KirinCallback.java
com.futureplatforms.kirin.generated.fs.KirinFile.java
com.futureplatforms.kirin.generated.fs.KirinFilesystemExtension.java
com.futureplatforms.kirin.generated.fs.KirinFilesystem.java
com.futureplatforms.kirin.generated.fs.KirinFoundFile.java
com.futureplatforms.kirin.generated.fs.KirinOptionalCallback.java
com.futureplatforms.kirin.generated.location.KirinLocationBackend.java
com.futureplatforms.kirin.generated.location.KirinLocationData.java
com.futureplatforms.kirin.generated.location.KirinLocationListener.java
com.futureplatforms.kirin.generated.location.KirinLocationPermissions.java
com.futureplatforms.kirin.generated.location.KirinLocation.java
com.futureplatforms.kirin.generated.preferences.KirinPreferenceListener.java
com.futureplatforms.kirin.generated.preferences.KirinPreferencesBackend.java
com.futureplatforms.kirin.generated.preferences.KirinPreferences.java
com.futureplatforms.kirin.generated.xhr.KirinXHRExtension.java
com.futureplatforms.kirin.generated.xhr.KirinXHRProgressEvent.java
com.futureplatforms.kirin.generated.xhr.KirinXHRResponse.java
com.futureplatforms.kirin.generated.xhr.KirinXHRequest.java
com.futureplatforms.kirin.generated.xhr.KirinXMLHTTPRequest.java
com.futureplatforms.kirin.helpers.IKirinExtensionHelper.java
com.futureplatforms.kirin.helpers.IKirinHelper.java
com.futureplatforms.kirin.helpers.KirinApplicationHelper.java
com.futureplatforms.kirin.helpers.KirinExtensionHelper.java
com.futureplatforms.kirin.helpers.KirinHelper.java
com.futureplatforms.kirin.helpers.KirinScreenHelper.java
com.futureplatforms.kirin.helpers.KirinUiFragmentHelper.java
com.futureplatforms.kirin.internal.JSONUtils.java
com.futureplatforms.kirin.internal.KirinPaths.java
com.futureplatforms.kirin.internal.attic.IOUtils.java
com.futureplatforms.kirin.internal.attic.KirinDropbox.java
com.futureplatforms.kirin.internal.attic.ProxyGenerator.java
com.futureplatforms.kirin.internal.attic.SDCardFileUtils.java
com.futureplatforms.kirin.internal.core.AbstractObjectHolder.java
com.futureplatforms.kirin.internal.core.DefaultObjectHandler.java
com.futureplatforms.kirin.internal.core.IJsContext.java
com.futureplatforms.kirin.internal.core.IKirinState.java
com.futureplatforms.kirin.internal.core.INativeContext.java
com.futureplatforms.kirin.internal.core.IObjectHolder.java
com.futureplatforms.kirin.internal.core.JsCommands.java
com.futureplatforms.kirin.internal.core.KirinAppState.java
com.futureplatforms.kirin.internal.core.KirinWebViewHolder.java
com.futureplatforms.kirin.internal.core.NativeContext.java
com.futureplatforms.kirin.internal.core.UiObjectHolder.java
com.futureplatforms.kirin.internal.fragmentation.CursorCoercer4.java
com.futureplatforms.kirin.internal.fragmentation.CursorCoercer5.java
com.futureplatforms.kirin.internal.fragmentation.CursorCoercer.java
com.futureplatforms.kirin.internal.fragmentation.WebChromeClient7.java
com.futureplatforms.kirin.internal.fragmentation.WebChromeClient8.java
com.futureplatforms.kirin.state.IKirinDropbox.java
com.futureplatforms.kirin.state.IKirinFileSystem.java
com.futureplatforms.kirin.ui.DebugMenuActions.java
com.futureplatforms.kirin.ui.JSListAdapter.java
com.futureplatforms.kirin.ui.JSOnClickListener.java
com.futureplatforms.kirin.ui.KirinRowRenderer.java