GPS not working in Async Task

2019-03-04 23:28发布

问题:

I have implemented a simple GPS program that fetches the co-ordinates and displays them on the screen. When I tried to improve on this design and implement an async task, the GPS doesn't seem to work for some reason or another. Is there some issue with regards to using async task with GPS? Here is my code:

private class DownloadTask extends AsyncTask<String, Void, Object> {
        protected Object doInBackground(String... args) {
            Log.i("MyApp", "Background thread starting");

            LocationManager mLocationManager;
            Gpslistener Gpslistener;

            Gpslistener = new Gpslistener();

            try{

               mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

               mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,Gpslistener);

            }catch (Exception e) {

                test_gps = true;
           }


        return null;
    }

    protected void onPostExecute(Object result) {

        if(test_gps == true){
            if (ParkingActivity.this.progressDialog != null) {
                ParkingActivity.this.progressDialog.dismiss();
            }               
            AlertMessage("GPS Error", "Unable to get location");
        }



public class Gpslistener implements LocationListener
{
        @Override
        public void onLocationChanged(Location loc)
        {
            loc.getLatitude();
            loc.getLongitude();
        }

        @Override
        public void onProviderDisabled(String provider)
        {       
        }

        @Override
        public void onProviderEnabled(String provider)
        {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
        }
    }

Each time I run it, it always catches an exception. The GPS permissions are set in the manifest and I'm always using a different application to ensure that a GPS connection is online so I eliminated those as potential errors. Honestly I can't think of anything else, without the async task it works perfectly! Any help is much appreciated, thanks!

Edited My exception logcat:

05-09 22:56:20.199: E/EXCEPTION:(8874): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-09 22:56:20.199: E/EXCEPTION:(8874): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.os.Handler.<init>(Handler.java:121)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:173)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:173)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.location.LocationManager._requestLocationUpdates(LocationManager.java:579)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.location.LocationManager.requestLocationUpdates(LocationManager.java:446)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at stefan.testservice.ParkingActivity$DownloadTask.doInBackground(ParkingActivity.java:163)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at stefan.testservice.ParkingActivity$DownloadTask.doInBackground(ParkingActivity.java:1)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
05-09 22:56:20.199: E/EXCEPTION:(8874):     at java.lang.Thread.run(Thread.java:1019)

回答1:

You can't do that. The thread dies as soon as doInBackground() returns. The GPS listener is a Handler which requires a Looper thread to operate. At the beginning of doInBackground() you need to call Looper.prepare() then at the end call Looper.loop(). It will loop forever until you call quit() on the thread's Looper object.

AsyncTask is really designed for one-shot temporary threads though, so I'd use a normal thread for this. Although, there's no reason you couldn't I suppose. You just have to make 100% sure that you end the loop or it will run forever even after the user closes the app.

Java Can't create handler inside thread that has not called Looper.prepare()



回答2:

like many other things , gps listener can only be listened to by a loopy thread (like the ui thread) . the easiest thing to do would be to it via the ui thread .

also , the gps listener isn't named like this for no reason . only when it gets a location (and that could take time) , it will call the method "onLocationChanged" . you don't need to have asyncTask for this , since all of the calls to "requestLocationUpdates" are asynchronous anyway...



回答3:

If you want a dirty and not much sensual way:

mLocationManager = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
Looper.prepare();
Looper.loop();
if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){    
  mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_MINIMUM_TIME, GPS_MINIMUM_DISTANCE, MyFragment.this);
}
Looper.myLooper().quit();

Basically, it makes the current thread, a main thread on which messages will be executed, after shortly you give up this thread being a main thread. I'm not sure of the consequences of this.