[android] #2421 - Initial build out of Telemetry Location infrastructure
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package com.mapbox.mapboxsdk.telemetry;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.media.AudioManager;
|
||||
import android.media.ToneGenerator;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
public class TelemetryLocationReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "TelemLocationReceiver";
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
public TelemetryLocationReceiver() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the BroadcastReceiver is receiving an Intent
|
||||
* broadcast. During this time you can use the other methods on
|
||||
* BroadcastReceiver to view/modify the current result values. This method
|
||||
* is always called within the main thread of its process, unless you
|
||||
* explicitly asked for it to be scheduled on a different thread using
|
||||
* {@link Context#registerReceiver(BroadcastReceiver,
|
||||
* IntentFilter, String, Handler)}. When it runs on the main
|
||||
* thread you should
|
||||
* never perform long-running operations in it (there is a timeout of
|
||||
* 10 seconds that the system allows before considering the receiver to
|
||||
* be blocked and a candidate to be killed). You cannot launch a popup dialog
|
||||
* in your implementation of onReceive().
|
||||
* <p/>
|
||||
* <p><b>If this BroadcastReceiver was launched through a <receiver> tag,
|
||||
* then the object is no longer alive after returning from this
|
||||
* function.</b> This means you should not perform any operations that
|
||||
* return a result to you asynchronously -- in particular, for interacting
|
||||
* with services, you should use
|
||||
* {@link Context#startService(Intent)} instead of
|
||||
* {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
|
||||
* to interact with a service that is already running, you can use
|
||||
* {@link #peekService}.
|
||||
* <p/>
|
||||
* <p>The Intent filters used in {@link Context#registerReceiver}
|
||||
* and in application manifests are <em>not</em> guaranteed to be exclusive. They
|
||||
* are hints to the operating system about how to find suitable recipients. It is
|
||||
* possible for senders to force delivery to specific recipients, bypassing filter
|
||||
* resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()}
|
||||
* implementations should respond only to known actions, ignoring any unexpected
|
||||
* Intents that they may receive.
|
||||
*
|
||||
* @param context The Context in which the receiver is running.
|
||||
* @param intent The Intent being received.
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
Location location = (Location)intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
|
||||
if (location != null) {
|
||||
Log.i(TAG, "location received = " + location);
|
||||
final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
|
||||
tg.startTone(ToneGenerator.TONE_PROP_BEEP);
|
||||
tg.stopTone();
|
||||
tg.release();
|
||||
} else {
|
||||
Log.i(TAG, "location NOT received");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.mapbox.mapboxsdk.telemetry;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
public class TelemetryService extends Service {
|
||||
|
||||
private static final String TAG = "TelemetryService";
|
||||
|
||||
private TelemetryLocationReceiver telemetryLocationReceiver = null;
|
||||
private PendingIntent locationPendingIntent = null;
|
||||
private PowerManager.WakeLock telemetryWakeLock;
|
||||
|
||||
/**
|
||||
* Return the communication channel to the service. May return null if
|
||||
* clients can not bind to the service. The returned
|
||||
* {@link IBinder} is usually for a complex interface
|
||||
* that has been <a href="{@docRoot}guide/components/aidl.html">described using
|
||||
* aidl</a>.
|
||||
* <p/>
|
||||
* <p><em>Note that unlike other application components, calls on to the
|
||||
* IBinder interface returned here may not happen on the main thread
|
||||
* of the process</em>. More information about the main thread can be found in
|
||||
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
|
||||
* Threads</a>.</p>
|
||||
*
|
||||
* @param intent The Intent that was used to bind to this service,
|
||||
* as given to {@link Context#bindService
|
||||
* Context.bindService}. Note that any extras that were included with
|
||||
* the Intent at that point will <em>not</em> be seen here.
|
||||
* @return Return an IBinder through which clients can call on to the
|
||||
* service.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by the system when the service is first created. Do not call this method directly.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// Enable Location Listening for lifecycle of app
|
||||
IntentFilter filter = new IntentFilter("com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver");
|
||||
telemetryLocationReceiver = new TelemetryLocationReceiver();
|
||||
registerReceiver(telemetryLocationReceiver, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system to notify a Service that it is no longer used and is being removed. The
|
||||
* service should clean up any resources it holds (threads, registered
|
||||
* receivers, etc) at this point. Upon return, there will be no more calls
|
||||
* in to this Service object and it is effectively dead. Do not call this method directly.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
shutdownTelemetry();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called if the service is currently running and the user has
|
||||
* removed a task that comes from the service's application. If you have
|
||||
* set {@link ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK}
|
||||
* then you will not receive this callback; instead, the service will simply
|
||||
* be stopped.
|
||||
*
|
||||
* @param rootIntent The original root Intent that was used to launch
|
||||
* the task that is being removed.
|
||||
*/
|
||||
@Override
|
||||
public void onTaskRemoved(Intent rootIntent) {
|
||||
shutdownTelemetry();
|
||||
super.onTaskRemoved(rootIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system every time a client explicitly starts the service by calling
|
||||
* {@link Context#startService}, providing the arguments it supplied and a
|
||||
* unique integer token representing the start request. Do not call this method directly.
|
||||
* <p/>
|
||||
* <p>For backwards compatibility, the default implementation calls
|
||||
* {@link #onStart} and returns either {@link #START_STICKY}
|
||||
* or {@link #START_STICKY_COMPATIBILITY}.
|
||||
* <p/>
|
||||
* <p>If you need your application to run on platform versions prior to API
|
||||
* level 5, you can use the following model to handle the older {@link #onStart}
|
||||
* callback in that case. The <code>handleCommand</code> method is implemented by
|
||||
* you as appropriate:
|
||||
* <p/>
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
|
||||
* start_compatibility}
|
||||
* <p/>
|
||||
* <p class="caution">Note that the system calls this on your
|
||||
* service's main thread. A service's main thread is the same
|
||||
* thread where UI operations take place for Activities running in the
|
||||
* same process. You should always avoid stalling the main
|
||||
* thread's event loop. When doing long-running operations,
|
||||
* network calls, or heavy disk I/O, you should kick off a new
|
||||
* thread, or use {@link AsyncTask}.</p>
|
||||
*
|
||||
* @param intent The Intent supplied to {@link Context#startService},
|
||||
* as given. This may be null if the service is being restarted after
|
||||
* its process has gone away, and it had previously returned anything
|
||||
* except {@link #START_STICKY_COMPATIBILITY}.
|
||||
* @param flags Additional data about this start request. Currently either
|
||||
* 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}.
|
||||
* @param startId A unique integer representing this specific request to
|
||||
* start. Use with {@link #stopSelfResult(int)}.
|
||||
* @return The return value indicates what semantics the system should
|
||||
* use for the service's current started state. It may be one of the
|
||||
* constants associated with the {@link #START_CONTINUATION_MASK} bits.
|
||||
* @see #stopSelfResult(int)
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
// Start WakeLock to keep Location Data working when device sleeps
|
||||
PowerManager mgr = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
||||
telemetryWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TelemetryWakeLock");
|
||||
telemetryWakeLock.acquire();
|
||||
|
||||
// Start Ambient Location Listening
|
||||
// TODO
|
||||
|
||||
Intent locIntent = new Intent("com.mapbox.hermes.LocationReceiver");
|
||||
locationPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 14872, locIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
try {
|
||||
// Request Location Updates to be delivered to PendingIntent
|
||||
// Currently Not supported in LOST
|
||||
// TODO
|
||||
// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 3.0f, mLocationPendingIntent);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Permissions Not Authorized For Location Updates: " + e);
|
||||
}
|
||||
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
private void shutdownTelemetry() {
|
||||
// TODO
|
||||
// locationManager.removeUpdates(mLocationPendingIntent);
|
||||
locationPendingIntent.cancel();
|
||||
unregisterReceiver(telemetryLocationReceiver);
|
||||
telemetryWakeLock.release();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user