Try Catch method for open bluetooth function - android

I made a simple android appication for connect with bluetooth serial device and I want to add closeBT if android not connected maybe the device is out of range because crash.
How do I do this? This code is correct?
protected void onStart() {
super.onStart();
findBT(); //Check if bluettoth enable and paired devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
closeBT();
}
}

Try-catch is not for the application logic! It is for doing stuff when something went wrong! You want to use an if-else here, like
if (findBT() != null) { // I don't know what findBT does, but maybe it returns BT-devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
// inform the user that a connection could not be established or something similar
}
} else {
// inform the user, that no BT-device was found.
}
you want to use closeBT() for instance when the user or your application decides to disconnect the BT-devices.

Related

How do I programmatically dismiss a crash dialog?

I'm building a DPC (Device Policy Controller), and one of the issues I'm seeing is that while the Play Store and Play Services are being updated, the Google Contact Sync service crashes -- leaving the typical crash dialog on the screen. Since part of the idea of the initial set up process is to have as little user interaction as possible, how can I dismiss this dialog programmatically (since I seem to be pretty much guaranteed that this will happen)?
I've tried dismissing system dialogs...
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
... but that doesn't seem to do the trick.
Since this is a DPC, anything that requires device ownership/administration is fine.
edit: Usually I have no UI on screen at the time, so if one is necessary please do mention it. Also, preferably the solution should work on at least 6.0+, if not 4.0+.
Try to do it onWindowsFocusChanged method like this for example :
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
Intent ctx= new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(ctx);
}
}
I'm not sure about app crash Dialog but maybe it'll help you
AppErrorDialog can be dismissed by broadcasting ACTION_CLOSE_SYSTEM_DIALOGS if Android version is N.
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
However, AppErrorDialog won't be displayed if phone is locked.
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
&& mLockScreenShown != LOCK_SCREEN_SHOWN;
} // ActivityManagerService
Please try this code.
try {
Class ActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
Class IActivityManager = Class.forName("android.app.IActivityManager");
Method getDefault = ActivityManagerNative.getMethod("getDefault", null);
Object am = IActivityManager.cast(getDefault.invoke(ActivityManagerNative, null));
Method closeSystemDialogs = am.getClass().getMethod("closeSystemDialogs", String.class);
closeSystemDialogs.invoke(am, "DPC close");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

Close exception in MainActivity gracefully

I newbie to Android development and I have a question.
I already look for this question in forum but no luck.
My MainActivity onCreate tries to connect to a sever.
In some cases the server can be down, and in this case, my app throw exception.
What should I do to finish the Activity gracefully?
I have tried to Toast a message and to finish() the activity but no message appears and the activity still running.
Whats wrong with my code ?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
mSocket = new Socket("127.0.0.1", 6000);
try {
conn = new ClientConnection(mSocket.getInputStream(),mSocket.getOutputStream());
GameSurfaceView gameSurface = (GameSurfaceView)findViewById(R.id.Game);
conn.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (UnknownHostException e) {
Log.e(TAG, "Unknown Host Exception");
e.printStackTrace();
Toast.makeText(this, "Unknown Host Exception", Toast.LENGTH_SHORT);
finish();
} catch (IOException e) {
Log.e(TAG, "IO Exception");
Toast.makeText(this, "IO Exception", Toast.LENGTH_SHORT);
finish();
}
catch (Exception e) {
Log.e(TAG, "Exception");
Toast.makeText(this, "IO Exception", Toast.LENGTH_SHORT);
finish();
}
Log.v(TAG,"Activity created");
}
Don't ever run network code in the UI thread. onCreate is the UI thread - You should never do any IO, network or other long processing task there. Read http://developer.android.com/training/best-background.html for more details.
Your toast is in the catch clause of the out try block - however all IOExceptions (including the UnknownHostException) are already caught in the inner try block. In there you only print the stack trace. That's why no message is ever shown. I don't see a need for two nested try blocks, one is probably all you need.
Assuming your app cannot run without server connection, the right approach would be to let the user know somehow that that's the case (AlertDialog, Toast, whatever) and then call Finish() on the activity to close it.
Edit: As pointed out in a deleted answer, calling show() is of course also needed in top of what I already mentioned:
Toast.makeText(this, "Unknown Host Exception", Toast.LENGTH_SHORT).show();

IOException on accept thread

One part of my application connects to a device through Bluetooth and normally works fine but occasionally it won't connect and I get the following error
03-11 10:29:20.328: E/BluetoothComService(8059): accept() failed
03-11 10:29:20.328: E/BluetoothComService(8059): java.io.IOException: Operation Canceled
03-11 10:29:20.328: E/BluetoothComService(8059): at android.bluetooth.BluetoothSocket.acceptNative(Native Method)
03-11 10:29:20.328: E/BluetoothComService(8059): at android.bluetooth.BluetoothSocket.accept(BluetoothSocket.java:316)
03-11 10:29:20.328: E/BluetoothComService(8059): at android.bluetooth.BluetoothServerSocket.accept(BluetoothServerSocket.java:105)
03-11 10:29:20.328: E/BluetoothComService(8059): at android.bluetooth.BluetoothServerSocket.accept(BluetoothServerSocket.java:91)
03-11 10:29:20.328: E/BluetoothComService(8059): at com.mypackage.name.bluetooth.BluetoothService$AcceptThread.run(BluetoothService.java:298)
This is the line where I get the exception
socket = mmServerSocket.accept();
And this is the complete AcceptThread
private class AcceptThread extends Thread {
// The local server socket
private BluetoothServerSocket mmServerSocket;
public boolean successInit = false;
public AcceptThread() {
closeAllConnections();
/*
* if(mmServerSocket != null) { try { mmServerSocket.close(); } catch
* (IOException e) { e.printStackTrace(); } }
*/
BluetoothServerSocket tmp = null;
// Create a new listening server socket
while (!successInit) {
try {
tmp = mAdapter
.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
successInit = true;
} catch (Exception e) {
successInit = false;
}
}
/*
* try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,
* MY_UUID); successInit= true; } catch (IOException e) { Log.e(TAG,
* "listen() failed", e); tmp = null; successInit = false; }
*/
mmServerSocket = tmp;
}
public void run() {
if (D)
Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mAdapter.cancelDiscovery();
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
Log.e("Error", "This isn't connecting");
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new
// socket.
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D)
Log.i(TAG, "END mAcceptThread");
}
public void cancel() {
if (D)
Log.d(TAG, "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of server failed", e);
}
}
}
Here is the function I call at the beginning of AcceptThread in hopes to close everything to restart it
public void closeAllConnections() {
if (mmInStream != null) {
try {mmInStream.close();}
catch (Exception e){Log.e(TAG, "close() of connect socket failed", e);}
}
if (mmOutStream != null) {
try {mmOutStream.close();}
catch (Exception e){Log.e(TAG, "close() of connect socket failed", e);}
}
if (mmSocket != null) {
try {
mmSocket.close();
//mmSocket.connect();
}
catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
I've read through the Bluetooth Docs and SO questions but I haven't found anything that works for me and it gets a bit confusing for me as this is my first time connecting through BT.
Note
The only "fix" I have found when this happens is to turn off the BT adapter, force close the program, restart BT adapter and restart app, which is not good for obvious reasons. I tried restarting the adapter programmatically but I still can't connect.
Can anyone see what might be wrong in my BlutoothService class, which is where AcceptThread is located? Or how I would go about resolving this issue? Thanks!
Update
It does, in fact, seem like the connection is sometimes closed on one Thread and trying to reconnect on another. The problem is that I can't figure out what would cause it to try and connect on a separate Thread or how to fix it when this happens.
The only way I can successfully reproduce this is if my BT device is turned off then I turn the BT adapter off. When I turn everything back on then I get the exception and cannot connect. I have customers that it happens to randomly and periodically so I'm hoping the issues are related.
Well, part of my problem was a hardware issue that was found out to be a problem on the third-party manufacturers end. They're firmware wasn't quite right and when it was reading the BT address, it was occasionally being corrupted.
On the software side, it was running the AcceptThread in two separate Threads periodically. What I did to fix that was to create a function to close the socket and input/output streams...
public void closeAllConnections()
{
if (mmInStream != null)
{
try {mmInStream.close();}
catch (Exception e){Log.e(TAG, "close() of connect socket failed", e);}
}
if (mmOutStream != null)
{
try {mmOutStream.close();}
catch (Exception e){Log.e(TAG, "close() of connect socket failed", e);}
}
if (mmSocket != null)
{
try {
mmSocket.close();
Log.e("TAG", "close() of connect socket successfu;");
} catch (IOException e) {
Log.e("TAG", "close() of connect socket failed", e);}
}
Then in the BluetoothCom class, I noticed it wasn't always checking for the BT object to be null before trying to restart the service.
private void setupService() {
// Initialize the BluetoothChatService to perform bluetooth connections
if((mChatService != null) && (mChatService.getState() != 0)) {
mChatService.stop();
}
// I didn't have this so it would always start a new instance of the Service
if (mChatService == null)
mChatService = new BluetoothService(mHandler);
mChatService.start();
}
This seems to have helped and I no longer have those problems. However, now testing on the Samsung Galaxy Tab 4 and I am once again having connection issues but only on this device. Maybe this information can help someone and I will update my answer if I figure anything else out with the new problem.
Note: As stated above, this Bluetooth app uses modified code from Android's BluetoothChat app.
Also, I have read (and noticed) that different manufacturers implement the BT stack differently which can lead to headaches (at least if yo don't know enough about it).
Although this is old post but I recently contact same issue so I want to write down the way I solve it.
It seems your code is from Google samples BlutoothChat (as it looks same, sorry if I misunderstand). I also create my own application that base on this sample (on API level 10). I meet the accept() fail issues if I try to connect one device to other device but at the end I solve this question by simply remove some code in MainActivty
On the Google samples main activity it contain many methods when activity change (Start, Pause, etc).
Original code have this
#Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
if (mChatService != null) {
if (mChatService.getState() == ChatService.STATE_NONE) {
mChatService.start();
}
}
}
This code start the Chat Service and running the AcceptThread to listening incoming connections.
When application start, this method will be call "once" and create the AcceptThread. If you do any other things that make the main activity onPause() pause (In Google samples case, if you click menu to start device_list activity the main activity will pause), when the application back to main activity it will call create AcceptThread method "one more time", this cause the problem because one thread already running but you try to interrupt it. And at the end happen accept() fail error and throw java.io.IOException: Operation Canceled error.
So to avoid this is simply remove the codes in OnResume()
#Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
}
or if you don't want delete any codes because you afraid cause some problem, put this code (mChatService != null) mChatService.stop(); in...
#Override
public synchronized void onPause() {
super.onPause();
if (mChatService != null) mChatService.stop();
if(D) Log.e(TAG, "- ON PAUSE -");
}
Both works perfect in my project. Method 1 not create the new thread if activity resume, and Method 2 kill all the thread if you leave the current activity and disconnect all current connections if you already have one (it will start the thread again once you turn back). Method 1 wouldn't return any error but method 2 will throw accept fail again if you leave the current activity, so I suggest to use method 1.
Need to notice that this error usually happen after you modify Google samples BlutoothChat, it will never appear on the original app.
I have seen many post talk about this issue, but not see any one come out with this answer, so just want to share this. Hope this is helpful.
That exception should occur when the BluetoothServerSocket is closed or garbage collected. I suspect that the exception is happening on an OLD copy of the thread. So something like: When you create the new thread the old thread gets cancelled and thus the BluetoothServerSocket is closed and thus accept correctly fails with that error. Check this in the debugger and/or logging on which thread the various events occur; e.g. set breakpoints on the line after accept and perhaps on the cancel function, then inspect the thread IDs there -- is the exception occurring on a previous thread?

Service Discovery Failed on reconnect with bluetooth device

i am trying to connect a bluetooth device with my android app. so far its working fine.
Now the issue is when my device gets out of range , i am showing one dialog box and asking user to reconnect or not.
sometimes i am able to re-connect with the device and sometimes i do get error i.e.
Service Discovery Failed
and i really don't know why its happening
private class ConnectThread extends Thread {
public ConnectThread() {
try {
bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID);
} catch (IOException e) {
System.out.println("IO EXCEPTION" + e.getMessage() +"");
}
}
public void run() {
bluetoothAdapter.cancelDiscovery();
try {
// I AM GETTING ERROR HERE
bluetoothSocket.connect();
} catch (IOException connectException) {
Log.d("Exception : ConnectThread -> Run" , connectException.getMessage()+"");
try {
bluetoothSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
}
}
From experience, and actually having the same issue today,
If I was to speculate, I would say your other device, upon disconnection(link loss) does not immediately detect it has disconnected (it can take up to 30 seconds if I remember), or it just behaves badly.
Thus, it does not readvertise the service on SDP (does not open the socket again), so when Android initiates the connection(as client) your server fails - has no open socket.
You should post the other device logs. And try with a different other device - but same Android phone and code!
Again, just a guess.
I had the same problem; my solution may be specific to the device I am using, but I found that by sleeping the thread for 1000ms between the last communication to the socket and the socket.close(), it would restart successfully.

How can I enable NFC reader via API?

There is any way I can enable Android NFC reader using API?
So apparently there is no way to enable the NFC from the API, even though Google does so within their source code (see below).
If you look at a line from the API for NfcAdapter.isEnabled():
Return true if this NFC Adapter has
any features enabled.
Application may use this as a helper
to suggest that the user should turn
on NFC in Settings.
If this method returns false, the NFC
hardware is guaranteed not to generate
or respond to any NFC transactions.
It looks like there is no way to do it within the API. Bummer. Your best bet is a dialog to inform the user they need to enable it in the settings, and perhaps launch a settings intent.
EDIT: The following is from the source, but it looks like they didn't allow the user to implement the methods in the API (I'm confused about this).
I found this from the android source code to help enable and disable the adapter.
Relevant source:
public boolean onPreferenceChange(Preference preference,
Object value) {
// Turn NFC on/off
final boolean desiredState = (Boolean) value;
mCheckbox.setEnabled(false);
// Start async update of the NFC adapter state, as the API is
// unfortunately blocking...
new Thread("toggleNFC") {
public void run() {
Log.d(TAG, "Setting NFC enabled state to: "
+ desiredState);
boolean success = false;
if (desiredState) {
success = mNfcAdapter.enable();
} else {
success = mNfcAdapter.disable();
}
if (success) {
Log.d(TAG,
"Successfully changed NFC enabled state to "
+ desiredState);
mHandler.post(new Runnable() {
public void run() {
handleNfcStateChanged(desiredState);
}
});
} else {
Log.w(TAG, "Error setting NFC enabled state to "
+ desiredState);
mHandler.post(new Runnable() {
public void run() {
mCheckbox.setEnabled(true);
mCheckbox
.setSummary(R.string.nfc_toggle_error);
}
});
}
}
}.start();
return false;
}
I got it working through reflection
This code works on API 15, haven't checked it against other verions yet
public boolean changeNfcEnabled(Context context, boolean enabled) {
// Turn NFC on/off
final boolean desiredState = enabled;
mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
if (mNfcAdapter == null) {
// NFC is not supported
return false;
}
new Thread("toggleNFC") {
public void run() {
Log.d(TAG, "Setting NFC enabled state to: " + desiredState);
boolean success = false;
Class<?> NfcManagerClass;
Method setNfcEnabled, setNfcDisabled;
boolean Nfc;
if (desiredState) {
try {
NfcManagerClass = Class.forName(mNfcAdapter.getClass().getName());
setNfcEnabled = NfcManagerClass.getDeclaredMethod("enable");
setNfcEnabled.setAccessible(true);
Nfc = (Boolean) setNfcEnabled.invoke(mNfcAdapter);
success = Nfc;
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
} else {
try {
NfcManagerClass = Class.forName(mNfcAdapter.getClass().getName());
setNfcDisabled = NfcManagerClass.getDeclaredMethod("disable");
setNfcDisabled.setAccessible(true);
Nfc = (Boolean) setNfcDisabled.invoke(mNfcAdapter);
success = Nfc;
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
if (success) {
Log.d(TAG, "Successfully changed NFC enabled state to "+ desiredState);
} else {
Log.w(TAG, "Error setting NFC enabled state to "+ desiredState);
}
}
}.start();
return false;
}//end method
This requires 2 permissions though, put them in the manifest:
<!-- change NFC status toggle -->
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
The NFC button's state switches accordingly when the code is used, so there are no issues when doing it manually in the seetings menu.
If you can see the NfcService Application Source Code, there is a Interface file INfcAdapter.aidl. In the file two API's are there namely "boolean enable()" and "boolean disable()". You can directly use this API's to enable and disable NfcService through an android application. But the trick over here is that you can not compile the code using SDK provided by the Android. You have to compile the application using the a makefile. I have successfully build a application.
I hope this forum would be help you to resolve this issue as well to get the clear understanding on the NFC power on/off API barries.
http://ranjithdroid.blogspot.com/2015/11/turn-onoff-android-nfc-by.html

Categories

Resources