当前位置: 首页 > 知识库问答 >
问题:

使用google play服务和FusedLocationProviderClient进行位置更新

鲍宁
2023-03-14

我想使用最新的融合位置提供商客户端在“后台服务”上获取位置更新。我不想使用所有人都在使用的位置侦听器和Google API客户端。我还需要使用google play服务提供的位置设置Api来检查该“后台服务”上的位置设置是禁用还是启用。请帮忙。

共有3个答案

宦源
2023-03-14

您可以像这样扩展服务类

public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener

你可以在这里查看完整的源代码BackgroundLocationService。JAVA

对于启用位置设置

   private void displayLocationSettingsRequest() {
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API).build();
    googleApiClient.connect();

    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(10000 / 2);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
    builder.setAlwaysShow(true);

    PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(@NonNull LocationSettingsResult result) {
            final Status status = result.getStatus();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:

                    try {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        status.startResolutionForResult(context, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException ignored) {
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    break;
            }
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
   // Check for the integer request code originally supplied to 
    startResolutionForResult().
        case REQUEST_CHECK_SETTINGS:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    //startLocationUpdates();
                    break;
                case Activity.RESULT_CANCELED:
                    displayLocationSettingsRequest();//keep asking
                    showToast("Location permission needed");
                    break;
            }
            break;
    }
}

您可以从服务中检查位置设置,如果位置关闭,

LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
  boolean gps_enabled = false;
      boolean network_enabled = false;

   try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
 } catch(Exception ex) {}

   try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
  } catch(Exception ex) {}

   if(!gps_enabled && !network_enabled) {
// notify user
 // Either you can display a Notification(Recommended way) or you can show dialog with 

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//It needs SYSTEM_ALERT_WINDOW permission. Add this permission in Manifest.

   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>     

 }
杜高谊
2023-03-14

您可以编写intentService的代码,如下所示。有人认为,由于它在后台运行,我们不会显示权限对话框。

public class GetLocationService extends IntentService
    implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static String TAG = GetLocationService.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;


public GetLocationService() {
    super(TAG);
}

/**
 * Creates an IntentService.  Invoked by your subclass's constructor.
 *
 * @param name Used to name the worker thread, important only for debugging.
 */
public GetLocationService(String name) {
    super(name);
}

@Override
protected void onHandleIntent(Intent intent) {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        Log.d(TAG, "disconnecting");
        mGoogleApiClient.disconnect();
    }
    Log.d(TAG, "onHandleIntent");
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    mGoogleApiClient.connect();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    LocationRequest locationRequestLow = LocationRequest.create();
    locationRequestLow.setPriority(LocationRequest.PRIORITY_LOW_POWER);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_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.
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
    } else {
        Log.d(TAG, "permission denied");
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
public void onLocationChanged(Location location) {
    Log.d(TAG, location.toString());    
}

}

虞高雅
2023-03-14

如果我们需要使用fusion location api,那么我们需要使用Google api client,对于后台服务来说,使用它不是一个问题,下面是我在后台获取位置更新时使用的示例,但还有一件事,因为Google从6.0引入了“DOZE”模式,所以当您的设备处于“DOZE”模式时,我无法提供surety give更新,

import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
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;

/**
 * Created By Dhaval Solanki
 */

public class ConnectionService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    String TAG = "ConnectionService";


    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private Location previousLocation;
    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;


    private Location mLastLocation;
    private Context context;

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "onBind");
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = getApplicationContext();
        Log.i(TAG, "onStartCommand");
        if (checkPermsion(context)) {
            setupLocationService(context);
        }
        return Service.START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationCLass.isServiceRunning = true;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "onUnbind");
        ApplicationCLass.isServiceRunning = false;
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        ApplicationCLass.isServiceRunning = false;
        super.onDestroy();
    }

    private void setupLocationService(Context context) {
        if (checkPlayServices()) {
            mGoogleApiClient = new GoogleApiClient.Builder(context)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
            createLocationRequest();
        }
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest().create();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mGoogleApiClient.connect();
    }

    public boolean checkPermsion(Context context) {
        int MyVersion = Build.VERSION.SDK_INT;
        if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return false;
            } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }

    private boolean checkPlayServices() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(this);
        if (result != ConnectionResult.SUCCESS) {
            return false;
        }
        return true;
    }


    private void startLocationUpdates() {
        if (mGoogleApiClient.isConnected()) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            if (Prefs.getUserLat(context).trim().length() > 0 && Prefs.getUserLong(context).trim().length() > 0) {
            } else {
                mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                        mGoogleApiClient);
                if (mLastLocation != null) {
                    Prefs.setUserLat(context, String.valueOf(mLastLocation.getLatitude()));
                    Prefs.setUserLong(context, String.valueOf(mLastLocation.getLongitude()));
                }
            }
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.i(TAG, "Connected to onConnected");
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connected to onConnectionSuspended");
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.i(TAG, "Connected to onConnectionFailed");
    }

    @Override
    public void onLocationChanged(Location location) {
        try {
            Logger.print("onLocationChanged", "latitued :" + location.getLatitude() + " ,, Longitude " + location.getLongitude());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}

另一个alaram服务是否继续运行

import android.app.ActivityManager;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AlarmService extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        boolean isServiceRunning = false;
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (ConnectionService.class.getName().equals(service.service.getClassName())) {
                isServiceRunning = true;
                break;
            }
        }
        Log.i("AlarmService", "Service is running " + isServiceRunning);
        if(!isServiceRunning) {
            startService(new Intent(getApplicationContext(),ConnectionService.class));
        } else {
            ConnectionService.checkConnectionAndConnect(getApplicationContext());
        }
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public AlarmService() {
        super("AlaramService");
    }
}

终于开启服务

private void checkAndStartService() {
        final ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        new AsyncTask<Void, Void, Boolean>() {
            boolean isServiceRunning = false;

            @Override
            protected Boolean doInBackground(Void... params) {
                for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
                    if (ConnectionService.class.getName().equals(service.service.getClassName())) {
                        isServiceRunning = true;
                        break;
                    }
                }
                return isServiceRunning;
            }

            @Override
            protected void onPostExecute(Boolean aBoolean) {
                super.onPostExecute(aBoolean);
                Log.i("onPostExecute", "Service running = " + aBoolean);
                if (!aBoolean) {
                    startService(new Intent(ActivitySplash.this, ConnectionService.class));
                    Intent i = new Intent(ActivitySplash.this, AlarmService.class);
                    PendingIntent pi = PendingIntent.getService(ActivitySplash.this, 0, i, 0);
                    AlarmManager am = (AlarmManager) ActivitySplash.this.getSystemService(Context.ALARM_SERVICE);
                    am.cancel(pi); // cancel any existing alarms
                    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pi);
                }
            }
        }.execute();
    }
 类似资料:
  • 随着被弃用,我很难使用在单击按钮后仅一次获得用户的位置。

  • 我需要每1分钟和每5米位移更新一次熔合位置(我知道这是一个错误的做法,但为了测试和在日志中显示),并且我在按下按钮后立即启动服务,我在logcat中获得位置,但只有一次。根据服务级别,onLocationChanged应该每1分钟调用一次,但它不会再次调用,即使我的GPS几乎每分钟打开一次,然后在之后关闭,但Logcat中仍然没有位置更新。我需要服务类来保持更新位置,而不影响UI或主线程 这是只显

  • 我想在我的LibGDX Android游戏中使用Google Play Game Services API的成就和排行榜。我所做的唯一一件事就是从游戏服务开发者网站上获取运行的示例。我已经尝试在我的项目中使用这段代码很多天了,但仍然一无所获。我也尝试过学习本教程http://helios.hud.ac.uk/u1070589/blog/?p=202但我没有“主游戏类(从ApplicationLis

  • 在我的应用程序中,我通过单击按钮将FusedLocationProviderClient的坐标存储到数据库中。问题是,当我重新启动手机或模拟器时,为空,我必须再次单击我订购的按钮才能使其工作。如果是否为空? 在我的按钮处理程序中,我调用,并使用纬度、经度和精度存储到数据库中。 任何帮助赞赏!

  • 当接近传感器被激活时,我使用FusedLocationProviderClient来获取设备位置。当用户接近接近传感器时,程序应该得到设备的位置,但是它没有得到必要的代码,因为我认为它卡在. isSucessful()if语句上。

  • 大约两周前,我们的应用程序的几个区域随机停止工作,特别是那些依赖最新位置的区域。这发生在多个设备上,包括真实设备和模拟器。在此之前,它每次都在工作。对我们来说幸运的是,所有停止工作的东西都隐藏在一面旗帜后面,我们能够在生产中禁用它。 我们的位置包装器代码两年来几乎没有被触碰过,在最近唯一一次更改(这是微不足道的)后,它在一个月内运行良好。换句话说,两年来它一直在毫无问题地工作。下面是一些片段。 现