我正在使用jobscheduler获取后台位置更新。但每次计划作业时,fusedLocationProviderClient都为空。为什么?我已经检查了if(fusedlocationproviderclient==null)条件,并且每次调度作业时,它下面的代码都会运行(这意味着fusedlocationproviderclient在初始化后为null)。请查看下面的代码。此外,locationavailability通常为false,因此不会调用onlocationresult来提供空的位置值。如何优化FusedLocationProviderClient。还有一件事,fusedlocationproviderclient总是空的,而locationavailability给出的是假相关的吗?
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.e("onStartJob", "onStartJob");//for debug
jobP = jobParameters;
if (!checkAndRequestPermissions()) {
Toast.makeText(this, "Please provide location permission for paramount app.", Toast.LENGTH_LONG).show();
provider = null;
} else {
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) {
}
if (mLocationRequest == null) {
Log.e("onStartJob", "LocationRequest initialized"); //for debug
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(100 * 1000);
mLocationRequest.setFastestInterval(60 * 1000);
}
if (client == null) {
Log.e("onStartJob", "client initialized"); //for debug
client = LocationServices.getFusedLocationProviderClient(this);
client.requestLocationUpdates(mLocationRequest, new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
Log.e("onLocationResult ", "onLocationResult");
onLocationChanged(locationResult.getLastLocation());
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
Log.e("onLocationAvailability", locationAvailability + "");;
}
},
Looper.myLooper());
}
try {
provider = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE) + "";
gpsProvider = provider;
} catch (Settings.SettingNotFoundException e) {
Log.e("provider", "gps provider error");
}
}
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
Log.e("onStopJob", "onStopJob");//for debug
if (ul != null) {
ul.cancel(true);
}
return true;
}
public void onLocationChanged(Location location) {
latitude = location.getLatitude() + "";
longitude = location.getLongitude() + "";
Log.e("latitude" , latitude);
}
上面代码中的日志值如下所示:
03-15 17:09:25.889 10687-10687/com.myProject.com.jobschedulers E/onStartJob: onStartJob
03-15 17:09:25.900 10687-10687/com.myProject.com.jobschedulers E/onstartJob: client initialized
03-15 17:09:25.957 10687-10687/com.myProject.com.jobschedulers E/onLocationResult: onLocationResult
03-15 17:09:25.960 10687-10687/com.myProject.com.jobschedulers E/onLocationAvailability: LocationAvailability[isLocationAvailable: true]
03-15 17:23:26.975 10687-10687/com.myProject.com.jobschedulers E/onStartJob: onStartJob
03-15 17:23:26.993 10687-10687/com.myProject.com.jobschedulers E/onstartJob: client initialized
03-15 17:23:27.017 10687-10687/com.myProject.com.jobschedulers E/onLocationAvailability: LocationAvailability[isLocationAvailable: false]
03-15 17:41:32.672 10687-10687/com.myProject.com.jobschedulers E/onStartJob: onStartJob
03-15 17:41:32.690 10687-10687/com.myProject.com.jobschedulers E/onstartJob: client initialized
03-15 17:41:32.741 10687-10687/com.myProject.com.jobschedulers E/onLocationAvailability: LocationAvailability[isLocationAvailable: false]
03-15 17:53:17.335 10687-10687/com.myProject.com.jobschedulers E/onStartJob: onStartJob
03-15 17:53:17.351 10687-10687/com.myProject.com.jobschedulers E/onstartJob: client initialized
03-15 17:53:17.383 10687-10687/com.myProject.com.jobschedulers E/onLocationAvailability: LocationAvailability[isLocationAvailable: false]
最佳答案
jobscheduler仅来自21api,考虑使用JobIntentService
从BroadcastReceiver
启动的PendingIntent
从FusedLocationProviderClient.requestLocationUpdates
启动,并从方法启动它。
它将如下所示:
class MainActivity : Activity() {
...
lateinit var mFusedLocationClient:FusedLocationProviderClient
lateinit var mLocationRequestBackground: LocationRequest
fun init {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(activity = this)
mLocationRequestBackground = LocationRequest()
mLocationRequestBackground.interval = UPDATE_INTERVAL_IN_MILLISECONDS_BACKGROUND // i.e. 15 minutes - you hope to get updates at this interval, in background it will be not more than few times per hour on Android Oreo
mLocationRequestBackground.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS_BACKGROUND //i.e. 1 minute - updates will not come faster than this
mLocationRequestBackground.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY //do not overwhelm user's device with requests, but use requests from other apps
mLocationRequestBackground.smallestDisplacement = 25f //distance in meters to trigger update
}
...
fun onStop() {
//start updating in background
mFusedLocationClient.requestLocationUpdates(mLocationRequestBackground,
LocationBroadcastReceiver.getPendingIntent(activity = this))
}
...
}
class LocationBroadcastReceiver : BroadcastReceiver() {
companion object {
const val EXTRA_LATITUDE = "EXTRA_LATITUDE"
const val EXTRA_LONGITUDE = "EXTRA_LONGITUDE"
const val WAKEUP = "com.appid.intent.action.WAKEUP"
fun getPendingIntent(context: Context, userId: String? = null): PendingIntent {
val alarmIntent = Intent(context, LocationBroadcastReceiver::class.java)
alarmIntent.action = WAKEUP
return PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
override fun onReceive(context: Context?, intent: Intent?) {
context ?: return
if (intent?.action != WAKEUP) return
val location: LocationResult? = LocationResult.extractResult(intent)
val loc: Location? = location?.lastLocation
loc?.apply {
val i = Intent(context, SendLocationService::class.java)
i.putExtra(EXTRA_LATITUDE, latitude)
i.putExtra(EXTRA_LONGITUDE, longitude)
SendLocationService.enqueueWork(context, i)
}
}
}
class SendLocationService : JobIntentService() {
companion object {
private const val JOB_ID = 1000
const val TAG = "SendLocationService"
fun enqueueWork(context: Context, work: Intent) {
enqueueWork(context, SendLocationService::class.java, JOB_ID, work)
}
}
private var sending: Boolean = false
override fun onHandleWork(intent: Intent) = runBlocking {
val latitude = intent.getDoubleExtra(LocationBroadcastReceiver.EXTRA_LATITUDE, 0.0)
val longitude = intent.getDoubleExtra(LocationBroadcastReceiver.EXTRA_LONGITUDE, 0.0)
suspendCoroutine<Unit> { continuation ->
YourApi.postMyLocation(lat = latitude, lng = longitude)
.callback { continuation.resume(Unit) }
}
}
override fun onStopCurrentWork(): Boolean {
return !sending
}
}
别忘了将它们添加到清单中
<service android:name=".services.SendLocationService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
<receiver android:name=".services.LocationBroadcastReceiver"
android:exported="false"/>