地理围栏不再适用于 JobIntentService
Geofencing doesn't work with JobIntentService anymore
我有一个地理围栏的 IntentService,我只是开始。但它必须在后台 运行,所以在 Android 8 中它有时会被列入白名单。
所以我很难使用 JobIntentService:
https://developer.android.com/reference/android/support/v4/app/JobIntentService
还看了这个:
这是我的 onHandleIntent(),我会在其中接收地理围栏调用:
//HANDLING INTENTS
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent != null) {
int transitionType = geofencingEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
Location triggering = geofencingEvent.getTriggeringLocation();
if (triggering != null) {
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition: " + triggering.getLatitude() + ", " + triggering.getLongitude() + " / accuracy: " + triggering.getAccuracy(), "D", "#updategeo " + Constants.GEOFENCE);
} else
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition null", "D", "#updategeo " + Constants.GEOFENCE);
Utils.appendLog("removing geofence after exit", "I", Constants.TRACKER + "#updategeo");
removeGeofencesAndStartTracking();
}
}
}
这是我的 Intent 服务代码,添加地理围栏逻辑:
//ADDING/REMOVING GEOFENCES
public void addGeofence(final Context context, final Location location, float radius) {
if (!isSettingGeofence) {
isSettingGeofence = true;
ArrayList geofences = new ArrayList<>();
geofences.add(new Geofence.Builder()
.setRequestId(geofenceRequestID)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.setCircularRegion(
location.getLatitude(), location.getLongitude(), radius)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build());
if (geofences.size() > 0) {
if (mGeofencingClient == null)
mGeofencingClient = LocationServices.getGeofencingClient(this);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Utils.appendLog("Geofence Transitions Service addGeofence checkSelfPermission ERROR", "E", Constants.GEOFENCE);
return;
}
Utils.appendLog("addGeofences is being called, wait for success or failure callbacks", "I", Constants.TRACKER + "#updategeo");
mGeofencingClient.addGeofences(getGeofencingRequest(location, geofences), getGeofencePendingIntent(context)).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
PSLocationService.getInstance(context).lastTimeDidExitRegion = null;
isSettingGeofence = false;
final RealmLocation realmLocation = new RealmLocation(location.getLatitude(), location.getLongitude(), location.getTime(), null, true);
Log.i("#geofenceRequestID", "addGeofence geofence realm location: " + realmLocation.getLocation());
final GeofenceRealmLocation geofenceRealmLocation = new GeofenceRealmLocation(geofenceRequestID, realmLocation);
Log.i("#geofenceRequestID", "addGeofence geofence geofence location: " + geofenceRealmLocation.getRealmLocation().getLocation());
realmLocation.setAccuracy(location.getAccuracy());
realmLocation.setSpeed(location.getSpeed());
Log.i("", "GLOBAL intances before addGeofences:" + Realm.getGlobalInstanceCount(PSApplicationClass.Config));
Realm realm = Realm.getInstance(PSApplicationClass.Config);
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(geofenceRealmLocation);
}
});
realm.close();
try {
final NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.cancel(1010);
} catch (Exception e) {
Utils.appendLog("Error removing notification: " + e.getMessage(), "I", Constants.GEOFENCE);
}
Log.i("", "GEOFENCETEST addGeofences SUCCESSS");
Utils.appendLog("Geofence Transitions Service setGeofenceRequest Success adding geofences!" +
location.getLatitude() +
" , " + location.getLongitude() + " / accuracy: " + location.getAccuracy(),
"I",
"#updategeo " + Constants.GEOFENCE);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i("", "GEOFENCETEST addGeofences FAILURE: " + e.getMessage());
isSettingGeofence = false;
try {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!networkEnabled) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
MyFirebaseMessagingService.generateNotificationStandard(context, null, context.getString(R.string.Error) + ": " + context.getString(R.string.geofence_error), null, null, false, false, MyFirebaseMessagingService.NETWORK_ERROR_NOTIFICATION);
}
});
}
} catch (Exception ex) {
Log.e("", "");
// catch Exception
}
Utils.appendLog("Geofence Transitions Service setGeofenceRequest FAILURE adding geofences!" +
e.getMessage(),
"E",
"#updategeo " + Constants.GEOFENCE);
}
});
} else {
Utils.appendLog("Geofence Transitions Service geofences size Error: " + geofences.size(), "E", Constants.GEOFENCE);
}
} else
Utils.appendLog("Geofence Transitions Service setGeofenceRequest is already setting a geofence", "I", Constants.GEOFENCE);
}
现在我改成了JobIntentService。
我运行这样的服务:
Intent bindIntent = new Intent(context, PSGeofenceTransitionsIntentService.class);
enqueueWork(context, bindIntent);
public static final int JOB_ID = 1;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, PSGeofenceTransitionsIntentService.class, JOB_ID, work);
}
我也将此添加到我的 Android 清单中:
<service android:name=".core.tracking.PSGeofenceTransitionsIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
并且我在新的onHandleWork
中处理了onHandleIntent的内容
@Override
protected void onHandleWork(@NonNull Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent != null) {
int transitionType = geofencingEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
Location triggering = geofencingEvent.getTriggeringLocation();
if (triggering != null) {
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition: " + triggering.getLatitude() + ", " + triggering.getLongitude() + " / accuracy: " + triggering.getAccuracy(), "D", "#updategeo " + Constants.GEOFENCE);
} else
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition null", "D", "#updategeo " + Constants.GEOFENCE);
Utils.appendLog("removing geofence after exit", "I", Constants.TRACKER + "#updategeo");
removeGeofencesAndStartTracking();
}
}
}
现在我从 Geofence 获得了 onHandleWork 事件,但只有转换类型 = -1。所以我没有收到 ENTER 或 EXIT 事件。为什么或如何修复此地理围栏服务?
有同样的问题。由于 Android 8 后台工作更受限制。有一种新的调用方式PendingIntent
。您无需将其更改为 JobIntentService
。查看最新的 Android 地理围栏侦听器实施指南:
https://developer.android.com/training/location/geofencing
总之,你只需要用GeofencingClient
调用PendingIntent
。
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
使用上面提供的 link 作为完整示例。
首先,您需要设置广播接收器,在您的 onReceive 方法中,为您的 JobIntentService 排队工作。因此,您不是直接启动 IntentService,而是在 PendingIntent 中调用广播接收器。
我有一个地理围栏的 IntentService,我只是开始。但它必须在后台 运行,所以在 Android 8 中它有时会被列入白名单。
所以我很难使用 JobIntentService:
https://developer.android.com/reference/android/support/v4/app/JobIntentService
还看了这个:
这是我的 onHandleIntent(),我会在其中接收地理围栏调用:
//HANDLING INTENTS
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent != null) {
int transitionType = geofencingEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
Location triggering = geofencingEvent.getTriggeringLocation();
if (triggering != null) {
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition: " + triggering.getLatitude() + ", " + triggering.getLongitude() + " / accuracy: " + triggering.getAccuracy(), "D", "#updategeo " + Constants.GEOFENCE);
} else
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition null", "D", "#updategeo " + Constants.GEOFENCE);
Utils.appendLog("removing geofence after exit", "I", Constants.TRACKER + "#updategeo");
removeGeofencesAndStartTracking();
}
}
}
这是我的 Intent 服务代码,添加地理围栏逻辑:
//ADDING/REMOVING GEOFENCES
public void addGeofence(final Context context, final Location location, float radius) {
if (!isSettingGeofence) {
isSettingGeofence = true;
ArrayList geofences = new ArrayList<>();
geofences.add(new Geofence.Builder()
.setRequestId(geofenceRequestID)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.setCircularRegion(
location.getLatitude(), location.getLongitude(), radius)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build());
if (geofences.size() > 0) {
if (mGeofencingClient == null)
mGeofencingClient = LocationServices.getGeofencingClient(this);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Utils.appendLog("Geofence Transitions Service addGeofence checkSelfPermission ERROR", "E", Constants.GEOFENCE);
return;
}
Utils.appendLog("addGeofences is being called, wait for success or failure callbacks", "I", Constants.TRACKER + "#updategeo");
mGeofencingClient.addGeofences(getGeofencingRequest(location, geofences), getGeofencePendingIntent(context)).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
PSLocationService.getInstance(context).lastTimeDidExitRegion = null;
isSettingGeofence = false;
final RealmLocation realmLocation = new RealmLocation(location.getLatitude(), location.getLongitude(), location.getTime(), null, true);
Log.i("#geofenceRequestID", "addGeofence geofence realm location: " + realmLocation.getLocation());
final GeofenceRealmLocation geofenceRealmLocation = new GeofenceRealmLocation(geofenceRequestID, realmLocation);
Log.i("#geofenceRequestID", "addGeofence geofence geofence location: " + geofenceRealmLocation.getRealmLocation().getLocation());
realmLocation.setAccuracy(location.getAccuracy());
realmLocation.setSpeed(location.getSpeed());
Log.i("", "GLOBAL intances before addGeofences:" + Realm.getGlobalInstanceCount(PSApplicationClass.Config));
Realm realm = Realm.getInstance(PSApplicationClass.Config);
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(geofenceRealmLocation);
}
});
realm.close();
try {
final NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.cancel(1010);
} catch (Exception e) {
Utils.appendLog("Error removing notification: " + e.getMessage(), "I", Constants.GEOFENCE);
}
Log.i("", "GEOFENCETEST addGeofences SUCCESSS");
Utils.appendLog("Geofence Transitions Service setGeofenceRequest Success adding geofences!" +
location.getLatitude() +
" , " + location.getLongitude() + " / accuracy: " + location.getAccuracy(),
"I",
"#updategeo " + Constants.GEOFENCE);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i("", "GEOFENCETEST addGeofences FAILURE: " + e.getMessage());
isSettingGeofence = false;
try {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!networkEnabled) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
MyFirebaseMessagingService.generateNotificationStandard(context, null, context.getString(R.string.Error) + ": " + context.getString(R.string.geofence_error), null, null, false, false, MyFirebaseMessagingService.NETWORK_ERROR_NOTIFICATION);
}
});
}
} catch (Exception ex) {
Log.e("", "");
// catch Exception
}
Utils.appendLog("Geofence Transitions Service setGeofenceRequest FAILURE adding geofences!" +
e.getMessage(),
"E",
"#updategeo " + Constants.GEOFENCE);
}
});
} else {
Utils.appendLog("Geofence Transitions Service geofences size Error: " + geofences.size(), "E", Constants.GEOFENCE);
}
} else
Utils.appendLog("Geofence Transitions Service setGeofenceRequest is already setting a geofence", "I", Constants.GEOFENCE);
}
现在我改成了JobIntentService。
我运行这样的服务:
Intent bindIntent = new Intent(context, PSGeofenceTransitionsIntentService.class);
enqueueWork(context, bindIntent);
public static final int JOB_ID = 1;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, PSGeofenceTransitionsIntentService.class, JOB_ID, work);
}
我也将此添加到我的 Android 清单中:
<service android:name=".core.tracking.PSGeofenceTransitionsIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
并且我在新的onHandleWork
中处理了onHandleIntent的内容 @Override
protected void onHandleWork(@NonNull Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent != null) {
int transitionType = geofencingEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
Location triggering = geofencingEvent.getTriggeringLocation();
if (triggering != null) {
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition: " + triggering.getLatitude() + ", " + triggering.getLongitude() + " / accuracy: " + triggering.getAccuracy(), "D", "#updategeo " + Constants.GEOFENCE);
} else
Utils.appendLog("GEOFENCE onHandleIntent got an EXIT transition null", "D", "#updategeo " + Constants.GEOFENCE);
Utils.appendLog("removing geofence after exit", "I", Constants.TRACKER + "#updategeo");
removeGeofencesAndStartTracking();
}
}
}
现在我从 Geofence 获得了 onHandleWork 事件,但只有转换类型 = -1。所以我没有收到 ENTER 或 EXIT 事件。为什么或如何修复此地理围栏服务?
有同样的问题。由于 Android 8 后台工作更受限制。有一种新的调用方式PendingIntent
。您无需将其更改为 JobIntentService
。查看最新的 Android 地理围栏侦听器实施指南:
https://developer.android.com/training/location/geofencing
总之,你只需要用GeofencingClient
调用PendingIntent
。
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
使用上面提供的 link 作为完整示例。
首先,您需要设置广播接收器,在您的 onReceive 方法中,为您的 JobIntentService 排队工作。因此,您不是直接启动 IntentService,而是在 PendingIntent 中调用广播接收器。