大家好,我正在研究地理围栏项目。我在andriod开发者页面看到了示例,我想实现自己的类。我使用的代码与在开发者页面中提供的代码相同,但我仍然无法调用我的GeofenceTransitionsIntentService类。在调试我的应用程序时,我收到了一个错误 状态{statusCode =未知状态代码:1000,分辨率= null} 我不该做什么?请帮我。谢谢。
Sample.java
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
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.LocationListener;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
import java.util.Map;
public class Sample extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener, ResultCallback<Status> {
// LogCat tag
private static final String TAG = "Sample";
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
private PendingIntent mGeofencePendingIntent;
private boolean mGeofencesAdded;
/**
* The list of geofences used in this sample.
*/
protected ArrayList<Geofence> mGeofenceList;
/**
* Used to persist application state about whether geofences were added.
*/
private SharedPreferences mSharedPreferences;
// UI elements
private TextView lblLocation;
private Button btnShowLocation, btnStartLocationUpdates;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lblLocation = (TextView) findViewById(R.id.lblLocation);
btnShowLocation = (Button) findViewById(R.id.btnShowLocation);
btnStartLocationUpdates = (Button) findViewById(R.id.btnLocationUpdates);
// Empty list for storing geofences.
mGeofenceList = new ArrayList<Geofence>();
// First we need to check availability of play services
mSharedPreferences = getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,
MODE_PRIVATE);
// Get the value of mGeofencesAdded from SharedPreferences. Set to false as a default.
mGeofencesAdded = mSharedPreferences.getBoolean(Constants.GEOFENCES_ADDED_KEY, false);
// Get the geofences used. Geofence data is hard coded in this sample.
populateGeofenceList();
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
}
// Show location button click listener
btnShowLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
displayLocation();
}
});
}
/**
* This sample hard codes geofence data. A real app might dynamically create geofences based on
* the user's location.
*/
public void populateGeofenceList() {
for (Map.Entry<String, LatLng> entry : Constants.BAY_AREA_LANDMARKS.entrySet()) {
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
// Set the circular region of this geofence.
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
// Set the expiration duration of the geofence. This geofence gets automatically
// removed after this period of time.
.setExpirationDuration(Constants.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)
// Create the geofence.
.build());
}
}
@Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
@Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
protected void onPause() {
super.onPause();
}
/**
* Method to display the location on UI
*/
private void displayLocation() {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(Sample.this, "API is not connected", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(Sample.this, "API is connected", Toast.LENGTH_SHORT).show();
try {
Toast.makeText(Sample.this, "inside try catch", Toast.LENGTH_SHORT).show();
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.
PendingIntent.getService(this, 0,
new Intent(this, GeofenceTransitionsIntentService.class)
, PendingIntent.FLAG_UPDATE_CURRENT))
.setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
Toast.makeText(Sample.this, "inside catch", Toast.LENGTH_SHORT).show();
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
logSecurityException(securityException);
}
}
}
private void logSecurityException(SecurityException securityException) {
Log.e(TAG, "Invalid location permission. " +
"You need to use ACCESS_FINE_LOCATION with geofences", securityException);
}
/**
* 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() {
Toast.makeText(Sample.this, "inside getGeofencingRequest", Toast.LENGTH_SHORT).show();
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();
}
/**
* 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.
*/
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
Toast.makeText(Sample.this, "inside getGeofencePendingIntent", Toast.LENGTH_SHORT).show();
return PendingIntent.getService(this, 579, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
@Override
public void onConnected(Bundle arg0) {
displayLocation();
}
@Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
// Update state and save in shared preferences.
mGeofencesAdded = !mGeofencesAdded;
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
editor.commit();
Toast.makeText(
this,
getString(mGeofencesAdded ? R.string.geofences_added :
R.string.geofences_removed),
Toast.LENGTH_SHORT
).show();
} else {
// Get the status code for the error and log it using a user-friendly message.
String errorMessage = GeofenceErrorMessages.getErrorString(this,
status.getStatusCode());
Log.e(TAG, errorMessage);
}
}
}
GeofenceTransitionsInentService.java
package material.concerto.com.mylocation;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;
import java.util.ArrayList;
import java.util.List;
/**
* Listener for geofence transition changes.
*
* Receives geofence transition events from Location Services in the form of an Intent containing
* the transition type and geofence id(s) that triggered the transition. Creates a notification
* as the output.
*/
public class GeofenceTransitionsIntentService extends IntentService {
protected static final String TAG = "gts";
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public GeofenceTransitionsIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
Toast.makeText(GeofenceTransitionsIntentService.this, "indside intent service constructor", Toast.LENGTH_SHORT).show();
}
@Override
public void onCreate() {
Toast.makeText(GeofenceTransitionsIntentService.this, "indside intent service oncreate", Toast.LENGTH_SHORT).show();
super.onCreate();
}
/**
* Handles incoming intents.
* @param intent sent by Location Services. This Intent is provided to Location
* Services (inside a PendingIntent) when addGeofences() is called.
*/
@Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(GeofenceTransitionsIntentService.this, "inside intent service", Toast.LENGTH_SHORT).show();
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
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<Geofence> 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, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
}
}
/**
* Gets transition details and returns them as a formatted string.
*
* @param context The app context.
* @param geofenceTransition The ID of the geofence transition.
* @param triggeringGeofences The geofence(s) triggered.
* @return The transition details formatted as String.
*/
private String getGeofenceTransitionDetails(
Context context,
int geofenceTransition,
List<Geofence> triggeringGeofences) {
String geofenceTransitionString = getTransitionString(geofenceTransition);
// Get the Ids of each geofence that was triggered.
ArrayList triggeringGeofencesIdsList = new ArrayList();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}
/**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the MainActivity.
*/
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), Sample.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(Sample.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Define the notification settings.
builder.setSmallIcon(R.drawable.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
/**
* Maps geofence transition types to their human-readable equivalents.
*
* @param transitionType A transition type constant defined in Geofence
* @return A String indicating the type of transition
*/
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return getString(R.string.geofence_transition_entered);
case Geofence.GEOFENCE_TRANSITION_EXIT:
return getString(R.string.geofence_transition_exited);
default:
return getString(R.string.unknown_geofence_transition);
}
}
}