Получить обновление местоположения, когда приложение находится в фоновом режиме - PullRequest
0 голосов
/ 24 апреля 2018

Я пытаюсь создать сервис, который выдает обновления местоположения, когда приложение работает в фоновом режиме, специально для 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)

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

Я вижу, что вы установили свой экземпляр GoogleApiClient в onStartCommand(), и, как говорится в жизненном цикле службы, onStartCommand() будет вызываться каждый раз, когда вы запускаете службу.Таким образом, каждый раз, когда он устанавливает ваш экземпляр GoogleApiClient.Я думаю, что это создает конфликт в вашем коде.Давайте рассмотрим сценарий для понимания проблемы.

  1. Вы запустили свой сервис один раз, а через секунду вы запустили его снова.Таким образом, он инициирует mLocationClient оба раза, потому что вы инициировали его в методе onStartCommand ().предположим, что 1-й экземпляр имеет значение mLocationClient1, а другой - mLocationClient2. (Эти значения приведены только для простоты объяснения).

  2. После успешного подключения mLocationClient1 он запускает метод onConnected () и внутри него выиспользовали mLocationClient, которое инициализируется новым значением mLocationClient2, которое еще не подключено.Следовательно, он возвращает ошибку о том, что googleapiclient не подключен.

Если вы считаете, что запустили свой сервис только один раз, то почему он вызывает onStartCommand () несколько раз, чем здесь, это ответ.всякий раз, когда вы удаляете свое приложение из списка недавних приложений, оно останавливает вашу службу, но вы создали службу START_STICKY, поэтому перезапустите службу и снова вызовите метод onStartCommand ().

Итак, я предлагаю вам установить *Метод 1023 * in onCreate() вместо onStartCommand(), поскольку метод onCreate() будет вызываться только при первом создании службы после ее уничтожения.

0 голосов
/ 24 апреля 2018

У меня была такая же проблема, попробуйте запустить код в Android Studio Emulator, а не в других эмуляторах. Причина в том, что вам нужно иметь сервисы Google Play на вашем устройстве.

...