【问题标题】:Android Geofence Automatically removed when location service is disabled / restarted禁用/重新启动位置服务时自动删除 Android 地理围栏
【发布时间】:2013-09-13 08:17:59
【问题描述】:

我已成功添加带有标志 NEVER_EXPIRE 的地理围栏。一切似乎都运行良好。

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

任何建议或任何想法为什么它会这样??

编辑::

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

【问题讨论】:

  • 我可以确认,如果位置服务被禁用,那么所有注册的地理围栏都会被删除。 [链接] (swebytes.com/2013/10/31/…) @b-ryce

标签: android geolocation geofencing


【解决方案1】:

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

Android Geofence eventually stop getting transition intents

这就是我说的(以防有人懒得点链接):

所以在玩了一会儿之后,看起来示例代码中定义的 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>

然后在 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);
        }
    }

然后我添加了看起来像这样的 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());
    }
}

希望对其他人有所帮助。

【讨论】:

  • 我回到了我提出并忘记的同一个帖子...无论如何感谢您的回复..
  • 但是,在我的情况下,即使应用程序处于后台,它也能正常工作。但主要问题是当您在设备上切换位置服务时,您将在 ReceiveTransitionsIntentService 上收到错误消息,通过该错误可能可以重置地理围栏等。我所做的是我删除了我的会话并将其设置为重置当用户返回应用程序时,地理围栏会返回。我正在寻找一种解决方案,用户不必回到应用程序,我们在后台设置地理围栏
【解决方案2】:

找到这个答案::: http://developer.android.com/reference/com/google/android/gms/location/LocationClient.html

如果用户禁用了网络位置提供程序,地理围栏服务将停止更新,所有已注册的地理围栏将被删除,并由提供的待处理意图生成一个意图。在这种情况下,hasError(Intent) 返回 true,getErrorCode(Intent) 返回 GEOFENCE_NOT_AVAILABLE。

现在:::: 当定位服务恢复时,我们如何注册地理围栏..(背景中)

【讨论】:

  • 想出了一种在后台执行此操作的方法。但是必须更改 GeofenceRequester.java 在此我们已将函数 GeofenceRequester(final Activity Activity_name) 的参数更改为 GeofenceRequester(final Context Context_name) 通过这个我们可以传递上下文以从背景或前台添加地理围栏。我希望这会有所帮助
【解决方案3】:

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

【讨论】:

  • 我创建了一个位置监听器,它使用每个位置更新来更新我,并且我从监听器调用了服务,它检查我的地理围栏是否已设置或我必须重置地理围栏。一切都很好,但是现在当我尝试从服务中添加地理围栏时,这是不可能的,因为要添加地理围栏,我需要将 Activity 传递给 GeofenceRequester(),而这在服务中是不可能的。现在怎么解决。??
【解决方案4】:

在前台服务中运行地理围栏代码。它会按预期工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多