我正在为Android构建一个简单的蓝牙应用程序,就像一个小小的学习项目。
我知道通常在android AsyncTask
中运行后台线程的正常方法,但我不想使用它。我只是使用Callable
和NewFixedThreadPool
因为我不像AsyncTask
那样熟悉它,我想稍微学习一下。
我正在尝试在后台线程中扫描可发现的设备。在提交可调用之前,我在Activity上显示了一个进度条,在调用方法结束时,我调用了一个回调到主线程,使进度条再次消失,还有一些其他任务。
虽然我的进度条的可见性设置回GONE
,但在此之后应该打印出一些日志消息,但它们永远不会打印出来。
此外,我无法拨打unregisterReceiver()
。
我的Callable类:
public class ScanTask implements Callable{
private static final String TAG = "ScanTask";
private BluetoothAdapter mAdapter;
private ArrayList<BluetoothDevice> mDevices = new ArrayList<>();
private BroadcastReceiver mBTReceiver = new BTReceiver();
private Context mContext;
private static OnCompletedListener mCompletionListener;
public interface OnCompletedListener{
void onComplete();
}
public static void setOnCompletedListener(OnCompletedListener listener){
mCompletionListener = listener;
}
public ScanTask(BluetoothAdapter adapter, Context context, ArrayList<BluetoothDevice> devices){ //constuctor for no future
mAdapter = adapter;
mContext = context;
mDevices = devices;
}
public ScanTask(BluetoothAdapter adapter, Context context){//constructor for future
mAdapter = adapter;
mContext = context;
}
public Void call(){//Future will be replace with return type
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
mContext.registerReceiver(mBTReceiver, filter);
mAdapter.startDiscovery();
try {
Thread.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
//callback signals completion
Log.d(TAG, "before oncomplete " + Thread.currentThread());
mContext.unregisterReceiver(mBTReceiver);
Log.d(TAG, "after unRegister");
mCompletionListener.onComplete();
Log.d(TAG, "after oncomplete");
return null;
}
public ArrayList<BluetoothDevice> getDevices(){
return mDevices;
}
private class BTReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action){
case BluetoothDevice.ACTION_FOUND:
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDevices.add(device);
break;
}
}
}
}
以及我的活动中的相关代码:
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.searchOption:
Log.d(TAG, Thread.currentThread().toString());
mProgressBar.setVisibility(ProgressBar.VISIBLE);
ScanTask discovery = new ScanTask(btAdapter, this); //ScanTask discovery = new ScanTask(btAdapter, this, mDevices); for no future
discovery.setOnCompletedListener(new ScanTask.OnCompletedListener() {
@Override
public void onComplete() {
Log.d(TAG, Thread.currentThread().toString());
mProgressBar.setVisibility(ProgressBar.GONE);
mDevices = discovery.getDevices();
}
});
Log.d(TAG, "after setVisibilty");
pool.submit(discovery);
break;
}
return true;
}