我正在尝试创建一项服务,该应用程序在应用程序处于专用于Android 8及更高版本的后台时提供位置更新,因为它们已优化后台服务。我在stackOverflow和Google API doc上阅读了一些答案,他们提到将PendingIntent传递给onRequestLocationUpdates即使在app处于后台时也会给出位置。正如doc中提到的那样。这是我的服务类:
public class LocationMonitoringService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = LocationMonitoringService.class.getSimpleName();
GoogleApiClient mLocationClient;
LocationRequest mLocationRequest = new LocationRequest();
public static final String ACTION_LOCATION_BROADCAST = LocationMonitoringService.class.getName() + "LocationBroadcast";
public static final String EXTRA_LATITUDE = "extra_latitude";
public static final String EXTRA_LONGITUDE = "extra_longitude";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mLocationClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest.setInterval(Constants.LOCATION_INTERVAL);
mLocationRequest.setFastestInterval(Constants.FASTEST_LOCATION_INTERVAL);
int priority = LocationRequest.PRIORITY_HIGH_ACCURACY; //by default
//PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER are the other priority modes
mLocationRequest.setPriority(priority);
mLocationClient.connect();
//Make it stick to the notification panel so it is less prone to get cancelled by the Operating System.
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/*
* LOCATION CALLBACKS
*/
@Override
public void onConnected(Bundle dataBundle) {
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.
Log.d(TAG, "== Error On onConnected() Permission not granted");
//Permission not granted by user so cancel the further execution.
return;
}
Intent intent = new Intent(this, LocationMonitoringService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, pendingIntent);
Log.d(TAG, "Connected to Google API");
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "Connection suspended");
}
//to get the location change
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Location changed");
if (location != null) {
Log.d(TAG, "== location != null");
//Send result to activities
sendMessageToUI(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
}
}
private void sendMessageToUI(String lat, String lng) {
Log.d(TAG, "Sending info...");
Intent intent = new Intent(ACTION_LOCATION_BROADCAST);
intent.putExtra(EXTRA_LATITUDE, lat);
intent.putExtra(EXTRA_LONGITUDE, lng);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Failed to connect to Google API");
}
}
在上面的代码中,当我将PendingIntent传递给requestLocationUpdates时,它向我抛出一个错误的GoogleAPIClient未连接。
以下是我得到的错误
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.internal.zzbcd.zze(Unknown Source)
at com.google.android.gms.internal.zzbcx.zze(Unknown Source)
at com.google.android.gms.internal.zzbcp.zze(Unknown Source)
at com.google.android.gms.internal.zzccb.requestLocationUpdates(Unknown Source)
at com.locationtracker.LocationMonitoringService.onConnected(LocationMonitoringService.java:93)
at com.google.android.gms.common.internal.zzac.zzn(Unknown Source)
at com.google.android.gms.internal.zzbcp.zzm(Unknown Source)
at com.google.android.gms.internal.zzbcd.zzpY(Unknown Source)
at com.google.android.gms.internal.zzbcd.onConnected(Unknown Source)
at com.google.android.gms.internal.zzbcx.onConnected(Unknown Source)
at com.google.android.gms.internal.zzbbi.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzaa.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzn.zzrj(Unknown Source)
at com.google.android.gms.common.internal.zze.zzs(Unknown Source)
at com.google.android.gms.common.internal.zzi.zzrk(Unknown Source)
at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5461)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
答案 0 :(得分:0)
我可以看到您已在GoogleApiClient
中设置了onStartCommand()
个实例,并且正如服务生命周期所说,每次启动服务时都会调用onStartCommand()
。因此,每次实例化您的GoogleApiClient实例。
我认为这会在您的代码中产生冲突。让我们考虑一个理解问题的场景。
您已经开始服务一次,一秒钟之后又重新开始服务。因此,它会同时启动mLocationClient
,因为您已在onStartCommand()方法中启动它。假设第一个实例的值为mLocationClient1,而另一个实例的值为mLocationClient2。(这个值只是为了简化说明)。
成功连接mLocationClient1
后,它会触发onConnected()方法,并在其中使用mLocationClient
,它由尚未连接的新值mLocationClient2
初始化。因此,它返回了googleapiclient未连接的错误。
如果您认为自己只启动了一次服务,那么它为什么多次调用onStartCommand()是一个答案。每当您从最近的应用程序列表中删除您的应用程序时,将停止您的服务,但您已创建START_STICKY
服务,因此,重新启动您的服务并再次调用onStartCommand()方法。
因此,我建议您在mLocationClient
方法而不是onCreate()
中设置onStartCommand()
,因为只有在第一次创建服务后才会调用onCreate()
方法&#39被毁坏了。
答案 1 :(得分:-1)
我遇到了同样的问题,尝试在Android Studio模拟器中运行代码,而不是其他模拟器。因此,您需要在设备中安装Google Play服务。