Problems with searching for available device, via bluetooth, in android - android

My app should just check, via bluetooth, if there is certain Arduino server around, and toast proper message.
This is the code when user presses button to search for server:
public void onClick(View v) {
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals("ARD_SPP")) {
sendButton.setVisibility(View.VISIBLE);
Toast.makeText(ConnectActivity.this, "Arduino server found, please sign up 1111", Toast.LENGTH_SHORT);
break;
}
}
}
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(discoveryResult, filter);
mBluetoothAdapter.startDiscovery();
}
And code inside BroadcastReceiver:
public void onReceive(Context context, Intent intent) {
Boolean b = false;
String action = intent.getAction();
ProgressDialog dialog = new ProgressDialog(ConnectActivity.this);
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
dialog.setMessage("Searching for Arduino server...");
dialog.show();
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
dialog.dismiss();
if (!b)
Toast.makeText(ConnectActivity.this, "Server not found", Toast.LENGTH_SHORT).show();
}
else if (BluetoothDevice.ACTION_FOUND.equals(action)){
String deviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
if (deviceName.equals("ARD_SPP")) {
Toast.makeText(ConnectActivity.this, "Arduino server found, please sign up 2222", Toast.LENGTH_SHORT).show();
sendButton.setVisibility(View.VISIBLE);
openButton.setVisibility(View.GONE);
b = true;
dialog.dismiss();
}
}
}
I've got three problems with this.
First, I have the problem with "Server not found" message. It is shown even when arduino is around. I really don't have idea where to put that line in my code. I tried to put it in different lilnes of code, but I couldn't get what is required.
Second, message that server is found is shown two times. I meam toast inside broadcast receiver, not toast inside pairedDevices(after this one I put 1111 to recognize which toast is shown). I don't understand what is the part of the code where that toast is executed for the second time.
And I also had problems with progress dialog. I couldn't remove dialog from the screen, it was still there even when the server is found. I put dialog.dismiss() both in discovery finished block and device found, but it is still on the screen.
Does anyone please can help me with this ?

You set your variable every time you received an intent.
Boolean b = false;
ProgressDialog dialog = new ProgressDialog(ConnectActivity.this);
This should not be put in the OnReceived() but must be setted as private variable of your BroadCastReceiver.
This will this the progress not dismiss and the "Server not found" toast, since b is always false when you received ACTION_DISCOVERY_FINISHED, and you try to dismiss a progressDialog not showed.
Concerning the multiple call of "Server found" call twice, check if you unregister your BroadcastReceiver when you don't need anymore.
Hope that help.
EDIT :
Set your broadcastReceiver like that, the progressDialog should be create in the ACTION_DISCOVERY_STARTED :
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
private boolean b = false;
private ProgressDialog dialog ;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
dialog = new ProgressDialog(ConnectActivity.this);
dialog.setMessage("Searching for Arduino server...");
dialog.show();
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
dialog.dismiss();
if (!b)
Toast.makeText(ConnectActivity.this, "Server not found", Toast.LENGTH_SHORT).show();
}
else if (BluetoothDevice.ACTION_FOUND.equals(action)){
String deviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
if (deviceName.equals("ARD_SPP")) {
Toast.makeText(ConnectActivity.this, "Arduino server found, please sign up 2222", Toast.LENGTH_SHORT).show();
sendButton.setVisibility(View.VISIBLE);
openButton.setVisibility(View.GONE);
b = true;
dialog.dismiss();
}
}
}
}

Related

App asks for USB permission on every Phone restart

I'm using an USB-Receiver to handle the Communication with a Temperature Sensor attached via USB to the Phone.
Everything is working fine so far, but if i restart the Phone, the App throws an USB-Permission pop-up directly after restarting, even if there isn't any USB-Device attached to the Phone at that Moment.
Has anyone an Idea of what's causing this strange Problem?
[ EDIT: I'm Sorry, the App isn't asking for USB Permission, the popup asks if i want to Open the app if "this device is connected" but there's obviously no device attached.]
Here is the Code of the USB-Receiver:
//Initial USB Settings Receiver
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
// is usb permission has been granted, try to open a connection
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// call method to set up device communication
Constants result = mcp2221.open();
if (result != Constants.SUCCESS) {
//nothing by now
} else {
openConnectionToMCP2221();
}
}
}
}
}
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
// close the connection and release all resources
closeAllResources();
// leave a bit of time for the COM thread to close
try {
Thread.sleep(20);
}catch(InterruptedException e){e.printStackTrace();}
mcp2221Comm = null;
Toast.makeText(getApplicationContext(), "Device detached",
Toast.LENGTH_SHORT).show();
}
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
Toast.makeText(getApplicationContext(), "Device attached",
Toast.LENGTH_SHORT).show();
mStopUSBThread=false;
// only try to connect if an MCP2221 is attached
if (device.getVendorId() == MCP2221_VID && device.getProductId() == MCP2221_PID) {
Constants result = mcp2221.open();
switch (result) {
case SUCCESS:
openConnectionToMCP2221();
break;
case CONNECTION_FAILED:
Toast.makeText(getApplicationContext(), "ERROR: connection failed", Toast.LENGTH_SHORT).show();
break;
case NO_USB_PERMISSION:
Toast.makeText(getApplicationContext(), "ERROR: no USB permission", Toast.LENGTH_SHORT).show();
mcp2221.requestUsbPermission(mPermissionIntent);
break;
default:
break;
}
}
}
}
}
};
And here is the onCreate() part:
//USB Connection
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
final IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbReceiver, filter);
//Checking if theres a Device already connected
.......
Got it!
It was an
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
</intent-filter>
that was declared in AndroidManifest.xml under <activity>.
I don't fully understand, why it caused this Bug, but removing it kept the functionality of my App while getting rid of the Problem.
Only 'negative' aspect might be, that now the App doesn't ask to open if the Sensor is attached to the phone.

dynamically register receiver which on receive starts a service

In my main activity I have a check box which when checked registers a receiver to listen out for changes to the bluetooth device i.e bluetooth connected to a device.
when the phone becomes connected to a preselected bluetooth device, I want a service to be started from within the on receive once its called.
the problem is that when after clicking the check box "on" in the main activity, thus registering the receiver, if the user clicks the back button to exit the app, the app/android life cycle calls onDestroy, and i get an error saying leaked receiver. how can i register the receiver and keep it registered even if the user clicks the back button to exit the main activity.
the app only has one activity which is the main activity.
the receiver gets unregistered when the user un-checks the checkbox.
addDrawerItems Method
final IntentFilter blueToothFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
blueToothFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
if (ctv.isChecked()) {
if (!isblueToothRegistered) {
registerReceiver(mReceiver, blueToothFilter);
isblueToothRegistered = true;
Toast.makeText(getApplicationContext(),"Bluetooth ON",Toast.LENGTH_LONG).show();
}
} else {
if (isblueToothRegistered) {
unregisterReceiver(mReceiver);
isblueToothRegistered = false;
Toast.makeText(getApplicationContext(),"Bluetooth OFF",Toast.LENGTH_LONG).show();
}
}
BroadCast Receiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
private Boolean bluetoothStart = false;
#Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context, "Receieved", Toast.LENGTH_LONG).show();
String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Intent serviceIntent = new Intent(context, CallDetectService.class);
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
//Toast.makeText(context, "Bluetooth Connected", Toast.LENGTH_LONG).show();
if (device.getName().equals(mPairedBluetoothDevice)) {
bluetoothStart = true;
serviceIntent.putExtra("btConnected",bluetoothStart);
startService(serviceIntent);
showStatusBarIcon(true);
detectEnabled = true;
SharedPreferences sharedPreferences3 = getSharedPreferences("driveSafeMode", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences3.edit();
editor.putBoolean("mode", detectEnabled);
editor.apply();
toggleUI();
// Toast.makeText(context, mPairedBluetoothDevice, Toast.LENGTH_LONG).show();
}
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)){
stopService(serviceIntent);
showStatusBarIcon(false);
detectEnabled = false;
SharedPreferences sharedPreferences3 = getSharedPreferences("driveSafeMode", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences3.edit();
editor.putBoolean("mode", detectEnabled);
editor.apply();
toggleUI();
}
}
};
maybe when the user checks the check boxes a separate service gets started which
its only job is to register the receiver onStartCommand and the unRegisterReceiver onDestroy. the thing is though in that case the service could be running for days, listening for a bluetooth device to be connected. would that be ok though ?
thanks for any help.
You should register your receiver in your manifest. Use code only to enable / disable it.

How to make the android Bluetooth keep scanning

Hi this is my first time posting.
Im making an android application that only discover Bluetooth device by using the friendly name and the mac address . Not pairing.
The problem im facing is my device fail to detect new device that enter the range after is start the scan about 10 to 12 second.
final BroadcastReceiver bReceiver = new BroadcastReceiver() {
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
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name and the MAC address of the object to the arrayAdapter
// System.out.println(device.getAddress());
for(int i=0;i<listmac.size();i++)
{
if(listmac.get(i).equals(device.getAddress())){
System.out.println(listname.get(i));
myListView.setItemChecked(i, true);
}
}
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
myBluetoothAdapter.cancelDiscovery();
}
else {
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
isBreceiverRegisted = true;
}
}
public void off(){
myBluetoothAdapter.disable();
Toast.makeText(getApplicationContext(),"Bluetooth turned off",
Toast.LENGTH_LONG).show();
}
Sorry for my broke english
Simply because the discovery task has a timeout to prevent endless searched.
To be able to detect that discovery ended you need add this intent
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// When discovery is finished , start discovery again
myBluetoothAdapter.startDiscovery();
}
}
Be very careful in general about accidentally leaving your device in discovery-mode. Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources.

monitor file receiving via bluetooth

I'm now trying to transfer files between Android devices via bluetooth. I already implemented my sender side. I'm not using InputStream/OutputStream. I'm using Intent.ACTION_SEND. Everything in there sender side works fine, but when it comes to the receiver side, I'm facing two problems.
There's the pop out notification saying "Do you want to receive this file?". Is there any way I can avoid this thing?
How can I know that there's a file coming in and the file transfer is finished or stopped at the receiver side?
It seems that these two problems can be solved using InputStream/OutputStream, but I don't really want to use them. Maybe a listener that monitors Bluetooth, or some functions in BluetoothAdapter/BluetoothDevice can do this?
Thanks for help. My code is like below: (in my MainActivity.java)
public void beginBT() {
if (isSender) {
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/log.txt");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
if (!findBluetoothForIntent(intent)){
Toast.makeText(this, "Bluetooth Not Found.", Toast.LENGTH_SHORT).show();
} else {
//intent will send the file via bluetooth
startActivity(intent);
}
} else { //receiver side
//make device be discoverable
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
public boolean findBluetoothForIntent(Intent intent){
List appsList = getPackageManager().queryIntentActivities(intent, 0);
String packageName = null;
String className = null;
for (Object info: appsList){
if (info instanceof ResolveInfo) {
packageName = ((ResolveInfo) info).activityInfo.packageName;
if (packageName.equals("com.android.bluetooth")){
className = ((ResolveInfo) info).activityInfo.name;
break;
}
}
}
if (className != null) {
intent.setClassName(packageName, className);
return true;
} else {
return false;
}
}
Answering my own question is always so much fun!!
About the pop out notification, I can't do anything about it, unless I use InStream/OutStream.
For the receiver side, use BroadcastReceiver to monitor actions of the device. Here I monitor the disconnecting action of bluetooth. Because there will be a connecting action when the device begin to receive file, and when it finishes, there will be a disconnecting action.
Don't know if the following code would help anybody, :)
MainActivity.java
private static final String BT_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == BT_DISCONNECTED) {
//now file transmitting has finished, can do something to the file
//if you know the file name, better to check if the file is actually there
// - make sure this disconnection not initiated by any other reason.
}
}
IntentFileter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter);
Warning: remember to unregister this receiver when you exit the activity, or simply when you don't need it

Finishing an activity from service

I am building an app which requires a connection to an MQTT server. Everything works fine, but I want to make it fail proof. More specifically, I need that when the service is unable to connect to the MQTT server, the application closes as it can't do anything. I tried to broadcast an intent to the activity, but the broadcast doesn't reach it after catching the exception. (I ommited some code for easier understanding)
Service's onHandleIntent()
try{
mqttClient.connect();
} catch (MqttException e) {
Intent msgint = new Intent();
msgint.setAction(constantStrings.SH_CONN_ERROR);
sendBroadcast(msgint);
Log.d("MqttLog","ERROR-MqttException " + e.getMessage());
}
The Activity I need to finish (SelectionGrid.class)
#Override
protected void onCreate(Bundle savedInstanceState) {
[...]
IntentFilter filter = new IntentFilter();
filter.addAction(constantStrings.SH_CONNERROR);
registerReceiver(SH_Communication, filter);
}
BroadcastReceiver SH_Communication = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(constantStrings.SH_CONN_ERROR)){
new AlertDialog.Builder(getApplicationContext())
.setTitle("Error")
.setMessage("No conection")
.setCancelable(false)
.setPositiveButton("Close app", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
SelectionGrid.this.finish();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
};
I do get the Log entry when catching the exception, but the broadcast never gets to the activity.
Is there any better way to do this?
I was able to solve it. It turned out that I was calling the wrong activity which looks a lot like the one I really needed. The code that I showed in the question is correct.

Categories

Resources