Blame view

src/com/eztlib/BluetoothService.java 13.2 KB
3c2353cd   杜方   1、畅游通核销app源码提交;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  package com.eztlib;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.lang.reflect.Method;
  import java.util.UUID;
  
  import android.annotation.SuppressLint;
  import android.bluetooth.BluetoothAdapter;
  import android.bluetooth.BluetoothDevice;
  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 com.ectrip.cyt.config.MyApp;
  import com.ectrip.cyt.utils.LogUtil;
  
  /**
   * 这个类处理所有工作的设置和管理蓝牙连接其他设备 它有一个线程,监听传入连接 一个线程用于连接设备和一个线程用于执行数据传输连接时
   * */
  public class BluetoothService
  {
  	static
  	{
  		try {
  			System.loadLibrary("EZTLIB");
  		} catch (Exception e) {
  			e.printStackTrace();
  		} catch (Throwable e) {
  			e.printStackTrace();
  		}
  	}
  	/// <summary>
  	/// 端口发送数据
  	/// </summary>
  	/// <param name="pDataIn">要写入的数据</param>
  	/// <param name="Inlen">数据长度</param>
  	/// <returns>返回写入的数据长度</returns>
  	public static native int BluSendBytes(byte[] pDataIn, int Inlen);
  
  	/// <summary>
  	/// 端口读取数据
  	/// </summary>
  	/// <param name="pDataOut">返回数据</param>
  	/// <param name="Outlen">想要读取长度</param>
  	/// <returns>返回读取到的数据长</returns>
  	public static native int BluReadBytes(byte[] pDataOut, int len);
  
  
  	//从BluetoothService处理程序发送消息类型
  	public static final int MESSAGE_STATE_CHANGE=1;
  	public static final int MESSAGE_READ=2;
  	public static final int MESSAGE_WRITE=3;
  	public static final int MESSAGE_DEVICE_NAME=4;
  	public static final int MESSAGE_TOAST=5;
  	// BluetoothService收到的处理程序关键的名字
  	public static final String DEVICE_NAME="device_name";
  	public static final String TOAST="toast";
  
  
  	public static final String TAG = "BluetoothService";
  	public static final boolean LogEnablD = false;
  
  	// 在创建服务器套接字记录SDP的名字
  	private static final String NAME = "EZTPrinter";
  	// 给这个应用程序设置一个独特的UUID
  	private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
  
  	// 当前连接状态的常量
  	public static final int STATE_NONE = 0; // 默认的,什么都没做
  	public static final int STATE_LISTEN = 1; // 进入连接的监听
  	public static final int STATE_CONNECTING = 2;// 启动一个外向连接
  	public static final int STATE_CONNECTED = 3; // 连接到一个远程设备
  	public static final int STATE_FAILL=8;//失败
  
  	private final BluetoothAdapter mAdapter;
  	private final Handler mHandler;
  	//	private AcceptThread mAcceptThread= null;
  	private ConnectThread mConnectThread= null;
  	private static ConnectedThread mConnectedThread= null;
  	private static int mState= STATE_NONE;
  	private static boolean stop=false;
  
  	//构造函数。准备一个新的BTPrinter会话 ontext UI活动上下文 handler 处理程序发送消息发送回UI活动
  	public BluetoothService(Context context, Handler handler) {
  		stop=true;
  		mAdapter = BluetoothAdapter.getDefaultAdapter();
  		mState = STATE_NONE;
  		mHandler = handler;
  
  		try {
  			COMPacket.COMClose();
  		} catch (Exception e) {
  			e.printStackTrace();
  		} catch (Throwable e) {
  			e.printStackTrace();
  		}
  		Thread thread=new Thread(new Runnable()
  		{
  			byte[] buffer = new byte[4096];
  			int bytes;
  
  			@Override
  			public void run()
  			{
  				while (!stop)
  				{
  					if ((mState==BluetoothService.STATE_CONNECTED) && (mConnectedThread != null))
  					{
  						bytes=BluReadBytes(buffer,buffer.length);
  						if(bytes>0)
  						{
  							mConnectedThread.write(buffer, 0, bytes);
  						}
  					}
  				}
  			}
  		});
  		stop=false;
  		thread.start();
  	}
  
  	//设置当前状态的连接 state 定义当前的连接状态
  	private synchronized void setState(int state) {
  		if (LogEnablD)
  		{Log.d(TAG, "setState()" + mState + "->" + state);}
  		mState = state;
  
  		// 给新状态Handler让UI可以更新
  		mHandler.obtainMessage(MESSAGE_STATE_CHANGE, state,-1).sendToTarget();
  	}
  
  	//返回当前的连接状态
  	public synchronized int getState() {return mState;}
  
  	//启动服务。特别是在聆听(服务器)模式开始AcceptThread 会话,调用活动onResume()
  	public synchronized void start() {
  		if (LogEnablD){Log.d(TAG, "start");}
  
  		// 取消任何线程试图连接
  		if (mConnectThread != null) {
  			mConnectThread.cancel();
  			mConnectThread = null;
  		}
  		// 在运行一个连接时取消任何线程
  		if (mConnectedThread != null) {
  			mConnectedThread.cancel();
  			mConnectedThread = null;
  		}
  
  		// 启动线程来监听BluetoothServerSocket
  //		if (mAcceptThread == null) {
  //			mAcceptThread = new AcceptThread();
  //			mAcceptThread.start();
  //		}
  		setState(STATE_LISTEN);
  		try {
  			COMPacket.COMClose();
  		} catch (Exception e) {
  			e.printStackTrace();
  		} catch (Throwable e) {
  			e.printStackTrace();
  		}
  	}
  
  	//启动ConnectThread发起连接到一个远程设备。 device BluetoothDevice的连接
  	public synchronized void connect(BluetoothDevice device) {
  		if (LogEnablD){LogUtil.d(TAG, "connect to:" + device);}
  
  		// 取消任何线程试图连接
  		if (mState == STATE_CONNECTING)
  		{
  			if (mConnectThread != null)
  			{
  				mConnectThread.cancel();
  				mConnectThread = null;
  			}
  		}
  		// 正在运行一个连接时取消任何线程
  		if (mConnectedThread != null)
  		{
  			mConnectedThread.cancel();
  			mConnectedThread = null;
  		}
  		// 启动线程与给定的设备
  		mConnectThread = new ConnectThread(device);
  		mConnectThread.start();
  		setState(STATE_CONNECTING);
  		COMPacket.COMClose();
  	}
  
  
  	//启动ConnectedThread开始管理一个蓝牙连接
  	//@param socket  BluetoothSocket上的连接
  	//@param device  这个BluetoothDevice已经连接
  	public synchronized void connected(BluetoothSocket socket,BluetoothDevice device)
  	{
  		if (LogEnablD){LogUtil.d(TAG, "Connected");}
  		// 取消线程完成连接
  		if (mConnectThread != null) {
  			mConnectThread.cancel();
  			mConnectThread = null;
  		}
  		// 正在运行一个连接取消任何线程
  		if (mConnectedThread != null) {
  			mConnectedThread.cancel();
  			mConnectedThread = null;
  		}
  		// 取消接受线程,因为只是想连接到一个设备
  //		if (mAcceptThread != null) {
  //			mAcceptThread.cancel();
  //			mAcceptThread = null;
  //		}
  		// 启动线程来管理连接和执行传输
  		mConnectedThread = new ConnectedThread(socket);
  		mConnectedThread.start();
  
  		// 发送连接设备的名称回到UI活动
  		Message msg = mHandler.obtainMessage(MESSAGE_DEVICE_NAME);
  		Bundle bundle = new Bundle();
  		bundle.putString(DEVICE_NAME, device.getName());
  		msg.setData(bundle);
  		mHandler.sendMessage(msg);
  
  		setState(STATE_CONNECTED);
  
  		COMPacket.COMOpen("Bluetooth",0,0);
  	}
  
  	//停止所有的线程
  	public synchronized void stop()
  	{
  		if (LogEnablD){Log.d(TAG, "stop");}
  		setState(STATE_NONE);
  		if (mConnectThread != null) {
  			mConnectThread.cancel();
  			mConnectThread = null;
  		}
  		if (mConnectedThread != null) {
  			mConnectedThread.cancel();
  			mConnectedThread = null;
  
  		}
  //		if (mAcceptThread != null) {
  //			mAcceptThread.cancel();
  //			mAcceptThread = null;
  //		}
  
  		COMPacket.COMClose();
  	}
  
  	//启动ConnectThread发起连接到一个远程设备
  	//@param device BluetoothDevice的连接
  	//连接请求失败并通知UI活动
  	private void connectionFailed() {
  		setState(STATE_FAILL);
  		// 一条失败消息发送回活动
  		MyApp.getInstance().setBluConnection(false);
  		Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
  		Bundle bundle = new Bundle();
  		bundle.putString(TOAST, "不能连接到设备!");
  		bundle.putBoolean("sucess", false);
  		msg.setData(bundle);
  		mHandler.sendMessage(msg);
  	}
  
  	//表示这个连接丢失并通知UI活动。
  	private void connectionLost() {
  		// 一条失败消息发送给Activity
  		Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
  		Bundle bundle = new Bundle();
  		bundle.putString(TOAST, "已断开与打印机的连接!");
  		msg.setData(bundle);
  		mHandler.sendMessage(msg);
  	}
  
  	//启动ConnectedThread开始管理一个蓝牙连接 socket BluetoothSocket上的连接 device
  	//装置的BluetoothDevice已经连接
  	//这个线程运行试图使一个外向连接一个设备。它运行直通要么连接成功要么失败。
  	private class ConnectThread extends Thread {
  		private BluetoothSocket mmSocket;
  		private BluetoothDevice mmDevice;
  
  		@SuppressLint("NewApi") public ConnectThread(BluetoothDevice device) {
  			mmDevice = device;
  			BluetoothSocket tmp = null;
  			// 为一个连接的BluetoothDevice得到一个BluetoothSocket
  			try {
  				Method m = null;
  				try {
  					m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
  				} catch (NoSuchMethodException e) {
  					e.printStackTrace();
  				}
  				try {
  					tmp = (BluetoothSocket) m.invoke(device, 1);
  					tmp.connect();
  					MyApp.getInstance().setBluConnection(true);
  				} catch (IllegalAccessException e) {
  					e.printStackTrace();
  					connectionFailed();
  					return;
  				} catch (IllegalArgumentException e) {
  					e.printStackTrace();
  					connectionFailed();
  					return;
  				} catch (Exception e){
  					e.printStackTrace();
  					connectionFailed();
  					return;
  				}
  			} catch (Exception e) {
  				connectionFailed();
  				Log.e(TAG, "create failed"+e);
  				return;
  			}
  			mmSocket = tmp;
  		}
  
  		public void run() {
  			LogUtil.i(TAG, "BEFIN mConnectThrread");
  			setName("ConnectThread");
  
  			mAdapter.cancelDiscovery();
  			// 让BluetoothSocket的连接
  
  			try {
  				// 一个阻塞调用返回成功连接或一个例外
  				if(!MyApp.getInstance().isBluConnection()){
  					if(mmSocket!=null){
  						mmSocket.connect();
  					}else{
  						setState(STATE_FAILL);
  						return;
  					}
  					if(mmSocket==null){
  						setState(STATE_FAILL);
  						return;
  					}
  				}
  			} catch (IOException e) {
  				e.printStackTrace();
  				// 关闭socket
  				connectionFailed();
  
  				try {
  					mmSocket.close();
  				} catch (IOException e2) {
  					Log.e(TAG,
  							"unable to close() socket during connection failure",
  							e2);
  				}
  				// 启动服务到重启的听力模式
  //				BluetoothService.this.start();
  				return;
  			}
  			if(MyApp.getInstance().isBluConnection()){
  				// 重置ConnectThread
  				synchronized (BluetoothService.this) {
  					mConnectThread = null;
  				}
  				// 启动连接的线程
  				connected(mmSocket, mmDevice);
  			}
  		}
  
  		public void cancel() {
  			try {
  				mmDevice.describeContents();
  				if(mmSocket!=null){
  					mmSocket.close();
  					mmSocket=null;
  				}
  
  			} catch (IOException e) {
  				Log.e(TAG, "close() of connect socket failed", e);
  			}
  		}
  	}
  
  	//这个线程运行在连接一个远程的设备上 它处理所有传入和传出的传输。
  	private class ConnectedThread extends Thread {
  		private BluetoothSocket mmSocket;
  		private InputStream mmInStream;
  		private OutputStream mmOutStream;
  		boolean stop=false;
  
  		public ConnectedThread(BluetoothSocket socket) {
  			Log.d(TAG, "create ConnectedThread");
  			mmSocket = socket;
  			InputStream tmpIn = null;
  			OutputStream tmpOut = null;
  
  			// BluetoothSocket输入和输出流
  			try {
  				tmpIn = socket.getInputStream();
  				tmpOut = socket.getOutputStream();
  			} catch (IOException e) {
  				Log.e(TAG, "temp sockets not created", e);
  			}
  
  			mmInStream = tmpIn;
  			mmOutStream = tmpOut;
  		}
  
  		public void run()
  		{
  			Log.i(TAG, "BEGIN mConnectedThread");
  			byte[] buffer = new byte[4096];
  			int bytes;
  			while (!stop)
  			{
  				try
  				{
  					// 从InputStream中阅读
  					bytes = mmInStream.read(buffer);
  					BluSendBytes(buffer,bytes);
  					//mHandler.obtainMessage(MainActivity.MESSAGE_READ,bytes, -1, buffer).sendToTarget();
  				}
  				catch (IOException e)
  				{
  					Log.e(TAG, "disconnected", e);
  					connectionLost();
  
  					if (mState != STATE_NONE)
  					{
  						BluetoothService.this.start();
  					}else{
  						connectionLost();
  					}
  					break;
  				}
  			}
  		}
  
  		//OutStream写入连接
  		//@param buffer 写的字节
  		public void write(byte[] buffer,int offset, int count) {
  			try
  			{
  				mmOutStream.write(buffer,offset,count);
  				// 分享所发送的消息回到UI的Activity
  				//mHandler.obtainMessage(MESSAGE_WRITE, -1, -1,buffer).sendToTarget();
  			} catch (IOException e)
  			{
  				Log.e(TAG, "Exception during write", e);
  			}
  		}
  
  		public void cancel() {
  			try {
  				mmInStream.close();
  				mmInStream=null;
  				mmOutStream.close();
  				mmOutStream=null;
  				stop=true;
  				mmSocket.close();
  			} catch (IOException e) {
  				Log.e(TAG, "close() of connect socket failed", e);
  			}
  		}
  	}
  
  	// 与设备配对 参考源码:platform/packages/apps/Settings.git
  	// \Settings\src\com\android\settings\bluetooth\CachedBluetoothDevice.java
  	public static boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {
  		Method createBondMethod = btClass.getMethod("createBond");
  		Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
  		return returnValue.booleanValue();
  	}
  
  	// 与设备解除配对 参考源码:platform/packages/apps/Settings.git
  	// \Settings\src\com\android\settings\bluetooth\CachedBluetoothDevice.java
  	public static boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
  		Method removeBondMethod = btClass.getMethod("removeBond");
  		Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
  		return returnValue.booleanValue();
  	}
  }