基于设备状态的位置更新
Location Updating on basis of device state
我需要在 ActivityRecognition 检测用户状态(每 3 分钟调用一次)后获取用户的位置(通过 fusedlocation API),例如 IN_VEHICLE、ON_FOOT、运行等
在每个事件中,我需要定期间隔后的用户位置例如:
如果用户还在,则 setInterval(5*60*60*1000);
并检查下一个位置
不早于 5 小时更新。但是 ActivityRecognation 会每 3 分钟调用一次。
如果用户 运行 则 setInterval(2*60*1000);
并在不到 before/After 2 分钟内检查下一次位置更新。但是 ActivityRecognation 会每 3 分钟调用一次。
如果用户 运行 则每 1 分钟发送一次位置信息
如果用户正在驾车,则每 15 分钟发送一次位置信息。
我尝试将 onConnected
中的布尔值 false 设置为 false,并在 class 级别设置为 true。但它总是变成真的,因为整个 Intent 服务在 3 分钟后被调用。
if (startLocationFirst){
requestLocatonSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationAPIclient.connect();// RequestLocation and GoogleAPIClient won't call until device comes from another ActivityRecognation State running,walking etc. And keep Updating location every 5 hours.
}
我目前遇到的问题
- ActivityRecognation 每 3 分钟获取一次用户状态,但它不应进入
startLocationFirst
布尔值,直到它来自另一个 ActivityRecognation 状态并继续更新 startLocationFirst
中设置的位置
这是带有 FusedLocation 的 IntentService
public class Activity_Recognized_Service extends IntentService implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, LocationListener {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public static final String TAG = "###RECOGNISED SRVCE###";
Timer timer;
GoogleApiClient LocationAPIclient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
boolean startLocationFirst=true;
public Activity_Recognized_Service() {
super("Activity_Recognized_Service");
}
public Activity_Recognized_Service(String name) {
super(name);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "On Handle Intent");
if (ActivityRecognitionResult.hasResult(intent)) {
Log.d(TAG, "ActivityRecognition Has Result");
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities(result.getProbableActivities());
Navigation_Drawer nav = new Navigation_Drawer();
nav.UserMovementResult(result);
}
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"On Create Calling");
if (LocationAPIclient == null) {
Log.d(TAG, "Location API is NULL Value Of This ");
LocationAPIclient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
}
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
for (DetectedActivity activity : probableActivities) {
switch (activity.getType()) {
case DetectedActivity.IN_VEHICLE:
Log.d(TAG, "In Vehicle " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("In Vehicle");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(10*60*1000,8*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
if (startLocationFirst){
Log.d(TAG,"Start Location Update For Car");
}
}
break;
case DetectedActivity.ON_BICYCLE:
Log.d(TAG, "On Bicycle " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("On Bicycle");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(7*60*1000,5*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.ON_FOOT:
Log.d(TAG, "On Foot " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("On Foot");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
}
break;
case DetectedActivity.RUNNING:
Log.d(TAG, "On Running " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Running");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.STILL:
Log.d(TAG, "On Still " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Still");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
// requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.TILTING:
Log.d(TAG, "On Tilting " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Tilting");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.WALKING:
Log.d(TAG, "On Walking " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Let's Walk");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
LocationAPIclient.connect();
}
break;
case DetectedActivity.UNKNOWN:
Log.d(TAG, "UnKnown " + activity.getConfidence());
break;
}
}
}
public void setTimer(int Minutes) {
Log.d(TAG, "==================================================");
Log.d(TAG, "Set Timeer Starts It will Run Every " + Minutes);
int MilliSeconds = 60000 * Minutes;
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
//CODE THAT YOU WANT TO EXECUTE AT GIVEN INTERVAL
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, MilliSeconds);
Log.d(TAG, "==================================================");
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "On Connected Running");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(LocationAPIclient);
if (mCurrentLocation!=null){
Log.d(TAG,"Last Known Location Is not Null ");
new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
}
else {
Log.d(TAG,"Last Known Location Is NULL Start Location Updates");
LocationServices.FusedLocationApi.requestLocationUpdates(LocationAPIclient,mLocationRequest,this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"On Location Changed Calling");
mCurrentLocation=location;
new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
Log.d(TAG,"Stopping Location Update");
// LocationServices.FusedLocationApi.removeLocationUpdates(LocationAPIclient,this);
}
public void requestLocatonSetting(int Interval,int FastestInterval,int LocationAccuracy){
mLocationRequest=new LocationRequest();
mLocationRequest.setInterval(Interval);
mLocationRequest.setFastestInterval(FastestInterval);
mLocationRequest.setPriority(LocationAccuracy);
}
}
编辑
这是一个更好的示例,仅使用您在上面提供的代码:
注册 ActivityRecognitionApi 时使用此服务:
public class LocationUpdateService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public static final String TAG = "###RECOGNISED SRVCE###";
private GoogleApiClient apiClient;
private PendingIntent pendingIntent;
private DetectedActivity lastActivity;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
apiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
apiClient.connect();
pendingIntent = PendingIntent.getService(this, 1, new Intent(this, YourIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
Log.d(TAG, "onStartCommand");
if (ActivityRecognitionResult.hasResult(intent)) {
Log.d(TAG, "ActivityRecognition Has Result");
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivity(result);
/* You should really use LocalBroadcastManager to send events out to an activity for UI updates */
// Navigation_Drawer nav = new Navigation_Drawer();
// nav.UserMovementResult(result);
}
return START_STICKY;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "On Connected Running");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
if (location!=null){
Log.d(TAG,"Last Known Location Is not Null ");
Intent intent = new Intent(this, YourIntentService.class).putExtra("lastKnown", location);
startService(intent);
/* No more need for this! */
// new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
}
else {
Log.d(TAG,"Last Known Location Is NULL Start Location Updates");
updateLocationSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY);
// LocationServices.FusedLocationApi.requestLocationUpdates(apiClient,mLocationRequest,this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private void handleDetectedActivity(ActivityRecognitionResult result) {
DetectedActivity mostProbableActivity = result.getMostProbableActivity();
switch (result.getMostProbableActivity().getType()) {
case DetectedActivity.IN_VEHICLE:
// Log.d(TAG, "In Vehicle " + activity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("In Vehicle");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
if (apiClient.isConnected()) {
updateLocationSetting(10 * 60 * 1000, 8 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.ON_BICYCLE:
Log.d(TAG, "On Bicycle " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("On Bicycle");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(7 * 60 * 1000, 5 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.ON_FOOT:
Log.d(TAG, "On Foot " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75) {
DetectedActivity nextHighest = result.getProbableActivities().get(1);
if (nextHighest.getType() == DetectedActivity.RUNNING && nextHighest != lastActivity) {
Log.d(TAG, "On Running " + mostProbableActivity.getConfidence());
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Running");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = nextHighest;
}
}
else if (nextHighest.getConfidence() >= 75 && nextHighest != lastActivity) {
Log.d(TAG, "On Walking " + mostProbableActivity.getConfidence());
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Let's Walk");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = nextHighest;
}
}
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("On Foot");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
}
break;
case DetectedActivity.STILL:
Log.d(TAG, "On Still " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Still");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(5 * 60 * 60 * 1000, 3 * 60 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.TILTING:
Log.d(TAG, "On Tilting " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Tilting");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
// case DetectedActivity.WALKING:
// Log.d(TAG, "On Walking " + mostProbableActivity.getConfidence());
// if (mostProbableActivity.getConfidence() >= 75) {
// //Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Let's Walk");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
//
// if (apiClient.isConnected()) {
// updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
// }
// }
// break;
case DetectedActivity.UNKNOWN:
Log.d(TAG, "UnKnown " + mostProbableActivity.getConfidence());
lastActivity = mostProbableActivity;
break;
}
}
private void updateLocationSetting(int Interval, int FastestInterval, int LocationAccuracy) {
LocationRequest request = new LocationRequest();
request.setInterval(Interval);
request.setFastestInterval(FastestInterval);
request.setPriority(LocationAccuracy);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
//TODO DO SOMETHING HERE!
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, request, pendingIntent);
}
}
这将是要使用的 IntentService,而不是您正在使用的 AsyncTask:
public class YourIntentService extends IntentService {
public YourIntentService() {
super("YOUR_INTENT_SERVICE");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null) {
if (LocationResult.hasResult(intent)) {
LocationResult result = LocationResult.extractResult(intent);
Location location = result.getLastLocation();
Log.d("YourIntentService", "Got new location: " + location);
}
else if (intent.hasExtra("lastKnown")) {
Location location = intent.getParcelableExtra("lastKnown");
Log.d("YourIntentService", "Got last known location: " + location);
}
else if (LocationAvailability.hasLocationAvailability(intent)) {
LocationAvailability locationAvailability = LocationAvailability.extractLocationAvailability(intent);
Log.d("YourIntentService", "Location Availability: " + locationAvailability.isLocationAvailable());
}
}
}
}
只要在 onHandleIntent
.
范围内调用此 Intent 服务就可以处理阻塞的网络请求
我稍微修改了 handleDetectedActivity
代码,这样在每次 activity 更新时,都不会发生新的位置更新。
首先,我不建议您改用 IntentService
the way you are now, as the service will be killed once it exits onHandleIntent
, which would cause a lot of issues since you are relying on callbacks. All of this should be put into a Service
。
至于处理基于 activity 识别的位置更新,我确实找到了这个很好的库,它简化了这个并且非常容易使用。 https://github.com/mrmans0n/smart-location-lib
这是一个示例,说明如何根据 activity 结果使用库进行位置更新。
SmartLocation.with(this).location(new LocationBasedOnActivityProvider(new LocationBasedOnActivityProvider.LocationBasedOnActivityListener() {
@Override
public LocationParams locationParamsForActivity(DetectedActivity detectedActivity) {
if (detectedActivity.getConfidence() >= 75) {
LocationParams.Builder builder = new LocationParams.Builder();
switch (detectedActivity.getType()) {
case DetectedActivity.IN_VEHICLE:
builder.setInterval(/*Interval*/)
.setAccuracy(/*Locaiton Accuracy*/);
break;
case DetectedActivity.ON_BICYCLE:
/* So on and so forth.... */
break;
}
return builder.build();
}
return null;
}
})).start(new OnLocationUpdatedListener() {
@Override
public void onLocationUpdated(Location location) {
//Do what you need here.
}
});
这应该被放入 onStart
函数的 Service
中,onStartCommand
根据您提供的意图额外处理更改。您还可以使用此库获取最后的已知位置,并获得单个修复。
最后一件事,如果您要将上下文传递给它,我建议您远离 AsyncTask
。而是使用 IntentService
,因为 onHandleIntent
函数在后台线程中是 运行,并且您可以使用 IntentService
的上下文来执行您需要的任何任务。当您启动 IntentService
.
时,您可以在意图中将 Location
对象作为额外的对象传递
我在与上面相同的代码中添加几行后执行此代码。
- 首先,我在
IntentService
中的 class 级别声明了 static int,因为 DectectedActivity.getType()
return int。 static int detectedActivity;
- 然后在我检查它是否和上次一样的状态像这样
if (activity.getConfidence() >= 75 && activity.getType()!=detectedActivity)
@Pablo Baxter it.Thanks 给了我某种逻辑 apply.I 在 IntentService
上测试了这个,但我需要在服务上测试它所以我可以更新 locations.Will 马上更新。
我需要在 ActivityRecognition 检测用户状态(每 3 分钟调用一次)后获取用户的位置(通过 fusedlocation API),例如 IN_VEHICLE、ON_FOOT、运行等
在每个事件中,我需要定期间隔后的用户位置例如:
如果用户还在,则 setInterval(5*60*60*1000);
并检查下一个位置
不早于 5 小时更新。但是 ActivityRecognation 会每 3 分钟调用一次。
如果用户 运行 则 setInterval(2*60*1000);
并在不到 before/After 2 分钟内检查下一次位置更新。但是 ActivityRecognation 会每 3 分钟调用一次。
如果用户 运行 则每 1 分钟发送一次位置信息 如果用户正在驾车,则每 15 分钟发送一次位置信息。
我尝试将 onConnected
中的布尔值 false 设置为 false,并在 class 级别设置为 true。但它总是变成真的,因为整个 Intent 服务在 3 分钟后被调用。
if (startLocationFirst){
requestLocatonSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationAPIclient.connect();// RequestLocation and GoogleAPIClient won't call until device comes from another ActivityRecognation State running,walking etc. And keep Updating location every 5 hours.
}
我目前遇到的问题
- ActivityRecognation 每 3 分钟获取一次用户状态,但它不应进入
startLocationFirst
布尔值,直到它来自另一个 ActivityRecognation 状态并继续更新startLocationFirst
中设置的位置
这是带有 FusedLocation 的 IntentService
public class Activity_Recognized_Service extends IntentService implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, LocationListener {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public static final String TAG = "###RECOGNISED SRVCE###";
Timer timer;
GoogleApiClient LocationAPIclient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
boolean startLocationFirst=true;
public Activity_Recognized_Service() {
super("Activity_Recognized_Service");
}
public Activity_Recognized_Service(String name) {
super(name);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "On Handle Intent");
if (ActivityRecognitionResult.hasResult(intent)) {
Log.d(TAG, "ActivityRecognition Has Result");
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities(result.getProbableActivities());
Navigation_Drawer nav = new Navigation_Drawer();
nav.UserMovementResult(result);
}
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"On Create Calling");
if (LocationAPIclient == null) {
Log.d(TAG, "Location API is NULL Value Of This ");
LocationAPIclient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
}
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
for (DetectedActivity activity : probableActivities) {
switch (activity.getType()) {
case DetectedActivity.IN_VEHICLE:
Log.d(TAG, "In Vehicle " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("In Vehicle");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(10*60*1000,8*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
if (startLocationFirst){
Log.d(TAG,"Start Location Update For Car");
}
}
break;
case DetectedActivity.ON_BICYCLE:
Log.d(TAG, "On Bicycle " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("On Bicycle");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(7*60*1000,5*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.ON_FOOT:
Log.d(TAG, "On Foot " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("On Foot");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
}
break;
case DetectedActivity.RUNNING:
Log.d(TAG, "On Running " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Running");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.STILL:
Log.d(TAG, "On Still " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Still");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
// requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.TILTING:
Log.d(TAG, "On Tilting " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Tilting");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
LocationAPIclient.connect();
}
break;
case DetectedActivity.WALKING:
Log.d(TAG, "On Walking " + activity.getConfidence());
if (activity.getConfidence() >= 75) {
//Send Notification To User
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("Let's Walk");
builder.setSmallIcon(R.drawable.elaxer_x);
builder.setContentTitle("Elaxer");
NotificationManagerCompat.from(this).notify(0, builder.build());
requestLocatonSetting(3*60*1000,2*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
LocationAPIclient.connect();
}
break;
case DetectedActivity.UNKNOWN:
Log.d(TAG, "UnKnown " + activity.getConfidence());
break;
}
}
}
public void setTimer(int Minutes) {
Log.d(TAG, "==================================================");
Log.d(TAG, "Set Timeer Starts It will Run Every " + Minutes);
int MilliSeconds = 60000 * Minutes;
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
//CODE THAT YOU WANT TO EXECUTE AT GIVEN INTERVAL
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, MilliSeconds);
Log.d(TAG, "==================================================");
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "On Connected Running");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(LocationAPIclient);
if (mCurrentLocation!=null){
Log.d(TAG,"Last Known Location Is not Null ");
new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
}
else {
Log.d(TAG,"Last Known Location Is NULL Start Location Updates");
LocationServices.FusedLocationApi.requestLocationUpdates(LocationAPIclient,mLocationRequest,this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"On Location Changed Calling");
mCurrentLocation=location;
new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
Log.d(TAG,"Stopping Location Update");
// LocationServices.FusedLocationApi.removeLocationUpdates(LocationAPIclient,this);
}
public void requestLocatonSetting(int Interval,int FastestInterval,int LocationAccuracy){
mLocationRequest=new LocationRequest();
mLocationRequest.setInterval(Interval);
mLocationRequest.setFastestInterval(FastestInterval);
mLocationRequest.setPriority(LocationAccuracy);
}
}
编辑
这是一个更好的示例,仅使用您在上面提供的代码:
注册 ActivityRecognitionApi 时使用此服务:
public class LocationUpdateService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public static final String TAG = "###RECOGNISED SRVCE###";
private GoogleApiClient apiClient;
private PendingIntent pendingIntent;
private DetectedActivity lastActivity;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
apiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
apiClient.connect();
pendingIntent = PendingIntent.getService(this, 1, new Intent(this, YourIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
Log.d(TAG, "onStartCommand");
if (ActivityRecognitionResult.hasResult(intent)) {
Log.d(TAG, "ActivityRecognition Has Result");
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivity(result);
/* You should really use LocalBroadcastManager to send events out to an activity for UI updates */
// Navigation_Drawer nav = new Navigation_Drawer();
// nav.UserMovementResult(result);
}
return START_STICKY;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "On Connected Running");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
if (location!=null){
Log.d(TAG,"Last Known Location Is not Null ");
Intent intent = new Intent(this, YourIntentService.class).putExtra("lastKnown", location);
startService(intent);
/* No more need for this! */
// new Location_sendeToServer_AsyncTask(this).execute(String.valueOf(mCurrentLocation.getLatitude()),String.valueOf(mCurrentLocation.getLongitude()),String.valueOf(mCurrentLocation.getAccuracy()));
}
else {
Log.d(TAG,"Last Known Location Is NULL Start Location Updates");
updateLocationSetting(5*60*60*1000,3*60*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY);
// LocationServices.FusedLocationApi.requestLocationUpdates(apiClient,mLocationRequest,this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private void handleDetectedActivity(ActivityRecognitionResult result) {
DetectedActivity mostProbableActivity = result.getMostProbableActivity();
switch (result.getMostProbableActivity().getType()) {
case DetectedActivity.IN_VEHICLE:
// Log.d(TAG, "In Vehicle " + activity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("In Vehicle");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
//requestLocatonSetting(6*60*1000,6*60*1000,LocationRequest.PRIORITY_HIGH_ACCURACY); //TEST
if (apiClient.isConnected()) {
updateLocationSetting(10 * 60 * 1000, 8 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.ON_BICYCLE:
Log.d(TAG, "On Bicycle " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("On Bicycle");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(7 * 60 * 1000, 5 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.ON_FOOT:
Log.d(TAG, "On Foot " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75) {
DetectedActivity nextHighest = result.getProbableActivities().get(1);
if (nextHighest.getType() == DetectedActivity.RUNNING && nextHighest != lastActivity) {
Log.d(TAG, "On Running " + mostProbableActivity.getConfidence());
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Running");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = nextHighest;
}
}
else if (nextHighest.getConfidence() >= 75 && nextHighest != lastActivity) {
Log.d(TAG, "On Walking " + mostProbableActivity.getConfidence());
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Let's Walk");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = nextHighest;
}
}
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("On Foot");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
}
break;
case DetectedActivity.STILL:
Log.d(TAG, "On Still " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Still");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(5 * 60 * 60 * 1000, 3 * 60 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
case DetectedActivity.TILTING:
Log.d(TAG, "On Tilting " + mostProbableActivity.getConfidence());
if (mostProbableActivity.getConfidence() >= 75 && mostProbableActivity != lastActivity) {
//Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Tilting");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
if (apiClient.isConnected()) {
updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
lastActivity = mostProbableActivity;
}
}
break;
// case DetectedActivity.WALKING:
// Log.d(TAG, "On Walking " + mostProbableActivity.getConfidence());
// if (mostProbableActivity.getConfidence() >= 75) {
// //Send Notification To User
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// builder.setContentText("Let's Walk");
// builder.setSmallIcon(R.drawable.elaxer_x);
// builder.setContentTitle("Elaxer");
// NotificationManagerCompat.from(this).notify(0, builder.build());
//
// if (apiClient.isConnected()) {
// updateLocationSetting(3 * 60 * 1000, 2 * 60 * 1000, LocationRequest.PRIORITY_HIGH_ACCURACY); //5 hours= hours * 60 min*60 sec* 1000 milliseconds
// }
// }
// break;
case DetectedActivity.UNKNOWN:
Log.d(TAG, "UnKnown " + mostProbableActivity.getConfidence());
lastActivity = mostProbableActivity;
break;
}
}
private void updateLocationSetting(int Interval, int FastestInterval, int LocationAccuracy) {
LocationRequest request = new LocationRequest();
request.setInterval(Interval);
request.setFastestInterval(FastestInterval);
request.setPriority(LocationAccuracy);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
//TODO DO SOMETHING HERE!
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, request, pendingIntent);
}
}
这将是要使用的 IntentService,而不是您正在使用的 AsyncTask:
public class YourIntentService extends IntentService {
public YourIntentService() {
super("YOUR_INTENT_SERVICE");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null) {
if (LocationResult.hasResult(intent)) {
LocationResult result = LocationResult.extractResult(intent);
Location location = result.getLastLocation();
Log.d("YourIntentService", "Got new location: " + location);
}
else if (intent.hasExtra("lastKnown")) {
Location location = intent.getParcelableExtra("lastKnown");
Log.d("YourIntentService", "Got last known location: " + location);
}
else if (LocationAvailability.hasLocationAvailability(intent)) {
LocationAvailability locationAvailability = LocationAvailability.extractLocationAvailability(intent);
Log.d("YourIntentService", "Location Availability: " + locationAvailability.isLocationAvailable());
}
}
}
}
只要在 onHandleIntent
.
我稍微修改了 handleDetectedActivity
代码,这样在每次 activity 更新时,都不会发生新的位置更新。
首先,我不建议您改用 IntentService
the way you are now, as the service will be killed once it exits onHandleIntent
, which would cause a lot of issues since you are relying on callbacks. All of this should be put into a Service
。
至于处理基于 activity 识别的位置更新,我确实找到了这个很好的库,它简化了这个并且非常容易使用。 https://github.com/mrmans0n/smart-location-lib
这是一个示例,说明如何根据 activity 结果使用库进行位置更新。
SmartLocation.with(this).location(new LocationBasedOnActivityProvider(new LocationBasedOnActivityProvider.LocationBasedOnActivityListener() {
@Override
public LocationParams locationParamsForActivity(DetectedActivity detectedActivity) {
if (detectedActivity.getConfidence() >= 75) {
LocationParams.Builder builder = new LocationParams.Builder();
switch (detectedActivity.getType()) {
case DetectedActivity.IN_VEHICLE:
builder.setInterval(/*Interval*/)
.setAccuracy(/*Locaiton Accuracy*/);
break;
case DetectedActivity.ON_BICYCLE:
/* So on and so forth.... */
break;
}
return builder.build();
}
return null;
}
})).start(new OnLocationUpdatedListener() {
@Override
public void onLocationUpdated(Location location) {
//Do what you need here.
}
});
这应该被放入 onStart
函数的 Service
中,onStartCommand
根据您提供的意图额外处理更改。您还可以使用此库获取最后的已知位置,并获得单个修复。
最后一件事,如果您要将上下文传递给它,我建议您远离 AsyncTask
。而是使用 IntentService
,因为 onHandleIntent
函数在后台线程中是 运行,并且您可以使用 IntentService
的上下文来执行您需要的任何任务。当您启动 IntentService
.
Location
对象作为额外的对象传递
我在与上面相同的代码中添加几行后执行此代码。
- 首先,我在
IntentService
中的 class 级别声明了 static int,因为DectectedActivity.getType()
return int。static int detectedActivity;
- 然后在我检查它是否和上次一样的状态像这样
if (activity.getConfidence() >= 75 && activity.getType()!=detectedActivity)
@Pablo Baxter it.Thanks 给了我某种逻辑 apply.I 在 IntentService
上测试了这个,但我需要在服务上测试它所以我可以更新 locations.Will 马上更新。