简体   繁体   English

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

[英]Android Geofence Automatically removed when location service is disabled / restarted

I have successfully added the geofence with the Flag NEVER_EXPIRE. 我已经使用Flag NEVER_EXPIRE成功添加了地理围栏。 And everything seems to be working fine. 一切似乎都运转正常。

But now while testing i found that if i stop the location services geofence stops working as EXPECTED. 但现在在测试时我发现如果我停止位置服务地理围栏停止工作为EXPECTED。 Further when i start the location services again my previously added geofence should again start working but no notifications are generated and it seems the geofence are automatically removed once the location services is disabled . 此外,当我再次启动位置服务时,我之前添加的地理围栏应该再次开始工作,但不会生成任何通知,并且一旦禁用位置服务,地理围栏似乎会自动删除。 And i have to again set all the locations to get back the geofence in working state. 我必须再次设置所有位置以恢复工作状态下的地理围栏。

Any suggestions or any idea why it behaves this way?? 任何建议或任何想法为什么它这样做?

EDIT:: 编辑::

Similar Issue is also seen when the Device is Turned off / Restarted etc. So basically all the geofences which are registered will be expired if Location Services is disabled / Device is restarted . 当设备关闭/重新启动等时也会出现类似的问题。因此,如果禁用位置服务/重新启动设备,基本上所有已注册的地理围栏都将过期。 Few of which i tried to handle by Session but i am looking for a solution by which we can set the Geofences back when the location service is enabled . 其中很少我尝试通过Session处理,但我正在寻找一种解决方案,通过该解决方案,我们可以在启用位置服务时将Geofences设置回来。

For watching in the background, I had the same issue and was able to solve it by changing the sample code from an IntentService to a BroadcastReceiver. 为了在后台观看,我遇到了同样的问题,并且能够通过将示例代码从IntentService更改为BroadcastReceiver来解决它。 All the details can be found on my post here: 所有细节都可以在我的帖子中找到:

Android Geofence eventually stop getting transition intents Android Geofence最终停止获得过渡意图

This is what I said (in case anyone is too lazy to follow the link): 这就是我所说的(如果有人懒得跟随链接):

So after playing around with this a bit, it looks like the ReceiveTransitionsIntentService as defined in the sample code will stop getting the notifications when the app is not around. 因此,在稍微讨论一下后,看起来示例代码中定义的ReceiveTransitionsIntentService将在应用程序不在时停止获取通知。 I think this is a big problem with the example code... Seems like that will trip folks like me up. 我认为这是示例代码的一个大问题......似乎这样会让像我一样的人绊倒。

So I used a broadcast receiver instead, and so far it seems to be working from my tests. 所以我使用了广播接收器,到目前为止它似乎正在我的测试中工作。

Add this to the manifest: 将其添加到清单:

<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>

Then in the GeofenceRequester class you need to change the createRequestPendingIntent method so that it goes to your BroadcastReceiver instead of the ReceiveTransitionsIntentService 然后在GeofenceRequester类中,您需要更改createRequestPendingIntent方法,以便它转到BroadcastReceiver而不是ReceiveTransitionsIntentService

private PendingIntent createRequestPendingIntent() {

        // If the PendingIntent already exists
        if (null != mGeofencePendingIntent) {

            // Return the existing intent
            return mGeofencePendingIntent;

        // If no PendingIntent exists
        } else {

            // Create an Intent pointing to the IntentService
            Intent intent = new Intent("com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE");
//            Intent intent = new Intent(context, ReceiveTransitionsIntentService.class);
            /*
             * Return a PendingIntent to start the IntentService.
             * Always create a PendingIntent sent to Location Services
             * with FLAG_UPDATE_CURRENT, so that sending the PendingIntent
             * again updates the original. Otherwise, Location Services
             * can't match the PendingIntent to requests made with it.
             */
            return PendingIntent.getBroadcast(
                    context,
                    0,
                    intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
        }
    }

Then I added the GeofenceReceiver class that looks something like this: 然后我添加了看起来像这样的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());
    }
}

Hopefully that helps someone else. 希望这有助于其他人。

Found this Answer::: http://developer.android.com/reference/com/google/android/gms/location/LocationClient.html 发现此答案::: http://developer.android.com/reference/com/google/android/gms/location/LocationClient.html

In case network location provider is disabled by the user, the geofence service will stop updating, all registered geofences will be removed and an intent is generated by the provided pending intent. 如果用户禁用了网络位置提供程序,则地理围栏服务将停止更新,将删除所有已注册的地理围栏,并通过提供的待处理意图生成意图。 In this case, hasError(Intent) returns true and getErrorCode(Intent) returns GEOFENCE_NOT_AVAILABLE. 在这种情况下,hasError(Intent)返回true,getErrorCode(Intent)返回GEOFENCE_NOT_AVAILABLE。

Now:::: How can we register the geofence back when the location service is back.. (IN BACKGROUND) 现在::::当位置服务回来时,我们如何注册地理围栏...(背景)

@rns.ravi - look what the docs says - you have to register a intent where you could then re-add all your geofences @ rns.ravi - 查看文档说的内容 - 您必须注册一个意图,然后您可以重新添加所有地理围栏

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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM