# APRSdroid Inter-App API

This document describes how Android applications can interact with
[APRSdroid](https://aprsdroid.org/). If you are an app developer aiming
to do interesting things with APRS, this is for you.

## Features

APRSdroid exposes the following data via broadcast Intents ("events"):

 * `SERVICE_STARTED` - APRSdroid's tracking service was launched
 * `SERVICE_STOPPED` - APRSdroid's tracking service was terminated
 * `POSITION` - an incoming/outgoing position packet (user, object or item)
 * `MESSAGE` - text messages received by APRSdroid
 * `MESSAGETX` - text messages sent by APRSdroid
 * `UPDATE` - any text added to APRSdroid's log, including raw packets

Furthermore, it is possible to influence APRSdroid with the following
Intents ("actions"):

 * `SERVICE` - start APRSdroid's tracking service
 * `ONCE` - send one position packet and stop
 * `SERVICE_STOP` - stop APRSdroid's tracking service
 * `SEND_PACKET` - send a (raw) APRS packet
 * `FREQUENCY` - change the frequency announced in position packets (requires
   APRSdroid 1.4.1)

All uppercase strings mentioned in this document are suffixes to
`"org.aprsdroid.app."` and need to be concatenated for the effective
Intent action names.

If you want to write a third-party app that is using APRSdroid's
service, the recommended way is to make a service that listens to
APRSdroid's `SERVICE_STARTED` event, launches its own service with the
according configuration, sends and receives packets within that service,
and terminates when a `SERVICE_STOPPED` event is received. That way, all
installed third party applications can be launched automatically
together with APRSdroid. You can use your own application's main
activity to configure (and optionally disable) your add-on.

## Events - Getting Data from APRSdroid

APRSdroid will inform applications using a broadcast Intent about all
relevant status changes. You need to register a
[BroadcastReceiver](https://developer.android.com/reference/android/content/BroadcastReceiver.html)
that will process APRSdroid's events, either in your app's manifest or
using the registerReceiver code.

	<!-- AndroidManifest.xml example to get a service started on
	     APRSdroid intents -->
	<receiver android:name=".APRSdroidEventReceiver">
	    <intent-filter>
	       <action android:name="org.aprsdroid.app.SERVICE_STARTED" />
	       <action android:name="org.aprsdroid.app.SERVICE_STOPPED" />
	    </intent-filter>
	</receiver>

Example code to listen for broadcasts:

	
	public class APRSdroidEventReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (!intent.getAction().startsWith("org.aprsdroid.app"))
				return;
			String a = intent.getAction().replace("org.aprsdroid.app.", "");
			switch (a) {
			case "SERVICE_STARTED":
				aprsdroid_running = true;
				break;
			case "SERVICE_STOPPED":
				aprsdroid_running = false;
				break;
			case "MESSAGE":
				String source = intent.getStringExtra("source");
				String message = intent.getStringExtra("body");
				Log.d("APRS Event", "message from " + source + ": " + body);
				break;
			case "POSITION":
				String callsign = intent.getStringExtra("callsign");
				Location location = intent.getParcelableExtra("location");
				Log.d("APRS Event", callsign + " position: " + location);
				break;
			}
		}
	}

### SERVICE_STARTED

This event will be triggered whenever APRSdroid's service is started and
successfully connects to the backend. After this event, it should be
safe to send out packets. Please note that packet delivery can not be
guaranteed despite all efforts.

Intent extras:

 * `"api_version"` (int): the API version code implemented by the
   installed version of APRSdroid. This document corresponds to API
   version `1`, changes / additions will lead to higher version numbers.
 * `"callsign"` (String): callsign and SSID of the APRSdroid user, in the format
  "N0CALL-5" or "N0CALL" (if no SSID was configured).

### SERVICE_STOPPED

This event will be triggered when APRSdroid's service terminates. It is
not guaranteed to be called (i.e. when the app is force-closed, the
event will not be triggered).

### UPDATE

The `UPDATE` event comes with the following extras:

 * `"type"` (int): the type of the log entry. Possible values:
	* 0: sent packet (generated by APRSdroid)
	* 1: info (APRSdroid's internal information message)
	* 2: error (something went wrong)
	* 3: incoming packet (received from APRS)
 * `"status"` (String): the text that was added to the log. For type 0
   and 3 this is the full raw packet content, header and data.

### MESSAGE / MESSAGETX

When the user sends a message or when a new message is received, the
`MESSAGETX` / `MESSAGE` events are fired. They are not fired for
retransmissions of outgoing messages, and neither for incoming ACKs /
REJs.

Both event types have the following extras:

 * `"source"` (String): callsign of the sender (your own one for
   `MESSAGETX`)
 * `"dest"` (String): callsign of the receiver (might have a different
   SSID on incoming messages to your callsign)
 * `"body"` (String): content of the message

### POSITION

A `POSITION` event is triggered every time when a position packet is
decoded (station, item or object) or transmitted. It contains the
following extras:

 * `"source"` (String): callsign that sent this packet.
 * `"callsign"` (String): callsign for which the position event was sent
   (this is the object/item name for objects/items, and equals to
   `"source"` for regular position packets).
 * `"location"` ([Location](https://developer.android.com/reference/android/location/Location.html)):
   the geo-coordinates of the position. This extra will have latitude,
   longitude, and time set. The accuracy fields is an approximation
   according to the original APRS position ambiguity. Bearing and speed
   will be set if they were present in the original packet.
 * `"packet"` (String): the raw packet that was parsed into this
   position report.

## Actions - Influencing APRSdroid

### Generic Intent Construction

To influence APRSdroid, you need to create an Intent with a string
action starting with `"org.aprsdroid.app."`, followed by the uppercase
action name. The intent should have additional parameters according to
the action description, and must be delivered using
[startService](https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent)).

The individual actions are described in the following.

### SERVICE / ONCE

Start the APRSdroid tracking service for an indeterminate runtime
(`SERVICE`) or for one position transmission (`ONCE`).

	// launch APRSdroid tracker
	Intent i = new Intent("org.aprsdroid.app.SERVICE").setPackage("org.aprsdroid.app");
	startService(i);

### SERVICE_STOP

Stop the tracking service.

	// stop APRSdroid tracker
	Intent i = new Intent("org.aprsdroid.app.SERVICE_STOP").setPackage("org.aprsdroid.app");
	startService(i);

### SEND_PACKET

Send a raw APRS packet via the (already running) APRSdroid service. Only
the packet payload needs to be configured, APRSdroid will automatically
complete the header (your callsign and the ARPS path) from its
configuration.

Intent extras (do not use `setData()`, it doesn't work!):

 * `data` (String): raw packet payload

Example for sending a raw status packet:

	// send raw status packet
	Intent i = new Intent("org.aprsdroid.app.SEND_PACKET").setPackage("org.aprsdroid.app");
	i.putExtra("data", ">third-party APRS status app");
	startService(i);

### FREQUENCY (APRSdroid 1.4.1)

Update the [frequency field](http://www.aprs.org/info/freqspec.txt) in the
position reports sent by APRSdroid. If the APRSdroid service is running, this
will immediately generate a position packet with the new frequency.

Intent extras:

 * `frequency` (String): the new frequency value, e.g. "438.750MHz", "145.500"
   or "" to disable, decimal separator must be a dot (".")

Example for updating the frequency:

	// send raw status packet
	Intent i = new Intent("org.aprsdroid.app.FREQUENCY").setPackage("org.aprsdroid.app");
	i.putExtra("frequency", "438.750");
	startService(i);

Invocation from the adb shell:

	am startservice -a org.aprsdroid.app.FREQUENCY -e frequency "438.750"


## (In-)Security

Currently, APRSdroid exposes the following personal information via
global broadcast to all applications:

 * Your location and the location of your peers
 * Your callsign and callsigns from all nearby stations
 * The content of APRS messages sent and received
 * Any other data sent and received by APRSdroid
 * The times when APRSdroid is active and in which configuration

As APRS (and ham radio in general) is considered public information,
access to this data is not limited in any way. **A future version of
APRSdroid might require third-party apps to have the "Access Fine
Location" permission.**

-----

APRSdroid can be influenced by third-party applications, in that they
can start the service, stop it, and send unlimited amounts of data
packets (over the air) in your name.

**A future version of APRSdroid will display an API key in its
preferences, which must be entered into third-party apps and supplied in
the Intents sent to APRSdroid.**
