效果图:
SearchDeviceActivity.java
[java] view plaincopy
package com.hello.project;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
public class SearchDeviceActivity extends Activity implements OnItemClickListener{
private BluetoothAdapter blueadapter=null;
private DeviceReceiver mydevice=new DeviceReceiver();
private List<String> deviceList=new ArrayList<String>();
private ListView deviceListview;
private Button btserch;
private ArrayAdapter<String> adapter;
private boolean hasregister=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.finddevice);
setView();
setBluetooth();
}
private void setView(){
deviceListview=(ListView)findViewById(R.id.devicelist);
adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceList);
deviceListview.setAdapter(adapter);
deviceListview.setOnItemClickListener(this);
btserch=(Button)findViewById(R.id.start_seach);
btserch.setOnClickListener(new ClinckMonitor());
}
@Override
protected void onStart() {
//注册蓝牙接收广播
if(!hasregister){
hasregister=true;
IntentFilter filterStart=new IntentFilter(BluetoothDevice.ACTION_FOUND);
IntentFilter filterEnd=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mydevice, filterStart);
registerReceiver(mydevice, filterEnd);
}
super.onStart();
}
@Override
protected void onDestroy() {
if(blueadapter!=null&&blueadapter.isDiscovering()){
blueadapter.cancelDiscovery();
}
if(hasregister){
hasregister=false;
unregisterReceiver(mydevice);
}
super.onDestroy();
}
/**
* Setting Up Bluetooth
*/
private void setBluetooth(){
blueadapter=BluetoothAdapter.getDefaultAdapter();
if(blueadapter!=null){ //Device support Bluetooth
//确认开启蓝牙
if(!blueadapter.isEnabled()){
//请求用户开启
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, RESULT_FIRST_USER);
//使蓝牙设备可见,方便配对
Intent in=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
in.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200);
startActivity(in);
//直接开启,不经过提示
blueadapter.enable();
}
}
else{ //Device does not support Bluetooth
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("No bluetooth devices");
dialog.setMessage("Your equipment does not support bluetooth, please change device");
dialog.setNegativeButton("cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
}
}
/**
* Finding Devices
*/
private void findAvalibleDevice(){
//获取可配对蓝牙设备
Set<BluetoothDevice> device=blueadapter.getBondedDevices();
if(blueadapter!=null&&blueadapter.isDiscovering()){
deviceList.clear();
adapter.notifyDataSetChanged();
}
if(device.size()>0){ //存在已经配对过的蓝牙设备
for(Iterator<BluetoothDevice> it=device.iterator();it.hasNext();){
BluetoothDevice btd=it.next();
deviceList.add(btd.getName()+'\n'+btd.getAddress());
adapter.notifyDataSetChanged();
}
}else{ //不存在已经配对过的蓝牙设备
deviceList.add("No can be matched to use bluetooth");
adapter.notifyDataSetChanged();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(resultCode){
case RESULT_OK:
findAvalibleDevice();
break;
case RESULT_CANCELED:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
private class ClinckMonitor implements OnClickListener{
@Override
public void onClick(View v) {
if(blueadapter.isDiscovering()){
blueadapter.cancelDiscovery();
btserch.setText("repeat search");
}else{
findAvalibleDevice();
blueadapter.startDiscovery();
btserch.setText("stop search");
}
}
}
/**
* 蓝牙搜索状态广播监听
* @author Andy
*
*/
private class DeviceReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action =intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){ //搜索到新设备
BluetoothDevice btd=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//搜索没有配过对的蓝牙设备
if (btd.getBondState() != BluetoothDevice.BOND_BONDED) {
deviceList.add(btd.getName()+'\n'+btd.getAddress());
adapter.notifyDataSetChanged();
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ //搜索结束
if (deviceListview.getCount() == 0) {
deviceList.add("No can be matched to use bluetooth");
adapter.notifyDataSetChanged();
}
btserch.setText("repeat search");
}
}
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
Log.e("msgParent", "Parent= "+arg0);
Log.e("msgView", "View= "+arg1);
Log.e("msgChildView", "ChildView= "+arg0.getChildAt(pos-arg0.getFirstVisiblePosition()));
final String msg = deviceList.get(pos);
if(blueadapter!=null&&blueadapter.isDiscovering()){
blueadapter.cancelDiscovery();
btserch.setText("repeat search");
}
AlertDialog.Builder dialog = new AlertDialog.Builder(this);// 定义一个弹出框对象
dialog.setTitle("Confirmed connecting device");
dialog.setMessage(msg);
dialog.setPositiveButton("connect",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
BluetoothMsg.BlueToothAddress=msg.substring(msg.length()-17);
if(BluetoothMsg.lastblueToothAddress!=BluetoothMsg.BlueToothAddress){
BluetoothMsg.lastblueToothAddress=BluetoothMsg.BlueToothAddress;
}
Intent in=new Intent(SearchDeviceActivity.this,BluetoothActivity.class);
startActivity(in);
}
});
dialog.setNegativeButton("cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
BluetoothMsg.BlueToothAddress = null;
}
});
dialog.show();
}
}
BluetoothMsg.java
[java] view plaincopy
package com.hello.project;
public class BluetoothMsg {
/**
* 蓝牙连接类型
* @author Andy
*
*/
public enum ServerOrCilent{
NONE,
SERVICE,
CILENT
};
//蓝牙连接方式
public static ServerOrCilent serviceOrCilent = ServerOrCilent.NONE;
//连接蓝牙地址
public static String BlueToothAddress = null,lastblueToothAddress=null;
//通信线程是否开启
public static boolean isOpen = false;
}
finddevice.xml
[java] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/devices"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom = "true"
android:id= "@+id/bt_bottombar">
<Button android:id="@+id/start_seach"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/start_service"
android:text="Began to search"/>
</RelativeLayout>
<ListView
android:id="@+id/devicelist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollingCache="false"
android:divider="#ffc6c6c6"
android:layout_weight="1.0"
android:layout_above = "@id/bt_bottombar"
android:layout_below="@id/devices"
/>
</RelativeLayout>
BluetoothActivity.java
[java] view plaincopy
package com.hello.project;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class BluetoothActivity extends Activity{
/* 一些常量,代表服务器的名称 */
public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
private ListView mListView;
private Button sendButton;
private Button disconnectButton;
private EditText editMsgView;
private ArrayAdapter<String> mAdapter;
private List<String> msgList=new ArrayList<String>();
Context mContext;
private BluetoothServerSocket mserverSocket = null;
private ServerThread startServerThread = null;
private clientThread clientConnectThread = null;
private BluetoothSocket socket = null;
private BluetoothDevice device = null;
private readThread mreadThread = null;;
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
mContext = this;
init();
}
private void init() {
mAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, msgList);
mListView = (ListView) findViewById(R.id.list);
mListView.setAdapter(mAdapter);
mListView.setFastScrollEnabled(true);
editMsgView= (EditText)findViewById(R.id.MessageText);
editMsgView.clearFocus();
sendButton= (Button)findViewById(R.id.btn_msg_send);
sendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String msgText =editMsgView.getText().toString();
if (msgText.length()>0) {
sendMessageHandle(msgText);
editMsgView.setText("");
editMsgView.clearFocus();
//close InputMethodManager
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editMsgView.getWindowToken(), 0);
}else
Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
}
});
disconnectButton= (Button)findViewById(R.id.btn_disconnect);
disconnectButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT)
{
shutdownClient();
}
else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE)
{
shutdownServer();
}
BluetoothMsg.isOpen = false;
BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.NONE;
Toast.makeText(mContext, "已断开连接!", Toast.LENGTH_SHORT).show();
}
});
}
private Handler LinkDetectedHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();
if(msg.what==1)
{
msgList.add((String)msg.obj);
}
else
{
msgList.add((String)msg.obj);
}
mAdapter.notifyDataSetChanged();
mListView.setSelection(msgList.size() - 1);
}
};
@Override
protected void onResume() {
BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.CILENT;
if(BluetoothMsg.isOpen)
{
Toast.makeText(mContext, "连接已经打开,可以通信。如果要再建立连接,请先断开!", Toast.LENGTH_SHORT).show();
return;
}
if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.CILENT)
{
String address = BluetoothMsg.BlueToothAddress;
if(!address.equals("null"))
{
device = mBluetoothAdapter.getRemoteDevice(address);
clientConnectThread = new clientThread();
clientConnectThread.start();
BluetoothMsg.isOpen = true;
}
else
{
Toast.makeText(mContext, "address is null !", Toast.LENGTH_SHORT).show();
}
}
else if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.SERVICE)
{
startServerThread = new ServerThread();
startServerThread.start();
BluetoothMsg.isOpen = true;
}
super.onResume();
}
//开启客户端
private class clientThread extends Thread {
@Override
public void run() {
try {
//创建一个Socket连接:只需要服务器在注册时的UUID号
// socket = device.createRfcommSocketToServiceRecord(BluetoothProtocols.OBEX_OBJECT_PUSH_PROTOCOL_UUID);
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
//连接
Message msg2 = new Message();
msg2.obj = "请稍候,正在连接服务器:"+BluetoothMsg.BlueToothAddress;
msg2.what = 0;
LinkDetectedHandler.sendMessage(msg2);
socket.connect();
Message msg = new Message();
msg.obj = "已经连接上服务端!可以发送信息。";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
//启动接受数据
mreadThread = new readThread();
mreadThread.start();
}
catch (IOException e)
{
Log.e("connect", "", e);
Message msg = new Message();
msg.obj = "连接服务端异常!断开连接重新试一试。";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
}
}
};
//开启服务器
private class ServerThread extends Thread {
@Override
public void run() {
try {
/* 创建一个蓝牙服务器
* 参数分别:服务器名称、UUID */
mserverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Log.d("server", "wait cilent connect...");
Message msg = new Message();
msg.obj = "请稍候,正在等待客户端的连接...";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
/* 接受客户端的连接请求 */
socket = mserverSocket.accept();
Log.d("server", "accept success !");
Message msg2 = new Message();
String info = "客户端已经连接上!可以发送信息。";
msg2.obj = info;
msg.what = 0;
LinkDetectedHandler.sendMessage(msg2);
//启动接受数据
mreadThread = new readThread();
mreadThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
};
/* 停止服务器 */
private void shutdownServer() {
new Thread() {
@Override
public void run() {
if(startServerThread != null)
{
startServerThread.interrupt();
startServerThread = null;
}
if(mreadThread != null)
{
mreadThread.interrupt();
mreadThread = null;
}
try {
if(socket != null)
{
socket.close();
socket = null;
}
if (mserverSocket != null)
{
mserverSocket.close();/* 关闭服务器 */
mserverSocket = null;
}
} catch (IOException e) {
Log.e("server", "mserverSocket.close()", e);
}
};
}.start();
}
/* 停止客户端连接 */
private void shutdownClient() {
new Thread() {
@Override
public void run() {
if(clientConnectThread!=null)
{
clientConnectThread.interrupt();
clientConnectThread= null;
}
if(mreadThread != null)
{
mreadThread.interrupt();
mreadThread = null;
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
};
}.start();
}
//发送数据
private void sendMessageHandle(String msg)
{
if (socket == null)
{
Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
return;
}
try {
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
msgList.add(msg);
mAdapter.notifyDataSetChanged();
mListView.setSelection(msgList.size() - 1);
}
//读取数据
private class readThread extends Thread {
@Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = socket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (true) {
try {
// Read from the InputStream
if( (bytes = mmInStream.read(buffer)) > 0 )
{
byte[] buf_data = new byte[bytes];
for(int i=0; i<bytes; i++)
{
buf_data[i] = buffer[i];
}
String s = new String(buf_data);
Message msg = new Message();
msg.obj = s;
msg.what = 1;
LinkDetectedHandler.sendMessage(msg);
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
break;
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT)
{
shutdownClient();
}
else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE)
{
shutdownServer();
}
BluetoothMsg.isOpen = false;
BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.NONE;
}
}
chat.xml
[java] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id= "@+id/edit_bottombar"
android:layout_alignParentBottom = "true">
<Button android:id="@+id/btn_disconnect"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft ="true"
android:text="断开"/>
<Button android:id="@+id/btn_msg_send"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_alignParentRight ="true"
android:text="发送"/>
<EditText
android:layout_width="fill_parent"
android:layout_height = "wrap_content"
android:layout_toLeftOf="@id/btn_msg_send"
android:layout_toRightOf="@+id/btn_disconnect"
android:hint = "说点什么呢?"
android:textSize="15dip"
android:id = "@+id/MessageText"/>
</RelativeLayout>
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollingCache="false"
android:divider="#ffc6c6c6"
android:layout_weight="1.0"
android:layout_above = "@id/edit_bottombar"
android:layout_below="@id/container"
/>
</RelativeLayout>
最后别忘了加入权限
[java] view plaincopy
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
扩展:蓝牙后台配对实现(网上看到的整理如下)
[java] view plaincopy
static public boolean createBond(Class btClass, BluetoothDevice btDevice)
throws Exception {
Method createBondMethod = btClass.getMethod("createBond");
Log.i("life", "createBondMethod = " + createBondMethod.getName());
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
return returnValue.booleanValue();
}
static public boolean setPin(Class btClass, BluetoothDevice btDevice,
String str) throws Exception {
Boolean returnValue = null;
try {
Method removeBondMethod = btClass.getDeclaredMethod("setPin",
new Class[] { byte[].class });
returnValue = (Boolean) removeBondMethod.invoke(btDevice,
new Object[] { str.getBytes() });
Log.i("life", "returnValue = " + returnValue);
} catch (SecurityException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnValue;
}
// 取消用户输入
static public boolean cancelPairingUserInput(Class btClass,
BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
// cancelBondProcess()
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
Log.i("life", "cancelPairingUserInputreturnValue = " + returnValue);
return returnValue.booleanValue();
}
然后监听蓝牙配对的广播 匹配“android.bluetooth.device.action.PAIRING_REQUEST”这个action
然后调用上面的setPin(mDevice.getClass(), mDevice, "1234"); // 手机和蓝牙采集器配对
createBond(mDevice.getClass(), mDevice);
cancelPairingUserInput(mDevice.getClass(), mDevice);
mDevice是你要去连接的那个蓝牙的对象 , 1234为配对的pin码