簡體   English   中英

應用程序在后台時獲取位置更新

[英]Get Location Update when app is in background

我正在嘗試創建一種服務,該應用專門針對Android 8及更高版本而在后台運行時提供位置更新,因為他們已經優化了后台服務。 我閱讀了關於stackOverflow和Google API文檔的一些答案,他們提到將PendingIntent傳遞給onRequestLocationUpdates會給出位置,即使應用程序在后台也是如此。 正如在文檔中提到的。 這是我的服務班級:

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)

我可以看到您已在onStartCommand() GoogleApiClient實例實例化,並且正如服務生命周期所說,每次啟動服務時都會調用onStartCommand() 因此,每次它實例化您的GoogleApiClient實例時。 我認為這在您的代碼中造成了沖突。 讓我們考慮一種方案來理解問題。

  1. 您已經啟動了一次服務,一秒鍾后又重新啟動了它。 因此,由於您已在onStartCommand()方法中啟動了mLocationClient ,因此它mLocationClient都啟動了。 假設第一個實例的值是mLocationClient1,另一個實例是mLocationClient2。(此值僅是為了簡化說明)。

  2. 成功連接mLocationClient1后,它會觸發onConnected()方法,並且在其中使用了mLocationClient ,該位置由尚未連接的新值mLocationClient2初始化。 因此,它返回未連接googleapiclient的錯誤。

如果您認為您只啟動了一次服務,那么為什么它多次調用onStartCommand()比這是一個答案。 每當您從最近的應用程序列表中刪除應用程序將停止服務,但您已經創建了START_STICKY服務,因此,請重新啟動服務並再次調用onStartCommand()方法。

所以,我建議你instatiate mLocationClientonCreate()方法,而不是onStartCommand()因為onCreate()時服務中創建第一次它的破壞之后方法才會被調用。

我遇到了同樣的問題,請嘗試在Android Studio模擬器(而不是其他模擬器)中運行代碼。 原因是您需要在設備中安裝Google Play服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM