cmu.troy.applogger.AppService.java Source code

Java tutorial

Introduction

Here is the source code for cmu.troy.applogger.AppService.java

Source

/***
  Copyright (c) 2008-2012 CommonsWare, LLC
  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.
      
  From _The Busy Coder's Guide to Advanced Android Development_
http://commonsware.com/AdvAndroid
 */

package cmu.troy.applogger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

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

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import cmu.troy.applogger.JSONKeys.JSONValues;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

public class AppService extends WakefulIntentService implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener {
    private static List<String> lastApps = new ArrayList<String>();

    private static Location lastLocation;

    private static Address lastAddress;

    private LocationClient mLocationClient;

    public AppService() {
        super("AppService");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();
    }

    @Override
    public void onDestroy() {
        mLocationClient.disconnect();
        super.onDestroy();
    }

    private List<String> getLastApps() throws IOException {
        return lastApps;
    }

    private List<String> getCurrentApps() {
        Context context = this.getApplicationContext();
        ActivityManager mgr = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasks = mgr.getRunningTasks(100);
        ArrayList<String> res = new ArrayList<String>();
        for (Iterator<RunningTaskInfo> i = tasks.iterator(); i.hasNext();) {
            RunningTaskInfo p = (RunningTaskInfo) i.next();
            res.add(p.baseActivity.flattenToString());
        }
        return res;
    }

    private List<String> getNewApps(List<String> oldApps, List<String> currentApps) {
        if (oldApps.size() == currentApps.size()) {
            for (int i = 0; i < oldApps.size(); i++)
                if (!oldApps.get(i).equals(currentApps.get(i)))
                    return currentApps;
            return new ArrayList<String>();
        } else
            return currentApps;
    }

    private void logApps(List<String> newApps, List<String> currentApps) throws IOException {
        /*
         * Empty newApps means current apps are the same with the last apps. So there is no need to
         * update last apps file or log file.
         */
        if (newApps == null || newApps.size() == 0)
            return;

        lastApps = currentApps;
        Date now = new Date();

        /* Append new Apps into log file */
        JSONObject job = new JSONObject();
        String id = String.valueOf(now.getTime());
        try {
            job.put(JSONKeys.id, id);
            job.put(JSONKeys.first, newApps.get(0));
            job.put(JSONKeys.log_type, JSONValues.OPEN_AN_APP);
            /* Log Location block */
            Location mLocation = null;
            if (mLocationClient.isConnected())
                mLocation = mLocationClient.getLastLocation();
            if (mLocation != null) {
                job.put(JSONKeys.loc_available, true);
                job.put(JSONKeys.latitude, mLocation.getLatitude());
                job.put(JSONKeys.longitude, mLocation.getLongitude());
                job.put(JSONKeys.location_accuracy, mLocation.getAccuracy());
                job.put(JSONKeys.location_updated_time, (new Date(mLocation.getTime())).toString());

                Date updateTime = new Date(mLocation.getTime());
                if ((updateTime.getTime() - now.getTime()) / 60000 > 5) {
                    Tools.runningLog("Last location is too old, a location update is triggered.");
                    LocationRequest request = new LocationRequest();
                    request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                    mLocationClient.requestLocationUpdates(request, new LocationListener() {
                        @Override
                        public void onLocationChanged(Location arg0) {
                        }
                    });
                }

                if (lastLocation == null || lastAddress == null
                        || lastLocation.distanceTo(mLocation) > Tools.SMALL_DISTANCE) {
                    /* Log Address if location is available */
                    Geocoder geocoder = new Geocoder(this, Locale.getDefault());
                    List<Address> addresses = null;
                    addresses = geocoder.getFromLocation(mLocation.getLatitude(), mLocation.getLongitude(), 1);
                    if (addresses != null && addresses.size() > 0) {
                        job.put(JSONKeys.addr_available, true);
                        Address address = addresses.get(0);
                        lastAddress = address;
                        job.put(JSONKeys.address,
                                address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "");
                        job.put(JSONKeys.city, address.getLocality());
                        job.put(JSONKeys.country, address.getCountryName());
                    } else {
                        job.put(JSONKeys.addr_available, false);
                    }
                } else {
                    job.put(JSONKeys.addr_available, true);
                    job.put(JSONKeys.address,
                            lastAddress.getMaxAddressLineIndex() > 0 ? lastAddress.getAddressLine(0) : "");
                    job.put(JSONKeys.city, lastAddress.getLocality());
                    job.put(JSONKeys.country, lastAddress.getCountryName());
                }
                lastLocation = mLocation;
            } else {
                if (!mLocationClient.isConnecting())
                    mLocationClient.connect();
                job.put(JSONKeys.loc_available, false);
            }
        } catch (JSONException e) {
            Log.e("JSON", e.toString());
        }
        Tools.logJsonNewBlock(job);
    }

    private boolean checkExternalStorageAvailable() {
        boolean mExternalStorageAvailable = false;
        boolean mExternalStorageWriteable = false;
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            mExternalStorageAvailable = mExternalStorageWriteable = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            mExternalStorageAvailable = true;
            mExternalStorageWriteable = false;
        } else {
            mExternalStorageAvailable = mExternalStorageWriteable = false;
        }
        if (!(mExternalStorageAvailable && mExternalStorageWriteable)) {
            return false;
        } else
            return true;
    }

    @Override
    protected void doWakefulWork(Intent intent) {
        try {
            if (checkExternalStorageAvailable()) {
                List<String> lastApps = getLastApps();
                List<String> currentApps = getCurrentApps();
                List<String> newApps = getNewApps(lastApps, currentApps);
                logApps(newApps, currentApps);
            } else
                Tools.toastFromHandler(handler, "Cannot access external storage!", getApplicationContext());
        } catch (Exception e) {
            Tools.toastFromHandler(handler, e.toString(), getApplicationContext());
        }

    }

    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onConnected(Bundle arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onDisconnected() {
        // TODO Auto-generated method stub

    }
}