地理围栏未触发

Posted

技术标签:

【中文标题】地理围栏未触发【英文标题】:Geofence not triggering 【发布时间】:2016-01-01 10:55:34 【问题描述】:

我正在尝试在我的 APP 上实现Geofence,但问题是当我在我标记的地方时没有触发。

我所做的是从Place Picker 设置LatitudeLongitude

我得到的值很好,因为我把它放在 google maps 上,而且这个地方是正确的,因为我读过很多答案,人们从 lat/long 设置了错误的值 em>。

我有两个课程:GeofenceSingleton.classGeofenceTransitionsIntentService

GeofenceSingleton.class 看起来像:

public class GeofenceSingleton implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> 

private GoogleApiClient googleApiClient;
private static GeofenceSingleton _singleInstance;
private static Context appContext;
private static final String ERR_MSG = "Application Context is not set!! " +
        "Please call GeofenceSngleton.init() with proper application context";
private PendingIntent mGeofencePendingIntent;
private static ArrayList<Geofence> mGeofenceList;


private GeofenceSingleton() 
    if (appContext == null)
        throw new IllegalStateException(ERR_MSG);

    this.googleApiClient = new GoogleApiClient.Builder(this.appContext)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    this.googleApiClient.connect();
    mGeofenceList = new ArrayList<Geofence>();


/**
 * @param applicationContext
 */
public static void init(Context applicationContext) 
    appContext = applicationContext;


public static GeofenceSingleton getInstance() 
    if (_singleInstance == null)
        synchronized (GeofenceSingleton.class) 
            if (_singleInstance == null)
                _singleInstance = new GeofenceSingleton();
        
    return _singleInstance;


@Override
public void onConnected(Bundle bundle) 



@Override
public void onConnectionSuspended(int i) 



@Override
public void onConnectionFailed(ConnectionResult connectionResult) 



public void addGeofence(Location location, String uid) 
    mGeofenceList.add(new Geofence.Builder()
            .setRequestId(uid)
            .setCircularRegion(
                    location.getLatitude(),
                    location.getLongitude(),
                    500
            )
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
            .setExpirationDuration(1000000)
            .build());


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


private PendingIntent getGeofencePendingIntent() 
     // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) 
        return mGeofencePendingIntent;
    
    Intent intent = new Intent(appContext, GeofenceSingleton.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
    // addGeofences() and removeGeofences().
    return PendingIntent.getService(appContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);


public void startGeofencing() 
    if (!googleApiClient.isConnected()) 
        Toast.makeText(appContext, "API client not connected", Toast.LENGTH_SHORT).show();
        return;
    

    LocationServices.GeofencingApi.addGeofences(
            googleApiClient,
     // The GeofenceRequest object.
            getGeofencingRequest(),
    // A pending intent that that is reused when calling removeGeofences(). This
    // pending intent is used to generate an intent when a matched geofence
    // transition is observed.
            getGeofencePendingIntent()
    ).setResultCallback(this); // Result processed in onResult().
    Toast.makeText(appContext,"Geofencing started", Toast.LENGTH_LONG).show();




public void removeGeofence()
    LocationServices.GeofencingApi.removeGeofences(
            googleApiClient,
// This is the same pending intent that was used in addGeofences().
            getGeofencePendingIntent()
    );


@Override
public void onResult(Status status) 
    if (status.isSuccess()) 
// Update state and save in shared preferences.

        Toast.makeText(
                appContext,
                "YO",
                Toast.LENGTH_SHORT
        ).show();
     else 
        Toast.makeText(
                appContext,
                "NOO",
                Toast.LENGTH_SHORT
        ).show();
    


还有GeofenceTransitionsIntentService

public class GeofenceTransitionsIntentService extends IntentService 

private static final String TAG = "Geofence-Service";
private Handler handler;
SharedPreferences sp;
SharedPreferences.Editor editor;
String EmailName, MessageEmail;
Context mContext;
Boolean EmailSent = false;

public GeofenceTransitionsIntentService() 
    super(TAG);


@Override
public void onCreate() 
    super.onCreate();
    this.mContext = this;
    sp = PreferenceManager.getDefaultSharedPreferences(this);
    handler = new Handler();


@Override
protected void onHandleIntent(Intent intent) 

    final GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    if (geofencingEvent.hasError()) 
        Log.e(TAG, "Error in geofencing event");
        return;
    

      // Get the transition type.
    final int geofenceTransition = geofencingEvent.getGeofenceTransition();

      // Test that the reported transition was of interest.
    if (geofenceTransition == 1) 

        handler.post(new Runnable() 
            @Override
            public void run() 
                Toast.makeText(getApplicationContext(), "Entered", Toast.LENGTH_SHORT).show();
                sendNotification();
            
        );
        Log.i(TAG, "Entered");


    

    else 
        // Log the error.
        handler.post(new Runnable() 
            @Override
            public void run() 
                Toast.makeText(getApplicationContext(), "Sorry you are out", Toast.LENGTH_SHORT).show();
            
        );
        Log.e(TAG, String.valueOf(geofenceTransition));
    



private void sendNotification() 
    Toast.makeText(GeofenceTransitionsIntentService.this, "HEEEEEEEY I'M IN", Toast.LENGTH_SHORT).show();




在我的MainActivity 我有这个:

GeofenceSingleton.init(this); //If I don't call this the class doesn't work
this.geofenceSingleton = GeofenceSingleton.getInstance();

然后我如下构建一个Geofence

Location geofence = new Location("");
geofence.setLatitude(Double.parseDouble(latitude));
geofence.setLongitude(Double.parseDouble(longitude));
geofenceSingleton.addGeofence(geofence, GeofenceKey);
geofenceSingleton.startGeofencing();

注意事项

我在manifest.xml 上添加了&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;

我将service 声明为&lt;service android:name=".GeofenceTransitionsIntentService"/&gt;

我在build.gradle 上添加了这一行:compile 'com.google.android.gms:play-services:7.8.0'

它只显示Toast.makeText(appContext,"YO",Toast.LENGTH_SHORT).show();那是因为状态是成功,并且还显示Toast.makeText(appContext,"Geofencing started", Toast.LENGTH_LONG).show();意味着它已经开始了。

问题

为什么我的IntentService 从来没有被调用过?

我在我家的Lat/Long 上测试了它,既然我在上面,它应该被触发,不是吗?

【问题讨论】:

成功了吗?顺便说一句,我用这 3 个文件创建了一个新项目,然后尝试执行它并且它有效,所以我也会为你工作。 也许您没有“进入”该区域,这就是没有事件的原因。创建地理围栏时,您就在里面。为了在您创建区域并且您已经在里面时触发它,您需要这样设置它:builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); 【参考方案1】:

它永远不会起作用,因为你正在做的是

Intent intent = new Intent(appContext, GeofenceSingleton.class);

将意图传递给 GeofenceSingleton ?

你需要做的是

Intent intent = new Intent(appContext, GeofenceTransitionsIntentService.class);

【讨论】:

@Skizo-ozᴉʞS 我可以收到 ENTER NOTIFICATION 但 EXIT NOTIFICATION 没有被解雇 @Skizo-ozᴉʞS 另外,当我给出的半径小于 25 米时,我没有收到 ENTER NOTIFICATION 任何想法为什么它不起作用??? 退出通知不会触发,因为您有 setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER) 您还需要添加 GEOFENCE_TRANSITION_ENTER 以获得退出转换【参考方案2】:

如果您的 Intent 已经使用正确的类构建(请参阅 varunkr's answer),您还需要确保该服务也包含在您的 AndroidManifest.xml 中。

<application
    ...

    <service android:name=".GeofencingTransitionIntentService" />

【讨论】:

【参考方案3】:

确保您的服务和广播接收在清单中启用了这些属性。

  android:enabled="true"
  android:exported="true"

【讨论】:

导出它不需要分配权限吗?【参考方案4】:

正如我已经回答 here 一样,Geofence API 类似于被动位置接收器,即当您需要 Geofence 工作时,您必须同时从 LocationServices.FusedLocationApi.requestLocationUpdates 请求坐标。

【讨论】:

以上是关于地理围栏未触发的主要内容,如果未能解决你的问题,请参考以下文章

在后台某个时间后未触发Android地理围栏?

地理围栏未触发

地理围栏未触发(未决意图和广播接收器)

Android 地理围栏未触发、导致 GPS 活动或调用 IntentService

实施地理围栏 - 在应用程序未运行时接收地理围栏转换事件

没有 requestLocationUpdates 不会触发 Android 地理围栏