【问题标题】:Geofencing doesn't work?地理围栏不起作用?
【发布时间】:2018-02-01 11:54:32
【问题描述】:

所以我一直在尝试来自互联网的简单地理围栏应用程序,但它们似乎都不起作用。在下面的示例中,当手机的经度和纬度满足常量类中定义的经度和纬度时,应触发通知。我用模拟器对其进行了测试,但是当我相应地更改模拟器 gps 坐标时,什么也没有发生。 根据文档,警报未按预期工作的一些可能原因:

  • 在您的地理围栏内或您的 地理围栏太小了
  • 设备上的 Wi-Fi 已关闭。
  • 您的地理围栏内没有可靠的网络连接。
  • 警报可能会延迟。

我在 android studio 上收到这条消息: https://drive.google.com/open?id=12VjaB5BNjdIrOD5QVJWLoRwnXEZq6KKB

这是我的日志:

02-01 13:42:09.932 14925-14925/? I/zygote: Not late-enabling -Xcheck:jni (already on)
02-01 13:42:09.955 14925-14925/? W/zygote: Unexpected CPU variant for X86 using defaults: x86
02-01 13:42:09.993 14925-14932/? E/zygote: Failed writing handshake bytes (-1 of 14): Broken pipe
02-01 13:42:09.993 14925-14932/? I/zygote: Debugger is no longer active
02-01 13:42:10.315 14925-14925/? I/InstantRun: starting instant run server: is main process
02-01 13:42:10.725 14925-14942/? D/OpenGLRenderer: HWUI GL Pipeline
02-01 13:42:10.784 14925-14942/? I/zygote: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
02-01 13:42:10.784 14925-14942/? I/OpenGLRenderer: Initialized EGL, version 1.4
02-01 13:42:10.784 14925-14942/? D/OpenGLRenderer: Swap behavior 1
02-01 13:42:10.785 14925-14942/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
02-01 13:42:10.785 14925-14942/? D/OpenGLRenderer: Swap behavior 0
02-01 13:42:10.810 14925-14942/? D/EGL_emulation: eglCreateContext: 0x9cb60b60: maj 2 min 0 rcv 2
02-01 13:42:10.872 14925-14942/? D/EGL_emulation: eglMakeCurrent: 0x9cb60b60: ver 2 0 (tinfo 0xa60b35d0)
02-01 13:42:10.963 14925-14942/? D/EGL_emulation: eglMakeCurrent: 0x9cb60b60: ver 2 0 (tinfo 0xa60b35d0)
02-01 13:42:11.480 14925-14925/com.shah.kaushal28.fence I/Choreographer: Skipped 31 frames!  The application may be doing too much work on its main thread.

MainActivity.java 类

package com.shah.kaushal28.fence;

import android.app.PendingIntent;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
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.LocationServices;
import com.google.android.gms.maps.model.LatLng;

import java.util.ArrayList;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        ResultCallback<Status>{

    private static final String TAG = "";
    protected ArrayList<Geofence> mGeofenceList;
    protected GoogleApiClient mGoogleApiClient;
    private Button mAddGeofencesButton;

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

        mAddGeofencesButton = (Button) findViewById(R.id.add_geofences_button);
        // Empty list for storing geofences.
        mGeofenceList = new ArrayList<Geofence>();

        // Get the geofences used. Geofence data is hard coded in this sample.
        populateGeofenceList();

        // Kick off the request to build GoogleApiClient.
        buildGoogleApiClient();

    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        Log.e(TAG, "building client successful");
    }

    public void populateGeofenceList() {
        for (Map.Entry<String, LatLng> entry : Constants.LANDMARKS.entrySet()) {
            mGeofenceList.add(new Geofence.Builder()
                    .setRequestId(entry.getKey())
                    .setCircularRegion(
                            entry.getValue().latitude,
                            entry.getValue().longitude,
                            Constants.GEOFENCE_RADIUS_IN_METERS
                    )
                    .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                            Geofence.GEOFENCE_TRANSITION_EXIT)
                    .build());
        }
        Log.e(TAG, "geofence populated");
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
            mGoogleApiClient.connect();
            Log.e(TAG, "mGoogleApiClient connected");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
            Log.e(TAG, "mGoogleApiClient disconnected");
        }
    }

    @Override
    public void onConnected(Bundle connectionHint) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // Do something with result.getErrorCode());
    }

    @Override
    public void onConnectionSuspended(int cause) {
        mGoogleApiClient.connect();
    }

    public void addGeofencesButtonHandler(View view) {
        if (!mGoogleApiClient.isConnected()) {
            Toast.makeText(this, "Google API Client not connected!", Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            LocationServices.GeofencingApi.addGeofences(
                    mGoogleApiClient,
                    getGeofencingRequest(),
                    getGeofencePendingIntent()
            ).setResultCallback(this); // Result processed in onResult().
        } catch (SecurityException securityException) {
            // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
        }
        Log.e(TAG, "geofence added");

    }

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

    private PendingIntent getGeofencePendingIntent() {
        Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling addgeoFences()
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
    public void onResult(Status status) {
        if (status.isSuccess()) {
            Toast.makeText(
                    this,
                    "Geofences Added",
                    Toast.LENGTH_SHORT
            ).show();
        } else {
            // Get the status code for the error and log it using a user-friendly message.
            System.out.println("Error");
            Toast.makeText(
                    this,
                    "Error",
                    Toast.LENGTH_SHORT
            ).show();
        }
    }
}

GeofenceTransitionsIntentService.java 类

package com.shah.kaushal28.fence;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
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 com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofenceStatusCodes;
import com.google.android.gms.location.GeofencingEvent;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Kaushal28 on 4/26/2017.
 */

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

    public GeofenceTransitionsIntentService() {
        super(TAG);  // use TAG to name the IntentService worker thread
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        GeofencingEvent event = GeofencingEvent.fromIntent(intent);
        if (event.hasError()) {
            Log.e(TAG, "GeofencingEvent Error: " + event.getErrorCode());
            return;
        }
        String description = getGeofenceTransitionDetails(event);
        sendNotification(description);
    }

    private static String getGeofenceTransitionDetails(GeofencingEvent event) {
        String transitionString =
                GeofenceStatusCodes.getStatusCodeString(event.getGeofenceTransition());
        List triggeringIDs = new ArrayList();
        for (Geofence geofence : event.getTriggeringGeofences()) {
            triggeringIDs.add(geofence.getRequestId());
        }
        return String.format("%s: %s", transitionString, TextUtils.join(", ", triggeringIDs));
    }

    private void sendNotification(String notificationDetails) {
        Log.e(TAG, "Notification Triggered");

        // Create an explicit content Intent that starts MainActivity.
        Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);

        // Get a PendingIntent containing the entire back stack.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class).addNextIntent(notificationIntent);
        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.setColor(Color.RED)
                .setContentTitle(notificationDetails)
                .setContentText("Click notification to return to App")
                .setContentIntent(notificationPendingIntent)
                .setAutoCancel(true);

        // Fire and notify the built Notification.
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, builder.build());
    }
}

Constants.java 类

package com.shah.kaushal28.fence;

/**
 * Created by Kaushal28 on 4/26/2017.
 */

import com.google.android.gms.maps.model.LatLng;

import java.util.HashMap;


public class Constants {

    public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = 12 * 60 * 60 * 1000;
    public static final float GEOFENCE_RADIUS_IN_METERS = 20;

    public static final HashMap<String, LatLng> LANDMARKS = new HashMap<String, LatLng>();
    static {
        // San Francisco International Airport.
        LANDMARKS.put("Moscone South", new LatLng(37.783888,-122.4009012));

        // Googleplex.
        LANDMARKS.put("Japantown", new LatLng(37.785281,-122.4296384));

        // Test
        LANDMARKS.put("SFO", new LatLng(37.621313,-122.378955));
    }
}

【问题讨论】:

  • GPS 很大程度上依赖于硬件和位置。很多人坐在他们的电脑前,想知道为什么他们的 GPS 代码没有像他们预期的那样工作。当我在学习这些东西时,我曾经制作 GPS 跟踪应用程序,并让它们在我上班的路上通知我有关地点,你可以看到它的变化非常快。不要依赖地理围栏之类的东西,只需使用它们来增强您的体验
  • 我在安卓模拟器上测试应用会不会是因为它。
  • 用您看到的一些日志记录更新您的问题,以便我们有一个想法
  • 这是我在真机上测试时的日志截图drive.google.com/open?id=10Sn_BgHDKS4E0cH2H8ROAO7z8xlnwgU8
  • 对不起,我应该说 - 为地理围栏添加更多日志记录,并在它不起作用时显示日志 - 即打印出你的 latlong 并显示它确实发生了变化等的东西,跨度>

标签: android geolocation gps geofencing android-geofence


【解决方案1】:

尝试使用更大的半径,然后将其减小到要求 -

查看谷歌文档-https://developer.android.com/training/location/geofencing.html

为您的地理围栏选择最佳半径

为获得最佳效果,地理围栏的最小半径应设置在 100 - 150 米之间。当 Wi-Fi 可用时,定位精度通常在 20 - 50 米之间。当室内定位可用时,精度范围可小至 5 米。除非您知道地理围栏内可以使用室内定位,否则假设 Wi-Fi 定位精度约为 50 米。

当 Wi-Fi 定位不可用时(例如,当您在农村地区开车时),定位精度会降低。精度范围可以大到几百米到几公里。在这种情况下,您应该使用更大的半径创建地理围栏。

【讨论】:

  • 我将它的半径改为 100 但仍然没有得到任何东西
  • 我正在android模拟器上测试应用程序,这可能是因为它。是的,这可能是您直接指定位置的原因,可能是您可以在模拟器中检查 Dwell,但我不确定。用真机试试..
  • 我用真机试了试,也没啥反应。
  • 已经断断续续地工作了好几天。什么狗屁节目。该示例已被弃用,文档使它看起来超级简单,该公司认为他们发明了位置管理的可怕油脂火灾。太可怕了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 2015-06-22
相关资源
最近更新 更多