问题描述
我目前的工作有检查用户的位置,每五分钟发送坐标到服务器的应用程序。我决定去与在谷歌播放服务,而不是普通的旧的LocationManager API的FusedLocation API,主要是因为我注意到在 LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY 优先级,宣称提供以合理的100米精度等级电池的使用,这正是我需要的。
在我的情况,我有一个活动的继承结构是:
公共类MainActivity扩展AppCompatActivity工具
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,LocationListener的
和它实现了相关的回调(onConnected,onConnectionFailed,onConnectionSuspended,onLocationChanged)。我也得到了GoogleApiClient的实例,用这种方法,由官方文档建议:
受保护的同步GoogleApiClient buildGoogleApiClient(){
返回新GoogleApiClient.Builder(本).addConnectionCallbacks(本)
.addOnConnectionFailedListener(本)
.addApi(LocationServices.API).build();
在onConnected,我用启动位置更新
LocationServices.FusedLocationApi.requestLocationUpdates(mApiClient,
mLocationRequest,这一点);
...在onLocationChanged()。捕获的变化
不过,我很快发现,位置更新似乎一段时间后停止。也许是因为这个方法是联系在一起的活动周期,我不知道。反正,我试图通过创建延伸IntentService的内部类,并通过AlarmManager启动它来解决这个问题。因此,在onConnected,我结束了这样:
AlarmManager alarmMan =(AlarmManager)本
.getSystemService(Context.ALARM_SERVICE); 意图updateIntent =新意图(这一点,LocUpService.class); 的PendingIntent pIntent = PendingIntent.getService(这一点,0,updateIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmMan.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,0,
1000 * 60 * 5,pIntent);
该LocUpService类看起来是这样的:
公共静态类LocUpService扩展IntentService { 公共LocUpService(){
超级(LocUpService); } @覆盖
保护无效onHandleIntent(意向意图){
COORDS COORDS = LocationUpdater.getLastKnownLocation(mApiClient);
} }
LocationUpdater是另一个类,它包含静态方法getLastKnownLocation,这是这样的:
公共静态COORDS getLastKnownLocation(GoogleApiClient apiClient){ COORDS COORDS =新COORDS();
地点= LocationServices.FusedLocationApi
.getLastLocation(apiClient); 如果(位置!= NULL){ coords.setLatitude(location.getLatitude());
coords.setLongitude(location.getLongitude()); Log.e(纬度,location.getLatitude()+度);
Log.e(LON,location.getLongitude()+度); }
返回COORDS;
}
但惊喜!我得到抛出:IllegalArgumentException:GoogleApiClient参数是必须的,当我清楚地通过参考静态方法,它再次我想一定有事情做与GoogleApiClient实例与Activity的生命周期以及一些与通过实例到脚麻受到牵连在IntentService。
所以,我在想:我怎么获得常规位置,而要疯了,每五分钟更新?难道我延伸服务,实现该组件的所有接口回调,在那里建立GoogleApiClient实例,并保持它在后台运行?难道我有一个AlarmManager开始延伸IntentService每五分钟就做好了,再有在建IntentService所有相关的回调和GoogleApiClient服务?难道我继续做我在做什么,但现在构建GoogleApiClient作为一个单身,期待它会有所作为?你会怎么做呢?
谢谢,对不起,这是这么啰嗦。
Our app has exactly that same requirement, I implemented that a couple of days ago and here is how I did it.
In the launch activity or wherever you want to start, configure a LocationTracker to run every 5 minutes, using an AlarmManager.
private void startLocationTracker() {
// Configure the LocationTracker's broadcast receiver to run every 5 minutes.
Intent intent = new Intent(this, LocationTracker.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(),
LocationProvider.FIVE_MINUTES, pendingIntent);
}
LocationTracker.java
public class LocationTracker extends BroadcastReceiver {
private PowerManager.WakeLock wakeLock;
@Override
public void onReceive(Context context, Intent intent) {
PowerManager pow = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pow.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wakeLock.acquire();
Location currentLocation = LocationProvider.getInstance().getCurrentLocation();
// Send new location to backend. // this will be different for you
UserService.registerLocation(context, new Handlers.OnRegisterLocationRequestCompleteHandler() {
@Override
public void onSuccess() {
Log.d("success", "UserService.RegisterLocation() succeeded");
wakeLock.release();
}
@Override
public void onFailure(int statusCode, String errorMessage) {
Log.d("error", "UserService.RegisterLocation() failed");
Log.d("error", errorMessage);
wakeLock.release();
}
}, currentLocation);
}
}
LocationProvider.java
public class LocationProvider {
private static LocationProvider instance = null;
private static Context context;
public static final int ONE_MINUTE = 1000 * 60;
public static final int FIVE_MINUTES = ONE_MINUTE * 5;
private static Location currentLocation;
private LocationProvider() {
}
public static LocationProvider getInstance() {
if (instance == null) {
instance = new LocationProvider();
}
return instance;
}
public void configureIfNeeded(Context ctx) {
if (context == null) {
context = ctx;
configureLocationUpdates();
}
}
private void configureLocationUpdates() {
final LocationRequest locationRequest = createLocationRequest();
final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.build();
googleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates(googleApiClient, locationRequest);
}
@Override
public void onConnectionSuspended(int i) {
}
});
googleApiClient.registerConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
});
googleApiClient.connect();
}
private static LocationRequest createLocationRequest() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(FIVE_MINUTES);
return locationRequest;
}
private static void startLocationUpdates(GoogleApiClient client, LocationRequest request) {
LocationServices.FusedLocationApi.requestLocationUpdates(client, request, new com.google.android.gms.location.LocationListener() {
@Override
public void onLocationChanged(Location location) {
currentLocation = location;
}
});
}
public Location getCurrentLocation() {
return currentLocation;
}
}
I first create an instance of the LocationProvider in a class that extends application, creating the instance when the app is launched:
MyApp.java
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
LocationProvider locationProvider = LocationProvider.getInstance();
locationProvider.configureIfNeeded(this);
}
}
The LocationProvider is instantiated and configured for location updates exactly once, because it is a singleton. Every 5 minutes it will update its currentLocation
value, which we can retrieve from anywhere we need with
Location loc = LocationProvider.getInstance().getCurrentLocation();
Running a background service of any kind is not required. The AlarmManager will broadcast to LocationTracker.onReceive() every 5 minutes and the partial wakelock will ensure that the code will finish running even if the device is standby. This is also energy efficient.
Note that you need the following permissions
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- For keeping the LocationTracker alive while it is doing networking -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
and don't forget to register the receiver:
<receiver android:name=".LocationTracker" />
这篇关于如何接收位置更新,每5分钟使用FusedLocation API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!