目录
第一节:AIDL实现远程服务的通信
一、远程服务的开启
二、远程服务的通信
第二节:Android线程间通信
一、什么是多线程?
二、ANR 的基础知识及产生
1、原因:
2、三种情况:
三、线程
四、实现的两种方式:
五、线程间通信
第三节:Socket&Https通信
一、什么是Socket
UDP:
DatagramSocket:
DatagramPacket:
TCP:
ServerSocket
Socket
二、UDP实例:服务端、客户端通信
三、TCP实例:多人聊天室
四、Https通信
第四节:经典蓝牙通信
一、蓝牙权限:
二、设置蓝牙:
第五节:低功耗蓝牙应用
第一节:AIDL实现远程服务的通信
AIDL
全称:(Android Interface definition language),Android接口定义的语言。
作用:进程间的通信接口。
一、远程服务的开启
1、在服务提供端App的Manifest文件中为service配置action属性,exported必须为true。
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.imooc.admin.myservice"/>
</intent-filter>
</service>
2、本地App端声明Intent对象,设置action和package,action为服务端manifest文件中指定的值,package为服务端包名,然后利用startService、BindService启动、绑定服务。
public void onClick(View v) {
switch (v.getId()){
case R.id.start_btn: {
//Android5.0 以前版本 可以隐式声明
//Intent intent=new Intent("com.imooc.admin.myservice");
//Android5.0以后版本 必须显示声明
Intent intent = new Intent();
intent.setAction("com.imooc.admin.myservice");
intent.setPackage("com.example.servicedemo");
startService(intent);
break;
}
case R.id.stop_btn: {
Intent intent=new Intent();
intent.setAction("com.imooc.admin.myservice");
intent.setPackage("com.example.servicedemo");
stopService(intent);
break;
}
case R.id.bind_btn: {
Intent intent=new Intent();
intent.setAction("com.imooc.admin.myservice");
intent.setPackage("com.example.servicedemo");
bindService(intent,mConnection,BIND_AUTO_CREATE);
break;
}
case R.id.unbind_btn: {
unbindService(mConnection);
break;
}
}
}
二、远程服务的通信
远程服务的启动并不能进行通信,要实现通信需要使用AIDL。IBinder也能实现通信,但是IBinder仅限于同一进程,而AIDL是进程间的通信。
步骤:
1、在远端创建AIDL文件。
- 右键->new->AIDL->AIDL File;
- 添加自定义方法,ReBuild。
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
//自定义方法:显示进度
void showProgress();
}
2、实现AIDL。实例化AIDL对象,并在Service的onBind中返回。
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.d(TAG, "onBind: 服务绑定了");
//throw new UnsupportedOperationException("Not yet implemented");
return new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void showProgress() throws RemoteException {
Log.d(TAG, "showProgress: 当前进度:"+mCount);
}
};
}
3、本地端创建目录,并拷贝远端aidl文件。
- 切换project模式,创建目录\src\main\aidl\远端包名
- 拷贝aidl文件到目录中,rebuild。
4、在Serviceconnection 中获取aidl,并调用自定义方法。
private ServiceConnection mConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface aidlInterface=IMyAidlInterface.Stub.asInterface(service);
try {
aidlInterface.showProgress();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
第二节:Android线程间通信
一、什么是多线程?
线程是程序中一个单一的顺序控制流程,在单个程序中同时运行多个线程完成不同的工作,称为多线程。
二、ANR 的基础知识及产生
应用程序无响应ANR(Application Not Responding)
1、原因:
- 系统繁忙
- app没有优化好
2、三种情况:
- 主要类型案件或触摸事件在特定时间(5秒)内无响应。
- BroadcastReceiver在特定时间(10秒)内无法处理完成。
- 小概率类型Service在特定的时间内无法完成处理。
三、线程
线程状态:创建、就绪、运行、阻塞、消亡
线程中常用的方法:
- start方法:启动线程。
- run方法:不需要调用,继承Thread类必须重写
- sleep方法:让当前线程睡眠,交出CPU,让CPU去执行其他的任务
- yield方法:让当前线程交出CPU权限,让CPU去执行其他线程。但是yield不能控制具体交出CPU的时间,另外、yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。
- join方法:让调用join方法的线程占用CPU指定的时间或直到线程执行完毕。
- interrupt方法:中断,可以使处于阻塞状态的线程抛出一个异常,也就是说,它可以用来中断一个处于阻塞状态的线程。
- getName方法:获取线程名称。
- currentThread方法:静态方法,获取当前线程。
提示:多线程会增加一定的系统开销,如,新建线程分配资源、线程切换的状态保存等,所以编程时应确定是否真的需要使用多线程。
四、实现的两种方式:
- 扩展java.lang.Thread类:创建类继承Thread或者new Thread。
- 实现Runnable接口:创建类实现Runnable接口,new Thread(runnable).start();
五、线程间通信
Handler、Looper、MessageQueue、Thread之间的关系
- 一个线程对应一个Looper。
- 一个Looper对应一个MessageQueue。
- 一个Looper可以对应多个Handler。
- 主线程默认开启Looper。
- 子线程Looper需要手动启动:Looper.prepare();Looper.loop();
备注:Looper.getMainLooper();获取主线程的Looper。
第三节:Socket&Https通信
一、什么是Socket
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket(套接字)。
- IP用来定位主机,Socket用来定位应用。
- Socket有两种通信模型UDP和TCP,都是传输层协议。
Http与socket的区别。在日常开发中客户端与服务端数据交互(xml或json格式)一般常用http协议,为什么还需要socket呢?二者的区别主要在以下几个方面:
- http是应用层协议,socket是传输层协议。
- http是无状态的协议,无法实现推送功能。
- http协议传输过程复杂,不适合传输少量的数据;socket的灵活性更高。
InetAddress类:
静态方法:
- getByAddress(byte[] addr) 通过IP地址获取InetAddress
- getByName(String host) 通过主机名获取InetAddress
- getLocalHost() 创建本地主机的InetAddress
常用方法:
- getAddress() 返回IP地址,byte[]类型
- getHostName() 返回主机名
UDP:
(User Datagram Protocol 用户数据报协议)使用UDP协议进行信息的传输之前不需要进行连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。
应用:视频、语音通讯等。特点是速度快,但是不可靠,容易丢包。
DatagramSocket:
表示数据报包,数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
构造:
- DatagramSocket() 本地默认IP地址,随机端口,常用于客户端。
- DatagramSocket(int port) 默认IP,指定端口,常用于服务端。
- DatagramSocket(int port, InetAddress laddr) 指定IP、指定端口。
常用方法:
- receive(DatagramPacket p) 从当前socket中接收数据。
- send(DatagramPacket p) 从当前socket向外发送数据。
DatagramPacket:
常用构造:
- DatagramPacket(byte[] buf, int length) 用于客户端接收数据
- DatagramPacket(byte[] buf, int length, InetAddress address, int port) 用于服务端发送数据
常用方法:
- getAddress() 获取IP地址
- getData() 获取数据
- getPort() 获取数据
- getSocketAddress() 获取SocketAddress (IP地址、和端口)
TCP:
(Transmission Control Protocol 传输控制协议)应用: 浏览器、邮件、文件传输等。特点速度慢,可靠,占用系统资源高。
ServerSocket
构造方法:
- ServerSocket()
- ServerSocket(int port)
- ServerSocket(int port, int backlog)
- ServerSocket(int port, int backlog, InetAddress bindAddr) port服务端要监听的端口,设置0,自动分配;backlog客户端连接请求的队列长度;bindAddr服务端绑定IP,多个网卡时使用。
常用方法:
accept() 等待客户端接入,返回客户端的Socket,阻塞状态。
getInetAddress() 返回IP地址,InetAddress类型。
getLocalPort() 返回端口,int类型。
Socket
构造方法:
- Socket()
- Socket(String host, int port)
- Socket(String host, int port, InetAddress localAddr, int localPort)
- Socket(InetAddress address, int port)
- Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 参数分别为目标IP、目标端口、绑定本地IP、绑定本地端口。除不带参数的构造外,其它构造函数会尝试建立与服务器的连接。如果成功,则返回Socket对象。
常用方法:
- getInetAddress() 返回远程服务端的IP地址,InetAddress 类型。
- getPort() 返回远程服务端的端口,整型。
- getLocalAddress() 返回本地IP地址,InetAddress 类型。
- getLocalPort() 返回本地端口,整型。
- getInputStream() 获得输入流,InputStream类型。
- getOutputStream() 获得输入流,OutputStream类型。
- isBound() Socket与本地端口绑定,返回true;否则返回false;
- isClosed() 连接已关闭,返回true;否则返回false
- isConnected() 如果曾经连接过,返回true;否则返回false
Http、Socket区别:
- Http 应用层协议
- Socket传输层协议,灵活高效,服务端推送能力
网络七层协议(OSI:Open System Interconnection开放系统互联):
- 分别是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
Https :验证证书、校验域名。
二、UDP实例:服务端、客户端通信
public class UdpClient {
private String mServerIp="172.20.10.4";
private InetAddress mServerAddress;
private int mServerPort=7777;
private DatagramSocket mSocket;
private Scanner mScanner;
public UdpClient() {
try {
mServerAddress=InetAddress.getByName(mServerIp);
mSocket=new DatagramSocket();
mScanner=new Scanner(System.in);
mScanner.useDelimiter("\n");
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void start(){
while(true){
try {
String clientMsg=mScanner.next();
byte[] clientMsgBytes=clientMsg.getBytes();
DatagramPacket clientPacket=new DatagramPacket(clientMsgBytes,clientMsgBytes.length,mServerAddress,mServerPort);
mSocket.send(clientPacket);
byte[] buf=new byte[1024];
DatagramPacket serverMsgPacket=new DatagramPacket(buf,buf.length);
mSocket.receive(serverMsgPacket);
String serverMsg=new String(serverMsgPacket.getData(),0,serverMsgPacket.getLength());
System.out.println("msg="+serverMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new UdpClient().start();
}
}
public class UdpServer {
private InetAddress mInetAddress;
private int mPort = 7777;
private DatagramSocket mSocket;
private Scanner mScanner;
public UdpServer() {
try {
mInetAddress=InetAddress.getLocalHost();
mSocket=new DatagramSocket(mPort,mInetAddress);
mScanner=new Scanner(System.in);
mScanner.useDelimiter("\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
}
}
public void start(){
while(true){
try {
//接收
byte[] buf=new byte[1024];
DatagramPacket receivedPacket=new DatagramPacket(buf,buf.length);
mSocket.receive(receivedPacket);//阻塞
//显示
InetAddress address = receivedPacket.getAddress();
int port = receivedPacket.getPort();
byte[] data = receivedPacket.getData();
String clientMsg=new String(data,0,receivedPacket.getLength());
System.out.println("address="+address+",port="+port+",msg="+clientMsg);
//发送
String returnedMsg = mScanner.next();
DatagramPacket sendPacket=new DatagramPacket(
returnedMsg.getBytes(),
returnedMsg.getBytes().length,
receivedPacket.getSocketAddress());
mSocket.send(sendPacket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
new UdpServer().start();
}
}
三、TCP实例:多人聊天室
服务端
public class TcpServer {
private ServerSocket mServerSocket;
public void start(){
try {
//监听9090端口
mServerSocket = new ServerSocket(9090);
//启动消息池
MsgPool.getInstance().start();
while(true) {
//等待客户端接入
Socket socket = mServerSocket.accept();//等待客户端,阻塞状态
System.out.println("IP="+socket.getInetAddress().getHostAddress()+
" Port="+socket.getPort()+" is online...");
//两个流都是阻塞状态,直接读取会导致其他客户端的接入进入等待状态。
//socket.getInputStream();//获取客户端输入流
//socket.getOutputStream();//获取客户端输出流
//为每个接入的客户端单独启动一个线程,进行读写操作
ClientTask clientTask=new ClientTask(socket);
//监听消息池
MsgPool.getInstance().addListener(clientTask);
clientTask.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new TcpServer().start();
}
}
服务端子线程:接收客户端发送的信息,并向所有客户端转发
public class ClientTask extends Thread implements MsgPool.MsgComingListener {
private Socket mSocket;
private InputStream mInputStream;
private OutputStream mOutputStream;
public ClientTask(Socket socket) {
try {
mSocket = socket;
mInputStream = socket.getInputStream();
mOutputStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(mInputStream));
try {
String line = null;
while ((line = reader.readLine()) != null) {
String msg=mSocket.getPort()+":"+line;
//显示客户端发来的消息
System.out.println(msg);
//将消息发送到消息池队列
MsgPool.getInstance().sendMsg(msg);
}
} catch (IOException e) {
System.out.println("异常:"+e.getMessage());
} finally {
System.out.println("ip=" + mSocket.getInetAddress().toString() + " port=" +
mSocket.getPort() + " is offline...");
}
}
//监听消息池发送出来的消息,发送给客户端
@Override
public void onMsgComing(String msg) {
try {
mOutputStream.write(msg.getBytes());
mOutputStream.write("\n".getBytes());
mOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
利用消息池,解决服务端向所有客户端转发数据可能出现的并发问题
//创建阻塞队列的消息池,实现单例模式
public class MsgPool {
private static MsgPool sInstance=new MsgPool();
private LinkedBlockingQueue<String> mQueue=new LinkedBlockingQueue<>();
//创建接口用来向订阅者发送消息
public interface MsgComingListener{
public void onMsgComing(String msg);
}
private List<MsgComingListener> mListeners=new ArrayList<>();
public void addListener(MsgComingListener listener){
mListeners.add(listener);
}
private MsgPool(){}
public static MsgPool getInstance(){
return sInstance;
}
//向消息队列添加消息
public void sendMsg(String msg){
try {
mQueue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//启动消息池,只要消息队列中有信息就会自动发送给所有订阅者
public void start(){
new Thread(){
@Override
public void run() {
while(true){
try {
String msg = mQueue.take();
notifyMsgComing(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public void notifyMsgComing(String msg){
for(MsgComingListener listener:mListeners){
listener.onMsgComing(msg);
}
}
}
客户端
public class TcpClient {
private Socket mSocket;
private InputStream mInputStream;
private OutputStream mOutputStream;
private Scanner mScanner;
public TcpClient() {
mScanner=new Scanner(System.in);
mScanner.useDelimiter("\n");
}
public void start(){
try {
mSocket=new Socket("172.20.10.4",9090);
mInputStream=mSocket.getInputStream();
mOutputStream=mSocket.getOutputStream();
final BufferedReader reader=new BufferedReader(new InputStreamReader(mInputStream));
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(mOutputStream));
//创建独立线程接收消息
new Thread(){
@Override
public void run() {
String line=null;
try {
while((line=reader.readLine())!=null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("异常:"+e.getMessage());
} finally {
System.out.println("服务器连接已断开");
}
}
}.start();
//发送消息
while(true){
String msg = mScanner.next();
writer.write(msg);
writer.newLine();
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new TcpClient().start();
}
}
移动客户端业务类
public class TcpClientBiz {
private Socket mSocket;
private InputStream mInputStream;
private OutputStream mOutputStream;
private Handler mUiHandler=new Handler(Looper.getMainLooper());
//通过创建监听实现业务类和UI解耦
public interface MsgComingListener{
public void onMsgComing(String msg);
public void onError(Exception ex);
}
private MsgComingListener mListener;
public void setListener(MsgComingListener listener) {
mListener = listener;
}
//启动业务类后自动连接服务器,接收消息并通知UI更新数据
public TcpClientBiz() {
//网络操作需要启动子线程
new Thread(){
@Override
public void run() {
try {
mSocket=new Socket("172.20.10.4",9090);
mInputStream = mSocket.getInputStream();
mOutputStream = mSocket.getOutputStream();
final BufferedReader reader=new BufferedReader(new InputStreamReader(mInputStream));
String line=null;
while((line=reader.readLine())!=null){
//子线程更新UI需要使用handler
Log.d("linshi", "run: "+line);
final String finalLine = line;
mUiHandler.post(new Runnable() {
@Override
public void run() {
if(mListener!=null){
mListener.onMsgComing(finalLine);
}
}
});
}
} catch (IOException e) {
if(mListener!=null){
mListener.onError(e);
}
}
}
}.start();
}
//向服务器发送消息
public void sendMsg(final String msg){
//网络操作,启动子线程
new Thread(){
@Override
public void run() {
try {
mOutputStream.write(msg.getBytes());
mOutputStream.write("\n".getBytes());
mOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
public void onDestroy(){
//尽量使用独立的try-catch
try {
if (mInputStream != null) {
mInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (mOutputStream != null) {
mOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (mSocket != null) {
mSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
移动客户端UI
public class MainActivity extends AppCompatActivity {
private Button mBtnSend;
private EditText mEdtInput;
private TextView mTvContent;
private TcpClientBiz mTcpClientBiz=new TcpClientBiz();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
initViews();
//初始化监听器
initEvents();
}
private void initEvents() {
//创建匿名类订阅业务类的消息,更新UI
mTcpClientBiz.setListener(new TcpClientBiz.MsgComingListener() {
@Override
public void onMsgComing(String msg) {
Log.d("linshi", "onMsgComing: "+msg);
mTvContent.append(msg+"\n");
}
@Override
public void onError(Exception ex) {
ex.printStackTrace();
}
});
//向服务器发送消息
mBtnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String msg=mEdtInput.getText().toString();
mEdtInput.setText("");
mTcpClientBiz.sendMsg(msg);
}
});
}
private void initViews() {
mBtnSend = findViewById(R.id.btn_send);
mEdtInput = findViewById(R.id.edt_input);
mTvContent = findViewById(R.id.tv_content);
}
@Override
protected void onDestroy() {
super.onDestroy();
//关闭连接
mTcpClientBiz.onDestroy();
}
}
源码
四、Https通信
第四节:经典蓝牙通信
一、蓝牙权限:
执行蓝牙通信需要权限BLUETOOTH,例如:请求链接、接受链接、传输数据等;如果需要启动设备发现或操作蓝牙设置,则需要声明BLUETOOTH_ADMIN权限。
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
二、设置蓝牙:
- 获取蓝牙适配器:BluetoothAdapter.getDefaultAdapter()
- 设备是否支持蓝牙:bluetoothAdapter对象为null,则不支持蓝牙。
- 设备是否开启蓝牙:bluetoothAdapter.isEnabled()
- 开启蓝牙:startActivity(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
- 查找已配对设备:bluetoothAdapter.getBondedDevices()
- 发现新设备:bluetoothAdapter.startDiscovery()
开启蓝牙代码:
public static final int REQUEST_ENABLE_BT = 10001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
if(bluetoothAdapter!=null){
Toast.makeText(this, "支持蓝牙", Toast.LENGTH_SHORT).show();
if(bluetoothAdapter.isEnabled()){
Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
}else{
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE_BT);
}
}else{
Toast.makeText(this, "不支持蓝牙", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==REQUEST_ENABLE_BT){
Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
}
}
查找设备代码:
Set<BluetoothDevice> bluetoothDevices=bluetoothAdapter.getBondedDevices();
if(bluetoothDevices.size()>0){
for(BluetoothDevice device:bluetoothDevices){
Log.d(TAG, "Device Name: "+device.getName());
Log.d(TAG, "Device Addr: "+device.getAddress());
}
}
搜索新的设备代码:
//如果正在搜索,则取消
if(bluetoothAdapter.isDiscovering()){
bluetoothAdapter.cancelDiscovery();
}
bluetoothAdapter.startDiscovery();//立刻返回是否成功启动发现操作
private BroadcastReceiver mBluetoothReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if(action.equals(BluetoothDevice.ACTION_FOUND)){
BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(TAG, "New device name: "+device.getName());
Log.d(TAG, "New device addr: "+device.getAddress());
}else if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){
Log.d(TAG, "Discovery done!");
}
}
};
IntentFilter filter=new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBluetoothReceiver,filter);
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBluetoothReceiver);
}
连接为服务器
设置服务器套接字并接受连接的基本过程:
-1.通过调用 listenUsingRfcommWithServiceRecord(String, UUID)获取 BluetoothServerSocket
-2.通过调用 accept() 开始侦听连接请求
-3.除非要接受更多连接,否则调用 close()
设置客户端
- 发起与远程设备(保持开放的服务器套接字的设备)的连接
a. 首先要获取表示该远程设备的 BluetoothDevice 对象
b. 然后使用 BluetoothDevice 来获取 BluetoothSocket 并发起连接
1. 使用 BluetoothDevice,通过调用 createRfcommSocketToServiceRecord(UUID) 获取BluetoothSocket
2. 通过调用 connect() 发起连接
第五节:低功耗蓝牙应用
蓝牙4.0 :BLE