2016年6月9日 星期四

Google paly service -Location,Geofencing

Google paly service -Location

Environment we need



Create a app that can so the Location_Concept






compile 'com.google.android.gms:play-services:8.4.0'


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

between the  <application></application>
<meta-data android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version"/>


Location Services

the fused location Provide use to get the location
Activity Recognition use to recognize wha tare u doing,on car,running?walk?


Fine and Coarse Location

Start codeing


1.in the activity,create a  GoogleApiClient api object.it is the entry point for Google Play services


mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();


addConnectionCallbacks use to add the callback to handle the action after the connection and get the result.

addOnConnectionFailedListener use to add the Listener to handle the connection failed .

2. implemenbt the class for the Activity

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

we need to implement all the method

LocationListener

Used for receiving notifications from the LocationManager when the location has changed. These methods are called if the LocationListener has been registered with the location manager service using the requestLocationUpdates(String, long, float, LocationListener) method.


Describe Workflow of the Location Service

1.create the GoogleApiClient object at OnCreate

2.GoogleApiClient to connect to the Location Service

3 Success or fail

3.1 handle success

3.1.1if success,OnConnnected method run,at here, create LocationRequest ,set the priority,frequence,than request the update from the LocationService

3.1.2 when LocationService see that the Device has a ne location,it call back the OnLocationChanged method,at here,we get the detail of the Location(Location object).

3.2 Handle the error

3.2.1 if not success ,will call onConnectionFailed

3.22 if preivous connected,but something get wrong,the connection suspended. onConnectionSuspended


code:to connect the LocationService


@Override
   protected void onStart() {
       super.onStart();
       mGoogleApiClient.connect();
   }

   @Override
   protected void onStop() {
        if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
       super.onStop();
   }



Code in onConnected



public void onConnected(Bundle bundle) {
       mLocationRequest = LocationRequest.create();
       mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
       mLocationRequest.setInterval(1000);
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           // TODO: Consider calling
           //    ActivityCompat#requestPermissions
           // here to request the missing permissions, and then overriding
           //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
           //                                          int[] grantResults)
           // to handle the case where the user grants the permission. See the documentation
           // for ActivityCompat#requestPermissions for more details.
           return;
       }
       LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

   }

Different Priority Values



Low_power is city level

No_power is use he loaction get by other application

important!!!In manifest,if we set android.permission.ACCESS_CROSS_LOCATION,will over write the above setting.


code in onLocationChanged

@Override
   public void onLocationChanged(Location location) {
       Log.d(LOG_TAG, location.toString());
       txtoutput.setText(location.toString());

   }


wrap up


Another example,example2:
create layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="pom2.poly.com.location2_1.MainActivity">


   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Latitude: " />

       <TextView
           android:id="@+id/tv_latitude"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="x" />
   </LinearLayout>

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Longitude: " />

       <TextView
           android:id="@+id/tv_longitude"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Longitude: " />
   </LinearLayout>
</LinearLayout>



add the dependency,Manifest as before

code in OnConnected

public void onConnected(Bundle bundle) {
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           // TODO: Consider calling
           //    ActivityCompat#requestPermissions
           // here to request the missing permissions, and then overriding
           //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
           //                                          int[] grantResults)
           // to handle the case where the user grants the permission. See the documentation
           // for ActivityCompat#requestPermissions for more details.
           return;
       }
       mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
       if (mLastLocation != null) {
           tv_latitude.setText(mLastLocation.getLatitude() + "");
           tv_longitude.setText(mLastLocation.getLongitude() + "");
       }


   }


here use the getLastLocation,retrieve the device's last known location(usually equivalent to the last known location of the device)

However,the location change,the text will not change,because only call once,no like the onLocationChanged method.



it is because we want continus,so the code like this now:

package pom2.poly.com.location2_1;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {

   private TextView tv_latitude;
   private TextView tv_longitude;
   private GoogleApiClient mGoogleApiClient;
   private Location mLastLocation;
   private LocationRequest mLocationRequest;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       tv_latitude = (TextView) findViewById(R.id.tv_latitude);
       tv_longitude = (TextView) findViewById(R.id.tv_longitude);
       mGoogleApiClient = buildGoogleAPIClient();
   }

   private GoogleApiClient buildGoogleAPIClient() {
       GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
       return mGoogleApiClient;
   }

   @Override
   public void onConnected(Bundle bundle) {
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           // TODO: Consider calling
           //    ActivityCompat#requestPermissions
           // here to request the missing permissions, and then overriding
           //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
           //                                          int[] grantResults)
           // to handle the case where the user grants the permission. See the documentation
           // for ActivityCompat#requestPermissions for more details.
           return;
       }
       mLocationRequest = LocationRequest.create();
       mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000);
       LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,this);


   }

   @Override
   public void onConnectionSuspended(int i) {

   }

   @Override
   public void onConnectionFailed(ConnectionResult connectionResult) {

   }

   @Override
   public void onLocationChanged(Location location) {
       tv_latitude.setText(mLastLocation.getLatitude() + "");
       tv_longitude.setText(mLastLocation.getLongitude() + "");

   }

   @Override
   protected void onStart() {
       super.onStart();
       mGoogleApiClient.connect();
   }

   @Override
   protected void onStop() {
       if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
       super.onStop();
   }
}






Activity Recognition App
completed like this






create a IntentService to handle the RecognitionResult


<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />



public class DetectedActivitiesIntentService extends IntentService {
   private final String TAG = "detection_is";
   private ActivityRecognitionResult mActivityRecognitionResult;
   private ArrayList<DetectedActivity> activityLisst;

   /**
    * Creates an IntentService.  Invoked by your subclass's constructor.
    *
    * @param name Used to name the worker thread, important only for debugging.
    */
   public DetectedActivitiesIntentService(String name) {
       super(name);
   }

   @Override
   protected void onHandleIntent(Intent intent) {
       mActivityRecognitionResult = ActivityRecognitionResult.extractResult(intent);
       activityLisst = (ArrayList<DetectedActivity>) mActivityRecognitionResult.getProbableActivities();
       Intent sendOutIntent = new Intent(Constants.BRODCAST_ACTION);
       sendOutIntent.putExtra("", activityLisst);
       LocalBroadcastManager.getInstance(this).sendBroadcast(sendOutIntent);


   }
}



First we get the ActivityRecognitionResult from the intent.
form the ActivityRecognitionResult .get the ProbableActivities Array List by getProbableActivities

than ,send back the ProbableActivities Array List by Local brodcast

here we don’t use sendBroadcast use LocalBroadcastManager.getInstance(this).sendBroadcast because we only send the Brodcast to the same app.



Now we need to make tha Main activity can recieve the Brodcast from this Intent Srevice


package pom2.poly.com.location2_1;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.DetectedActivity;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {


   private GoogleApiClient mGoogleApiClient;

   private LocationRequest mLocationRequest;
   private Button removeButton;
   private Button requestButton;
   private TextView detected_activity_textView;
   private ActivityDetectionBroadcastReciver mActivityDetectionBroadcastReciver;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       removeButton = (Button) findViewById(R.id.remove_activity_update_button);
       requestButton = (Button) findViewById(R.id.request_activity_update_button);
       detected_activity_textView = (TextView) findViewById(R.id.detected_activity_textView);
       mActivityDetectionBroadcastReciver = new ActivityDetectionBroadcastReciver();
       mGoogleApiClient = buildGoogleAPIClient();

   }

   private GoogleApiClient buildGoogleAPIClient() {
       GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
       return mGoogleApiClient;
   }

   @Override
   public void onConnected(Bundle bundle) {
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           // TODO: Consider calling
           //    ActivityCompat#requestPermissions
           // here to request the missing permissions, and then overriding
           //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
           //                                          int[] grantResults)
           // to handle the case where the user grants the permission. See the documentation
           // for ActivityCompat#requestPermissions for more details.
           return;
       }
       mLocationRequest = LocationRequest.create();
       mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000);
       LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);


   }

   @Override
   public void onConnectionSuspended(int i) {

   }

   @Override
   public void onConnectionFailed(ConnectionResult connectionResult) {

   }

   @Override
   public void onLocationChanged(Location location) {


   }

   @Override
   protected void onStart() {
       super.onStart();
       mGoogleApiClient.connect();
   }

   @Override
   protected void onStop() {
       if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
       super.onStop();
   }

   private String getActivityString(int code) {
       switch (code) {
           case DetectedActivity.IN_VEHICLE:

               return "IN_VEHICLE";

           case DetectedActivity.ON_BICYCLE:
               return "ON_BICYCLE";

           case DetectedActivity.ON_FOOT:
               return "ON_FOOT";

           case DetectedActivity.RUNNING:
               return "RUNNING";

           case DetectedActivity.STILL:
               return "STILL";

           case DetectedActivity.TILTING:
               return "TILTING";

           case DetectedActivity.UNKNOWN:
               return "UNKNOWN";

           case DetectedActivity.WALKING:
               return "WALKING";
         
       }
       return "";
   }

   protected class ActivityDetectionBroadcastReciver extends BroadcastReceiver {
       private static final String TAG = "ActivityDetectionBroadcastReciver";

       @Override
       public void onReceive(Context context, Intent intent) {
           ArrayList<DetectedActivity> activityLiss = intent.getParcelableArrayListExtra(Constants.ACTIVITY_EXTRA);
           String startStatus = "";
           for (DetectedActivity acticity : activityLiss) {
               startStatus = startStatus + getActivityString(acticity.getType()) + " " + acticity.getConfidence() + " %" + "%\n";
           }
           detected_activity_textView.setText(startStatus);

       }
   }
}



on the above ,we have create a BrodcastReceiver


before the Brodcast receiver and receive the brodcast,we need to register it.
we nee to register and unregiste the receiver at Resume and Pause


@Override
   protected void onResume() {
       super.onResume();
       IntentFilter intentFilter = new IntentFilter(Constants.BRODCAST_ACTION);
       LocalBroadcastManager.getInstance(this).registerReceiver(mActivityDetectionBroadcastReciver, intentFilter);
   }

   @Override
   protected void onPause() {
       LocalBroadcastManager.getInstance(this).unregisterReceiver(mActivityDetectionBroadcastReciver);
       super.onPause();

   }





resquest Button do this

public void requestActivityUpdate(View view) {
       if (mGoogleApiClient.isConnected()) {
           ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 1000, getActivityDetectionPendinhIntent()).setResultCallback(this);
           requestButton.setEnabled(false);
           requestButton.setEnabled(true);


       } else {
           Toast.makeText(this, "not yet Connect", Toast.LENGTH_SHORT).show();
       }





   }


private PendingIntent getActivityDetectionPendinhIntent() {
       Intent intent = new Intent(this, DetectedActivitiesIntentService.class);

       // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
       // requestActivityUpdates() and removeActivityUpdates().
       return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);


   }

when click the request button,itwill make the Intent Service can keep continue get the ActivityRecognition information ,and the Brodcast Receiver will receiver the information form the Intent Service.

remove Button do this-to remove the ActivityRecognition keep request

public void removetActivityUpdate(View view) {

       if (mGoogleApiClient.isConnected()) {
           ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(mGoogleApiClient, getActivityDetectionPendinhIntent()).setResultCallback(this);
           requestButton.setEnabled(true);
           requestButton.setEnabled(false);
       } else {
           Toast.makeText(this, "not yet Connect", Toast.LENGTH_SHORT).show();
       }


   }










Geofencing-地理圍欄
we will create a app
when use near the coffe shop,have a notification,leave the coffee shop,have other notifaction



The develop forkflow


create GoogleAPI Client

use GeoFence builder to create a GeoFence

after create many GeoFence put them into the Arraylis
Add the GeoFencing request to the client

Start a simple app



set the dependency and Manifest

compile 'com.google.android.gms:play-services:6.5.+'


<meta-data
           android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version" />


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


set the layout


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:orientation="vertical"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="pom2.poly.com.my_geofence.MainActivity">

   <Button
       android:layout_width="wrap_content"
       android:id="@+id/add_geofences_button"
       android:layout_height="wrap_content"
       android:text="@string/buttonText"
       android:onClick="addGeoFenceButtonHander"/>
</LinearLayout>





Create a IntentService to send Notification when in or out the Geofence

public class GeoFenceTransitionsIntentService extends IntentService {
   final static String TAG="GeoFenceTransitionsIntentService";
   /**
    * Creates an IntentService.  Invoked by your subclass's constructor.
    *
    * @param name Used to name the worker thread, important only for debugging.
    */
   public GeoFenceTransitionsIntentService(){
       super(TAG);

   }
   public GeoFenceTransitionsIntentService(String name) {
       super(name);
   }

   @Override
   public void onCreate() {
       super.onCreate();
   }

   @Override
   protected void onHandleIntent(Intent intent) {
    //TODO
   }
}


<service
           android:name=".GeoFenceTransitionsIntentService"
           android:exported="false"></service>



now write the code of onHandleIntent in the IntentService




  1. get Geofence Event from the Intent

GeofencingEvent geofencingEvent=GeofencingEvent.fromIntent(intent);
       //check GeofencingEvent has error
       if(geofencingEvent.hasError()){

           Log.e(TAG, geofencingEvent.getErrorCode()+"");
           return;
       }


use hasError() t ocheck has error or not,if have error,so the error code and leave

2.get geofenceTransition Exit or Enter the Geofence?

int geofenceTransition = geofencingEvent.getGeofenceTransition();

       // Test that the reported transition was of interest.
       if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
               geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

           //TODO
       } else {
           // Log the error.
           Log.e(TAG, "Error: "+geofenceTransition);
       }


3.get What Geofence is triggered?

at TODO place

List triggeringGeofences = geofencingEvent.getTriggeringGeofences();

String geofenceTransitionDetails = getGeofenceTransitionDetails(
                   this,
                   geofenceTransition,
                   triggeringGeofences
           );


private String getGeofenceTransitionDetails(GeoFenceTransitionsIntentService geoFenceTransitionsIntentService, int geofenceTransition, List<Geofence> triggeringGeofences) {
       String geofencesID = "";
       for (Geofence gf : triggeringGeofences) {
           geofencesID = geofencesID + gf.getRequestId() + ",";
       }
       return getgeofenceTransitionString(geofenceTransition) + " " + geofencesID;
   }

   private String getgeofenceTransitionString(int geofenceTransition) {
       switch (geofenceTransition) {
           case Geofence.GEOFENCE_TRANSITION_ENTER:
               return "GEOFENCE_TRANSITION_ENTER";


           case Geofence.GEOFENCE_TRANSITION_EXIT:
               return "GEOFENCE_TRANSITION_EXIT";


           case Geofence.GEOFENCE_TRANSITION_DWELL:
               return "GEOFENCE_TRANSITION_DWELL";

           default:
               return "Unkwon";
       }
   }



The list hold all the Geofences triggered


string show all the ID of the triggered GeoFences


3.sendNotification to show the  all the ID of the triggered GeoFences

The code in onHandle


sendNotification(geofenceTransitionDetails);



private void sendNotification(String geofenceTransitionDetails) {
       //build your notification here.
//Create a  Notification builder first
       NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this);
//set the small icon(Must)
       nBuilder.setSmallIcon(R.mipmap.ic_launcher);
//set setContentTitle(must)
       nBuilder.setContentTitle("GeoFence");
//set setContentText(must)
       nBuilder.setContentText(geofenceTransitionDetails);
       //Create an explicit intent for what the notification should open.
       Intent openAActivityIntent = new Intent(this, MainActivity.class);

       //Using TaskStackBuilder, create an artificial “backstack” so that when the user clicks the back button, it is clear to Android where the user will go.
       TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
       stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack

       //create the Pending intent that use by the click
       stackBuilder.addNextIntent(openAActivityIntent);
       PendingIntent resultPendingIntent =
               stackBuilder.getPendingIntent(
                       0,
                       PendingIntent.FLAG_UPDATE_CURRENT
               );
//sett the PendingIntent to the builder
       nBuilder.setContentIntent(resultPendingIntent);
       //use NotificationManager to show the Notification we build
       NotificationManager mNotificationManager =
               (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
       mNotificationManager.notify(Contast.GEOFENCE_NOTIFICATION_ID, nBuilder.build());
   }



4.the hole code in onHandleIntent


GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
       //check GeofencingEvent has error
       if (geofencingEvent.hasError()) {

           Log.e(TAG, geofencingEvent.getErrorCode() + "");
           return;
       }
       // Get the transition type.
       int geofenceTransition = geofencingEvent.getGeofenceTransition();

       // Test that the reported transition was of interest.
       if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
               geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

           // Get the geofences that were triggered. A single event can trigger
           // multiple geofences.
           List triggeringGeofences = geofencingEvent.getTriggeringGeofences();

           // Get the transition details as a String.
           String geofenceTransitionDetails = getGeofenceTransitionDetails(
                   this,
                   geofenceTransition,
                   triggeringGeofences
           );

           // Send notification and log the transition details.
           sendNotification(geofenceTransitionDetails);
           Log.i(TAG, geofenceTransitionDetails);
       } else {
           // Log the error.
           Log.e(TAG, "Error: " + geofenceTransition);
       }


Coding the Main Activity





public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {

   private GoogleApiClient mGoogleApiClient;
   private LocationRequest mLocationRequest;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
   }

   @Override
   public void onConnected(Bundle bundle) {
       mLocationRequest = LocationRequest.create();
       mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
       mLocationRequest.setInterval(1000);
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           // TODO: Consider calling
           //    ActivityCompat#requestPermissions
           // here to request the missing permissions, and then overriding
           //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
           //                                          int[] grantResults)
           // to handle the case where the user grants the permission. See the documentation
           // for ActivityCompat#requestPermissions for more details.
           return;

       }
       LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
   }

   @Override
   public void onConnectionSuspended(int i) {

   }

   @Override
   public void onLocationChanged(Location location) {

   }

   @Override
   public void onConnectionFailed(ConnectionResult connectionResult) {

   }

   @Override
   protected void onStart() {
       super.onStart();
       mGoogleApiClient.connect();
   }

   @Override
   protected void onStop() {
       if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
       super.onStop();
   }

}




Find Latitudes and Longitudes


Create the Geofence List



public class Contast {
   public static final  int GEOFENCE_NOTIFICATION_ID=173;

   public static final HashMap<String,LatLng> BAY_AREA_LANDMARKS=new HashMap<>();

   static {
       BAY_AREA_LANDMARKS.put("1",new LatLng(22.404466,113.981428));
   }
}



before,we justcreate a hash map to hold the list of LatLng,new we need to thrnslate list of LatLng to the GeoGence object

private ArrayList<Geofence> populateGeofenceList(HashMap<String, LatLng> hm) {
       ArrayList<Geofence> geoFenceList=new ArrayList<>();

       for (String key : hm.keySet()) {
           LatLng ll=hm.get(key);
           Geofence geofence=new Geofence.Builder().setRequestId(key).setCircularRegion(ll.latitude, ll.longitude, 1)
           // Set the expiration duration of the geofence. This geofence gets automatically
           // removed after this period of time.
           .setExpirationDuration(Contast.GEOFENCE_EXPIRATION_IN_MILLISECONDS)// 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).build();
           geoFenceList.add(geofence);
       }

       return geoFenceList;

   }


in Mainactivity

mgeoFenceList=populateGeofenceList(Contast.BAY_AREA_LANDMARKS);

Creating the Geofencing Request
it Specifies the list of geofences to be monitored and how the geofence notifications should be reported.



private GeofencingRequest getGeofencingRequest(List<Geofence> geofencesList) {
       GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
       builder.addGeofences(geofencesList);
       builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_EXIT);


       return builder.build();

   }


use INITIAL_TRIGGER_ENTER,because it is use to et,when the device already in the geofence,but the geofence haven’t add,whem it add,what will triger?exit,enter,DWELL?


Creating the Geofenced Pending Intent
use to starts an IntentService :GeoFenceTransitionsIntentService!!!!

private PendingIntent getGeofencingPendingIntent() {
       Intent intent = new Intent(this, GeoFenceTransitionsIntentService.class);
       PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
       return pendingIntent;
   }



Add geofences
it need the geoFenceList ,GeofencingRequest and GeofencingPendingIntent(to control waht will do after out or in a GeoFebc,this example is send out a notification)
mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();

       mgeoFenceList = populateGeofenceList(Contast.BAY_AREA_LANDMARKS);
       mGeofencingRequest=getGeofencingRequest(mgeoFenceList);
       mGeofencingPendingIntent=getGeofencingPendingIntent();
       LocationServices.GeofencingApi.addGeofences(mGoogleApiClient,mGeofencingRequest,mGeofencingPendingIntent).setResultCallback(this);


public void onResult(Status status) {
       if (status.isSuccess()) {
           Toast.makeText(this, "GF added", Toast.LENGTH_SHORT).show();
       } else {
           Log.d(TAG, "error: " + status.getStatus() + " " + status.getStatusMessage());

       }
   }


in the onResult,whill receive the status code of success or not add the geofence


Finishing the Button handler Code

click the button,add the GeoFence.

if (mGoogleApiClient.isConnected()) {
           mgeoFenceList = populateGeofenceList(Contast.BAY_AREA_LANDMARKS);
           mGeofencingRequest = getGeofencingRequest(mgeoFenceList);
           mGeofencingPendingIntent = getGeofencingPendingIntent();
           LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, mGeofencingRequest, mGeofencingPendingIntent).setResultCallback(this);
       } else {
           Toast.makeText(this, "not yet connected", Toast.LENGTH_SHORT).show();
       }



remeber to add:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />