我的服务是使用ActivityRecognition API和LocationListener在用户停止驾驶时保存当前位置。
应用程序打开时工作正常,但在应用程序关闭后我无法保持检测。
这是检测活动和服务的服务。保存位置:
public class ActivityRecognitionService extends IntentService implements LocationListener {
public Location currentBestLocation;
private LocationManager locationManager ;
private String provider;
private String TAG = this.getClass().getSimpleName();
public ActivityRecognitionService() {
super("ActivityRecognitionService");
}
@Override
public void onCreate() {
super.onCreate();
try {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
if (provider != null && !provider.equals("")) {
Location location = locationManager.getLastKnownLocation(provider);
locationManager.requestLocationUpdates(provider, 1000, 1, this);
if (location != null)
onLocationChanged(location);
else
Toast.makeText(this, "Location can't be retrieved", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "No Provider Found", Toast.LENGTH_SHORT).show();
}
} catch(SecurityException e) {
Toast.makeText(this, "Enable location permissions from settings", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onHandleIntent(Intent intent) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Log.i(TAG, "Detected activity being called... ");
// Get the list of the probable activities associated with the current state of the
// device. Each activity is associated with a confidence level, which is an int between
// 0 and 100.
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
for (final DetectedActivity activity : detectedActivities) {
Log.i(TAG, "Detected activity: " + getActivityString(activity.getType()) + ", " + activity.getConfidence());
if(activity.getConfidence() < 60)
continue;
logActivity(getActivityString(activity.getType()), activity.getConfidence());
List<UserActivity> userActivities = UserActivity.listAll(UserActivity.class);
if(!userActivities.isEmpty()) {
UserActivity last = userActivities.get(userActivities.size() - 1);
if(last.activity.equals("in vehicle") && activity.getType() != DetectedActivity.IN_VEHICLE) {
logParking();
}
}
}
}
private void logActivity(String type, int confidence) {
UserActivity ua = new UserActivity(type, confidence, (System.currentTimeMillis() / 1000L));
ua.save();
}
private void logParking() {
Location l = currentBestLocation;
CarLocation cl = new CarLocation(l.getLongitude(), l.getLatitude(), (System.currentTimeMillis() / 1000L));
cl.save();
}
static String getActivityString( int detectedActivityType) {
switch(detectedActivityType) {
case DetectedActivity.IN_VEHICLE:
return "in vehicle";
case DetectedActivity.ON_BICYCLE:
return "on bicycle";
case DetectedActivity.ON_FOOT:
return "on foot";
case DetectedActivity.RUNNING:
return "running";
case DetectedActivity.STILL:
return "still";
case DetectedActivity.TILTING:
return "tilting";
case DetectedActivity.UNKNOWN:
return "unknown";
case DetectedActivity.WALKING:
return "walking";
default:
return "unknown";
}
}
/**
* Only replaces current location if this reading is
* more likely to be accurate
* @param location
* @return
*/
private static final int TWO_MINUTES = 1000 * 60 * 2;
protected boolean isBetterLocation(Location location) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
@Override
public void onLocationChanged(Location location) {
if(isBetterLocation(location)) {
currentBestLocation = location;
}
}
@Override
public void onProviderDisabled(String provider) {
permissionsCheck();
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void permissionsCheck() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// Check Permissions Now
ActivityCompat.requestPermissions(
LocationScene.mActivity,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
0);
}
}
}
此服务用于启动上述服务并使其保持运行:
public class BackgroundDetectedActivitiesService extends Service {
private static final String TAG = BackgroundDetectedActivitiesService.class.getSimpleName();
IBinder mBinder = new BackgroundDetectedActivitiesService.LocalBinder();
private Intent mIntentService;
private PendingIntent mPendingIntent;
private ActivityRecognitionClient mActivityRecognitionClient;
public BackgroundDetectedActivitiesService() {
}
@Override
public void onCreate() {
super.onCreate();
mActivityRecognitionClient = new ActivityRecognitionClient(this);
mIntentService = new Intent(this, uk.co.appoly.wheres_my_car.services.ActivityRecognitionService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);
requestActivityUpdatesButtonHandler();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
public void requestActivityUpdatesButtonHandler() {
Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
20000,
mPendingIntent);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
Toast.makeText(getApplicationContext(),
"Successfully requested activity updates",
Toast.LENGTH_SHORT)
.show();
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(getApplicationContext(),
"Requesting activity updates failed to start",
Toast.LENGTH_SHORT)
.show();
}
});
}
public void removeActivityUpdatesButtonHandler() {
Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
mPendingIntent);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
Toast.makeText(getApplicationContext(),
"Removed activity updates successfully!",
Toast.LENGTH_SHORT)
.show();
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(getApplicationContext(), "Failed to remove activity updates!",
Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
//removeActivityUpdatesButtonHandler();
/**/
}
public class LocalBinder extends Binder {
public BackgroundDetectedActivitiesService getServerInstance() {
return BackgroundDetectedActivitiesService.this;
}
}
}
我的android清单中有这个:
<service
android:name="uk.co.appoly.wheres_my_car.services.ActivityRecognitionService"
android:exported="false" />
<service android:name="uk.co.appoly.wheres_my_car.services.BackgroundDetectedActivitiesService"></service>
(加上正确的权限)
我正在从我的MainActivity启动服务,如下所示:
activityRecognitionClient = ActivityRecognition.getClient(mContext);
transitionIntent = new Intent(MainActivity.this, BackgroundDetectedActivitiesService.class);
startService(transitionIntent);
我一直试图解决这个问题大约一天但无济于事。我究竟做错了什么?