0

我正在創建一個應用程序,它使用IntentService中的AlarmManagerGoogleAPIClient的幫助下每30分鐘檢查用戶的位置。IntentService中的「GoogleApiClient尚未連接」錯誤

我得到這個錯誤時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.java類:

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()方法放在別的地方?

回答

0

我想我想通了這個問題; mClient需要一段時間才能連接到Google服務,因此連接mClient時必須執行getCurrentLocation()。由於@Maxim Berezovsky的回答,我添加了一個onConnected(Bundle bundle)回調來解決這個問題,但是這引發了另一個問題:onHandleIntent()退出速度比mClient可以連接更快,所以在連接mClient之前服務就會被終止。爲了解決這個問題我在服務中使用此代碼:

@Override 
    public void onDestroy() { 
     if (mClient.isConnected()) 
      mClient.disconnect(); 
     super.onDestroy(); 
    } 

這將確保移動客戶端將不即使服務被殺害斷開。

我不確定這種方法是否耗電,但這是迄今爲止最好的。希望它能幫助別人。

相關問題