/** * Copyright (c) 2012-2013 Nokia Corporation. All rights reserved. * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. * Oracle and Java are trademarks or registered trademarks of Oracle and/or its * affiliates. Other product and company names mentioned herein may be trademarks * or trade names of their respective owners. * See LICENSE.TXT for license information. */ package com.nokia.example.attractions.location; import javax.microedition.location.LocationException; import javax.microedition.location.LocationProvider; import javax.microedition.location.QualifiedCoordinates; /** * Abstract location finder. * * Extended by the classes CellIdLocationFinder and GpsLocationFinder. * * @see com.nokia.example.attractions.location.CellIdLocationFinder * @see com.nokia.example.attractions.location.GpsLocationFinder */ public abstract class AbstractLocationFinder extends LocationFinder { protected int interval = 60000; private LocationProvider lp; private long lastRequestTime = -1; private static boolean supportsFindingLocation = true; private final Object updateLock = new Object(); private UpdateThread updateThread; /** * Get a location provider. * @return location provider * @throws LocationException * @throws SecurityException */ protected abstract LocationProvider getLocationProvider() throws LocationException, SecurityException; /** * @see LocationFinder#init(com.nokia.example.attractions.location.LocationFinder.Listener) */ protected final void init(Listener listener) throws InitializationException, SecurityException { super.init(listener); LocationProvider lp = null; try { lp = getLocationProvider(); } catch (LocationException se) { throw new InitializationException(se.getMessage()); } if (lp == null) { throw new InitializationException("Provider not found"); } this.lp = lp; } /** * @see LocationFinder#start(int) */ public synchronized final void start() { if (supportsFindingLocation && updateThread == null) { updateThread = new UpdateThread(); updateThread.start(); } } /** * @see LocationFinder#quit() */ public synchronized final void quit() { if (updateThread != null) { updateThread.cancel(); updateThread = null; } } private void requestLocation() { synchronized (updateLock) { if (System.currentTimeMillis() >= lastRequestTime + interval) { lastRequestTime = System.currentTimeMillis(); try { QualifiedCoordinates coordinates = lp.getLocation(-1).getQualifiedCoordinates(); if (coordinates != null) { double lat = coordinates.getLatitude(); double lon = coordinates.getLongitude(); int accuracy = (int) coordinates.getHorizontalAccuracy(); accuracy = Math.max(accuracy, 10); listener.newLocation(lat, lon, accuracy); } } catch (LocationException e) { if(shouldQuit(e)) { supportsFindingLocation = false; quit(); } } catch (InterruptedException e) { } catch (SecurityException e) { supportsFindingLocation = false; quit(); } } } } /** * @param e * @return true if should quit because location provider doesn't work */ protected abstract boolean shouldQuit(LocationException e); private class UpdateThread extends Thread { private static final long MIN_DELAY = 5000; private volatile boolean running = true; public void run() { while (running) { requestLocation(); try { sleep(Math.max(interval + lastRequestTime - System.currentTimeMillis(), MIN_DELAY)); } catch (InterruptedException e) { } } } public void cancel() { running = false; } } }