Android RequestLocationUpdate在精确的固定时间间隔后更新
目标:在精确15分钟后将当前服务位置保存到数据库中(使用较少的电池)。我在应用程序中的各个点使用这些位置Android RequestLocationUpdate在精确的固定时间间隔后更新,android,gps,location,location-client,Android,Gps,Location,Location Client,目标:在精确15分钟后将当前服务位置保存到数据库中(使用较少的电池)。我在应用程序中的各个点使用这些位置 locationrequest = LocationRequest.create(); locationrequest.setInterval(5*60000); locationrequest .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); locationcli
locationrequest = LocationRequest.create();
locationrequest.setInterval(5*60000);
locationrequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
问题:我使用的上述代码没有根据设置的间隔值请求位置。尽管如此,我知道这个间隔是不精确的。您可能根本接收不到更新,或者接收更新的速度可能比请求的慢。您也可能会比要求的更快收到它们。有时,位置会在1分钟后更新,我不想浪费处理和电池来获得小间隔的位置
public class LoginActivity extends Activity implements OnClickListener
,
GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_screen);
///my code
mIntentService = new Intent(LoginActivity.this,LocationService.class);
mIntentService.putExtra("time",String.valueOf(System.currentTimeMillis()) );
mPendingIntent = PendingIntent.getService(LoginActivity.this, 1, mIntentService, 0);
int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resp == ConnectionResult.SUCCESS){
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
else{
Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();
}
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
@Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
Log.i("fused", " onConnected " );
// mIntentService = new Intent(LoginActivity.this,LocationService.class);
// mPendingIntent = PendingIntent.getService(LoginActivity.this, 1, mIntentService, 0);
locationrequest = LocationRequest.create();
locationrequest.setInterval(5*60000);
// locationrequest
// .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
// locationrequest = LocationRequest.create();
// locationrequest.setInterval(1000);//??
// locationclient.requestLocationUpdates(locationrequest, this);
}
@Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
}
定位服务
public class LocationService extends IntentService {
private String TAG = this.getClass().getSimpleName();
public LocationService() {
super("Fused Location");
}
public LocationService(String name) {
super("Fused Location");
}
@Override
protected void onHandleIntent(Intent intent) {
// Log.i("fused", "onHandleIntent LocationService");
Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
if(location !=null){
String time= intent.getStringExtra("time");
Log.i("fused", "onHandleIntent LocationService " +time+"---"+ location.getLatitude() + "," + location.getLongitude());
updateTransientLocation(getApplicationContext(), location);
}
}
此外,我需要只在后台定期将这些位置保存在数据库中,因此,如果没有挂起的服务意图,就不能使用RequestLocationUpdate
关于代码,我已经参考了
谢谢
编辑-解决方案我的问题就是这样解决的
活动中的代码
Intent myIntent = new Intent(context,LocationReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, myIntent, 0);
alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
// 120000,pi);
- 我删除了location服务类并添加了location receiver
public class LocationReceiver extends BroadcastReceiver implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
SharedPreferences prefs = null;
LocationClient locationclient = null;
Context contxt;
/** For location poller NO LONGER IN USE **/
@Override
public void onReceive(Context context, Intent intent) {
contxt=context;
//Log.i("locationreciever", "in location rec");
Log.i("fused", "in location rec");
int resp = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
if (resp == ConnectionResult.SUCCESS) {
locationclient = new LocationClient(context, this, this);
locationclient.connect();
} else {
Log.i("fused", "loc client Google Play Service Error");
}
}
@Override
public void onLocationChanged(Location location) {
Log.i("fused", " onLocationChanged Location Request :" + location.getLatitude() + "," + location.getLongitude());
updateTransientLocation(contxt, location);
if (locationclient != null) {
if (locationclient.isConnected()) {
locationclient.removeLocationUpdates(this);
locationclient.disconnect();
}
}
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
Log.i("fused", "loc client connection failed");
}
@Override
public void onConnected(Bundle arg0) {
Log.i("fused", "loc client onConnected");
LocationRequest locationrequest = LocationRequest.create();
locationrequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationclient.requestLocationUpdates(locationrequest, this);
}
@Override
public void onDisconnected() {
Log.i("fused", "loc client disconnected");
}
}
最好的解决方案是使用您当前的方法。你会告诉操作系统,你不需要更多地定位,但可能会有其他东西在请求定位,在这种情况下,你最好接受它,因为手机已经醒来获取GPS定位,并将其广播给每个对某个位置感兴趣的进程。这样,您的应用程序实际上可能永远不需要打开GPS,因为您基本上只是在使用另一个进程请求的定位,而该进程通常每15分钟请求一次。这里要搜索的关键字是new 如果坚持每15分钟获取一个位置,则可以使用来计划每15分钟运行一次作业,而不是安排位置请求。在alarm manager中,您可以立即请求新的单个位置,然后完全停止请求新位置,直到计划再次运行作业。如果您沿着这条路线走下去,您可能会在得到结果之前遇到服务结束的问题,因为位置服务的异步性质。因此,您希望在alarm manager中轮询一个位置。你可以用一个这样的项目 本文档提供了如何安排重复事件的示例: 根据您的需要,您应该考虑一个事实,即位置可能不是每15分钟可用。可能用户不在GPS/wifi/电话范围内。因此,提前一点或更频繁地开始一项任务可能有益,也可能有害,以确保在15分钟的时间窗口过后有一个合理的解决方案 综上所述,下面是您真正感兴趣的代码片段,用于解决您的特定问题(直接取自CWAC locationpoller站点): 1。创建定期报警管理器
mgr=(AlarmManager)getSystemService(ALARM_SERVICE);
Intent i=new Intent(this, LocationPoller.class);
Bundle bundle = new Bundle();
LocationPollerParameter parameter = new LocationPollerParameter(bundle);
parameter.setIntentToBroadcastOnCompletion(new Intent(this, LocationReceiver.class));
// try GPS and fall back to NETWORK_PROVIDER
parameter.setProviders(new String[] {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER});
parameter.setTimeout(60000);
i.putExtras(bundle);
pi=PendingIntent.getBroadcast(this, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
PERIOD,
pi);
2。创建广播接收器以接收您的位置数据
Bundle b=intent.getExtras();
LocationPollerResult locationResult = new LocationPollerResult(b);
Location loc=locationResult.getLocation();
String msg;
if (loc==null) {
loc=locationResult.getLastKnownLocation();
if (loc==null) {
msg=locationResult.getError();
}
else {
msg="TIMEOUT, lastKnown="+loc.toString();
}
}
else {
msg=loc.toString();
}
if (msg==null) {
msg="Invalid broadcast received!";
}
从
从API 19开始,所有重复报警都是不精确的。如果您的应用程序需要精确的交付时间,那么它必须使用一次性精确警报,并按上述方式重新安排每次的时间。targetSdkVersion早于API 19的传统应用程序将继续将其所有报警(包括重复报警)视为精确报警
因此,您必须执行以下操作:
public void startTheClock(int interval) {
Intent pingerIntent = new Intent(this, findLoc.class);
pingerIntent.setAction("start_clock");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(),
0,
pingerIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(
Context.ALARM_SERVICE);
alarms.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + interval,
pendingIntent);
}
在捕获该意图的类中(在本例中为findLoc.java):
其中,间隔是以毫秒为单位的常数
注意:我实际上遇到了一些问题,因为它在setExact(…)
上显示了一个错误,因为我的最小SDK不支持这个。如果您希望SDK上的相同行为低于19且高于或等于19,这有点自相矛盾。几乎所有这些:)但是,您可能希望通过实际轮询后台服务中的位置来简化它。我已经添加了一个项目的链接,这个链接可能会引起您的兴趣,同时还添加了一个链接,它解释了一点关于新的融合位置提供程序的信息,您可能应该支持它,或者您也应该支持它。
public class findLoc extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
callMethodThatSearchesForLocation();
startTheClock(INTERVAL);
}
}