Intentservice类没有从pendinginent调用?

时间:2015-09-08 09:51:51

标签: android android-pendingintent intentservice

大家好,我正在研究地理围栏项目。我在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);
        }
    }
}

0 个答案:

没有答案