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

带JobScheduler的融合位置提供程序

寿高阳
2023-03-14

我在MainActivity类中有一个提供纬度和经度值的融合位置提供程序代码,它使用persistableBundle传递给JobService类。当用户使用应用程序时,它工作正常(即应用程序位于前台)。一旦应用程序被刷出或销毁,MainActivity的最后更新值就会一直通过作业调度器重复上传(即,作业调度器始终获得相同的值,融合的位置提供程序不工作)。即使应用程序不在前台,我应该怎么做才能使其正常工作?(注:当应用程序被最小化时,它会工作。例如,它可以在最近的应用程序列表中看到,但一旦从列表中刷出,问题就会出现)

主要活动。班

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // JobScheduler starts
        btnStartJob = (Button)findViewById(R.id.startjob);

        jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
        btnStartJob.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {

                ComponentName jobService =
                        new ComponentName(getPackageName(), MyJobService.class.getName());
                PersistableBundle bundle = new PersistableBundle();
                bundle.putString("lat", latitude+"");
                bundle.putString("lon", longitude+"");

                JobInfo jobInfo =
                        new JobInfo.Builder(MYJOBID, jobService).setPeriodic(10000).
                        setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).
                        setRequiresCharging(false).
                        setRequiresDeviceIdle(false).
                        setPersisted(true).
                        setExtras(bundle).
                        build();

                int jobId = jobScheduler.schedule(jobInfo);
                if(jobScheduler.schedule(jobInfo)>0){
                }else{
                }
            }
        });
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    }


    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Toast.makeText(getApplicationContext(),
                        "This device is not supported.", Toast.LENGTH_LONG)
                        .show();
                finish();
            }
            return false;
        }
        return true;
    }

    @Override
    public void onConnected(Bundle bundle) {
        createLocationRequest(bundle);
    }

    protected void createLocationRequest(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
            @Override
            public void onLocationResult(final LocationResult locationResult) {
                latitude = locationResult.getLastLocation().getLatitude() + "";
                longitude = locationResult.getLastLocation().getLongitude() + "";
                Log.e("onLocationResult lat", latitude);
                Log.e("onLocationResult Lon", longitude);
            }

            @Override
            public void onLocationAvailability(LocationAvailability locationAvailability) {
            }
        }, null);
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
                + result.getErrorCode());
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        checkPlayServices();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mGoogleApiClient != null) {
            mGoogleApiClient.connect();
            Log.i(TAG, "mGoogleApiClient.connect()");
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

MyJobService类

public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        latitude = jobParameters.getExtras().getString("lat");
        longitude = jobParameters.getExtras().getString("lon");
        Log.e("service1",latitude + "");
        Log.e("service2",longitude + "");
        return true;
    }
}

更新1:

试图在Jobservice中实现融合的位置,但不起作用

public class MyJobService extends JobService implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener{

    String latitude = null;
    String longitude = null;


    public MyJobService() {
    }

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        Log.d("onStart", "onStartJob() :: ");
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        Toast.makeText(this,
                "MyJobService.onStopJob()",
                Toast.LENGTH_SHORT).show();
        return false;
    }

    //fused location provider starts

    private GoogleApiClient mGoogleApiClient;
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
    private LocationRequest mLocationRequest;
    private static final String TAG = "zzzz";

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }


    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
//                GooglePlayServicesUtil.getErrorDialog(resultCode, this,
//                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
                Log.e("GooglePlayServices", resultCode + "");
            } else {
                Toast.makeText(getApplicationContext(),
                        "This device is not supported.", Toast.LENGTH_LONG)
                        .show();
                stopSelf();
            }
            return false;
        }
        return true;
    }

    @Override
    public void onConnected(Bundle bundle) {
        createLocationRequest(bundle);
    }

    protected void createLocationRequest(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
            @Override
            public void onLocationResult(final LocationResult locationResult) {
                latitude = locationResult.getLastLocation().getLatitude() + "";
                longitude = locationResult.getLastLocation().getLongitude() + "";
                Log.e("onLocationResult lat", latitude);
                Log.e("onLocationResult Lon", longitude);
            }

            @Override
            public void onLocationAvailability(LocationAvailability locationAvailability) {
            }
        }, null);
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
                + result.getErrorCode());
    }
// fused location provider ends
}

共有3个答案

龚安民
2023-03-14

在更新和以前的答案的基础上,我终于能够让它工作了。

通过调用fusedLocationProvider到我的作业调度器的onStartJob中的getLastKnownLocation。

请参阅以下代码

ComponentName jobServiceComponent = new ComponentName(context, LocationJobService.class);
    JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(0, jobServiceComponent);
    jobInfoBuilder.setPeriodic(Constants.JOB_SERVICE_INTERVAL);
    jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
    jobInfoBuilder.setRequiresCharging(false);
    jobInfoBuilder.setRequiresDeviceIdle(false);
    jobInfoBuilder.setPersisted(true);

    JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
    int resultCode = scheduler.schedule(jobInfoBuilder.build());

并启动此作业计划程序

@Override
public boolean onStartJob(JobParameters params) {
    updateBackgroundLocation(params);
    return true;
}

private void updateBackgroundLocation(JobParameters params) {

    if (jobCancelled) { return; }
    new Thread(new Runnable() {
        @Override
        public void run() {
            updateLocation(params);
        }
    }).start();

}

private void updateLocation(JobParameters params) {

    LocationServices.getFusedLocationProviderClient(getApplicationContext())
            .getLastLocation().addOnSuccessListener(location -> {
                //perform your update here with last known location.

    }).addOnFailureListener(e -> {
        e.printStackTrace();
    });
    jobFinished(params, true);
}

@Override
public boolean onStopJob(JobParameters params) {
    jobCancelled = true;
    return false;
}
陶星波
2023-03-14

您需要将融合的位置服务逻辑放在作业服务中,因为当您关闭应用程序时,您的位置侦听器也会被破坏,所以当您的应用程序在前台或后台不可用时,您需要在作业服务中获取新位置,当您的作业服务调用您决定的时间时,您需要实现获取位置的逻辑,以及更新位置的逻辑,

您可以使用最后已知的位置来获取位置。

梁丘波鸿
2023-03-14

我不知道您是否仍在尝试解决这个问题,但问题是当应用程序被销毁时,作业调度程序总是获取错误的数据(旧数据)。解决方案可能是在您的手机上缓冲sqlite数据库。因为在销毁应用程序时不会擦除数据库,所以您可以将最新的GPS数据放入数据库,然后让调度程序从那里获取它。它应该可以正常工作。

请善良,这是我第一次尝试帮助;)

 类似资料:
  • 这就是我如何注册我的应用程序来接收位置更新: 我悬而未决的意图几乎在所要求的时间间隔内被后台调用... 到目前为止还好。 问题:当WIFI被禁用/没有连接到任何网络,或者当没有3G/4G网络数据启用-融合位置提供商没有提供新的位置更新!! 我的位置访问设置打开,并检查GPS卫星和WI-FI和移动网络位置。 更大的问题是:有时在这种情况下,我确实通过挂起的意图接收位置更新回调,但它知道最后的位置(即

  • 我正在检查移动设备上是否启用了位置服务,如果是,请监听构建GoogleAppClient并监听位置更改。我面临的问题是,一旦在mobile中打开位置并重新启用,我就无法获得位置(纬度/长)。位置始终为空。 isLocationEnabled检查位置是否已打开

  • 我想通过Android LocationManager API使用fused location provider,因为: 我不想让应用程序Phonelocator依赖于google play服务 现有的实现已经在工作和测试 看起来这是可能的。只需将字符串“融合”作为安装了google play服务的手机上的位置提供程序传递即可。 我想选择使用优先级高精度配置文件。我怀疑,默认情况下,它没有被使用。

  • 我一直在尝试获取我当前的位置更新,并按照Google的建议使用了融合位置提供商,但我无法获得任何更新。我在网上彻底搜索了,但找不到任何解决方案。融合提供商返回的位置甚至不接近我所在的位置,它显示了其他一些国家。有人能在这里帮我吗?

  • 嗨,我已经实现了融合位置提供程序Api,用于在服务中获取位置更新。我能够根据设置的间隔触发onlocationchange事件。但是,当我将setsmallstDisplace设置为10米时,即使设备静止,事件也会被触发。是否有人有类似的问题。请提供建议。下面是代码 为了找到两个位置值之间的距离,我使用了这种方法。 但是即使设备是静止的,我也能得到43.51 , 49.32 , 520.02的距离

  • 我已经开始在Android上开发最后一个定位服务功能:地理围栏!!模拟位置提供程序有任何已知的问题吗?下面的示例(https://developer.android.com/training/location/geofencing.html),即使当前位置在geofence内,我的intent服务也从未启动。我正在使用FakeGPS android应用程序作为模拟位置提供程序,如果我模拟一条路线,