Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RequestLocationUpdate在精确的固定时间间隔后更新_Android_Gps_Location_Location Client - Fatal编程技术网

Android RequestLocationUpdate在精确的固定时间间隔后更新

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

目标:精确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

    }

}
定位服务

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);

    }

}