I've searched and tried everything I could, but I just can't get this to work. From all the examples I've seen, I seem to be doing the right thing, but maybe I'm missing something.
I'm trying to discover Bluetooth devices on Android and have been following the guide on the Android Developer page: http://developer.android.com/guide/topics/connectivity/bluetooth.html
I can enable BT when the app starts and get the name and address of my device. However, I can't see the names of other nearby devices (supposed to show up as a toast). The intriguing part is, when I enable BT before starting the app, it actually does what I want and shows the nearby devices' name.
Here's the code:
public class MainActivity extends AppCompatActivity {
TextView mTextView;
BluetoothAdapter mBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
final String status;
// Check BT support
if (mBluetoothAdapter == null){
// Device does not support BT
status = "Your device does not support Bluetooth";
}
else {
String myAddress = mBluetoothAdapter.getAddress();
String myName = mBluetoothAdapter.getName();
status = myName + ": " + myAddress;
}
mTextView = (TextView)findViewById(R.id.textView);
// If BT is enabled before app start, discover devices
// This is where things work, for some reason
if (mBluetoothAdapter.isEnabled()){
mTextView.setText(status);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver, filter);
getBTdevices();
}
// If BT is not enabled, enable it and look for devices
else{
mTextView.setText(status);
mBluetoothAdapter.enable();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver, filter);
getBTdevices();
}
}
protected void getBTdevices(){
// Stop discovery and start
if (mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TextView textView = (TextView)findViewById(R.id.textView2);
textView.setText("Start");
String action = intent.getAction();
// If device is found
if (BluetoothDevice.ACTION_FOUND.equals(action)){
// Get BT device from intent
textView.setText("Device found");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(context, "Device found: "+ device.getName(), Toast.LENGTH_LONG).show();
System.out.println("Discovered!");
}
}
};
protected void onDestroy(){
super.onDestroy();
if (mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
unregisterReceiver(mBroadcastReceiver);
}
}
Some help would really be appreciated, I don't know what else I can do.
EDIT: Forgot to mention, I have set both the BLUETOOTH and BLUETOOTH_ADMIN permissions in the manifest.
Related
I am trying to discover bluetooth devices and append results to TableLayout.
Basically, I'm trying to start the discovery and print deviceName and rssi to table layout.
Here is my code:
public class DatabaseActivity extends AppCompatActivity {
public BluetoothAdapter bluetoothAdapter;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress();
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
// Append to tableBLE
TableLayout tl = findViewById(R.id.tableBLE);
appendTableFront(tl, deviceName + "_" + rssi);
Log.d("PBK_Test - Detected", deviceName + "_" + rssi);
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_database);
// Bluetooth
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
// Device doesn't support Bluetooth
}
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 0);
}
// Start Discovery
bluetoothAdapter.startDiscovery();
// Register for broadcasts when a device is discovered.
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver, filter);
// Make discoverable
if (bluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
public void appendTableFront(TableLayout tl, String msg) {
TableRow newRow = new TableRow(this);
newRow.setBackgroundColor(Color.GRAY);
newRow.setLayoutParams(new TableRow.LayoutParams(
TableRow.LayoutParams.MATCH_PARENT,
TableRow.LayoutParams.WRAP_CONTENT));
TextView label_id = new TextView(this);
label_id.setText(msg);
label_id.setTextColor(Color.WHITE);
label_id.setPadding(5, 5, 5, 5);
newRow.addView(label_id);
tl.addView(newRow);
}
}
I can become discoverable, but not detecting other devices.
I tried the built-in bluetooth discovery and it works fine.
Edit:
I added Log.d("PBK_Test - Detected", deviceName + "_" + rssi); to onReceive and it is not shown as well.
newRow might be null, because there's no final keyword and you change the scope.
Remove this instruction: runOnUiThread() ...because it's not running in the background.
I figured it out myself.
The problem is not in the code --
You have to get into Settings -> App -> <app_name> -> Permissions, to manually give your app permissions, EVEN IF YOU HAVE DECLARED THEM IN MANIFEST.
Citation:
This video https://www.youtube.com/watch?v=dLZDJgblgj8
I have made an application that allows many-to-one communication using Bluetooth and it is working perfectly fine. Now, i wanted to use the service of the application in another application (e.g. Discovering Devices, Connecting to Device). So, I marked my project as library and added it as library in my new project. However, when i call the Discovering Device Activity (Available in library) from the application, the activity starts, but it doesn't discovers the devices ? Can someone help on this ?
I have included all the library project activity and permissions in my app's manifest.
Here is the sample code for the same -
In Library -
This is how the DeviceListActivity Looks like -
`
public class DeviceListActivity extends Activity{
String insecure="8ce255c0-200a-11e0-ac64-0800200c9a66";
private int flag=0;
int flag_toast=0;
ArrayList<Pair<String,String>> x=new ArrayList<Pair<String,String>>();
private static final String TAG = "DeviceListActivity";
ArrayList<String> temp=new ArrayList<String>();
Map<String, String> services = new HashMap<String, String>();
/**
* Return Intent extra
*/
public static String EXTRA_DEVICE_ADDRESS = "device_address";
/**
* Member fields
*/
private BluetoothAdapter mBtAdapter;
/**
* Newly discovered devices
*/
ImageView animation;
private ArrayList<BluetoothDevice> btDeviceList = new ArrayList<BluetoothDevice>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the window
// requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_device_list);
// Set result CANCELED in case the user backs out
setResult(Activity.RESULT_CANCELED);
// Initialize the button to perform device discovery
animation=(ImageView)findViewById(R.id.imageAnimation);
/*scanButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.GONE);
}
});*/
// Initialize array adapters. One for already paired devices and
// one for newly discovered devices
//ArrayAdapter<String> pairedDevicesArrayAdapter =new ArrayAdapter<String>(this, R.layout.device_name);
//mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
//Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_UUID);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
/* this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
*/
// Get the local Bluetooth adapter
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
animation.setBackgroundResource(R.drawable.animation);
doDiscovery();
}
#Override
protected void onDestroy() {
super.onDestroy();
// Make sure we're not doing discovery anymore
if (mBtAdapter != null) {
mBtAdapter.cancelDiscovery();
}
// Unregister broadcast listeners
this.unregisterReceiver(mReceiver);
}
/**
* Start device discover with the BluetoothAdapter
*/
public void doDiscovery() {
Log.d(TAG, "doDiscovery()");
// If we're already discovering, stop it
if (mBtAdapter.isDiscovering()) {
mBtAdapter.cancelDiscovery();
}
// Request discover from BluetoothAdapter
mBtAdapter.startDiscovery();
}
private void connect_automatic(String name){
flag++;
Log.d(name,"Called " + Integer.toString(flag)+" times");
Log.d("Flag is = ",Integer.toString(flag));
int i,j;
for(i=0;i<x.size();i++){
for (j=i+1;j<x.size();j++)
if (x.get(i).getFirst().equals(x.get(j).getFirst())==true && x.get(i).getSecond().equals(x.get(j).getSecond())==true)
x.remove(j);
}
for(i=0;i<x.size();i++){
Log.d("Found "+x.get(i).getFirst(),x.get(i).getSecond());
}
Log.d("Size =",Integer.toString(x.size()));
if (x.size()>=1){
Log.d("Size is =",Integer.toString(x.size()));
String address = x.get(0).getFirst();
if (flag_toast==0)
Toast.makeText(DeviceListActivity.this, "Merchant Found", Toast.LENGTH_SHORT).show();
flag_toast++;
Log.d("Connecting to ",x.get(0).getFirst());
// Create the result Intent and include the MAC address
Intent intent = new Intent();
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
// Set result and finish this Activity
setResult(Activity.RESULT_OK, intent);
finish();
}
}
/**
* The BroadcastReceiver that listens for discovered devices and changes the title when
* discovery is finished
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
flag++;
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
//mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
btDeviceList.add(device);
// When discovery is finished, change the Activity title
}
else
{
Log.d("Action=",action.toString());
if(BluetoothDevice.ACTION_UUID.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if(uuidExtra!=null)
for (int i=0; i<uuidExtra.length; i++) {
if(uuidExtra[i].toString().length()>0){
Log.d("\n Device: " + device.getName() + ", " + device, ", Service: " + uuidExtra[i].toString());
// services.put(device.getName(), uuidExtra[i].toString());
//flag=btDeviceList.size();
if (/*uuidExtra[i].toString().equals(secure)==true ||*/ uuidExtra[i].toString().equals(insecure)==true){
Pair<String,String> t=new Pair<String, String>(device.getAddress(), uuidExtra[i].toString());
x.add(t);
}
//connect_automatic();
}
}
Log.d("Device List =",Integer.toString(flag));
connect_automatic(device.getName());
//Log.d("Boolean",Boolean.toString(services.isEmpty()))
}
else
{
if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.d("Discovery","Started...");
}
else
{
if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.d("Discover","Finished");
//setProgressBarIndeterminateVisibility(false);
Iterator<BluetoothDevice> itr = btDeviceList.iterator();
while (itr.hasNext()) {
// Get Services for paired devices
BluetoothDevice device = itr.next();
temp.add(device.getName());
Log.d("ok","Getting Services for " + device.getName() + ", " + device);
if(!device.fetchUuidsWithSdp()) {
Log.d("!ok","SDP Failed for " + device.getName());
}
else{
Log.d("SDP Passed for ",device.getName());
}
}
//connect_automatic();
}
}
}
}
}
};}`
And here is how i call it in my new application -
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null)
{
ensureDiscoverable();
Intent intent = new Intent(this, DeviceListActivity.class);
startActivityForResult(intent, REQUEST_CONNECT_DEVICE_INSECURE);
}
}
The bluetooth scan should stop as soon as it finds a device of choice, and then after stopping it should start again, when i do the following, i get error saying the app has stopped. i want to scan for 3 times, and store their radiuses.
private BluetoothAdapter mBtAdapter;
mBtAdapter.startDiscovery();
//this string stores the MAC Address of the required device
string name = "12:34:D3:s3:we";
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
if(device.getAddress.equals(name)){
mBtAdapter.cancelDiscovery();
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
mBtAdapter.startDiscovery();
}
}
}
I am using a usb POS printer with my application. I have successfully written the code to connect, request permission and print data. However, I'm unsure how do notify the user when the printer is disconnected, if it is then the device falls back to the network printer.
So this is my BroadcastReceiver for requesting permission:
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
mDevice = device;
if(mConnection == null){
Log.i(m_Tag, "Connection is null");
}
Log.i(m_Tag, "Connected successfully");
}else{
Log.i(m_Tag, "Device is null");
}
}
else {
}
}
}
}
};
I have trawled through the forums here and suggested answers and I've checked out this http://developer.android.com/guide/topics/connectivity/usb/host.html I can't find a solid way to do it without including a device filter xml file. I can't do this because I'm unsure as to what model of printer will be used by the end user.
My brain is fried from this, if someone could please point out how to do this, I'd greatly appreciate it.
Quite late, but for future readers here is how I do it.
In onStart() I register a broadcast receiver for the ACTION_USB_DEVICE_DETACHED action.
#Override
protected void onStart() {
Log.d(TAG, "onStart()");
super.onStart();
// Catch a USB detach broadcast intent.
detachReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
jobsDone();
}
}
};
// Set the intent filter for the broadcast receiver, and register.
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(detachReceiver, filter);
}
In my jobsDone() I just finish the Activity which is basically the same as pressing "back".
private void jobsDone() {
Log.d(TAG, "jobsDone()");
this.finish();
}
Since in my case only one USB device can be attached at one single time I do not have to bother with device_filter.xml for the detach.
Also remember to unregister the receiver.
#Override
protected void onStop() {
Log.d(TAG, "onStop()");
super.onStop();
// Unregister the BroadcastReceiver
unregisterReceiver(detachReceiver);
}
I am new to Android programming. I want to make a library (a JAR file) that contains the Bluetooth discovery functionality.
Since it is a library, the method inside should be a sequential method (start the Bluetooth discovery, wait for an amount of time, and return the result).
I made a code below, but it does not work. In the LogCat, I could see the intents, but the BroadcastReceiver could not catch the intents.
Is there something wrong with the code?.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mSendButton = (Button) findViewById(R.id.button1);
mSendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery();
}
});
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e("device_name", device.getName());
Log.e("device_add", device.getAddress());
numberOfDevice++;
Found_Device = true;
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
if(numberOfDevice == 0){
Log.e("DISCOVERY", "No Device found");
}
Log.e("DISCOVERY", "Number of device :" + numberOfDevice);
Discovery_Finish = true;
}
}
};
public void doDiscovery(){
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
Discovery_Finish = false;
Found_Device = false;
long counter = 0;
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
while((Found_Device == false) || (Discovery_Finish == false)){
counter++;
if (counter >= 1000000){
break;
}
}
// Add a code to check the number of device
unregisterReceiver(mReceiver);
mBluetoothAdapter.cancelDiscovery();
}
Is there any way to check the intent without using BroadcastReceiver?
Thank you for your help.
I think you are missing to start the discovering the other devices.
You are overwriting your IntentFilter when you do this:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
You should do it like this:
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_FOUND);