Monday, 4 August 2014

Python Script for Location Updates

Below is a simple python script to automate location updates to the emulator.

# Karun Matharu (ksm113@imperial.ac.uk)
# Imperial College London
# A simple python telnet script to connect to the emulator on
# localhost 5554 and issue geo fix commands
import sys
import telnetlib
import getpass
import time
import random
HOST = "localhost"
PORT = 5554
TIMEOUT = 2
# Sleep time between each location update
TIME_GAP = 4
# Starting values for longitude and latitude
lon = 50.000000
lat = 50.000000
tn = telnetlib.Telnet(HOST, PORT, TIMEOUT)
print tn.read_some()
while (True):
a = random.random()
b = random.random()
lat = lat + a
lon = lon + b
s = "geo fix " + str(lon) + " " + str(lat) + "\n"
tn.write(s)
print(s)
time.sleep(TIME_GAP)
view raw gistfile1.py hosted with ❤ by GitHub

Saturday, 2 August 2014

Location Updates within a Service

Requesting location updates within a remote service may cause the following exception:

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

The requestLocationUpdates() function requires access to a Looper to deal with messages in a queue. When calling this method in a background service, the method may not implicitly have access to the threads Looper. Defining the thread's Looper explicitly by adding an additional argument 'Looper.getMainLooper()' deals with the issue.

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener, Looper.getMainLooper());
view raw gistfile1.java hosted with ❤ by GitHub

Friday, 1 August 2014

Dealing with System Service Dependencies

As an example of a case where a system service depends on another, below is the constructor for a 'test' service which when constructed, initializes a location manager.

/*
Import libraries and variable declarations
*/
public TestService(Context context) {
super();
mContext = context;
mWorker = new TestWorkerThread("TestServiceWorker");
mWorker.start();
Log.i(TAG, "Spawned worker thread");
//Initialize the locationManager when the TestService starts
locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
/*
Other functions
*/
view raw gistfile1.java hosted with ❤ by GitHub

The 'test' service requires that the 'LocationManagerService' is running before 'test' is created so that it can successfully initialize  a location manager.

When Android is started, 'init' is a component of the bootloader sequence which initializes a number of daemons which run continuously whilst the operating system is running.

One of those daemons 'Zygote' is the process responsible for starting system services. It does this by executing the initAndLoop() function of the SystemServer Class.

SystemServer located in frameworks/base/services/java/com/android/server/SystemServer.java

In order to ensure 'LocationManagerService' is running before 'test' service, place the 'test' service's addService code anywhere below that of the 'LocationManagerService'.

//Within initAndLoop()
if (!disableLocation) {
try {
Slog.i(TAG, "Location Manager");
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
reportWtf("starting Location Manager", e);
}
try {
Slog.i(TAG, "Country Detector");
countryDetector = new CountryDetectorService(context);
ServiceManager.addService(Context.COUNTRY_DETECTOR, countryDetector);
} catch (Throwable e) {
reportWtf("starting Country Detector", e);
}
}
/*
Register Other Services
*/
//Register Test Service
try {
Slog.i(TAG, "Test Service");
ServiceManager.addService("test", new TestService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting TestService Service", e);
}
view raw gistfile1.java hosted with ❤ by GitHub