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());
}
|
full project:https://github.com/roy989898/Location1_example.git
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();
}
}
|
the app whole code ise here:https://github.com/roy989898/Location2_1.git
Activity Recognition App
completed like this
the starting code is here:https://github.com/roy989898/Location2_1/tree/47d76c40c8c53602fc62939bf71ce6261299a281
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();
}
}
|
the whole app code:https://github.com/roy989898/Location2_1/tree/a5a369ce6356a98c711b89fe51ec237a2af0a7cd
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
answer is here:https://github.com/udacity/google-play-services/tree/master/LocationLessons_Final/LocationLesson3_1
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
- 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" />
the whole project code:https://github.com/roy989898/Location_GeoFence_example.git