Pending Intent不会触发Geofencing中的意图服务

时间:2017-04-03 07:05:23

标签: geofencing android-geofence

当用户进入已定义的地理围栏区域时,我正在使用意图服务来创建通知。问题是,当我第一次运行应用程序时,它工作正常,我在我的Intent服务上获得pending-intent,但之后有些日子(2-3),我没有在Intent服务上获得所需的意图。

我不知道为什么它会在几天后停止工作。如果我启动应用程序,它将再次正常启动,但在几天后再次停止。

这是我的活动代码 -

public class MainActivity extends AppCompatActivity implements View.OnClickListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, ResultCallback, OnRequestPermissionsResultCallback {

GoogleApiClient mGoogleApiClient;
Location mGeoLocation;
Geofence mGeofence;

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

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


    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, 100);

    }
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mGeoLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    mGoogleApiClient.connect();
}

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


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

@Override
public void onClick(View v) {
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
   Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT);
    Log.e("Here I am","Using geofencing in my mobile on 'onConnectionFailed'  of main activity");
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }

    if (mGeoLocation != null) {
        mGeofence = new Geofence.Builder()
                .setRequestId("Appstudioz")
                .setCircularRegion(mGeoLocation.getLatitude(), mGeoLocation.getLongitude(), 100)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                .build();
        mGoogleApiClient.connect();
        Intent intent = new Intent(this, MyIntentServiceGeoFencing.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofence(mGeofence);
        LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, builder.build(), pendingIntent).setResultCallback(this);


    }
}
@Override
public void onConnectionSuspended(int i) {
    Log.e("Here I am","Using geofencing in my mobile 'onConnectionSuspended' of main activity");
}

@Override
public void onResult(@NonNull Result result) {
    Log.e("Here I am","Using geofencing in my mobile 'onResult' of main activity");
}
}

这是我的意图服务 -

public class MyIntentServiceGeoFencing extends IntentService {
public MyIntentServiceGeoFencing() {
    super("MyIntentServiceGeoFencing");
}
@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        String message="";
        Log.e("Here I am","Using geofencing in my mobile 'In intent Service'");
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if(geofencingEvent.getGeofenceTransition()== Geofence.GEOFENCE_TRANSITION_ENTER)
        {
            message="Entering Appstudioz";
        }
        else if(geofencingEvent.getGeofenceTransition()== Geofence.GEOFENCE_TRANSITION_EXIT)
        {
            message="Exiting Appstudioz";
        }
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.cast_ic_notification_small_icon)
                        .setContentTitle("Geofence Notification")
                        .setContentText(message);

// Sets an ID for the notification
        int mNotificationId = 001;
// Gets an instance of the NotificationManager service
        NotificationManager mNotifyMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
        mNotifyMgr.notify(mNotificationId, mBuilder.build());
        if(message.equals("Entering Appstudioz")) {
            ((AudioManager) getSystemService(AUDIO_SERVICE)).setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
        }
        else
        {
            ((AudioManager) getSystemService(AUDIO_SERVICE)).setRingerMode(AudioManager.RINGER_MODE_NORMAL);
        }

    }
}
}

2 个答案:

答案 0 :(得分:4)

我找到了解决方案。以下是该应用程序未根据官方谷歌文档获得Pending Intents的原因 -

1.设备重启。
2.该应用程序已卸载并重新安装 3.应用程序的数据被清除 4.Google Play服务数据已清除 5.该应用已收到GEOFENCE_NOT_AVAILABLE警报。(当Android位置提供商(GPS)关闭时)

在这些事件发生后,您必须重新注册地理围栏。

在我的情况下,设备重启和位置提供商(GPS)被关闭,是未获得待处理意图的原因。

答案 1 :(得分:0)

当您终止应用程序时,服务将停止运行,因此,您可以使用广播接收器来解决此问题

public class GeofenceReceiver extends BroadcastReceiver
implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    ResultCallback<Status>{

GoogleApiClient mGoogleApiClient;
PendingIntent mGeofencePendingIntent ;
Context mContext;

@Override
public void onReceive(Context context, Intent intent) {
    mContext = context;
    mGoogleApiClient = new GoogleApiClient.Builder(mContext)
            .addOnConnectionFailedListener(this)
            .addConnectionCallbacks(this)
            .addApi(LocationServices.API)
            .build();

    mGoogleApiClient.connect();
}



@Override
public void onConnected(@Nullable Bundle bundle) {
    try {
        LocationServices.GeofencingApi.addGeofences(
                mGoogleApiClient,
                // The GeofenceRequest object.
                getGeofencingRequest(),
                getGeofencePendingIntent()
        ).setResultCallback(this); // Result processed in onResult().
    } catch (SecurityException securityException) {
        Log.i(getClass().getSimpleName(),securityException.getMessage());
    }
}

// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

/**
 * Runs when the result of calling addGeofences() and removeGeofences() becomes available.
 * Either method can complete successfully or with an error.
 *
 * Since this activity implements the {@link ResultCallback} interface, we are required to
 * define this method.
 *
 * @param status The Status returned through a PendingIntent when addGeofences() or
 *               removeGeofences() get called.
 */
@Override
public void onResult(@NonNull Status status) {
    if (status.isSuccess()) {
        Log.i(getClass().getSimpleName(),"Success");
    } else {
        // Get the status code for the error and log it using a user-friendly message.
        Log.i(getClass().getSimpleName(),getErrorString(status.getStatusCode()));
    }
}

private GeofencingRequest getGeofencingRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_DWELL);
    builder.addGeofences(getGeofecne());
    return builder.build();
}

private List<Geofence> getGeofecne(){
    List<Geofence> mGeofenceList = new ArrayList<>();

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

            // Set the circular region of this geofence.
            .setCircularRegion(
                    25.768466, //lat
                    47.567625, //long
                    50) // radios

            // Set the expiration duration of the geofence. This geofence gets automatically
            // removed after this period of time.
            //1000 millis  * 60 sec * 5 min
            .setExpirationDuration(1000 * 60 * 5)

            // 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_DWELL)
            //it's must to set time in millis with dwell transition
            .setLoiteringDelay(3000)
            // Create the geofence.
            .build());

    return mGeofenceList;

}

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(mContext, GeofenceTransitionsIntentService.class);
    return PendingIntent.getService(mContext, 0, intent, PendingIntent.
            FLAG_UPDATE_CURRENT);
}

}

此处是您的通知服务

public class GeofenceTransitionsIntentService extends IntentService {
protected static final String TAG = "GeofenceTransitionsIS";

/**
 * 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);
}

/**
 * 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) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    if (geofencingEvent.hasError()) {
        Log.e(TAG, getErrorString(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_DWELL) {

        // Get the transition details as a String.
        String geofenceTransitionDetails = "Discount 10% for you";

        // 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));
    }
}

public static String getErrorString(int errorCode) {
    switch (errorCode) {
        case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
            return "not Available";
        case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
            return "Too many Geofences";
        case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
            return "Too many Pending Intents";
        default:
            return "unknown geofence error";
    }
}


/**
 * 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(), MainActivity.class);

    // Construct a task stack.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

    // Add the main Activity to the task stack as the parent.
    stackBuilder.addParentStack(MainActivity.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.common_google_signin_btn_icon_dark_normal)
            // In a real app, you may want to use a library like Volley
            // to decode the Bitmap.
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                    R.drawable.cast_abc_scrubber_primary_mtrl_alpha))
            .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());
}

}

有关更多信息,请查看我的回购中有完整示例

https://github.com/3zcs/Geofence