简体   繁体   中英

Running GPS positioning in a background thread on Android

I have curious problem, in my application, the GPS-positioning takes quite a long time (as it tends to do) and therefore I wanted to run it as its own thread while the user is making choices in other views.

My structure is that I have a "main" view that is always active in the background, then the user is shown a series of views in which he or she makes a few choices. In the end, the user is presented with a result based on the choices made and the current position. All of this works, but I wanted to move the GPS-bit to its own thread so that the user wouldn't have to wait for it to finish.

All of the user's choices and the GPS coordinates is stored in a singleton called CurrentLogEntry. All communication between the different parts of the program is performed through it.

I created a handleMessage(Message msg) override in the main view and then I implemented this function in Main.java:

void startGPSThread() {
    Thread t = new Thread() {

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);     
        boolean isDebug = CurrentLogEntry.getInstance().isDebug();

        // Define a listener that responds to location updates
        LocationListener locationListener  = new LocationListener() {

            public void onStatusChanged(String provider, int status, Bundle extras) {
                /* This is called when the GPS status changes */
                String tag = "onStatusChanged, ";
                switch (status) {
                    case LocationProvider.OUT_OF_SERVICE:
                        Log.w(tag, "Status Changed: Out of Service");
                        break;
                    case LocationProvider.TEMPORARILY_UNAVAILABLE:
                        Log.w(tag, "Status Changed: Temporarily Unavailable");
                        break;
                    case LocationProvider.AVAILABLE:
                        break;
                }
            }

            public void onProviderEnabled(String provider) {
            }

            public void onProviderDisabled(String provider) {
                // This is called if the GPS is disabled in settings.
                // Bring up the GPS settings
                Intent intent = new Intent(
                        android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
            }

            public void onLocationChanged(Location location) {

                // Once a location has been received, ignore all other position
                // updates.
                locationManager.removeUpdates(locationListener);
                locationManager.removeUpdates(this);

                // Make sure that the received location is a valid one,
                // otherwise show a warning toast and hit "back".
                if (location == null) {
                    String warningString = "Location was unititialized!";

                    if (isDebug) {
                        Toast.makeText(getApplicationContext(),
                                warningString,
                                Toast.LENGTH_LONG).show();
                    }

                    KeyEvent kev = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
                    onKeyDown(KeyEvent.KEYCODE_BACK, kev);
                }

                CurrentLogEntry.getInstance().setUserLatitude(location.getLatitude());
                CurrentLogEntry.getInstance().setUserLongitude(location.getLongitude());

                //Send update to the main thread
                int result = 0;
                if (location.getLatitude() == 0 || location.getLongitude() == 0) {
                    result = -1;
                }

                messageHandler.sendMessage(Message.obtain(messageHandler, result));
            }
        };

        @Override
        public void run() {

            locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, 0, 0, locationListener);

            // Wait until a position has bee acquired.
            while(!CurrentLogEntry.getInstance().isReadyToCalculate()){
                try {
                    wait(250);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    };

    t.start();
}

This function is called in Main.onCreate() .

Unfortunately, this doesn't work at all. The program crashes as soon as it reaches locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); and that has me completely stumped.

Can anyone enlighten me as to why this won't run as a background thread? Also, do I really need the wait-polling at the end to ensure that the thread stays alive until it receives its data? The GPS bit worked just fine before I wanted to put it in a thread of its own, so what in the world am I doing wrong?

From what i understand you have to make the Thread a Looper thread in order to run Location Updates in the background...however i am still trying to figure this out myself...when i figure out how to do this i will post it.

Probably have the same error that i received, which is can't create handler in thread where Looper.prepare() has not been called

Hope you get it working bud

Check the this thread and specifically for this answer. They deal with the same subject, location, and the same problem, running it from a Thread loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM