[英]Fused location provider with JobScheduler
我在 MainActivity 類中有一個融合的位置提供程序代碼,提供緯度和經度值,它使用persistableBundle 傳遞給 JobService 類。 當用戶使用應用程序時它工作正常(即應用程序在前台)。 一旦應用程序被刷出或銷毀,來自 MainActivity 的最后更新值就會一直通過作業調度程序重復上傳(即作業調度程序始終獲得相同的值,融合位置提供程序不起作用)。 即使應用程序不在前台,我應該怎么做才能使其工作? (PS,當應用最小化時,它可以工作。即它可以在最近的應用列表中看到,但一旦從列表中滑出就會出現問題)
主Activity.class
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// JobScheduler starts
btnStartJob = (Button)findViewById(R.id.startjob);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
btnStartJob.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
PersistableBundle bundle = new PersistableBundle();
bundle.putString("lat", latitude+"");
bundle.putString("lon", longitude+"");
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(10000).
setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).
setRequiresCharging(false).
setRequiresDeviceIdle(false).
setPersisted(true).
setExtras(bundle).
build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
}else{
}
}
});
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
@Override
public void onConnected(Bundle bundle) {
createLocationRequest(bundle);
}
protected void createLocationRequest(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
@Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.e("onLocationResult lat", latitude);
Log.e("onLocationResult Lon", longitude);
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
}
}, null);
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
@Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
Log.i(TAG, "mGoogleApiClient.connect()");
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
MyJobService 類
public class MyJobService extends JobService {
@Override
public boolean onStartJob(JobParameters jobParameters) {
latitude = jobParameters.getExtras().getString("lat");
longitude = jobParameters.getExtras().getString("lon");
Log.e("service1",latitude + "");
Log.e("service2",longitude + "");
return true;
}
}
更新 1:
試圖在 Jobservice 中實現融合位置但不起作用
public class MyJobService extends JobService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
String latitude = null;
String longitude = null;
public MyJobService() {
}
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d("onStart", "onStartJob() :: ");
return false;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"MyJobService.onStopJob()",
Toast.LENGTH_SHORT).show();
return false;
}
//fused location provider starts
private GoogleApiClient mGoogleApiClient;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private LocationRequest mLocationRequest;
private static final String TAG = "zzzz";
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
// GooglePlayServicesUtil.getErrorDialog(resultCode, this,
// PLAY_SERVICES_RESOLUTION_REQUEST).show();
Log.e("GooglePlayServices", resultCode + "");
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
stopSelf();
}
return false;
}
return true;
}
@Override
public void onConnected(Bundle bundle) {
createLocationRequest(bundle);
}
protected void createLocationRequest(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
@Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.e("onLocationResult lat", latitude);
Log.e("onLocationResult Lon", longitude);
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
}
}, null);
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
// fused location provider ends
}
我不知道你是否還在嘗試解決這個問題,但問題是當應用程序被銷毀時,作業調度程序總是得到錯誤的數據(舊數據)。 解決方案可能是在手機上緩沖sqlite數據庫。 因為在銷毀應用程序時不會擦除數據庫,所以您可以將最新的 GPS 數據放入數據庫,然后讓調度程序從那里獲取它。 它應該工作得很好。
請善待,這是我第一次嘗試提供幫助;)
您需要將融合的位置服務邏輯放在作業服務中,因為當您關閉應用程序時,您的位置偵聽器也被破壞,因此當您的應用程序在前台或后台不可用時,您需要在作業服務中獲取新位置,當您的作業服務稱為您決定的時間,您需要實現獲取位置的邏輯,以及更新位置的邏輯,
您可以使用最后一個已知位置來獲取位置。
即使應用程序在后台,也可以使用此服務連續獲取位置。 使用這個類而不是你的Jobscheduler
public class LocationTracker extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener,android.location.LocationListener {
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private LocationRequest mLocationRequest;
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 100; // 100 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 *2; // 1 minute
//Location Request code
private final int REQUEST_LOCATION = 2;
//Location manager for location services
private LocationManager mLocationManager;
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
getLocation();
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(60000*2);// Update location every second
mLocationRequest.setSmallestDisplacement(100);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
createLocationRequest();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
updateProviderLocation(mLastLocation);
}
}
}
@Override
public IBinder onBind(Intent intent) {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
return null;
}
@Override
public void onCreate() {
super.onCreate();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
private void createLocationRequest() {
Log.i("TAG", "CreateLocationRequest");
mLocationRequest = new LocationRequest();
long UPDATE_INTERVAL = 60 * 1000 *2;
mLocationRequest.setInterval(UPDATE_INTERVAL);
long FASTEST_INTERVAL = 10000;
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
//**************************
builder.setAlwaysShow(true); //this is the key ingredient
//**************************
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mGoogleApiClient.connect();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
mGoogleApiClient.disconnect();
stopLocationUpdates();
super.onDestroy();
}
@Override
public void onLocationChanged(Location location) {
//Log.d("Location", location.getLatitude() + "," + location.getLongitude());
try {
if (mLastLocation.getLatitude()!=location.getLatitude()||mLastLocation.getLongitude()!=location.getLongitude()) {
updateProviderLocation(location);
mLastLocation = location;
}
}catch (Exception e){
}
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
private void updateProviderLocation(Location location){
//Upload to your server
}
private void stopLocationUpdates() {
try {
if (mGoogleApiClient.isConnected())
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void getLocation() {
try {
// getting GPS status
Boolean isGPSEnabled = mLocationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
Boolean isNetworkEnabled = mLocationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.e("Location", "No provider enabled");
} else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
if (isGPSEnabled) {
if (mLocationManager != null) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
}
}else if (isNetworkEnabled) {
if (mLocationManager != null) {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
}
}
// if GPS Enabled get lat/long using GPS Services
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
基於更新和以前的答案,我終於能夠讓它工作。
通過調用fusedLocationProvider
到getLastKnownLocation
在我的作業調度的onStartJob。
看下面的代碼
ComponentName jobServiceComponent = new ComponentName(context, LocationJobService.class);
JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(0, jobServiceComponent);
jobInfoBuilder.setPeriodic(Constants.JOB_SERVICE_INTERVAL);
jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
jobInfoBuilder.setRequiresCharging(false);
jobInfoBuilder.setRequiresDeviceIdle(false);
jobInfoBuilder.setPersisted(true);
JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
int resultCode = scheduler.schedule(jobInfoBuilder.build());
並啟動此作業調度程序
@Override
public boolean onStartJob(JobParameters params) {
updateBackgroundLocation(params);
return true;
}
private void updateBackgroundLocation(JobParameters params) {
if (jobCancelled) { return; }
new Thread(new Runnable() {
@Override
public void run() {
updateLocation(params);
}
}).start();
}
private void updateLocation(JobParameters params) {
LocationServices.getFusedLocationProviderClient(getApplicationContext())
.getLastLocation().addOnSuccessListener(location -> {
//perform your update here with last known location.
}).addOnFailureListener(e -> {
e.printStackTrace();
});
jobFinished(params, true);
}
@Override
public boolean onStopJob(JobParameters params) {
jobCancelled = true;
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.