Thursday, May25, 2017 L-36.com

GPS and NMEA over Bluetooth to Android

Using the Bluetooth GPS Provider Plugin


Overview

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

Resource id #14
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


Ad by Google

Disclaimer:
The information on this web site has not been checked for accuracy. It is for entertainment purposes only and should be independently verified before using for any other reason. There are five sources. 1) Documents and manuals from a variety of sources. These have not been checked for accuracy and in many cases have not even been read by anyone associated with L-36.com. I have no idea of they are useful or accurate, I leave that to the reader. 2) Articles others have written and submitted. If you have questions on these, please contact the author. 3) Articles that represent my personal opinions. These are intended to promote thought and for entertainment. These are not intended to be fact, they are my opinions. 4) Small programs that generate result presented on a web page. Like any computer program, these may and in some cases do have errors. Almost all of these also make simplifying assumptions so they are not totally accurate even if there are no errors. Please verify all results. 5) Weather information is from numerious of sources and is presented automatically. It is not checked for accuracy either by anyone at L-36.com or by the source which is typically the US Government. See the NOAA web site for their disclaimer. Finally, tide and current data on this site is from 2007 and 2008 data bases, which may contain even older data. Changes in harbors due to building or dredging change tides and currents and for that reason many of the locations presented are no longer supported by newer data bases. For example, there is very little tidal current data in newer data bases so current data is likely wrong to some extent. This data is NOT FOR NAVIGATION. See the XTide disclaimer for details. In addition, tide and current are influenced by storms, river flow, and other factors beyond the ability of any predictive program.