Android----蓝牙通信使用 不同手机下同一应用通信

  

</pre><p>---------有人说学到东西不是在做的过程,而是在总结整理的时候!</p><p>          自己没有多少开发Android的经验,对于很多问题都是不太清楚,最近有个想法需要实现两部手机的相互通信,互相动态改变对方手机上的内容,达到两部手机显示同样内容的目的。最开始想到的是网络通信,但是需要用到服务器,或者说这样受限很多,速度上也可能会降低。最后定位到蓝牙这个功能。然后就是找资料看书。。。</p><p>          为了证明自己的想法能够实现,所以决定先实现一个简单的蓝牙连接,并且能互传一段文字的功能。然后经过一天的努力终于实现了~~~虽然很简单,为了理清自己接下来的问题,先写篇博文总结下蓝牙的连接和通信,也好提炼出一个后面可以利用的东西。</p><p>     自己看的资料大都将的非常全面,但是对于自己一步步尝试还是有些模糊。</p><p>一、 首先介绍的是BlueToothAdapter  借助于这个东西你可以初始化蓝牙设备,与蓝牙设备进行连接,创建Socket等等非常重要。</p><p><pre name="code" class="java">BluetoothAdapter bluetooth=BluetoothAdapter.getDefaultAdapter();


我们会去使用上面的方法来获取本地设备,之后就可以这个设备进行想做的事情。

   待会会说怎么去用,接下来我们来想象一下一台手机蓝牙的工作流程,也就是在我们自己的app里应该实现的东西


大概分为以上几个部分,大家要明白的是,我们进行蓝牙连接,应该是实现两部手机相同app的通信(也就是我们自己的app了),当然也有很多与其他提供蓝牙服务的app通信的情况,不过我觉得实现单一app通信足够理解蓝牙通信过程。

1.打开蓝牙:

   下面是一段打开蓝牙的code,bluetooth就是本地蓝牙设备(可以这么理解)

 private void initBluetooth()
    {//判断设备是否开启蓝牙,若没开启则打开开启蓝牙界面供用户选择
    	if(!this.bluetooth.isEnabled())//这个bluetooth就是利用BluetoothAdapter.getDefaultAdapter()获取到的BluetoothAdapter对象
    	{
    	Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    	startActivityForResult(intent, ENABLE_BLUETOOTH);

    	}
    	else
    	{
    		Toast.makeText(MainActivity.this, "BlueTooth open Already", 2000).show();
    		
    	}
    }

  如果用户在执行上面代码之前没有打开蓝牙,那么用户手机将会显示这么一个界面,让用户选择是否打开蓝牙,根据用户不同的选择页面将会返回不同的值


根据StartActivityForResult返回值的不同进行相应操作。如果不OK得话,你可以一直请求用户开蓝牙~~~~~,那么就这样简单的完成了step one

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	// TODO Auto-generated method stub
	if(requestCode==ENABLE_BLUETOOTH)
	{
        if(requestCode==RESULT_OK)
        {
        	Toast.makeText(MainActivity.this, "BlueTooth open", 2000).show();
        	
        }
        else
        {
        	Toast.makeText(MainActivity.this, "oooops not lucky", 2000).show();
        }
	}
	else if(requestCode==DISCOVERABLE_BLUETOOTH)
	{
		if(resultCode==RESULT_CANCELED)
		{
			Toast.makeText(MainActivity.this, "just ok man !", 2000).show();
		}
	}
}


2.设置模式

   可能并无模式这种说法,实际上就是设置一下自己可不可以被人发现什么的,分为下面三种

  SCAN_MODE_CONNECTABLE_DISCOVERABLE 启用查询扫描和页面扫描,意味着设备可以被任意执行发现扫描的蓝牙设备发现

  SCAN_MODE_CONNECTABLE 启用页面扫描禁用查询扫描,意味着只有先前连接过的设备可以查询到本设备

  SCAN_MODE_NONE 当然就是不可发现喽!

设置模式的代码也很简单:

private void disCoverable()
    {
    	startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE), DISCOVERABLE_BLUETOOTH);
    }
和请求打开蓝牙类似,也是会调起一个Preference Activity,用户进行选择,之后返回一个值,根据返回值去做什么这就是我们自己的事了。

注意 一般默认可被发现时间为两分钟也就是120秒,当然这个值可以在启动的Intent中进行设置。

用户手机将会显示上面界面

问题来了,程序刚刚运行就弹出两个选择框,这样的用户体验真实差的不可容忍,听说也有默认设置的办法(不给用户选择的权利),这个今后学到了再说!


3.搜索周边设备

   先上代码君~~~~

 if(this.bluetooth.isEnabled())
        {
        	this.bluetooth.startDiscovery();
        }


没错就这么一行,关键代码,手机就开始自动搜索了,八国只用这一行是肯定记录不下来搜索出的设备信息,而且也不知道设备是何时搜索完成!那么Android中的一方霸主BroadCaster出场了,注册广播接收器,来获取搜索状态!

接下来是接收器的代码

下面这个接收开始和结束的广播,(结束后大家可以把获取的的设备信息进行展示,或者把搜索动画停掉=====)

public class discoverMonitor extends BroadcastReceiver{
	private String discoverStarted=BluetoothAdapter.ACTION_DISCOVERY_STARTED;
	private String discoverFinished=BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
	  if(discoverStarted.equals(intent.getAction()))//搜索开始
	  {
//		  Toast.makeText(context, "here we go-----discover started", 2000).show();
		  Log.i("---------->", "here we go-----discover started");
	  }
	  else if(discoverFinished.equals(intent.getAction()))//搜索结束
	  {
//		  Toast.makeText(context, "we have finished-----discover finished", 2000).show();
		  Log.i("---------->", "we have finished-----discover finished");
	  }
		
	}

}

接下来是搜索到设备的广播接收者,手机每搜到一个就会发出一个广播,所以得到搜索到的设备的信息这里是关键

public class discoverResult extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String remoteDeviceName=intent.getStringExtra(BluetoothDevice.EXTRA_NAME);//设备名称
		BluetoothDevice remoteDevice=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);//获取搜索到的设备信息
		bluetoothDevice device=new bluetoothDevice();//自己写的类
		if(remoteDeviceName!=null)
		{
			device.setremoteDeviceName(remoteDeviceName);
		}
		if(remoteDevice!=null)
		{
			device.setremoteDevice(remoteDevice);
		}
		DeviceCollect.Devices.add(device);//加到一个ArrayList中
		Toast.makeText(context, "en....one more", 2000).show();
		Log.i("---------->", "en ------one more devices");
	}

}

当然不能忘了进行注册,注意要在执行搜索代码前进行注册

  private void registerBR()
    {
    	registerReceiver(new discoverMonitor(), new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
    	registerReceiver(new discoverMonitor(), new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
    	registerReceiver(new discoverResult(), new IntentFilter(BluetoothDevice.ACTION_FOUND));
    }

bluetoothDevice类

public class bluetoothDevice {
	private String remoteDeviceName;
	private BluetoothDevice remoteDevice;
	public String getremoteDeviceName()
	{
		return this.remoteDeviceName;
	}
	public BluetoothDevice getremBluetoothDevice()
	{
		return this.remoteDevice;
	}
	public void setremoteDeviceName(String name)
	{
		this.remoteDeviceName=name;
	}
	public void setremoteDevice(BluetoothDevice device)
	{
		this.remoteDevice=device;
	}

}

DeviceCollect类

public class DeviceCollect {

	public static ArrayList<bluetoothDevice> Devices;
	static
	{
		DeviceCollect.Devices=new ArrayList<bluetoothDevice>();
	}
}
3.列出所有设备,选择其中进行连接

    这个部分其实是关键,还是像一开始说的我们要实现两部手机同一app的通信,这就意味着我们的app要能接收连接请求,并且还能发出连接请求!想明白这些其实也就简单了,就是说和网络通信类似,我们app里既要运行着server代码,还要能主动发出client请求!

   我没有把列出设备作为重点,所以我没列出设备,但是通过第二步已经拿到了周边设备信息放在了ArrayList里,想要列出的话用ListView就可以了,然后通过单击不同的Item进行连接。

那么。我们就假设已经获取到了一个Item中的设备信息我想去连接这个设备。此时我就是要做Client了,要求对方必须等待着client的请求(运行着server代码)

我们先来看看Server代码

private UUID startServerSocket(BluetoothAdapter bluetooth)
{
	UUID uuid=UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666");//设置一个UUID
	String name="bluetoothserver";
	try{
		final BluetoothServerSocket btserver=bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);//监听连接请求
		Thread acceptTread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				BluetoothSocket serverSocket;
				try {Log.i("------------>", "waitforconnect  now be Server");
					serverSocket = btserver.accept();//连接建立前保持阻塞
					Log.i("connectToServerSocket------------>", "OK connected");
					Message what=handler.obtainMessage();
					what.arg1=0x31;
					handler.sendMessage(what);//只是为了toast
					transferSocket=serverSocket;//为了能进行发送信息
					while(true)//一直监听传入的数据
					{
					listenForMessages(serverSocket, new StringBuilder());//监听传入数据的函数
					}
				
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}); 
		acceptTread.start();
	}
	catch(IOException e)
	{
		e.printStackTrace();
	}
	
	return uuid;
}

上面有个UUID(全局统一标示),这就是我们自己的APP能够在不同手机上通过蓝牙进行连接的关键,首先我的程序作为server在等待着一个请求时UUID为上面code中数据的Client请求。其他app默认情况下不可能知道我程序内设置的UUID,这也就保证了只有自己的APP可以发出这样的请求。

bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);  调用这个方法就可以实现监听一个传入的连接请求


Client请求代码


public void connectToServerSocket(BluetoothDevice device,UUID uuid)
{ 
	try{
		final BluetoothSocket clientSocket=device.createRfcommSocketToServiceRecord(uuid);//创建客户端socket
		Thread connectthread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					Log.i("------------>", "waitforconnect  now be client");
					clientSocket.connect();
					Log.i("connectToServerSocket------------>", "OK connected");
					Message what=handler.obtainMessage();
					what.arg1=0x31;
					handler.sendMessage(what);
					transferSocket=clientSocket;//套接字
					while(true)
					{
					listenForMessages(clientSocket, new StringBuilder());
					}
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}); 
		connectthread.start();
	}catch(IOException e)
	{
		e.printStackTrace();
	}
}

device.createRfcommSocketToServiceRecord(uuid);//创建客户端Socket  

要保证UUID正确性,也就是和server端等待的是相同的。

根据返回的套接字就可以进行通信了,这个网络通信差不太多。

5.数据传递

这个就不说了。。。我自己写的程序里有这一部分。可以看下。首先我要说,程序写的很烂,可复用的部分也不是很多,因为我刚刚理清思路,还不知道如何去安排代码。也希望对这个比较熟悉的朋友能够给出推荐,给个好的Demo最好了。


关键的别忘了在Manifest里声明权限

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


第一次发文,语言组织力简直弱爆~~,也希望以后能有所进步,比较乱,大家见谅


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值