以下是android5.1的相关操作,蓝牙操作的基础是BluetoothAdapter,在整个系统中,该类仅有一个实例。
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
判断蓝牙是否可用:
Boolean BTis = mBluetoothAdapter.isEnabled(); // 返回值为true表示可用
获取蓝牙的状态:
Int posi = mBluetoothAdapter.getState();
对应的状态如下:
public staticfinal int STATE_OFF = 10;
public staticfinal int STATE_TURNING_ON = 11;
public staticfinal int STATE_ON = 12;
public staticfinal int STATE_TURNING_OFF = 13;
···
打开/关闭蓝牙
mBluetoothAdapter.enable(); //打开蓝牙
mBluetoothAdapter.disable(); // 关闭蓝牙
设置蓝牙可见(其他设备可以搜索到该蓝牙)
利用反射机制
private void setbtvisible() {
int timeout = 3600; // 可知可见时间,单位/s
BluetoothAdapter adapter=BluetoothAdapter.getDefaultAdapter();
try {
Method setDiscoverableTimeout =
BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);
setDiscoverableTimeout.setAccessible(true);
Method setScanMode =
BluetoothAdapter.class.getMethod("setScanMode", int.class,int.class);
setScanMode.setAccessible(true);
setDiscoverableTimeout.invoke(adapter, timeout);
setScanMode.invoke(adapter,
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,timeout);
} catch (Exception e) {
e.printStackTrace();
}
}
开始/结束 扫描
mBluetoothAdapter.startDiscovery(); // 开始扫描
mBluetoothAdapter.cancelDiscovery();// 结束扫描
配对又分为主动配对和被动配对,在配对时,可以自动配对,就是不弹出配对码,这些代码比较长,就不贴出来了。
连接蓝牙耳机
privateBluetoothHeadset mBluetoothHeadset;
在使用之前的初始化,一般在oncreate函数或者在构造函数中初始化
private void initOrCloseBtCheck(boolean init) {
if (init) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.getProfileProxy(mcontext, new ServiceListener() {
public void onServiceConnected(int profile,BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
}
}, BluetoothProfile.HEADSET);
} else {
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET,mBluetoothHeadset);
}
}
初始化之后就可以连接了, device为蓝牙耳机设备。
public void conheadset(BluetoothDevice device) throws NoSuchMethodException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = mBluetoothHeadset.getClass().getDeclaredMethod("connect",BluetoothDevice.class);
m.setAccessible(true);
boolean successHeadset = (Boolean)m.invoke(mBluetoothHeadset, device);
}
发送文件
向蓝牙设备发送文件,输入2个参数,蓝牙设备以及需要发送的文件。
发送文件一般需要单开一个线程,并且在发送之前必须得检查文件的格式,有的格式并不支持,可以一次性发送多个文件。
private Handler mOthHandler;
public void sendfile(BluetoothDevice device,
final ArrayList filePaths) {
final BluetoothDevice remount = device;
if (filePaths != null) {
if (null == mOthHandler) {
HandlerThread handlerThread = new HandlerThread("other_thread");
handlerThread.start();
mOthHandler = new Handler(handlerThread.getLooper());
}
mOthHandler.post(new Runnable() {
@Override
public void run() {
Log.d("fang ", "send_bgin");
final ArrayList value = new ArrayList();
boolean audio = true;
for (int i = 0; i < filePaths.size(); i++) {
String path = filePaths.get(i);
String mimeType = getMIMEType(new File(path));
if (!mimeType.equals("audio/*")) {
audio = false;
}
value.add(Uri.parse("file://" + path));
}
final Bundle b = new Bundle();
b.putParcelableArrayList(Intent.EXTRA_STREAM, value);
Intent intent = new Intent();
intent.setAction("jsr.watch.send_bt");
intent.setType(audio ? "audio/*" : "*/*");
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, remount);
intent.putExtras(b);
mcontext.startActivity(intent);
}
});
}
}
public static String getMIMEType(File f) {
String type = "";
String fileName = f.getName();
String ext = fileName.substring(fileName.lastIndexOf(".") + 1,
fileName.length()).toLowerCase();
if (ext.equals("jpg") || ext.equals("jpeg") || ext.equals("gif")
|| ext.equals("png") || ext.equals("bmp")) {
type = "image/*";
} else if (ext.equals("mp3") || ext.equals("amr") || ext.equals("wma")
|| ext.equals("aac") || ext.equals("m4a") || ext.equals("mid")
|| ext.equals("xmf") || ext.equals("ogg") || ext.equals("wav")
|| ext.equals("qcp") || ext.equals("awb")) {
type = "audio/*";
} else if (ext.equals("3gp") || ext.equals("mp4") || ext.equals("avi")) {
type = "video/*";
} else if (ext.equals("apk")) {
type = "application/vnd.android.package-archive";
} else if (ext.equals("vcf")) {
type = "text/x-vcard";
} else if (ext.equals("txt")) {
type = "text/plain";
} else {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
if (type == null)
type = "*/*";
}
return type;
}
现在问题是,我们发送了intent.setAction("jsr.watch.send_bt")这样一个intent,会启动路径
packages\apps\Bluetooth\src\com\android\bluetooth\opp
下的BluetoothOppLauncherActivity,在其onCreate函数最后一个else之前添加一个判断,就是上面所发的intent
else if(action.equals("jsr.watch.send_bt")){
final String mimeType = intent.getType();
final ArrayList uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (mimeType != null && uris != null) {
Thread t = new Thread(new Runnable() {
public void run() {
BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
.saveSendingFileInfo(mimeType,uris, false);
}
});
t.start();
BluetoothDevice remoteDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Intent intentbt = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
intentbt.putExtra(BluetoothDevice.EXTRA_DEVICE, remoteDevice);
intentbt.setClassName("com.android.bluetooth",
"com.android.bluetooth.opp.BluetoothOppReceiver");
sendBroadcast(intentbt);
finish();
return;
} else {
Log.e(TAG, "type is null; or sending files URIs are null");
finish();
return;
}