蓝牙即时通信

代码地址:http://download.csdn.net/detail/u011324501/9418403

备注:亲测可用,若连接失败请关闭Bluetooth chat 重新打开。

1.BluetoothAdapter 顾名思义,蓝牙适配器,直到我们建立bluetoothSocket连接之前,都要不断操作它

      BluetoothAdapter里的方法很多,常用的有以下几个:

      cancelDiscovery() 根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索

      disable()关闭蓝牙

      enable()打开蓝牙,这个方法打开蓝牙不会弹出提示,更多的时候我们需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户:

Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enabler,reCode);//同startActivity(enabler);

      getAddress()获取本地蓝牙地址

      getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter

      getName()获取本地蓝牙名称

      getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备

      getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)

      isDiscovering()判断当前是否正在查找设备,是返回true

      isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false

     listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步

      startDiscovery()开始搜索,这是搜索的第一步

 2.BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备

      createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket


这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter

关于手机蓝牙各类服务对应的UUID:http://blog.csdn.net/yuanbieli/article/details/6691502    

3.BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,这个类一种只有三个方法
两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接close()关闭蓝牙连接。

4.BluetoothSocket,跟BluetoothServerSocket相对,是客户端

一共5个方法,不出意外,都会用到

      close(),关闭

      connect()连接

      getInptuStream()获取输入流

      getOutputStream()获取输出流

      getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备

5、蓝牙权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 

 <uses-permission android:name="android.permission.BLUETOOTH"/> 

main.xml布局代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >
	
    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="fill_parent"
        android:layout_height="250dip"        
        android:scrollbars="vertical" >

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
    </ScrollView>
	<RelativeLayout
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content" >
      <Button
          android:id="@+id/connect"
          android:layout_width="150dip"
          android:layout_height="wrap_content"
          android:layout_alignParentBottom="true"
          android:layout_alignParentRight="true"
          android:layout_marginBottom="16dp"
          android:onClick="onConnectButtonClicked"
          android:text="@string/connect"
          android:textColor="#FFD700" />

      <Button
          android:id="@+id/send"
          android:text="@string/send"
          android:layout_width="150dip"
          android:textColor="#FFD700"
          android:layout_height="wrap_content"
          android:layout_alignBaseline="@+id/connect"
          android:layout_alignBottom="@+id/connect"
          android:layout_alignParentLeft="true" />

      <EditText
          android:id="@+id/input"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_above="@+id/connect"
          android:layout_alignParentLeft="true"
          android:ems="10"
          android:inputType="none" />
      
      </RelativeLayout>

</LinearLayout>
MainActivity.java代码:

package com.example.bluetooth;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

/*
 * 若连接失败请关闭Bluetooth chat 重新打开。
 *
 * */
public class MainActivity extends Activity {

	private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); // 获取本地蓝牙适配器,即蓝牙设备
	public static String smsg = ""; // 显示用数据缓存
	private String fmsg = ""; // 保存用数据缓存
	BluetoothDevice _device = null; // 蓝牙设备
	private ScrollView scrollview; // 翻页句柄
	public static BluetoothSocket _socket = null; // 蓝牙通信socket
	private final static int REQUEST_CONNECT_DEVICE = 1; // 宏定义查询设备句柄
	//private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; // SPP服务UUID号
	private final static String MY_UUID = "fa87c0d0-afac-11de-8a39-0800200c9a66"; // SPP服务UUID号
	
	private InputStream is; // 输入流,用来接收蓝牙数据
	boolean _discoveryFinished = false;
	boolean bRun = true;
	boolean abc = true;
	boolean bThread = false;
	
	private TextView textview;
	private Button connect;
	private Button send;
	private EditText input;
	private String inputdate;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		initUI();
		
	}

	//初始化ui
	private void initUI() {
		// TODO Auto-generated method stub
		bluetooth();
		textview = (TextView)findViewById(R.id.textview);
		connect = (Button)findViewById(R.id.connect);
		input = (EditText)findViewById(R.id.input);
		send = (Button)findViewById(R.id.send);
		send.setOnClickListener(new sendListener());
		scrollview = (ScrollView)findViewById(R.id.scrollview);
		
	}
	//发送数据
	public class sendListener implements OnClickListener{

		@Override
		public void onClick(View arg0) {
			// TODO Auto-generated method stub
			inputdate = input.getText().toString();//获取发送数据
			if(inputdate!=null && _device!=null){
				send(inputdate);
			}else{
				Toast.makeText(getApplication(), "请输入数据或查看蓝牙是否有连接!", Toast.LENGTH_SHORT).show();
			}
			
		}
		
	}
	
	public void bluetooth(){
		// 如果打开本地蓝牙设备不成功,提示信息,结束程序
		if (_bluetooth == null) {
			Toast.makeText(this, "无法打开手机蓝牙,请确认手机是否有蓝牙功能!", Toast.LENGTH_LONG)
					.show();
			finish();
			return;
		}

		// 设置设备可以被搜索
		new Thread() {
			public void run() {
				if (_bluetooth.isEnabled() == false) {
					_bluetooth.enable();
				}
			}
		}.start();
	}

	// 接收活动结果,响应startActivityForResult()
		public void onActivityResult(int requestCode, int resultCode, Intent data) {
			switch (requestCode) {
			case REQUEST_CONNECT_DEVICE: // 连接结果,由DeviceListActivity设置返回
				// 响应返回结果
				if (resultCode == Activity.RESULT_OK) { // 连接成功,由DeviceListActivity设置返回
					// MAC地址,由DeviceListActivity设置返回
					String address = data.getExtras().getString(
							DeviceListActivity.EXTRA_DEVICE_ADDRESS);
					// 得到蓝牙设备句柄
					_device = _bluetooth.getRemoteDevice(address);

					// 用服务号得到socket
					try {
						_socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
						// 创建蓝牙客户端
					} catch (IOException e) {
						Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT).show();
					}
					// 连接socket					
					try {
						_socket.connect();
						Toast.makeText(this, "连接" + _device.getName() + "成功!",
								Toast.LENGTH_SHORT).show();
						connect.setText("断开");
					} catch (IOException e) {
						try {
							Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT)
									.show();
							_socket.close();
							_socket = null;
						} catch (IOException ee) {
							Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT)
									.show();
						}

						return;
					}

					// 打开接收线程
					try {
						is = _socket.getInputStream(); // 得到蓝牙数据输入流
					} catch (IOException e) {
						Toast.makeText(this, "接收数据失败!", Toast.LENGTH_SHORT).show();
						return;
					}
					if (bThread == false) {
						ReadThread.start();
						bThread = true;
					} else {
						bRun = true;
					}
				}
				break;
			default:
				break;
			}
		}
		
		// 接收数据线程
		Thread ReadThread = new Thread() {
			public void run() {
				int num = 0;
				byte[] buffer = new byte[1024];
				byte[] buffer_new = new byte[1024];
				int i = 0;
				int n = 0;
				bRun = true;
				// 接收线程
				while (true) {
					try {
						while (is.available() == 0) {
							while (bRun == false) {
							}
						}
						while (true) {
							num = is.read(buffer); // 读入数据
							n = 0;

							String s0 = new String(buffer, 0, num);
							fmsg += s0; // 保存收到数据
							for (i = 0; i < num; i++) {
								if ((buffer[i] == 0x0d) && (buffer[i + 1] == 0x0a)) {
									buffer_new[n] = 0x0a;
									i++;

								} else {
									buffer_new[n] = buffer[i];
								}
								n++;
							}
							String s = new String(buffer_new, 0, n);
							if (abc == true)
								smsg += s+"\n"; // 写入接收缓存,并换行

							if (is.available() == 0)
								break; // 短时间没有数据才跳出进行显示
						}
						// 发送显示消息,进行显示刷新
						handler.sendMessage(handler.obtainMessage());
					} catch (IOException e) {
					}
				}
			}
		};

		// 消息处理队列
		Handler handler = new Handler() {
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				if (abc == true) {
					textview.setText(smsg); //显示数据
					//smsg = "";
					scrollview.scrollTo(0, textview.getMeasuredHeight()); // 跳至数据最后一页
				}
			}
		};
		// 关闭程序掉用处理部分
		public void onDestroy() {
			super.onDestroy();
			if (_socket != null) // 关闭连接socket
				try {
					_socket.close();
				} catch (IOException e) {
				}
			// _bluetooth.disable(); //关闭蓝牙服务
		}
		
		// 连接按键响应函数
		public void onConnectButtonClicked(View v) {
			if (_bluetooth.isEnabled() == false) { // 如果蓝牙服务不可用则提示
				Toast.makeText(this, " 打开蓝牙中...", Toast.LENGTH_LONG).show();
				return;
			}

			// 如未连接设备则打开DeviceListActivity进行设备搜索			
			if (_socket == null) {
				Intent serverIntent = new Intent(this, DeviceListActivity.class); // 跳转程序设置
				startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); // 设置返回宏定义
			} else {
				// 关闭连接socket
				try {

					is.close();
					_socket.close();
					_socket = null;
					bRun = false;
					connect.setText("连接");
				} catch (IOException e) {
				}
			}
			return;
		}
			
		// 通过蓝牙发送数据
		public void send(String msg) {
			// int i=0;
			// int n=0;
			try {
				// System.out.println(111111);
				OutputStream os = _socket.getOutputStream(); // 蓝牙连接输出流
				byte[] bos = msg.getBytes();
				// bytesToHexString(bos);
				os.write(bos);
				System.out.println("发送成功");
			} catch (IOException e) {
				System.out.println("发送失败");
			}
		}
		
		/*
		 *  发送数据
		 */
		public void sendmesg(String msg) {
			int i = 0;
			int n = 0;
			try {
				OutputStream os = _socket.getOutputStream(); // 蓝牙连接输出流
				// byte[] bos = edit0.getText().toString().getBytes();
				byte[] bos = msg.getBytes();
				for (i = 0; i < bos.length; i++) {
					if (bos[i] == 0x0a)
						n++;
				}
				byte[] bos_new = new byte[bos.length + n];
				n = 0;
				for (i = 0; i < bos.length; i++) { // 手机中换行为0a,将其改为0d 0a后再发送
					if (bos[i] == 0x0a) {
						bos_new[n] = 0x0d;
						n++;
						bos_new[n] = 0x0a;
					} else {
						bos_new[n] = bos[i];
					}
					n++;
				}

				os.write(bos_new);

			} catch (IOException e) {
			}
		}
		
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}
DeviceListActivity.java代码:

package com.example.bluetooth;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class DeviceListActivity extends Activity {
	// 调试用
	private static final String TAG = "DeviceListActivity";
	private static final boolean D = true;

	// 返回时数据标签
	public static String EXTRA_DEVICE_ADDRESS = "设备地址";

	// 成员域
	private BluetoothAdapter mBtAdapter;
	private ArrayAdapter<String> mPairedDevicesArrayAdapter;
	private ArrayAdapter<String> mNewDevicesArrayAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// 创建并显示窗口
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); // 设置窗口显示模式为窗口方式
		setContentView(R.layout.device_list);

		// 设定默认返回值为取消
		setResult(Activity.RESULT_CANCELED);

		// 设定扫描按键响应
		Button scanButton = (Button) findViewById(R.id.button_scan);
		scanButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				doDiscovery();
				v.setVisibility(View.GONE);
			}
		});

		// 初使化设备存储数组
		mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,
				R.layout.device_name);
		mNewDevicesArrayAdapter = new ArrayAdapter<String>(this,
				R.layout.device_name);

		// 设置已配队设备列表

		ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
		pairedListView.setAdapter(mPairedDevicesArrayAdapter);
		pairedListView.setOnItemClickListener(mDeviceClickListener);

		// 设置新查找设备列表
		ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
		newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
		newDevicesListView.setOnItemClickListener(mDeviceClickListener);

		// 注册接收查找到设备action接收器
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		this.registerReceiver(mReceiver, filter);

		// 注册查找结束action接收器
		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		this.registerReceiver(mReceiver, filter);

		// 得到本地蓝牙句柄
		mBtAdapter = BluetoothAdapter.getDefaultAdapter();

		// 得到已配对蓝牙设备列表
		// Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

		// 添加已配对设备到列表并显示
		// if (pairedDevices.size() > 0) {
		// findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
		// for (BluetoothDevice device : pairedDevices) {
		// mPairedDevicesArrayAdapter.add(device.getName() + "\n" +
		// device.getAddress());
		// }
		// } else {
		// String noDevices = "No devices have been paired";
		// mPairedDevicesArrayAdapter.add(noDevices);
		// }
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		// 关闭服务查找
		if (mBtAdapter != null) {
			mBtAdapter.cancelDiscovery();
		}

		// 注销action接收器
		this.unregisterReceiver(mReceiver);
	}

	public void OnCancel(View v) {
		finish();
	}

	/**
	 * 开始服务和设备查找
	 */
	private void doDiscovery() {
		if (D)
			Log.d(TAG, "doDiscovery()");

		// 在窗口显示查找中信息
		setProgressBarIndeterminateVisibility(true);
		setTitle("查找设备中...");

		// 显示其它设备(未配对设备)列表
		findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);

		// 关闭再进行的服务查找
		if (mBtAdapter.isDiscovering()) {
			mBtAdapter.cancelDiscovery();
		}
		// 并重新开始
		mBtAdapter.startDiscovery();
	}

	// 选择设备响应函数
	private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
		public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
			// 准备连接设备,关闭服务查找
			mBtAdapter.cancelDiscovery();

			// 得到mac地址
			String info = ((TextView) v).getText().toString();
			String address = info.substring(info.length() - 17);

			// 设置返回数据
			Intent intent = new Intent();
			intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

			// 设置返回值并结束程序
			setResult(Activity.RESULT_OK, intent);
			finish();
		}
	};

	// 查找到设备和搜索完成action监听器
	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();

			// 查找到设备action
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				// 得到蓝牙设备
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				// 如果是已配对的则略过,已得到显示,其余的在添加到列表中进行显示
				if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
					mNewDevicesArrayAdapter.add(device.getName() + "\n"
							+ device.getAddress());
				} else { // 添加到已配对设备列表
					mPairedDevicesArrayAdapter.add(device.getName() + "\n"
							+ device.getAddress());
				}
				// 搜索完成action
			} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
					.equals(action)) {
				setProgressBarIndeterminateVisibility(false);
				setTitle("选择要连接的设备");
				if (mNewDevicesArrayAdapter.getCount() == 0) {
					String noDevices = "没有找到新设备";
					mNewDevicesArrayAdapter.add(noDevices);
				}
				// if(mPairedDevicesArrayAdapter.getCount() > 0)
				// findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
			}
		}
	};
}

备注:亲测可用,若连接失败请关闭Bluetooth chat 重新打开。



你可能感兴趣的:(android,BlueTooth,蓝牙通信)