"GoogleApiClient is not connected yet" IntentService 错误
"GoogleApiClient is not connected yet" error in IntentService
我正在创建一个应用程序,它使用 IntentService
中的 AlarmManager
在 GoogleAPIClient
的帮助下每 30 分钟检查一次用户的位置。
当 onHandleIntent()
在我的服务中触发时,我收到此错误:
FATAL EXCEPTION: IntentService[FindLocationService]
Process: ir.imanirt.remindmeathome, PID: 1382
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.internal.zzqb.zzd(Unknown Source)
at com.google.android.gms.internal.zzqf.zzd(Unknown Source)
at com.google.android.gms.internal.zzqd.zzd(Unknown Source)
at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
at ir.imanirt.remindmeathome.FindLocationService.getCurrentLocation(FindLocationService.java:122)
at ir.imanirt.remindmeathome.FindLocationService.onHandleIntent(FindLocationService.java:105)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
这是我的FindLocationService.javaclass:
import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FindLocationService extends IntentService {
private static final String TAG = "FINDLOCATIONSERVICE";
private static final int SERVICE_REQUEST_CODE = 101;
private GoogleApiClient mClient;
private NotificationCompat.Builder mNotificationBuilder;
public FindLocationService() {
super(FindLocationService.class.getName());
}
public static Intent newIntent(Context context) {
return new Intent(context, FindLocationService.class);
}
public static boolean isServiceAlarmOn(Context context) {
Intent i = FindLocationService.newIntent(context);
PendingIntent pendingIntent = PendingIntent
.getService(context, SERVICE_REQUEST_CODE, i, PendingIntent.FLAG_NO_CREATE);
return pendingIntent != null;
}
public static void setServiceAlarm(Context context, boolean isOn) {
final int GPS_TIME = 1000 * 60; //every 1 minute (for the sake of testing)
Intent i = FindLocationService.newIntent(context);
PendingIntent pendingIntent = PendingIntent.getService(context, SERVICE_REQUEST_CODE, i, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (isOn) {
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), GPS_TIME, pendingIntent);
} else {
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
}
}
@Override
public void onDestroy() {
mClient.disconnect();
super.onDestroy();
}
@Override
public void onCreate() {
super.onCreate();
mNotificationBuilder = new NotificationCompat.Builder(this);
mNotificationBuilder.setSmallIcon(android.R.drawable.star_on);
mNotificationBuilder.setContentTitle("Got a Location!!"); //set properties for notification
mClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "Connected to Google location API");
}
@Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG, "Failed to connect to Google API");
}
})
.build();
mClient.connect();
}
@Override
protected void onHandleIntent(Intent intent) {
getCurrentLocation();
}
private void getCurrentLocation() {
LocationRequest request = new LocationRequest();
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
request.setNumUpdates(1);
request.setInterval(0);
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Location permission denied.");
return;
}
//I believe this is the line that causes the error:
LocationServices.FusedLocationApi.requestLocationUpdates(mClient, request, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Got a location fix: " + location);
//Notify user about the new location
mNotificationBuilder.setContentText("Location is " + location);
NotificationManager mNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mNotificationBuilder.build());
}
});
}
}
此外,我的片段中有一个按钮调用 setServiceAlarm
来打开警报管理器。
如错误所示,当 onHandleIntent
启动时,我的 GoogleAPIClient
实例 (mClient
) 未连接。我把mClient.connect()
放在onHandleIntent
里面,还是不行。我不明白为什么?我是否使用了错误的逻辑来编写我的代码?我应该将我的客户端构建器或我的 mClient.connect()
方法放在其他地方吗?
Google 建议在执行任何 GPS 相关 activity 之前检查 GoogleApiClient.isConnected()
。
并执行您的操作 onConnected(Bundle connectionHint)
我想我找到了问题; mClient
需要一些时间来连接到 google 服务,因此 getCurrentLocation()
必须在 mClient
连接时执行。感谢@Maxim Berezovsky 的回答,我添加了一个 onConnected(Bundle bundle)
回调来解决这个问题,但这引发了另一个问题:onHandleIntent()
退出速度快于 mClient
连接速度,因此服务在 mClient
偶数连接。为了解决这个问题,我在服务中使用了这段代码:
@Override
public void onDestroy() {
if (mClient.isConnected())
mClient.disconnect();
super.onDestroy();
}
这将确保即使服务被终止,mClient 也不会断开连接。
我不确定这种方法是否耗电,但这是目前为止最好的方法。希望对大家有帮助。
我正在创建一个应用程序,它使用 IntentService
中的 AlarmManager
在 GoogleAPIClient
的帮助下每 30 分钟检查一次用户的位置。
当 onHandleIntent()
在我的服务中触发时,我收到此错误:
FATAL EXCEPTION: IntentService[FindLocationService]
Process: ir.imanirt.remindmeathome, PID: 1382
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.internal.zzqb.zzd(Unknown Source)
at com.google.android.gms.internal.zzqf.zzd(Unknown Source)
at com.google.android.gms.internal.zzqd.zzd(Unknown Source)
at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
at ir.imanirt.remindmeathome.FindLocationService.getCurrentLocation(FindLocationService.java:122)
at ir.imanirt.remindmeathome.FindLocationService.onHandleIntent(FindLocationService.java:105)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
这是我的FindLocationService.javaclass:
import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FindLocationService extends IntentService {
private static final String TAG = "FINDLOCATIONSERVICE";
private static final int SERVICE_REQUEST_CODE = 101;
private GoogleApiClient mClient;
private NotificationCompat.Builder mNotificationBuilder;
public FindLocationService() {
super(FindLocationService.class.getName());
}
public static Intent newIntent(Context context) {
return new Intent(context, FindLocationService.class);
}
public static boolean isServiceAlarmOn(Context context) {
Intent i = FindLocationService.newIntent(context);
PendingIntent pendingIntent = PendingIntent
.getService(context, SERVICE_REQUEST_CODE, i, PendingIntent.FLAG_NO_CREATE);
return pendingIntent != null;
}
public static void setServiceAlarm(Context context, boolean isOn) {
final int GPS_TIME = 1000 * 60; //every 1 minute (for the sake of testing)
Intent i = FindLocationService.newIntent(context);
PendingIntent pendingIntent = PendingIntent.getService(context, SERVICE_REQUEST_CODE, i, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (isOn) {
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), GPS_TIME, pendingIntent);
} else {
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
}
}
@Override
public void onDestroy() {
mClient.disconnect();
super.onDestroy();
}
@Override
public void onCreate() {
super.onCreate();
mNotificationBuilder = new NotificationCompat.Builder(this);
mNotificationBuilder.setSmallIcon(android.R.drawable.star_on);
mNotificationBuilder.setContentTitle("Got a Location!!"); //set properties for notification
mClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG, "Connected to Google location API");
}
@Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG, "Failed to connect to Google API");
}
})
.build();
mClient.connect();
}
@Override
protected void onHandleIntent(Intent intent) {
getCurrentLocation();
}
private void getCurrentLocation() {
LocationRequest request = new LocationRequest();
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
request.setNumUpdates(1);
request.setInterval(0);
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Location permission denied.");
return;
}
//I believe this is the line that causes the error:
LocationServices.FusedLocationApi.requestLocationUpdates(mClient, request, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Got a location fix: " + location);
//Notify user about the new location
mNotificationBuilder.setContentText("Location is " + location);
NotificationManager mNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mNotificationBuilder.build());
}
});
}
}
此外,我的片段中有一个按钮调用 setServiceAlarm
来打开警报管理器。
如错误所示,当 onHandleIntent
启动时,我的 GoogleAPIClient
实例 (mClient
) 未连接。我把mClient.connect()
放在onHandleIntent
里面,还是不行。我不明白为什么?我是否使用了错误的逻辑来编写我的代码?我应该将我的客户端构建器或我的 mClient.connect()
方法放在其他地方吗?
Google 建议在执行任何 GPS 相关 activity 之前检查 GoogleApiClient.isConnected()
。
并执行您的操作 onConnected(Bundle connectionHint)
我想我找到了问题; mClient
需要一些时间来连接到 google 服务,因此 getCurrentLocation()
必须在 mClient
连接时执行。感谢@Maxim Berezovsky 的回答,我添加了一个 onConnected(Bundle bundle)
回调来解决这个问题,但这引发了另一个问题:onHandleIntent()
退出速度快于 mClient
连接速度,因此服务在 mClient
偶数连接。为了解决这个问题,我在服务中使用了这段代码:
@Override
public void onDestroy() {
if (mClient.isConnected())
mClient.disconnect();
super.onDestroy();
}
这将确保即使服务被终止,mClient 也不会断开连接。
我不确定这种方法是否耗电,但这是目前为止最好的方法。希望对大家有帮助。