目标:在完全 15分钟后在服务中使用更少的电池来保存服务在数据库中的当前位置。我在我的应用中的不同位置使用这些位置
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
}
}
LocationService
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);
}
}
此外,我需要在后台只在数据库中定期保存这些位置,因此无法使用requestLocationUpdates而无需等待服务的意图。
我已将this提到代码
感谢。
编辑 - 解决方案这就是我的问题解决方法
活动代码
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);
LocationReceiver
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");
}
}
答案 0 :(得分:1)
最好的解决方案是使用您当前的方法。你告诉操作系统你不经常需要位置,但是其他东西可能正在请求位置,在这种情况下你可能只是接受它,因为手机已经唤醒了获得GPS修复并将其广播到对某个位置感兴趣的每个进程。这样,您的应用程序实际上可能永远不必打开GPS,因为您基本上只使用另一个进程请求的位置修复程序,每15分钟更频繁一次。要在此处搜索的关键字是新的fused location provider。
如果您坚持每15分钟获取一个位置,则可以使用AlarmManager来安排作业每15分钟运行一次,而不是安排位置请求。在警报管理器中,您可以立即请求新的单个位置,然后完全停止请求新位置,直到您的作业再次安排运行。如果你沿着这条路走下去,由于位置服务的异步特性,你可能会在得到结果之前遇到服务结束的问题。因此,您希望轮询以获取警报管理器中的某个位置。您可以使用CWAC LocationPoller之类的项目
该文档包含如何安排重复活动的示例: https://developer.android.com/training/scheduling/alarms.html
根据您的需要,您应该考虑一个位置可能每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。创建BroadcastReceiver以接收您的位置数据
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!";
}
答案 1 :(得分:-1)
从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):
public class findLoc extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
callMethodThatSearchesForLocation();
startTheClock(INTERVAL);
}
}
其中interval是以毫秒为单位的常量。
注意:我实际上遇到了一些问题,因为它在setExact(..)
上显示错误,因为我的最低SDK不支持此问题。如果您希望SDK上的相同行为低于19且高于或等于19,那么这有点悖论。