GPS and NMEA over Bluetooth to Android

Using the Bluetooth GPS Provider Plugin


This article shows how to modify an Android application that uses internal GPS and external nmea data and add gps over nmea. It also explains how to take that app and use it. The secret is using the plug in feature of Bluetooth GPS Provider and adding their Plugin code to the build stack of the Android app along with some simple changes to the target app.

Bluetooth GPS Provider

A new feature to the best Bluetooth GPS helper is called the plugin. This feature is enabled in the Preferences section under Plugins. Just check the app you want to link to. As far as the Bluetooth GPS Provider app, that is all you have to do. You may notice that there are two choices and I have selected my StartLine app. But where you start is on the first choice, the example plugin app provided with the plugin code from

Get source code

The source code is on Bitbucket HERE

Modify the code

I had to do some small modifications to the source code to make it fit with my system. I changed the two build.gradle files to use the versions that I used in StartLine. You could probably add the necessary files to Android Studio but I wanted to make sure that the plugin would work with the versions I was using so did the modifications instead. I also checked and modified the AndroidManifest.xml file to match the versions I was using.

Note the Folder Names

You will notice that the structure of the plugin is de.mobilej. Don't change that. The example has folders like com.somewhere.something. You can change that to reflect you folder domain structure if you want. When you use your app, those folders will reflect your naming structure. com.somewhere.something should be replaced by your app name. If you do change the folder names, do the same in the example java code.

Run the Example

Compile and run the example. Get Bluetooth connected to the example app and select the plugin in Bluetooth GPS Provider. Going back to the main screen on Bluetooth GPS Provider you should see the fake location sent from the example and perhaps hello plugin. If you see the location, then it is working.

Install your app

Use the basic structure of the example but replace the example app with your app. In my case StartLine. Modify settings.gradle. Starting with the line

include ':btgpspluginexample', ':plugininterface'
change it to call your app.

include ':startline', ':plugininterface'

Modify the App

The plugin takes data from the app so the first modification is to get the data where the plugin can find it. In my case, I am using a modified version of the Google BluetoothChatService.java as my Bluetooth service. In that app I have a data array to save my nmea data for use by the rest of my app. When I get a RMC message, I save it.

writeDataArray(NMEA_RMC, readMessage);
I also have a variable in the chat service

// Plugin support public final static ConditionVariable conditionVariable = new ConditionVariable(false);
When I decode the RMC nmea sentence, I save it and set the condition variable. I have modified this to include saving GSA sentences as well but the idea is have a place to save the sentence and tell the plugin that is it time to read it.

writeDataArray(NMEA_RMC, readMessage); BluetoothChatService.conditionVariable.open();

That variable tells the plugin that there is new data. It will wait until that variable is opened and then read the data and wait for new data.

Modify the PluginService.java

Include PluginService.java from the example in your app folder. That plugin as sent sends fake data. You need to modify it to send the real data. Your needs may be different but this is what I did. Note that in my case data comes every 1000 ms so I set a timer to remove the block and return null if there is no data. This is important so that BtGps does not hang up if the OS closes the program. In that case, the timer will expire and BtGps can close the plugin per the code below.

@Override public String getNMEA() throws RemoteException { Log.d(TAG, "getNMEA Started"); if(BluetoothChatService.conditionVariable.block(1100)){ // the timeout goes here, 1000 ms for now BluetoothChatService.conditionVariable.close(); Log.d(TAG, "getNMEA Sent"); return BluetoothChatService.readDataArray(BluetoothChatService.NMEA_RMC); } else { return null; // timeout } }

Modify AndoridManifest

Include the service in your applications AndroidManifext (modify the com.somewhere.something appropriately)

<service android:name="com.somewhere.something.PluginService" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="de.mobilej.btgps.PLUGIN" /> </intent-filter> </service>

Include plugin layout or modify PluginService

There is a layout called plugin in the example. I included it in my layouts. However it doesn't do anything so a better solution is to modify the plugin code to remove the reference to the layout.

@Override public RemoteViews getMainScreenWidget() throws RemoteException { return null; }

Stop the Service (optional)

The proper way to stop the service is from Bluetooth GPS Provider by pressing Stop. However, you can also stop the plugin when exiting your app if you have exit code. StartLine does this when you use the Exit function by issuing the following commands. If you force close Bluetooth GPS Provider instead of stopping it, things might crash. I included the following in my Exit code.

// stop BtGps Intent stopIntent = new Intent("stop_btgps_provider"); startService(stopIntent);

Instructional Video

NOTICE: Some pages have affiliate links to Amazon. As an Amazon Associate, I earn from qualifying purchases. Please read website Cookie, Privacy, and Disclamers by clicking HERE. To contact me click HERE. For my YouTube page click HERE