google.geofence.GooglegeofenceModule.java Source code

Java tutorial

Introduction

Here is the source code for google.geofence.GooglegeofenceModule.java

Source

/**
 * This file was auto-generated by the Titanium Module SDK helper for Android
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 *
 */
package google.geofence;

import java.util.ArrayList;
import java.util.HashMap;

import org.appcelerator.kroll.KrollFunction;
import org.appcelerator.kroll.KrollModule;
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.util.TiRHelper.ResourceNotFoundException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources.NotFoundException;
import android.os.Bundle;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationServices;
import com.google.gson.Gson;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;

@Kroll.module(name = "Googlegeofence", id = "google.geofence")
public class GooglegeofenceModule extends KrollModule
        implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> {

    // Standard Debugging variables
    private static final String TAG = "GooglegeofencingModule";
    protected ArrayList<Geofence> mGeofenceList;
    private KrollFunction callback = null;
    private PendingIntent mGeofencePendingIntent = null;
    private String monitoringFences = null;
    private String oldFences = null;
    SharedPreferences mSharedPreferences;
    /**
     * Used to keep track of whether geofences were added.
     */
    boolean mGeofencesAdded;

    Gson gson = new Gson();

    /**
     * Provides the entry point to Google Play services.
     */
    protected GoogleApiClient mGoogleApiClient;
    TiApplication appContext = TiApplication.getInstance();

    public class EventHandler {
        @Subscribe
        @Kroll.method
        public void onEvent(GeoFenceEvent event) {
            System.out.println("in POJO handler for event " + event.getEventName());

            if (event.getEventName().equals("enterregions")) {
                fireEvent("enterregions", event.getData());
            }
            if (event.getEventName().equals("exitregions")) {
                fireEvent("exitregions", event.getData());
            }

            if (event.getEventName().equals("error")) {
                fireEvent("error", event.getData());
            }

        }
    }

    // You can define constants with @Kroll.constant, for example:
    // @Kroll.constant public static final String EXTERNAL_NAME = value;

    public GooglegeofenceModule() {
        super();
    }

    @Kroll.onAppCreate
    public static void onAppCreate(TiApplication app) {
        System.out.println("App starting");
        // put module init code that needs to run when the application is
        // created

    }

    @Kroll.onAppCreate
    public static void onAppStop(TiApplication app) {
        System.out.println("App stopping");
    }

    /*
     * @Kroll.method public void startBackgroundService() {
     * 
     * System.out.println("ATTEMPTING TO start service");
     * 
     * 
     * try{
     * 
     * Intent geoFenceTransitionsIntentService = new Intent(appContext,
     * GeofenceTransitionsIntentService.class);
     * TiApplication.getInstance().startService
     * (geoFenceTransitionsIntentService);
     * 
     * System.out.println("geoFenceTransitionsIntentService  Created");
     * 
     * }catch(Exception ex) { System.out.println("Exception caught "+ex); }
     * 
     * 
     * 
     * }
     */

    /**
     * Gets a PendingIntent to send with the request to add or remove Geofences.
     * Location Services issues the Intent inside this PendingIntent whenever a
     * geofence transition occurs for the current list of geofences.
     * 
     * @return A PendingIntent for the IntentService that handles geofence
     *         transitions.
     */
    @Kroll.method
    private PendingIntent getGeofencePendingIntent() {
        // Reuse the PendingIntent if we already have it.
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent;
        }
        System.out.println("ATTEMPTING TO start service");

        Intent intent = null;
        try {

            intent = new Intent(appContext, GeofenceTransitionsIntentService.class);
            TiApplication.getInstance().startService(intent);

            System.out.println("geoFenceTransitionsIntentService  Created");

        } catch (Exception ex) {
            System.out.println("Exception caught " + ex);

        }

        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent
        // back when calling
        // addGeofences() and removeGeofences().
        return PendingIntent.getService(appContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    /**
     * Builds and returns a GeofencingRequest. Specifies the list of geofences
     * to be monitored. Also specifies how the geofence notifications are
     * initially triggered.
     */
    private GeofencingRequest getGeofencingRequest() {
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();

        // The INITIAL_TRIGGER_ENTER flag indicates that geofencing service
        // should trigger a
        // GEOFENCE_TRANSITION_ENTER notification when the geofence is added and
        // if the device
        // is already inside that geofence.
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);

        // Add the geofences to be monitored by geofencing service.
        builder.addGeofences(mGeofenceList);

        // Return a GeofencingRequest.
        return builder.build();
    }

    public void createGeofences(double lon, double lat, float radius, String identifier) {

        mGeofenceList.add(new Geofence.Builder()
                // Set the request ID of the geofence. This is a string to
                // identify this
                // geofence.
                .setRequestId(identifier)

                // Set the circular region of this geofence.
                .setCircularRegion(lat, lon, radius)

                // Set the expiration duration of the geofence. This geofence
                // gets automatically
                // removed after this period of time.
                .setExpirationDuration(Geofence.NEVER_EXPIRE)

                // Set the transition types of interest. Alerts are only
                // generated for these
                // transition. We track entry and exit transitions in this
                // sample.

                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)

                // Create the geofence.
                .build());
    }

    @Kroll.method
    public void startMonitoringForRegions(String regions) throws JSONException {

        /**
         * Used to persist application state about whether geofences were added.
         */

        // Retrieve an instance of the SharedPreferences object.
        mSharedPreferences = appContext.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);

        // Get the value of mGeofencesAdded from SharedPreferences. Set to false
        // as a default.
        mGeofencesAdded = mSharedPreferences.getBoolean(Constants.GEOFENCES_ADDED_KEY, false);
        if (monitoringFences != null) {
            oldFences = monitoringFences;
        }
        monitoringFences = regions;
        EventHandler handler = new EventHandler();
        EventBus.getDefault().register(handler);
        JSONArray jsonarray = new JSONArray(regions);

        mGeofenceList = new ArrayList<Geofence>();
        for (int i = 0; i < jsonarray.length(); i++) {

            JSONObject region = jsonarray.getJSONObject(i);

            JSONObject center = region.getJSONObject("center");

            Double lat = center.getDouble("latitude");

            Double lng = center.getDouble("longitude");

            int radius = region.getInt("radius");

            String identifier = region.getString("identifier");

            System.out.println(lat);

            System.out.println(lng);

            System.out.println(radius);

            System.out.println(identifier);

            createGeofences(lng, lat, radius, identifier);

        }

        if (mGoogleApiClient == null) {
            buildGoogleApiClient();
        }

        try {
            if (mGoogleApiClient.isConnected()) {
                System.out.println("You are connected to google api client...");

                sendGeoFences();

            } else if (mGoogleApiClient.isConnecting()) {
                System.out.println("Still connecting...");
            } else {
                System.out.println("not connected...");

                try {
                    mGoogleApiClient.connect();
                } catch (Error err) {
                    System.out.println("error is: " + err.toString());
                }

            }

        } catch (SecurityException securityException) {
            // Catch exception generated if the app does not use
            // ACCESS_FINE_LOCATION permission.
            // logSecurityException(securityException);
            System.out.println("security error...");
        }

    }

    @Kroll.method
    public void stopMonitoringAllRegions() throws JSONException {

        if (monitoringFences == null) {
            HashMap<String, String> event = new HashMap<String, String>();
            event.put("regions", null);
            fireEvent("removeregions", event);
            return;
        }

        LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient,
                // This is the same pending intent that was used in addGeofences().
                getGeofencePendingIntent()).setResultCallback(this); // Result
        // processed
        // in
        // onResult().

    }

    /**
     * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the
     * LocationServices API.
     */
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(appContext).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
    }

    private void sendGeoFences() {
        // TODO Auto-generated method stub

        LocationServices.GeofencingApi.addGeofences(mGoogleApiClient,
                // The GeofenceRequest object.
                getGeofencingRequest(),
                // A pending intent that that is reused when calling
                // removeGeofences(). This
                // pending intent is used to generate an intent when a
                // matched geofence
                // transition is observed.
                getGeofencePendingIntent()).setResultCallback(this); // Result
        // processed
        // in
        // onResult().

    }

    @Kroll.method
    public void onResult(Status arg0) {
        // TODO Auto-generated method stub
        if (arg0.isSuccess()) {
            // Update state and save in shared preferences.
            mGeofencesAdded = !mGeofencesAdded;
            SharedPreferences.Editor editor = mSharedPreferences.edit();
            editor.putBoolean(Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
            editor.apply();

            // Update the UI. Adding geofences enables the Remove Geofences
            // button, and removing
            // geofences enables the Add Geofences button.
            setEnabledState();
            System.out.println("Successful status is: " + arg0.getStatusCode());

        } else {
            System.out.println("Non successful status is: " + arg0.getStatusCode() + " " + arg0.describeContents());

            HashMap<String, String> event = new HashMap<String, String>();
            String errorMessage = null;
            try {
                errorMessage = GeofenceErrorMessages.getErrorString(TiApplication.getInstance(),
                        arg0.getStatusCode());
            } catch (ResourceNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            event.put("error", errorMessage);
            event.put("errorcode", Integer.toString(arg0.getStatusCode()));
            fireEvent("error", event);
        }

    }

    private void setEnabledState() {
        // TODO Auto-generated method stub

        if (mGeofencesAdded) {

            HashMap<String, String> event = new HashMap<String, String>();
            event.put("regions", oldFences);
            fireEvent("removeregions", event);
            monitoringFences = null;
            oldFences = null;

        } else {
            HashMap<String, String> event = new HashMap<String, String>();
            event.put("regions", monitoringFences);
            fireEvent("monitorregions", event);

        }

    }

    @Kroll.method
    public void onConnectionFailed(ConnectionResult arg0) {
        System.out.println("Connection failed: ConnectionResult.getErrorCode() = " + arg0.getErrorCode());

    }

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

        System.out.println("Connected to google api client");

        sendGeoFences();

    }

    public void onConnectionSuspended(int arg0) {
        // TODO Auto-generated method stub

        System.out.println("Connection to google api client suspended");

    }

}