地理围栏未触发
Posted
技术标签:
【中文标题】地理围栏未触发【英文标题】:Geofence not triggering 【发布时间】:2016-01-01 10:55:34 【问题描述】:我正在尝试在我的 APP 上实现Geofence
,但问题是当我在我标记的地方时没有触发。
我所做的是从Place Picker 设置Latitude
和Longitude
。
我得到的值很好,因为我把它放在 google maps
上,而且这个地方是正确的,因为我读过很多答案,人们从 lat/long 设置了错误的值 em>。
我有两个课程:GeofenceSingleton.class
和 GeofenceTransitionsIntentService
。
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
上添加了<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
我将service
声明为<service android:name=".GeofenceTransitionsIntentService"/>
我在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
请求坐标。
【讨论】:
以上是关于地理围栏未触发的主要内容,如果未能解决你的问题,请参考以下文章