Android實(shí)現(xiàn)藍(lán)牙客戶端與服務(wù)器端通信示例
一、首先說(shuō)明:藍(lán)牙通信必須用手機(jī)測(cè)試,因?yàn)閍vd里沒(méi)有相關(guān)的硬件,會(huì)報(bào)錯(cuò)!
好了,看看最后的效果圖:

二、概述:
1.判斷是否支持Bluetooth
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(bluetoothAdapter == null) {
//the device doesn't support bluetooth
} else {
//the device support bluetooth
}
2.如果支持,打開(kāi)Bluetooth
if(!bluetoothAdapter.isEnable()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
}
3.監(jiān)視Bluetooth打開(kāi)狀態(tài)
BroadcastReceiver bluetoothState = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String stateExtra = BluetoothAdapter.EXTRA_STATE;
int state = intent.getIntExtra(stateExtra, -1);
switch(state) {
case BluetoothAdapter.STATE_TURNING_ON:
break;
case BluetoothAdapter.STATE_ON:
break;
case BluetoothAdapter.STATE_TURNING_OFF:
break;
case BluetoothAdapter.STATE_OFF:
break;
}
}
}
registerReceiver(bluetoothState,new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
4.設(shè)置本地設(shè)備可以被其它設(shè)備搜索
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(discoveryIntent,REQUEST_DISCOVERY);
BroadcastReceiver discovery = new BroadcastReceiver() {
@Override
public void onRecevie(Content context, Intent intent) {
String scanMode = BluetoothAdapter.EXTRA_SCAN_MODE;
String preScanMode = BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE;
int mode = intent.getIntExtra(scanMode);
}
}
registerReceiver(discovery,new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
5.搜索設(shè)備
開(kāi)始搜索 bluetoothAdapter.startDiscovery();
停止搜索 bluetoothAdapter.cancelDiscovery();
當(dāng)發(fā)現(xiàn)一個(gè)設(shè)備時(shí),系統(tǒng)會(huì)發(fā)出ACTION_FOUND廣播消息,我們可以實(shí)現(xiàn)接收這個(gè)消息的BroadcastReceiver
BroadcastReceiver deviceFound = new BroadcastReceiver() {
@Override
public void onReceiver(Content content, Intent intent) {
String remoteDeviceName = intent.getStringExtra(BluetoothAdapter.EXTRA_NAME);
BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothAdapter.EXTRA_DEVICE);
}
}
registerReceiver(deviceFound, new IntentFilter(BluetoothAdapter.ACTION_FOUND);
6.連接設(shè)備
連接兩個(gè)藍(lán)牙設(shè)備要分別實(shí)現(xiàn)服務(wù)器端(BluetoothServerSocket)和客戶端(BluetoothSocket),這點(diǎn)與J2SE中的
ServerSocket和Socket很類似。
BluetoothServerSocket在服務(wù)器端調(diào)用方法accept()監(jiān)聽(tīng),當(dāng)有客戶端請(qǐng)求到來(lái)時(shí),accept()方法返回BluetoothSocket,客戶端得到后,兩端便可以通信。通過(guò)InputStream和OutputStream來(lái)實(shí)現(xiàn)數(shù)據(jù)的傳輸。
accept方法是阻塞的,所以不能放在UI線程中,當(dāng)用到BluetoothServerSocket和BluetoothSocket時(shí),通常把它們放在各自的新線程中。
三、如何實(shí)現(xiàn)
以下是開(kāi)發(fā)中的幾個(gè)關(guān)鍵步驟:
1)首先開(kāi)啟藍(lán)牙
2)搜索可用設(shè)備
3)創(chuàng)建藍(lán)牙socket,獲取輸入輸出流
4)讀取和寫入數(shù)據(jù)
5)斷開(kāi)連接關(guān)閉藍(lán)牙
1、因?yàn)橛许?yè)面切換,這里我使用了TabHost,但原來(lái)的效果不好,沒(méi)有動(dòng)畫,那只好自己復(fù)寫了
/**
* 帶有動(dòng)畫效果的TabHost
*
* @Project App_Bluetooth
* @Package com.android.bluetooth
* @author chenlin
* @version 1.0
* @Date 2013年6月2日
* @Note TODO
*/
public class AnimationTabHost extends TabHost {
private int mCurrentTabID = 0;//當(dāng)前的tabId
private final long mDuration = 400;//動(dòng)畫時(shí)間
public AnimationTabHost(Context context) {
this(context, null);
}
public AnimationTabHost(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 切換動(dòng)畫
*/
@Override
public void setCurrentTab(int index) {
//向右平移
if (index > mCurrentTabID) {
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF,
-1.0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f);
translateAnimation.setDuration(mDuration);
getCurrentView().startAnimation(translateAnimation);
//向左平移
} else if (index < mCurrentTabID) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 0f);
translateAnimation.setDuration(mDuration);
getCurrentView().startAnimation(translateAnimation);
}
super.setCurrentTab(index);
//-----方向平移------------------------------
if (index > mCurrentTabID) {
TranslateAnimation translateAnimation = new TranslateAnimation( //
Animation.RELATIVE_TO_PARENT, 1.0f,// RELATIVE_TO_SELF
Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f);
translateAnimation.setDuration(mDuration);
getCurrentView().startAnimation(translateAnimation);
} else if (index < mCurrentTabID) {
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, -1.0f, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f,
Animation.RELATIVE_TO_PARENT, 0f);
translateAnimation.setDuration(mDuration);
getCurrentView().startAnimation(translateAnimation);
}
mCurrentTabID = index;
}
}
2、先搭建好主頁(yè),使用復(fù)寫的TabHost滑動(dòng),如何滑動(dòng),根據(jù)狀態(tài),有三種狀態(tài)
/**
* 主頁(yè)
*
* @Project App_Bluetooth
* @Package com.android.bluetooth
* @author chenlin
* @version 1.0
* @Date 2013年6月2日
*/
@SuppressWarnings("deprecation")
public class BluetoothActivity extends TabActivity {
static AnimationTabHost mTabHost;//動(dòng)畫tabhost
static String BlueToothAddress;//藍(lán)牙地址
static Type mType = Type.NONE;//類型
static boolean isOpen = false;
//類型:
enum Type {
NONE, SERVICE, CILENT
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initTab();
}
private void initTab() {
//初始化
mTabHost = (AnimationTabHost) getTabHost();
//添加tab
mTabHost.addTab(mTabHost.newTabSpec("Tab1").setIndicator("設(shè)備列表", getResources().getDrawable(android.R.drawable.ic_menu_add))
.setContent(new Intent(this, DeviceActivity.class)));
mTabHost.addTab(mTabHost.newTabSpec("Tab2").setIndicator("會(huì)話列表", getResources().getDrawable(android.R.drawable.ic_menu_add))
.setContent(new Intent(this, ChatActivity.class)));
//添加監(jiān)聽(tīng)
mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
if (tabId.equals("Tab1")) {
//TODO
}
}
});
//默認(rèn)在第一個(gè)tabhost上面
mTabHost.setCurrentTab(0);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Toast.makeText(this, "address:", Toast.LENGTH_SHORT).show();
}
}
3、有了主頁(yè),就開(kāi)始分別實(shí)現(xiàn)兩個(gè)列表頁(yè)面,一個(gè)是尋找設(shè)備頁(yè)面DeviceActivity.Java,另一個(gè)是會(huì)話頁(yè)面ChatActivity.java
1)設(shè)備頁(yè)面DeviceActivity.java
/**
* 發(fā)現(xiàn)的設(shè)備列表
* @Project App_Bluetooth
* @Package com.android.bluetooth
* @author chenlin
* @version 1.0
* @Date 2013年6月2日
* @Note TODO
*/
public class DeviceActivity extends Activity {
private ListView mListView;
//數(shù)據(jù)
private ArrayList<DeviceBean> mDatas;
private Button mBtnSearch, mBtnService;
private ChatListAdapter mAdapter;
//藍(lán)牙適配器
private BluetoothAdapter mBtAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.devices);
initDatas();
initViews();
registerBroadcast();
init();
}
private void initDatas() {
mDatas = new ArrayList<DeviceBean>();
mAdapter = new ChatListAdapter(this, mDatas);
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* 列出所有的藍(lán)牙設(shè)備
*/
private void init() {
Log.i("tag", "mBtAdapter=="+ mBtAdapter);
//根據(jù)適配器得到所有的設(shè)備信息
Set<BluetoothDevice> deviceSet = mBtAdapter.getBondedDevices();
if (deviceSet.size() > 0) {
for (BluetoothDevice device : deviceSet) {
mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), true));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}
} else {
mDatas.add(new DeviceBean("沒(méi)有配對(duì)的設(shè)備", true));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}
}
/**
* 注冊(cè)廣播
*/
private void registerBroadcast() {
//設(shè)備被發(fā)現(xiàn)廣播
IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, discoveryFilter);
// 設(shè)備發(fā)現(xiàn)完成
IntentFilter foundFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, foundFilter);
}
/**
* 初始化視圖
*/
private void initViews() {
mListView = (ListView) findViewById(R.id.list);
mListView.setAdapter(mAdapter);
mListView.setFastScrollEnabled(true);
mListView.setOnItemClickListener(mDeviceClickListener);
mBtnSearch = (Button) findViewById(R.id.start_seach);
mBtnSearch.setOnClickListener(mSearchListener);
mBtnService = (Button) findViewById(R.id.start_service);
mBtnService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
BluetoothActivity.mType = Type.SERVICE;
BluetoothActivity.mTabHost.setCurrentTab(1);
}
});
}
/**
* 搜索監(jiān)聽(tīng)
*/
private OnClickListener mSearchListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
if (mBtAdapter.isDiscovering()) {
mBtAdapter.cancelDiscovery();
mBtnSearch.setText("重新搜索");
} else {
mDatas.clear();
mAdapter.notifyDataSetChanged();
init();
/* 開(kāi)始搜索 */
mBtAdapter.startDiscovery();
mBtnSearch.setText("ֹͣ停止搜索");
}
}
};
/**
* 點(diǎn)擊設(shè)備監(jiān)聽(tīng)
*/
private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DeviceBean bean = mDatas.get(position);
String info = bean.message;
String address = info.substring(info.length() - 17);
BluetoothActivity.BlueToothAddress = address;
AlertDialog.Builder stopDialog = new AlertDialog.Builder(DeviceActivity.this);
stopDialog.setTitle("連接");//標(biāo)題
stopDialog.setMessage(bean.message);
stopDialog.setPositiveButton("連接", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mBtAdapter.cancelDiscovery();
mBtnSearch.setText("重新搜索");
BluetoothActivity.mType = Type.CILENT;
BluetoothActivity.mTabHost.setCurrentTab(1);
dialog.cancel();
}
});
stopDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
BluetoothActivity.BlueToothAddress = null;
dialog.cancel();
}
});
stopDialog.show();
}
};
/**
* 發(fā)現(xiàn)設(shè)備廣播
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 獲得設(shè)備信息
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 如果綁定的狀態(tài)不一樣
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), false));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}
// 如果搜索完成了
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility(false);
if (mListView.getCount() == 0) {
mDatas.add(new DeviceBean("û沒(méi)有發(fā)現(xiàn)藍(lán)牙設(shè)備", false));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}
mBtnSearch.setText("重新搜索");
}
}
};
@Override
public void onStart() {
super.onStart();
if (!mBtAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, 3);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBtAdapter != null) {
mBtAdapter.cancelDiscovery();
}
this.unregisterReceiver(mReceiver);
}
}
2)會(huì)話頁(yè)面ChatActivity.java
/**
* 會(huì)話界面
*
* @Project App_Bluetooth
* @Package com.android.bluetooth
* @author chenlin
* @version 1.0
* @Date 2013年3月2日
* @Note TODO
*/
public class ChatActivity extends Activity implements OnItemClickListener, OnClickListener {
private static final int STATUS_CONNECT = 0x11;
private ListView mListView;
private ArrayList<DeviceBean> mDatas;
private Button mBtnSend;// 發(fā)送按鈕
private Button mBtnDisconn;// 斷開(kāi)連接
private EditText mEtMsg;
private DeviceListAdapter mAdapter;
/* 一些常量,代表服務(wù)器的名稱 */
public static final String PROTOCOL_SCHEME_L2CAP = "btl2cap";
public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
public static final String PROTOCOL_SCHEME_BT_OBEX = "btgoep";
public static final String PROTOCOL_SCHEME_TCP_OBEX = "tcpobex";
// 藍(lán)牙服務(wù)端socket
private BluetoothServerSocket mServerSocket;
// 藍(lán)牙客戶端socket
private BluetoothSocket mSocket;
// 設(shè)備
private BluetoothDevice mDevice;
private BluetoothAdapter mBluetoothAdapter;
// --線程類-----------------
private ServerThread mServerThread;
private ClientThread mClientThread;
private ReadThread mReadThread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
initDatas();
initViews();
initEvents();
}
private void initEvents() {
mListView.setOnItemClickListener(this);
// 發(fā)送信息
mBtnSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String text = mEtMsg.getText().toString();
if (!TextUtils.isEmpty(text)) {
// 發(fā)送信息
sendMessageHandle(text);
mEtMsg.setText("");
mEtMsg.clearFocus();
// 隱藏軟鍵盤
InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
manager.hideSoftInputFromWindow(mEtMsg.getWindowToken(), 0);
} else
Toast.makeText(ChatActivity.this, "發(fā)送內(nèi)容不能為空!", Toast.LENGTH_SHORT).show();
}
});
// 關(guān)閉會(huì)話
mBtnDisconn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (BluetoothActivity.mType == Type.CILENT) {
shutdownClient();
} else if (BluetoothActivity.mType == Type.SERVICE) {
shutdownServer();
}
BluetoothActivity.isOpen = false;
BluetoothActivity.mType = Type.NONE;
Toast.makeText(ChatActivity.this, "已斷開(kāi)連接!", Toast.LENGTH_SHORT).show();
}
});
}
private void initViews() {
mListView = (ListView) findViewById(R.id.list);
mListView.setAdapter(mAdapter);
mListView.setFastScrollEnabled(true);
mEtMsg = (EditText) findViewById(R.id.MessageText);
mEtMsg.clearFocus();
mBtnSend = (Button) findViewById(R.id.btn_msg_send);
mBtnDisconn = (Button) findViewById(R.id.btn_disconnect);
}
private void initDatas() {
mDatas = new ArrayList<DeviceBean>();
mAdapter = new DeviceListAdapter(this, mDatas);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* 信息處理
*/
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String info = (String) msg.obj;
switch (msg.what) {
case STATUS_CONNECT:
Toast.makeText(ChatActivity.this, info, 0).show();
break;
}
if (msg.what == 1) {
mDatas.add(new DeviceBean(info, true));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}else {
mDatas.add(new DeviceBean(info, false));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
}
}
};
@Override
public void onResume() {
super.onResume();
if (BluetoothActivity.isOpen) {
Toast.makeText(this, "連接已經(jīng)打開(kāi),可以通信。如果要再建立連接,請(qǐng)先斷開(kāi)", Toast.LENGTH_SHORT).show();
return;
}
if (BluetoothActivity.mType == Type.CILENT) {
String address = BluetoothActivity.BlueToothAddress;
if (!"".equals(address)) {
mDevice = mBluetoothAdapter.getRemoteDevice(address);
mClientThread = new ClientThread();
mClientThread.start();
BluetoothActivity.isOpen = true;
} else {
Toast.makeText(this, "address is null !", Toast.LENGTH_SHORT).show();
}
} else if (BluetoothActivity.mType == Type.SERVICE) {
mServerThread = new ServerThread();
mServerThread.start();
BluetoothActivity.isOpen = true;
}
}
// 客戶端線程
private class ClientThread extends Thread {
public void run() {
try {
mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Message msg = new Message();
msg.obj = "請(qǐng)稍候,正在連接服務(wù)器:" + BluetoothActivity.BlueToothAddress;
msg.what = STATUS_CONNECT;
mHandler.sendMessage(msg);
mSocket.connect();
msg = new Message();
msg.obj = "已經(jīng)連接上服務(wù)端!可以發(fā)送信息。";
msg.what = STATUS_CONNECT;
mHandler.sendMessage(msg);
// 啟動(dòng)接受數(shù)據(jù)
mReadThread = new ReadThread();
mReadThread.start();
} catch (IOException e) {
Message msg = new Message();
msg.obj = "連接服務(wù)端異常!斷開(kāi)連接重新試一試。";
msg.what = STATUS_CONNECT;
mHandler.sendMessage(msg);
}
}
};
// 開(kāi)啟服務(wù)器
private class ServerThread extends Thread {
public void run() {
try {
// 創(chuàng)建一個(gè)藍(lán)牙服務(wù)器 參數(shù)分別:服務(wù)器名稱、UUID
mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Message msg = new Message();
msg.obj = "請(qǐng)稍候,正在等待客戶端的連接...";
msg.what = STATUS_CONNECT;
mHandler.sendMessage(msg);
/* 接受客戶端的連接請(qǐng)求 */
mSocket = mServerSocket.accept();
msg = new Message();
msg.obj = "客戶端已經(jīng)連接上!可以發(fā)送信息。";
msg.what = STATUS_CONNECT;
mHandler.sendMessage(msg);
// 啟動(dòng)接受數(shù)據(jù)
mReadThread = new ReadThread();
mReadThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
};
/* 停止服務(wù)器 */
private void shutdownServer() {
new Thread() {
public void run() {
if (mServerThread != null) {
mServerThread.interrupt();
mServerThread = null;
}
if (mReadThread != null) {
mReadThread.interrupt();
mReadThread = null;
}
try {
if (mSocket != null) {
mSocket.close();
mSocket = null;
}
if (mServerSocket != null) {
mServerSocket.close();
mServerSocket = null;
}
} catch (IOException e) {
Log.e("server", "mserverSocket.close()", e);
}
};
}.start();
}
/* ͣ停止客戶端連接 */
private void shutdownClient() {
new Thread() {
public void run() {
if (mClientThread != null) {
mClientThread.interrupt();
mClientThread = null;
}
if (mReadThread != null) {
mReadThread.interrupt();
mReadThread = null;
}
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
mSocket = null;
}
};
}.start();
}
// 發(fā)送數(shù)據(jù)
private void sendMessageHandle(String msg) {
if (mSocket == null) {
Toast.makeText(this, "沒(méi)有連接", Toast.LENGTH_SHORT).show();
return;
}
try {
OutputStream os = mSocket.getOutputStream();
os.write(msg.getBytes());
mDatas.add(new DeviceBean(msg, false));
mAdapter.notifyDataSetChanged();
mListView.setSelection(mDatas.size() - 1);
} catch (IOException e) {
e.printStackTrace();
}
}
// 讀取數(shù)據(jù)
private class ReadThread extends Thread {
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream is = null;
try {
is = mSocket.getInputStream();
while (true) {
if ((bytes = is.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;
mHandler.sendMessage(msg);
}
}
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onClick(View view) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (BluetoothActivity.mType == Type.CILENT) {
shutdownClient();
} else if (BluetoothActivity.mType == Type.SERVICE) {
shutdownServer();
}
BluetoothActivity.isOpen = false;
BluetoothActivity.mType = Type.NONE;
}
}
三、相關(guān)代碼下載
demo下載:http://xiazai.jb51.net/201701/yuanma/App_BlueTooth_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android使用SkinManager實(shí)現(xiàn)換膚功能的示例
本篇文章主要介紹了android使用SkinManager實(shí)現(xiàn)換膚功能的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Android中g(shù)ravity與layout_gravity的使用區(qū)別分析
本篇文章介紹了,在Android中g(shù)ravity與layout_gravity的使用區(qū)別分析。需要的朋友參考下2013-04-04
說(shuō)說(shuō)Android的UI刷新機(jī)制的實(shí)現(xiàn)
這篇文章主要介紹了說(shuō)說(shuō)Android的UI刷新機(jī)制的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Android?AccessibilityService?事件分發(fā)原理分析總結(jié)
這篇文章主要介紹了Android?AccessibilityService?事件分發(fā)原理分析總結(jié),AccessibilityService有很多用來(lái)接收外部調(diào)用事件變化的方法,這些方法封裝在內(nèi)部接口Callbacks中,文章圍繞AccessibilityService相關(guān)資料展開(kāi)詳情,需要的朋友可以參考一下2022-06-06
Android實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能
這篇文章主要介紹了Android實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
Android編程實(shí)現(xiàn)通過(guò)反射獲取資源Id的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)通過(guò)反射獲取資源Id的方法,結(jié)合實(shí)例形式分析了Android反射機(jī)制操作資源的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-01-01

