藍芽小試牛刀之模擬藍芽客戶端向服務端傳資料
阿新 • • 發佈:2019-01-31
今天我們來實現一下客戶端和服務端通過藍芽傳資料
效果圖如下:
這個佈局太簡單了,我就不給出了,直接上邏輯.
MainActivity:
public class MainActivity extends Activity implements View.OnClickListener {
private Button btn1;
private Button btn2;
private Button btn3;
private Button btn4;
private Button btn5;
private Button btn6;
private Button btn7;
private BluetoothAdapter mBlueToothAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
}
private void setListener () {
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
btn3.setOnClickListener(this);
btn4.setOnClickListener(this);
btn5.setOnClickListener(this);
btn6.setOnClickListener(this);
btn7.setOnClickListener(this);
}
private void initView() {
btn1 = ((Button) findViewById(R.id.btn1));
btn2 = ((Button) findViewById(R.id.btn2));
btn3 = ((Button) findViewById(R.id.btn3));
btn4 = ((Button) findViewById(R.id.btn4));
btn5 = ((Button) findViewById(R.id.btn5));
btn6 = ((Button) findViewById(R.id.btn6));
btn7 = ((Button) findViewById(R.id.btn7));
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1://開啟藍芽
onOpen();
break;
case R.id.btn2://關閉藍芽
onClose();
break;
case R.id.btn3://允許搜尋
onAbleFound();
break;
case R.id.btn4://開始搜尋
onFound();
break;
case R.id.btn5://客戶端
Intent intent=new Intent(this,ClientSocketActivity.class);
startActivity(intent);
break;
case R.id.btn6://伺服器端
Intent intent1=new Intent(this,ServerSocketActivity.class);
startActivity(intent1);
break;
case R.id.btn7://OBEX伺服器端
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==300){
//藍芽已開啟
Toast.makeText(MainActivity.this,"藍芽已開啟",Toast.LENGTH_SHORT).show();
}
}
/*
* 開啟藍芽
* */
public void onOpen(){
mBlueToothAdapter= BluetoothAdapter.getDefaultAdapter();
if (mBlueToothAdapter==null){
Toast.makeText(MainActivity.this,"手機不支援藍芽",Toast.LENGTH_SHORT).show();
return;
}
if (!mBlueToothAdapter.isEnabled()){//藍芽未開啟 則開啟藍芽
Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,300);
}
}
/*
* 關閉藍芽
* */
public void onClose(){
if (mBlueToothAdapter.enable())
mBlueToothAdapter.disable();
Toast.makeText(MainActivity.this,"藍芽已關閉",Toast.LENGTH_SHORT).show();
}
/*
* 允許被搜尋到 時長300
* */
public void onAbleFound(){
if (mBlueToothAdapter!=null&&mBlueToothAdapter.isEnabled()){
if (mBlueToothAdapter.getScanMode()==BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
Intent discoverableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//使本機在300秒內可被搜尋
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(discoverableIntent);
Toast.makeText(MainActivity.this,"藍芽已允許被檢測",Toast.LENGTH_SHORT).show();
}
}
}
public void onFound(){
Intent intent=new Intent(MainActivity.this,BlueListActivity.class);
startActivity(intent);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onRestart() {
super.onRestart();
}
}
客戶端邏輯:
/*
* 客戶端
*
* */
public class ClientSocketActivity extends AppCompatActivity implements View.OnClickListener {
private BluetoothAdapter mBluetoothAdapter;
private static final int REQUEST_BLUELIST=200;
BluetoothDevice device;
private Button btn;
BluetoothSocket socket=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
initView();
setListener();
Log.i("onCreate----","onCreate");
// 獲取到藍芽預設的介面卡
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()){
finish();
return;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode!=REQUEST_BLUELIST){
return;
}
if (resultCode!=RESULT_OK){
return;
}
device=data.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
new Thread(new Runnable() {
@Override
public void run() {
//開始連線
connect();
}
}).start();
}
private void connect() {
try {
socket=device.createRfcommSocketToServiceRecord(UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3"));
if (socket!=null){
socket.connect();
OutputStream outputStream=socket.getOutputStream();
if (outputStream != null) {
// 需要傳送的資訊
String text ="向服務端"+device.getName()+"傳送的資訊";
// 以utf-8的格式傳送出去
outputStream.write(text.getBytes("UTF-8"));
// Toast.makeText(ClientSocketActivity.this,"訊息已發出,等待服務端接收",Toast.LENGTH_SHORT).show();
}
}
} catch (IOException e) {
e.printStackTrace();
// Toast.makeText(ClientSocketActivity.this,"socket未連線",Toast.LENGTH_SHORT).show();
}finally {
}
}
private void setListener() {
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳轉到搜尋藍芽列表 選擇一個要連線的伺服器 回到客戶端 開始連線
Intent intent=new Intent(ClientSocketActivity.this,BlueListActivity.class);
startActivityForResult(intent,REQUEST_BLUELIST);
}
});
}
private void initView() {
// 獲取到ListView元件
btn=(Button)findViewById(R.id.btn);
}
@Override
public void onClick(View v) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (socket!=null){
socket=null;
}
}
}
activity_client佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lzq.bluetoothmanager.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="客戶端"
/>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜尋藍芽裝置"
/>
</LinearLayout>
服務端邏輯:
/*
* 服務端
*
* */
public class ServerSocketActivity extends Activity implements View.OnClickListener {
private BluetoothAdapter mBluetoothAdapter;
private Thread serverWorker=new Thread(){
@Override
public void run() {
listen();
}
};
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 通過msg傳遞過來的資訊,吐司一下收到的資訊
Toast.makeText(ServerSocketActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
}
};
private BluetoothServerSocket serverSocket;
private BluetoothSocket clientSocket;
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_server);
initView();
setListener();
// 獲取到藍芽預設的介面卡
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()){
finish();
return;
}
//開啟伺服器
serverWorker.start();
}
/*
* 監聽是否有客戶端連線
* */
private void listen() {
try {
serverSocket=mBluetoothAdapter.listenUsingRfcommWithServiceRecord("服務端",UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3"));
/*
* 客戶連線列表
* */
final List<String> lines=new ArrayList<>();
handler.post(new Runnable() {
@Override
public void run() {
lines.add("Rfcomm server started...");
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(ServerSocketActivity.this,android.R.layout.simple_list_item_1,lines);
lv.setAdapter(arrayAdapter);
}
});
clientSocket=serverSocket.accept();
//處理請求內容
if (clientSocket!=null){
Log.i("clientSocket---","已經連線上客戶端");
// Toast.makeText(ServerSocketActivity.this,"已經連線上客戶端",Toast.LENGTH_SHORT).show();
InputStream inputStream = clientSocket.getInputStream();
// 無線迴圈來接收資料
while (true) {
// 建立一個128位元組的緩衝
byte[] buffer = new byte[128];
// 每次讀取128位元組,並儲存其讀取的角標
int count = inputStream.read(buffer);
// 建立Message類,向handler傳送資料
Message msg = new Message();
// 傳送一個String的資料,讓他向上轉型為obj型別
msg.obj = new String(buffer, 0, count, "utf-8");
// 傳送資料
handler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void setListener() {
}
private void shutDownServer() {
new Thread(new Runnable() {
@Override
public void run() {
serverWorker.interrupt();
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket=null;
}
}
}).start();
}
private void initView() {
lv = (ListView) findViewById(R.id.lv);
}
@Override
public void onClick(View v) {
}
@Override
protected void onDestroy() {
super.onDestroy();
shutDownServer();
}
}
activity_server佈局
<?xml version="1.0" encoding="utf-8"?>
<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="com.example.lzq.bluetoothmanager.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="服務端"
/>
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
BlueListActivity
/*
* 搜尋藍芽列表
*
* */
public class BlueListActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private ListView lvDevices;
private ArrayAdapter<String> arrayAdapter;
//藍芽裝置資訊集合包括 name address
private List<String> bluetoothDevicesStr = new ArrayList<String>();
//藍芽裝置物件集合
private List<BluetoothDevice> bluetoothDevices = new ArrayList<BluetoothDevice>();
private BluetoothAdapter mBluetoothAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_list);
initView();
setListener();
// 為listview設定字元換陣列介面卡
arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevicesStr);
// 為listView繫結介面卡
lvDevices.setAdapter(arrayAdapter);
// 為listView設定item點選事件偵聽
lvDevices.setOnItemClickListener(this);
// 獲取到藍芽預設的介面卡
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter==null){
Toast.makeText(BlueListActivity.this,"手機不支援藍芽",Toast.LENGTH_SHORT).show();
return;
}
if (!mBluetoothAdapter.isEnabled()){//藍芽未開啟 則開啟藍芽
Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,200);
}
// 獲取曾經匹配的藍芽裝置 用Set集合保持已匹配的藍芽裝置
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
if (devices.size() > 0) {
for (BluetoothDevice bluetoothDevice : devices) {
// 儲存到arrayList集合中
bluetoothDevicesStr.add("曾經匹配過的藍芽--"+bluetoothDevice.getName() + ":"
+ bluetoothDevice.getAddress() + "\n");
bluetoothDevices.add(bluetoothDevice);
}
}
// 因為藍芽搜尋到裝置和完成搜尋都是通過廣播來告訴其他應用的
// 這裡註冊找到裝置和完成搜尋廣播
IntentFilter filter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //裝置已經連線廣播
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //裝置斷開連線廣播
registerReceiver(receiver, filter);
//開始搜尋
Search();
}
private void setListener() {
}
private void initView() {
// 獲取到ListView元件
lvDevices = (ListView) findViewById(R.id.lv);
}
public void Search() {
setTitle("正在掃描...");
// 點選搜尋周邊裝置,如果正在搜尋,則暫停搜尋
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
}
// 註冊廣播接收者
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent intent) {
// 獲取到廣播的action
String action = intent.getAction();
// 判斷廣播是搜尋到裝置還是搜尋完成
if (action.equals(BluetoothDevice.ACTION_FOUND)) {
// 找到裝置後獲取其裝置
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判斷這個裝置是否是之前已經繫結過了,如果是則不需要新增,在程式初始化的時候已經添加了
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 裝置沒有繫結過,則將其保持到arrayList集合中
bluetoothDevicesStr.add(device.getName() + ":"
+ device.getAddress() + "\n");
// 更新字串陣列介面卡,將內容顯示在listView中
arrayAdapter.notifyDataSetChanged();
bluetoothDevices.add(device);
}
} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
setTitle("搜尋完成");
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1://開啟藍芽
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
if (bluetoothDevicesStr!=null){
bluetoothDevicesStr=null;
}
if (bluetoothDevices!=null){
bluetoothDevices=null;
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mBluetoothAdapter.cancelDiscovery();
Intent intent=new Intent();
intent.putExtra(BluetoothDevice.EXTRA_DEVICE,bluetoothDevices.get(position));
setResult(RESULT_OK,intent);
finish();
}
}
注意:測試時要在兩個手機同時安裝app,且一個開啟伺服器,作為服務端,另一個開啟客戶端,模擬向服務端傳送資料。