Handling multiple bluetooth connections through services - android

I am developing an application where an android phone is a bluetooth Server that accepts bluetooth connections and later uses them to send and receive data to other phones.
My idea was to use a BluetoothAdapter and react to the ACTION_FOUND intent by starting a service. However, I don't see how I can stay connected to the Services that get created this way. I put the following into the AndroidManifest file:
<service
android:label="#string/bluetooth_connection_activity"
android:name=".BluetoothConnection" >
<intent-filter>
<action android:name="android.bluetooth.device.action.FOUND" />
</intent-filter>
</service>
Is this the right way to do it?
Is my assumption right that by now, every time a device is found, a new service is created? If yes, how can I keep connected to this service so I can use the bluetooth connection?
If you think I am doing this completely the wrong way, please also tell me.

You can use ACTION_FOUND in BroadcastReceiver for discovering BT devices.
mBT = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBT.getBoundedDevices();
if (pairedDevices.size()>0) {
for (BluetoothDevice device : pairedDevices) {
device.getName();
device.getAddress();
}
}
OR:
create BroadcastReceiver and mBT.startDiscovery();
see
1) "Android in Action" page 367
2) "Android SDK" http://developer.android.com/guide/topics/wireless/bluetooth.html
3) sample BluetoothChat in Android-SDK http://developer.android.com/resources/samples/BluetoothChat/index.html

Related

Connecting a Device as a USB Device with STM32 as a USB Host

I want to connect the Android device as a USB Device to an STM32 board which acts as a host device.
My application code for Android looks like:
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usb_connection">
<uses-feature android:name="android.hardware.usb.accessory" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
So when I am trying to get the connected USB device details, the USB Device list is always null :
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Map<String,UsbDevice> deviceList = manager.getDeviceList();
Again, I also tried to get the accessory list, the USB accessory list is also null.
UsbAccessory[] accessoryList = manager.getAccessoryList();
Then tried ADB commands to connect the device. I have created a Desktop application in JAVA to run ADB command and its working fine. But when I tried run ADB command from my Android App, it's giving java.io.IOException: Error running exec(). Command: [ ADB, pull , ...] Working Directory: null Environment: null.
STM32 firmware is written in C.
Please help me I am stuck for a long time.
Hey here is my library for Android Accessory mode activation on Stm32(with cube Mx and HAL verified on series f4 and f1) and USB class for bulk communication:
https://github.com/once2go/Stm32-Android-Accessory
What are you trying to do on the STM32 side? You need to first connect to the Android device over USB and determine (on the STM32 side) whether the Android device is in AOA mode (by checking the Vendor and Product ID). If it's not, you need to send some USB requests that will toggle it (I've included the STM32 USBH library call name):
USBH_GetProtocol Version
USBH_SetString 0 manufacturer name
USBH_SetString 1 model name
USBH_SetString 2 description
USBH_SetString 3 version
USBH_SetString 4 URI
USBH_SetString 5 serial number
Start Accessory
You can see that process explained in more detail here:
https://source.android.com/devices/accessories/aoa#attempt-to-start-in-accessory-mode
Once you've done that, you'll disconnect from the USB device (it will reset the connection) and you'll need to redo the enumeration process. This time, the Vendor and Product ID should be that of an AOA device (0x18D1 & 0x2D00/1). Now you can just connect to it and use a fairly standard USBH_CDC communication process, with a few caveats. When you try to find the interface (in your interface init function), your subclass is 0xFF and your protocol is going to be 0x00).
It took me a while to get everything communicating properly, so having a usb logic analyzer is a really handy tool to make sure things are communicating properly.
Here are some other resources for getting the Android device to communicate once the STM32 is doing things correctly.
https://source.android.com/devices/accessories/aoa2
https://developer.android.com/guide/topics/connectivity/usb/accessory.html#manifest

USB Communication between android and PC

Background :I have tried finding help on stackoverflow, android developers, and various other resources on web. This is my last hope.
I am new to communication and starting with implementation of USB. Following are my questions:
1) When I connect my phone to windows PC, which one is host?
Suppose I want to create an application that can send data, am I making my phone host?
2) For the case (Windows PC and Android phone), the other one would be a peripheral or a device? are they same?
3) From android developers website and a windows forum about USB, I understand that there are certain steps that need to be followed, and it's like
- Create an instance of USBManager.
- Create get list of devices
- Choose a device from which you want to establish connection
- Create an interface
- get endpoint from that interface.
- Create instance of DeviceConnections and call bulkTransfer method and send data.
But when I tried above steps, I get device == null.
I don't even know if my understanding for above communication method is correct.
Can someone please help me understand and establish basic communication between a PC and a android phone and send at least "hello world".
Big thank you for even reading such a long question.
Here is code sample of what I have done. here devicelist returns null.
public class MainActivity extends AppCompatActivity {
android.widget.Button usbButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final CustomUSBManager cmanager = new CustomUSBManager();
//1) //Create instance of USB Manager using getSystemService
final UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
//2) //Create a list of devices
HashMap<String,UsbDevice> deviceList = manager.getDeviceList();
Log.d("Devicelist = ", String.valueOf(deviceList.get(0)));
//3) //Get a specific device from the list
//-----------------------------------------------------------------
Here is my manifest file.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.neeraj.usbcommunication1">
<uses-feature android:name="android.hardware.usb.host"></uses-feature>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
final UsbDevice device = deviceList.get(0); //getting first device
This will not work the way you want. The UsbManager.getDeviceList() is meant to be used with Android devices with an USB port (for example a tablet). However, you connect an Android device acting as a device to your PC acting as a host.
If you want to communicate between Android USB device and some USB host you need to use the accessory mode (https://developer.android.com/guide/topics/connectivity/usb/). But this mode requires special driver support on the USB host side (which is your PC).
Also note that getDeviceList() makes no sense in Accessory mode. This is because the connected accessory is a USB host, not a USB device.
Read more about this in this post: Android to PC USB Read/Write
Note that my answer is based on this answer: https://stackoverflow.com/a/14099963/5457878

Connect to specific Bluetooth device with a click

I'm trying to connect to a specific device using my Android APP, until now what I was able to do is get the paired items doing this :
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set < BluetoothDevice > pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device: pairedDevices) {
mDeviceName.add(device.getName());
mDeviceMAC.add(device.getAddress());
}
}
bluetoothClass.setDeviceName(mDeviceName);
bluetoothClass.setDeviceMac(mDeviceMAC);
Where I get the MAC and the Device name of all of my paired devices. The thing that I would like to do is when I select one it connects to the Bluetooth device.
EXAMPLE
On a Samsung S4 when I turn on the Bluetooth it popups a Dialog whitch contains all of my paired devices and when I click on anyone it connects (I've i'm able to ...) so basically I want to do this, since now I've been getting the paired devices (I don't know if it's the best way to get that but it does) and then when user click on anyone it connects to the device.
It's something like this question but it's unfortunately unanswered.
It's impossible to give you an example within this format, so I have provided you
with a good sample and helpful links to help you understand the sample.
I recommend you follow the steps I have provided and then, when you have
specific problems, you can bring it here, with the code snippet you are having
difficulty with.
I recommend you use download this sample code:
http://developer.android.com/samples/BluetoothChat/index.html
If you haven't already, it's good to study this:
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html
This is a good tutorial and they have many tutorials:
http://www.tutorialspoint.com/android/android_bluetooth.htm
You will need the following permissions in your manifest:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
This is one intent that is advisable to use, to check to see if BT is enabled:
if (!mBluetoothAdapter.isEnabled()) {
android.content.Intent enableIntent = new android.content.Intent(
android.bluetooth.BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
and to make your device discoverable to other devices:
if (mBluetoothAdapter.getScanMode() !=
android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
android.content.Intent discoverableIntent =
new android.content.Intent(
android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(
android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300); // You are able to set how long it is discoverable.
startActivity(discoverableIntent);
}
As I mentioned in my answer here:
You can avoid using an intent to search for paired devices. When
connecting to a device that is not paired, a notification will pop up
asking to pair the devices. Once paired this message should not show
again for these devices, the connection should be automatic (according
to how you have written your program).
I use an intent to enable bluetooth, and to make my device
discoverable, I then set up my code to connect, and press a button to
connect. In your case, you will need to ensure your accessories are
discoverable also. In my case I use a unique UUID, and both devices
must recognise this to connect. This can only be used if you are
programming both devices, whether both are android or one android and
one other device type.
You will need to understand how to use sockets, this is how the devices communicate.
I recommend studying these two links:
http://developer.android.com/reference/android/bluetooth/BluetoothSocket.html
http://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html
Sockets are used to set up connections between devices. There will be a server socket and device sockets (determined by many factors, the programmer, the actual devices). The server socket listens for incoming connections, when a connection is accepted the devices connect, each with a simple socket.
I am not sure how much you know about threading.
The connection needs to be managed with threads:
http://developer.android.com/guide/components/processes-and-threads.html
http://android-developers.blogspot.com.au/2009/05/painless-threading.html
The connection between the devices is managed on threads separate from the User
Interface thread. This is to prevent the phone from locking up while it is
setting up, seeking and making a BT connection.
For instance:
AcceptThread - the thread that listens for a connection and accepts the connection (via the serversocket). This thread can run for an extended time waiting for a device to connect with.
ConnectThread - the thread that the device connecting to the server uses to connect to the serversocket.
ConnectedThread - this is the thread that manages the connection between both sockets.
Let me know if this helps you.

How do I actually BOND a device?

Everywhere I look I find this method "getBondedDevices()" for my bluetooth adapter. However, I have my tablet and another bluetooth device sitting next to me, and I can't figure out how to actually get the device to show up on the list of bonded devices.
In Bluetooth terms, "bonded" and "paired" are basically synonyms (officially, the process of pairing leads to a bond, but most people use them interchangeable). In order for your device to be added to that list, you must go through the process of Discovery, which is how one device searches and finds another, and then Pair the two together.
You can actually do this from the device settings as a user, but if you are looking to so so within the context of an app, your process will likely look something like this:
Register a BroadcastReceiver for BluetoothDevice.ACTION_FOUND and BluetoothAdapter. ACTION_DISCOVERY_FINISHED
Start discovery by calling BluetoothAdapter.startDiscovery()
Your receiver will get called with the first action every time a new device is found in range, and you can inspect it to see if it's the one you want to connect with. You can call BluetoothAdapter.cancelDiscovery() once you've found it to not waste the battery any more than necessary.
When discovery is complete, if you haven't canceled it, your receiver will get called with the second action; so you know not to expect any more devices.
With a device instance in hand, open a BluetoothSocket and connect(). If the devices are not already bonded, this will initiate pairing and may show some system UI for a PIN code.
Once paired, your device will show up in the bonded devices list until the user goes into settings and removes it.
The connect() method also actually opens the socket link, and when it returns without throwing an exception the two devices are connected.
Now connected, you can call getInputStream() and getOutputStream() from the socket to read and write data.
Basically, you can inspect the list of bonded devices to quickly get access to an external device, but in most applications you will be doing a combination of this and true discovery to make sure you can always connect to the remote device regardless of what the user does. If a device is already bonded, you'd just be doing steps 5-7 to connect and communicate.
For more information and sample code, check out the "Discovering Devices" and "Connecting Devices" sections of the Android SDK Bluetooth Guide.
HTH
API level 19 and above you can call createBond() on BluetoothDevice instace to which you want to connect.
You will require some permissions to discover and list the visible devices
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Code to discover and list the devices:
bluetoothFilter.addAction(BluetoothDevice.ACTION_FOUND);
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(bluetoothReceiver, bluetoothFilter);
private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_FOUND");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
devicesList.add((device.getName() != null ? device.getName() : device.getAddress()));
bluetoothDevicesAdapter.notifyDataSetChanged();
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_DISCOVERY_STARTED");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_DISCOVERY_FINISHED");
getActivity().unregisterReceiver(bluetoothReceiver);
}
}
};
Just call createBond() on selected device.

Android Bluetooth - Determine if a paired device is 'on'

I want to determine if a paired device is currently active. I don't really need to connect to it, just determine if it has a heartbeat.
I'm fighting a series of IO errors while trying to connect a bluetooth socket, but I'm not sure I really need to.
Assuming you are using Android
If you have a BluetoothDevice object to this device, you can register to listen for the Broadcast Actions - ACL_CONNECTED or ACL_DISCONNECTED and keep track of the connection state.
If you want to find out wether a BT-Headset is currently actively connected (audio being routed to it), do the following:
Declare the following intent-filter
<intent-filter >
<action android:name="android.bluetooth.headset.action.AUDIO_STATE_CHANGED" />
</intent-filter>
and in your Receiver in onReceive check for:
if ("android.bluetooth.headset.action.AUDIO_STATE_CHANGED".equals(intent.getAction())) {
headsetAudioState = intent.getIntExtra("android.bluetooth.headset.extra.AUDIO_STATE", -2);
}
and save the int as a static variable. Access it anytime you want to know if BT audio is connected(1) / disconnected(0). Not pretty, but gets the job done.
Also check out:
https://github.com/android/platform_frameworks_base/blob/gingerbread/core/java/android/bluetooth/BluetoothHeadset.java

Categories

Resources