I guess this is a more generic question, but my Android program seems to call onResume in the main UI thread in between these two thread-creation-related function calls. This causes other invocations that I don't want to happen, and so far the only way around it that I've found is setting global flags (which I don't like, and is bad programming practice in my opinion). It looks rather like this:
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
Somehow, in between these calls (which are made from the UI thread by a BluetoothCommHandler object), onResume gets called. If anyone could point me to a good source of when onResume and other activity lifecycle events are triggered, I would be much obliged. Further, I checked this: http://developer.android.com/reference/android/app/Activity.html, and it didn't seem to have any hints that I could find.
A last note - the onResume ALWAYS gets called in between those two commands getting called, and that makes me think it's not really a thread-switching issue.
I've also just noticed that the onResume gets called as the pair of an onPause that gets called WAY earlier - still no idea why it happens precisely between these two function calls though.
EDIT: Code is included below.
Invocation of the bluetooth handler object:
mBComm = new BluetoothCommHandler(this, mHandler);
The onResume function in the main UI thread (the mNoRestartFlag
is so that this particular bit gets called only when I want it to. It's NOT the flag I'm referring to above - it handles another case that I'm not speaking about here):
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,
mFilters, mTechLists);
Log.i(TAG, "OnResume called.");
if(mBComm != null && !mNoRestartFlag) {
mBComm.start();
}
}
Activity OptionsHandler (same as DeviceListActivity) declaration in the AndroidManifest (note that it's a Theme.Dialog styled activity, which pops on top of the UI thread, causing the onPause I've referred to above):
activity android:name=".OptionsHandler"
android:label="@string/select_device"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
The actual connectThread gets created:
public synchronized void connect(BluetoothDevice bd) {
Log.i(TAG, "connect called from inside BluetoothCommHandler");
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
mConnectThread = new ConnectThread(bd);
mConnect开发者_JAVA技巧Thread.start();
}
The creation and running of the ConnectThread (the mDontKill
flag IS the flag I am mentioning above that I use to bypass the onResume symptoms):
public ConnectThread(BluetoothDevice bd) {
Log.i(TAG, "created ConnectThread");
mBD = bd;
BluetoothSocket bs = null;
try {
bs = mBD.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.i(TAG, "Could not create an RFCOMM socket!", e);
}
mBS = bs;
if (mBS != null) Log.i(TAG, "BluetoothSocket acquired");
else Log.i(TAG, "BluetoothSocket null!");
mDontKillFlag = true;
}
public void run() {
Log.i(TAG, "BEGIN ConnectThread");
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
mDontKillFlag = false;
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mBS.connect();
Log.i(TAG, "Connected to BluetoothDevice");
} catch (IOException e) {
Log.i(TAG, e.toString());
// Close the socket
try {
mBS.close();
} catch (IOException e2) {
Log.i(TAG, "unable to close RFCOMM socket", e2);
}
Log.i(TAG, "About to call connectionFailed");
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommHandler.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mBS, mBD);
}
The actual start() function that causes the issues:
public synchronized void start() {
if (D) Log.i(TAG, "start called from inside BluetoothCommHandler");
// Cancel any thread attempting to make a connection
if (mConnectThread != null && !mDontKillFlag)
{mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{mConnectedThread.cancel(); mConnectedThread = null;}
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
Legend: mBS
is a member variable that is a BluetoothSocket and mDB
is a member variable that is a BluetoothDevice.
To summarize, I create a BluetoothCommHandler object on the UI Thread, this tries to create a ConnectThread and then while calling the accept() command on a bluetooth socket, it fails because the cancel() function for the thread has been called (that simply has a try-catch that closes the socket). This cancel is called from the start() function that is listed above, that is called by the onResume function. The onResume is the complement of the onPause that is getting called because of a selector dialog appearing over the main UI activity. This onResume seems to always get called in between the first two lines of code that I mentioned pre-EDIT. I'm trying to figure out why it always happens exactly THERE, so that I can have an accept() occur without the socket being closed.
精彩评论