MRobbyF / open-gpstracker

Automatically exported from code.google.com/p/open-gpstracker
0 stars 0 forks source link

GPSLoggerService requires Looper when calling LocationManager #124

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. install ogt apk
2. install own apk (GeoTracing Mobitracer in my case)
3. bind to GPSLoggerService
4. call startLogging()

- What is the expected output? What do you see instead?
Expected is that GPS logging will start. But instead an exception is thrown 
within the GPSLoggerService, with the message: "Can't create handler inside 
thread that has not called Looper.prepare()". This exception is thrown when 
calling the Android LocationManager. 

- Additional information.
After Googling it appears that in this case the calls to LocationManager when 
called as a remote service (OGT makes internal calls) via IPC need to use the 
Looper: 
http://developer.android.com/reference/android/os/Looper.html
here is an example:
http://www.slideshare.net/peterbuck/android-development-4033626

I have tried using this approach and indeed this worked: from my app (apk) I 
can bind to the GPSLoggerService and start logging. I have used the following 
worker thread within GPSLoggerService:

    private class LocationManagerWorkerThread extends Thread
    {
        public LocationManagerWorkerThread()
        {
            super("LocationManagerWorkerThread");
        }

        public void run()
        {
            Looper.prepare();
            requestLocationUpdates();
            mLocationManager.addGpsStatusListener(mStatusListener);
            mLoggingState = Constants.LOGGING;
            Log.d(TAG, "GPS Logging started OK");

            Looper.loop();
        }
    }

This thread is started wihtin startLogging():

  public synchronized long startLogging()
    {
        startNewTrack();
        // requestLocationUpdates();
        // this.mLocationManager.addGpsStatusListener( this.mStatusListener );
        // this.mLoggingState = Constants.LOGGING;
        new LocationManagerWorkerThread().start();
        updateWakeLock();

        setupNotification();
        crashProtectState();
        return mTrackId;
    }

Somehow subsequent calls to stopLogging etc. don't need the 
WorkerThread+Looper. 

I can make the changes in GPSLoggerService if you want.

Original issue reported on code.google.com by jus...@gmail.com on 9 Jul 2010 at 1:04

GoogleCodeExporter commented 8 years ago
I tried to reproduce this problem with the attached project, but couldn't. Can 
you send me your project code or adjust the attached project?

Original comment by rcgr...@gmail.com on 21 Jul 2010 at 8:45

Attachments:

GoogleCodeExporter commented 8 years ago
In your attached project Fiddle.java only calls startup() (bind) and 
getLoggingState() through the GPSLoggingServiceManager. These calls will not 
cause the exception. The exception occurs when calling startLogging(name). In 
Fiddle.java try to replace onClick() with something like this.

public void onClick( View v )
{
 long loggerTrackId = mLoggerServiceManager.startGPSLogging( null );

((TextView) findViewById( R.id.status ) ).setText( "Logging state: " + 
              mLoggerServiceManager.getLoggingState() + " trackId=" + loggerTrackId);
}

Also in onDestroy() you need to call            mLoggerServiceManager.shutdown() to be 
complete.

BTW I don't call startGPSLogging() any more but just start the OGT LoggerMap 
Activity from my app to control the entire logging control and track export.
I only call startup()/shutdown()/getLoggingState() and storeMediaUri() (for 
waypoint names) on the remote service through GPSLoggerServiceManager. This 
works well (apart from issue 117).

So I guess the ultimate test will need to verify basically all AIDL services. 
Simple services may not need the Looper, only CPU intensive ones (?).

Original comment by jus...@gmail.com on 22 Jul 2010 at 11:38

GoogleCodeExporter commented 8 years ago
It isn't CPU, the LocationManager creates an Handler on the Thread of the 
calling method. When the OGT application runs it has a main thread with Looper 
on it, calling in from a remote process creates a thread without that looper.

Creating a new thread with looper is indeed the solution. I just need to make 
sure there is only 1 service thread in the OGT process and that it handles all 
the callbacks from the the different managers.

Original comment by rcgr...@gmail.com on 23 Jul 2010 at 3:39

GoogleCodeExporter commented 8 years ago
The GPSLoggerServiceThread in GPSLoggerService has an own Handler that is now 
used to register all kinds of listeners. 

In onCreate() the new GPSLoggerServiceThread().start(); is done and 
mHandler.sendMessage(msg) is used to queue a command to start the location 
updates.

Original comment by rcgr...@gmail.com on 24 Jul 2010 at 2:02

GoogleCodeExporter commented 8 years ago
Reopening

Released versions 19 and 20 proved unstable with regard to threading and the 
service. Version 21 uses the old 18 service code and lacks a handler for calls 
from other processes.

Original comment by rcgr...@gmail.com on 2 Nov 2010 at 8:35

GoogleCodeExporter commented 8 years ago

Original comment by rcgr...@gmail.com on 28 Nov 2010 at 9:03