Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Android nRF-ToolBox multiple BLE services within a single Android Service

Hello all,

I've been working on creating a test app for a product that I've been developing for sometime. It has multiple BLE services such as Device information (DIS), Cycling Power (CP), Battery Service, DFU and a custom service. I've got no prior experience with Java or xml, so the answer might be obvious to the following questions.

I've adjusted the Cycling Speed and Cadence example in the nRF Toolbox application to receive and display the Cycling Power Measurement, the Cycling Power Feature, Sensor location and the DIS firmware, hardware, model number and serial number Characteristics.

I added all these characteristics in the Cycling Power Manager, but with so many services I'd like to implement this becomes quite a mess and I'd like to seperate each BLE service into a serperate manager/class(es).

I've noticed that the Battery service is already implemented by extension of the Cycling Power Manager (CSCManger in the original toolbox)

public class CPManager extends BatteryManager <CPManagerCallbacks>

From what I've attempted, failed and then read, I cannot extend this class further with other services like this. So what would be the best solution to extend the manager/service with more BLE services without putting all services and characteristics in a single class, while sending all handled BLE data to a single Activity?

Second question: I've removed all other BLE services in the first menu except the DFU and the Cycling Power services by removing the <service from the AndroidManifest.xml file as the template service readme file stated it would. However the Beacon service remains in the main menu, no matter which services I disable or remove. So where does the beacon service come from?

Thank you in advance for helping me out.

  • Hello Simon,

    Thank you for the answers, but I still have a few more questions as I'm trying to implement sending an BLE message to the Cycling Power Control Point Characteristic on a button press in the GUI. I've implemented the clickEvent, which is called when I press the button. However I now face the issue with calling the function in the CPmanager in order to write the BLE message.

    A few other services and the nRF Blink use the following piece of code to get the manager instance and with the instance they are able to call the public functions of the manager. For example the blinky implementation

    	public BlinkyViewModel(@NonNull final Application application) {
    		super(application);
    
    		// Initialize the manager
    		mBlinkyManager = new BlinkyManager(getApplication());
    		mBlinkyManager.setGattCallbacks(this);
    	}

    Here is the function call of the send function in the BlinkyManager

    	public void toggleLED(final boolean isOn) {
    		mBlinkyManager.send(isOn);
    		mLEDState.setValue(isOn);
    	}

    However, if I attempt to do the same from my Activity the function is called, but the characteristic variable has a null value and returns without transmitting the message. I've checked it multiple times that the variable is correctly given a value on service discovery in the manager, so I assume that instead of getting the active manager instance, the new BlinkyManager(getApplication) call creates a new instance of the manager which has all its characteristics set to null on initialization of the class.

    I've also attempted to use the Broadcast receiver functionality in the Service code, which listens to the ACTION_DISCONNECT action. So on the button clickEvent I've created a function to broadcast the Intent.

    	private void sendStatZeroOffsetBroadcast()
    	{
    		final Intent broadcast = new Intent(CPService.BROADCAST_ZERO_OFFSET_START);
    		LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
    	}

    This works, but I'm only able to receive it on the Activity receiver and not in the Service broadcast receiver, despite adding the broadcast filter to both receiver's intent filter.

    So my question is as following: How can I call a function from my CPmanager from my CPActivity, am I using the correct method or is there another option?

  • Hi

    Our Android expert took a look at your reply, and here are his suggestions for you:

    It seems like you might be creating multiple instances of the manager. You should use the same manager instance throughout the app. I would suggest moving your manager to the service and let all the communication happen in the service. You can then have a broadcast receiver on the activities to listen to all the broadcasts sent from the service. In addition, you should bind your activities to the service using a binder and then use that binder to access the same manager and call its public methods to send data. This will help you maintain one instance of the manager. One such example would be to look at the proximity profile which shows how a service can be bound to an activity and how to call the public API within the manager in the service from the activity using the binder.
    Best regards,
    Simon
  • Hello Simon,

    I've got the binder working and I got quite a lot of functionality already implemented, but I required a bit more layout space and I am currently implementing a tab layout.

    For further development and verification of the product I'm developing this app for I would like to capture the NUS service TX data with the app. The product uses the NUS to stream data to another nRF device at 200 messages per second, which writes it to an SD card. If I currently try to capture this with my app, I get an noticeable delay/responsiveness issue. From the streaming device I can also see that If i try to plot a single message per second in my app layout it starts to drop packets as my TX queue overflows. So I wonder if there's an solution for this by using a queue, interface, thread or other way to deal with high data throughput? I had a look at the NUS example in the toolbox, but i saw nothing special. Or should I use a separate thread for my GUI? I think i saw this being used for the proximity or glucose example.

    I also want to implement a text log for BLE messages just as is implemented in the nRF Connect app to display messages send between the app and the device. Is there something in the toolbox which already has this functionality or what I could use for this?

  • Hi

    Are you able to find out if this is delay is on the phone or nRF side (if you're using an nRF device on one side that is)? I think we need more information to decide what causes this delay. Are you able to take a sniffer trace of the connection so we can get some more details of what's causing this delay? You're of course welcome to try adding a separate thread for your GUI, but I can't say if it will help without knowing the cause of this delay.

    Please check out the nRF Logger API, that should help you with a text log solution.

    Best regards,

    Simon

  • I've stumbled onto something: The options menu is recreated/refreshed on each action/iteration of the GUI. I found out about it as I set a breakpoint in the onCreateOptionsMenu and the breakpoint would be hit continously and immediately after I continued from the same breakpoint. It seems that the onCreateOptionsMenu is called in some sort of while loop, but in a file that read-only and in a package controlled by Android Studio of some sort, so I can't edit it or change my permissions.

    With the menu disabled, having the NUS service enabled does not break my application as much as it did previously. Though I do note that not all functionality works as intended. It seems that quite a few BLE messages are lost when I attempt to write to a characteristic, even though the functions to write to the characteristic are indeed called. Previously they would not be called as the whole GUI was unresponsive with the options menu and the NUS service enabled.

    I have done a bit of testing with reliableWrite in order to solve the missing BLE messages, but that seems to do more harm than good. Do you have any suggestions to resolve this?

Related