禁用/重新启动位置服务时,Android Geofence会自动删除

禁用/重新启动位置服务时,Android Geofence会自动删除,android,geolocation,geofencing,Android,Geolocation,Geofencing,我已成功添加带有永不过期标志的地理围栏。一切似乎都很顺利 但现在在测试时,我发现如果我停止定位服务,Geopfence将停止按预期工作。此外,当我再次启动位置服务时,我先前添加的地理围栏应再次开始工作,但不会生成任何通知,并且在禁用位置服务后,地理围栏似乎会自动删除。我必须再次设置所有位置,使土工栅栏恢复工作状态 有任何建议或想法说明它为什么会这样吗 编辑:: 当设备关闭/重新启动时,也会出现类似问题。因此,如果位置服务被禁用/设备重新启动,则基本上所有注册的地理围栏都将过期。我尝试通过会话处理

我已成功添加带有永不过期标志的地理围栏。一切似乎都很顺利

但现在在测试时,我发现如果我停止定位服务,Geopfence将停止按预期工作。此外,当我再次启动位置服务时,我先前添加的地理围栏应再次开始工作,但不会生成任何通知,并且在禁用位置服务后,地理围栏似乎会自动删除。我必须再次设置所有位置,使土工栅栏恢复工作状态

有任何建议或想法说明它为什么会这样吗

编辑::

当设备关闭/重新启动时,也会出现类似问题。因此,如果位置服务被禁用/设备重新启动,则基本上所有注册的地理围栏都将过期。我尝试通过会话处理其中的一些问题,但我正在寻找一种解决方案,通过该解决方案,我们可以在启用位置服务时将Geofences设置回原来的位置

找到了这个答案::

如果用户禁用网络位置提供程序,geofence服务将停止更新,所有已注册的geofence将被删除,并由提供的挂起意图生成意图。在这种情况下,hasError(Intent)返回true,getErrorCode(Intent)返回geopfence\u NOT\u AVAILABLE


现在:::当定位服务恢复时,我们如何注册地理围栏。。(在后台)

在后台观看时,我遇到了同样的问题,通过将示例代码从IntentService更改为BroadcastReceiver,我能够解决这个问题。所有细节都可以在我的帖子中找到:

这就是我所说的(以防任何人懒得跟随链接):

因此,在稍微处理一下这个问题之后,看起来示例代码中定义的ReceiveTransitionsIntentService将在应用程序不在时停止接收通知。我认为这是示例代码的一个大问题。。。看来这会让我这样的人绊倒

所以我用了一个广播接收器,到目前为止,它似乎在我的测试工作

将此添加到清单:

<receiver android:name="com.aol.android.geofence.GeofenceReceiver"
        android:exported="false">
        <intent-filter >
            <action android:name="com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE"/>
        </intent-filter>
    </receiver>
然后我添加了GeofenceReceiver类,该类类似于:

public class GeofenceReceiver extends BroadcastReceiver {
    Context context;

    Intent broadcastIntent = new Intent();

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;

        broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);

        if (LocationClient.hasError(intent)) {
            handleError(intent);
        } else {
            handleEnterExit(intent);
        }
    }

    private void handleError(Intent intent){
        // Get the error code
        int errorCode = LocationClient.getErrorCode(intent);

        // Get the error message
        String errorMessage = LocationServiceErrorMessages.getErrorString(
                context, errorCode);

        // Log the error
        Log.e(GeofenceUtils.APPTAG,
                context.getString(R.string.geofence_transition_error_detail,
                        errorMessage));

        // Set the action and error message for the broadcast intent
        broadcastIntent
                .setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR)
                .putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage);

        // Broadcast the error *locally* to other components in this app
        LocalBroadcastManager.getInstance(context).sendBroadcast(
                broadcastIntent);
    }


    private void handleEnterExit(Intent intent) {
        // Get the type of transition (entry or exit)
        int transition = LocationClient.getGeofenceTransition(intent);

        // Test that a valid transition was reported
        if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER)
                || (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) {

            // Post a notification
            List<Geofence> geofences = LocationClient
                    .getTriggeringGeofences(intent);
            String[] geofenceIds = new String[geofences.size()];
            String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER,
                    geofenceIds);
            String transitionType = GeofenceUtils
                    .getTransitionString(transition);

            for (int index = 0; index < geofences.size(); index++) {
                Geofence geofence = geofences.get(index);
                // ...do something with the geofence entry or exit. I'm saving them to a local sqlite db

            }
            // Create an Intent to broadcast to the app
            broadcastIntent
                    .setAction(GeofenceUtils.ACTION_GEOFENCE_TRANSITION)
                    .addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES)
                    .putExtra(GeofenceUtils.EXTRA_GEOFENCE_ID, geofenceIds)
                    .putExtra(GeofenceUtils.EXTRA_GEOFENCE_TRANSITION_TYPE,
                            transitionType);

            LocalBroadcastManager.getInstance(MyApplication.getContext())
                    .sendBroadcast(broadcastIntent);

            // Log the transition type and a message
            Log.d(GeofenceUtils.APPTAG, transitionType + ": " + ids);
            Log.d(GeofenceUtils.APPTAG,
                    context.getString(R.string.geofence_transition_notification_text));

            // In debug mode, log the result
            Log.d(GeofenceUtils.APPTAG, "transition");

            // An invalid transition was reported
        } else {
            // Always log as an error
            Log.e(GeofenceUtils.APPTAG,
                    context.getString(R.string.geofence_transition_invalid_type,
                            transition));
        }
    }

    /**
     * Posts a notification in the notification bar when a transition is
     * detected. If the user clicks the notification, control goes to the main
     * Activity.
     * 
     * @param transitionType
     *            The type of transition that occurred.
     * 
     */
    private void sendNotification(String transitionType, String locationName) {

        // Create an explicit content Intent that starts the main Activity
        Intent notificationIntent = new Intent(context, MainActivity.class);

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

        // Adds 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(
                context);

        // Set the notification contents
        builder.setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(transitionType + ": " + locationName)
                .setContentText(
                        context.getString(R.string.geofence_transition_notification_text))
                .setContentIntent(notificationPendingIntent);

        // Get an instance of the Notification manager
        NotificationManager mNotificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        // Issue the notification
        mNotificationManager.notify(0, builder.build());
    }
}
公共类GeofenceReceiver扩展了BroadcastReceiver{
语境;
意向广播意向=新意向();
@凌驾
公共void onReceive(上下文、意图){
this.context=上下文;
broadcastIntent.addCategory(GeofenceUtils.CATEGORY\u LOCATION\u SERVICES);
if(LocationClient.hasError(intent)){
handleError(意图);
}否则{
handleinterexit(意图);
}
}
私有无效句柄错误(意图){
//获取错误代码
int errorCode=LocationClient.getErrorCode(intent);
//获取错误消息
String errorMessage=LocationServiceErrorMessages.getErrorString(
上下文、错误代码);
//记录错误
Log.e(GeofenceUtils.APPTAG,
context.getString(R.string.geofrance\u transition\u error\u detail,
错误消息);
//为广播目的设置操作和错误消息
广播意图
.setAction(GeofenceUtils.ACTION\u GEOFENCE\u错误)
.putExtra(geofenseUtils.EXTRA\u geofense\u状态,错误消息);
//将错误*本地*广播到此应用程序中的其他组件
LocalBroadcastManager.getInstance(上下文).sendBroadcast(
广播意图);
}
私有无效HandleInterExit(意向){
//获取转换类型(入口或出口)
int transition=LocationClient.getGeofenceTransition(意图);
//测试是否报告了有效的转换
如果((转换==地理围栏。地理围栏\转换\输入)
||(过渡==地理围栏。地理围栏\过渡\出口)){
//张贴通知
列出geofences=LocationClient
.gettriggeringgeofenses(意图);
String[]geofineids=新字符串[geofines.size()];
String ID=TextUtils.join(geofenseutils.geofense\u ID\u分隔符,
大地水准面);
字符串transitionType=GeofenceUtils
.getTransitionString(转换);
对于(int index=0;indexpublic class GeofenceReceiver extends BroadcastReceiver {
    Context context;

    Intent broadcastIntent = new Intent();

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;

        broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);

        if (LocationClient.hasError(intent)) {
            handleError(intent);
        } else {
            handleEnterExit(intent);
        }
    }

    private void handleError(Intent intent){
        // Get the error code
        int errorCode = LocationClient.getErrorCode(intent);

        // Get the error message
        String errorMessage = LocationServiceErrorMessages.getErrorString(
                context, errorCode);

        // Log the error
        Log.e(GeofenceUtils.APPTAG,
                context.getString(R.string.geofence_transition_error_detail,
                        errorMessage));

        // Set the action and error message for the broadcast intent
        broadcastIntent
                .setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR)
                .putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage);

        // Broadcast the error *locally* to other components in this app
        LocalBroadcastManager.getInstance(context).sendBroadcast(
                broadcastIntent);
    }


    private void handleEnterExit(Intent intent) {
        // Get the type of transition (entry or exit)
        int transition = LocationClient.getGeofenceTransition(intent);

        // Test that a valid transition was reported
        if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER)
                || (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) {

            // Post a notification
            List<Geofence> geofences = LocationClient
                    .getTriggeringGeofences(intent);
            String[] geofenceIds = new String[geofences.size()];
            String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER,
                    geofenceIds);
            String transitionType = GeofenceUtils
                    .getTransitionString(transition);

            for (int index = 0; index < geofences.size(); index++) {
                Geofence geofence = geofences.get(index);
                // ...do something with the geofence entry or exit. I'm saving them to a local sqlite db

            }
            // Create an Intent to broadcast to the app
            broadcastIntent
                    .setAction(GeofenceUtils.ACTION_GEOFENCE_TRANSITION)
                    .addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES)
                    .putExtra(GeofenceUtils.EXTRA_GEOFENCE_ID, geofenceIds)
                    .putExtra(GeofenceUtils.EXTRA_GEOFENCE_TRANSITION_TYPE,
                            transitionType);

            LocalBroadcastManager.getInstance(MyApplication.getContext())
                    .sendBroadcast(broadcastIntent);

            // Log the transition type and a message
            Log.d(GeofenceUtils.APPTAG, transitionType + ": " + ids);
            Log.d(GeofenceUtils.APPTAG,
                    context.getString(R.string.geofence_transition_notification_text));

            // In debug mode, log the result
            Log.d(GeofenceUtils.APPTAG, "transition");

            // An invalid transition was reported
        } else {
            // Always log as an error
            Log.e(GeofenceUtils.APPTAG,
                    context.getString(R.string.geofence_transition_invalid_type,
                            transition));
        }
    }

    /**
     * Posts a notification in the notification bar when a transition is
     * detected. If the user clicks the notification, control goes to the main
     * Activity.
     * 
     * @param transitionType
     *            The type of transition that occurred.
     * 
     */
    private void sendNotification(String transitionType, String locationName) {

        // Create an explicit content Intent that starts the main Activity
        Intent notificationIntent = new Intent(context, MainActivity.class);

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

        // Adds 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(
                context);

        // Set the notification contents
        builder.setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(transitionType + ": " + locationName)
                .setContentText(
                        context.getString(R.string.geofence_transition_notification_text))
                .setContentIntent(notificationPendingIntent);

        // Get an instance of the Notification manager
        NotificationManager mNotificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        // Issue the notification
        mNotificationManager.notify(0, builder.build());
    }
}
public void requestLocationUpdates (LocationRequest request, PendingIntent callbackIntent)

Requests location updates with a callback on the specified PendingIntent.

This method is suited for the background use cases, more specifically for receiving location updates, even when the app has been killed by the system. In order to do so, use a PendingIntent for a started service. For foreground use cases, the LocationListener version of the method is recommended, see requestLocationUpdates(LocationRequest, LocationListener).

Any previous LocationRequests registered on this PendingIntent will be replaced.

Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value on the intent.

Parameters
request The location request for the updates.
callbackIntent  A pending intent to be sent for each location update.