簡體   English   中英

與 JobScheduler 融合的位置提供程序

[英]Fused location provider with JobScheduler

我在 MainActivity 類中有一個融合的位置提供程序代碼,提供緯度和經度值,它使用persistableBundle 傳遞給 JobService 類。 當用戶使用應用程序時它工作正常(即應用程序在前台)。 一旦應用程序被刷出或銷毀,來自 MainActivity 的最后更新值就會一直通過作業調度程序重復上傳(即作業調度程序始終獲得相同的值,融合位置提供程序不起作用)。 即使應用程序不在前台,我應該怎么做才能使其工作? (PS,當應用最小化時,它可以工作。即它可以在最近的應用列表中看到,但一旦從列表中滑出就會出現問題)

主Activity.class

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
}

我不知道你是否還在嘗試解決這個問題,但問題是當應用程序被銷毀時,作業調度程序總是得到錯誤的數據(舊數據)。 解決方案可能是在手機上緩沖sqlite數據庫。 因為在銷毀應用程序時不會擦除數據庫,所以您可以將最新的 GPS 數據放入數據庫,然后讓調度程序從那里獲取它。 它應該工作得很好。

請善待,這是我第一次嘗試提供幫助;)

您需要將融合的位置服務邏輯放在作業服務中,因為當您關閉應用程序時,您的位置偵聽器也被破壞,因此當您的應用程序在前台或后台不可用時,您需要在作業服務中獲取新位置,當您的作業服務稱為您決定的時間,您需要實現獲取位置的邏輯,以及更新位置的邏輯,

您可以使用最后一個已知位置來獲取位置。

即使應用程序在后台,也可以使用此服務連續獲取位置。 使用這個類而不是你的Jobscheduler

    public class LocationTracker extends Service implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener,android.location.LocationListener {

    private GoogleApiClient mGoogleApiClient;
    private Location mLastLocation;
    private LocationRequest mLocationRequest;

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 100; // 100 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 *2; // 1 minute

    //Location Request code
    private final int REQUEST_LOCATION = 2;

    //Location manager for location services
    private LocationManager mLocationManager;


    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        getLocation();
    }


    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(60000*2);// Update location every second
        mLocationRequest.setSmallestDisplacement(100);

        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        createLocationRequest();
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                    mGoogleApiClient);
            if (mLastLocation != null) {
            updateProviderLocation(mLastLocation);
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();


        }

        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }


    }
    private void createLocationRequest() {
        Log.i("TAG", "CreateLocationRequest");
        mLocationRequest = new LocationRequest();
        long UPDATE_INTERVAL = 60 * 1000 *2;
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        long FASTEST_INTERVAL = 10000;
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        //**************************
        builder.setAlwaysShow(true); //this is the key ingredient
        //**************************

    }
    @Override
    public void onConnectionSuspended(int i) {


    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
            mGoogleApiClient.connect();
        return super.onStartCommand(intent, flags, startId);
    }

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



    @Override
    public void onLocationChanged(Location location) {
       //Log.d("Location", location.getLatitude() + "," + location.getLongitude());
      try {


            if (mLastLocation.getLatitude()!=location.getLatitude()||mLastLocation.getLongitude()!=location.getLongitude()) {
                updateProviderLocation(location);
                mLastLocation = location;
            }



        }catch (Exception e){

      }


    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

    @Override
    public void onProviderDisabled(String s) {

    }


    private void updateProviderLocation(Location location){
       //Upload to your server

    }




    private void stopLocationUpdates() {

        try {
            if (mGoogleApiClient.isConnected())
                LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

            if (mLocationManager != null) {
                mLocationManager.removeUpdates(this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void getLocation() {
        try {


            // getting GPS status
            Boolean isGPSEnabled = mLocationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            Boolean isNetworkEnabled = mLocationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                Log.e("Location", "No provider enabled");
            } else {
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                    // here to request the missing permissions, and then overriding
                    //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                    //                                          int[] grantResults)
                    // to handle the case where the user grants the permission. See the documentation
                    // for ActivityCompat#requestPermissions for more details.
                    return;
                }

                if (isGPSEnabled) {

                    if (mLocationManager != null) {
                        mLocationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                    }


                }else if (isNetworkEnabled) {
                    if (mLocationManager != null) {
                            mLocationManager.requestLocationUpdates(
                                    LocationManager.NETWORK_PROVIDER,
                                    MIN_TIME_BW_UPDATES,
                                    MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                            Log.d("Network", "Network");
                    }
                }
                // if GPS Enabled get lat/long using GPS Services

            }

        } catch (Exception e) {
            e.printStackTrace();
        }


    }



}

基於更新和以前的答案,我終於能夠讓它工作。

通過調用fusedLocationProvidergetLastKnownLocation在我的作業調度的onStartJob。

看下面的代碼

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM