android實(shí)現(xiàn)手機(jī)與單片機(jī)藍(lán)牙模塊通信
本文實(shí)例為大家分享了android實(shí)現(xiàn)手機(jī)與單片機(jī)藍(lán)牙模塊通信的具體代碼,供大家參考,具體內(nèi)容如下
我是參考原博客的內(nèi)容去寫的,由于原博客寫的不全,少了關(guān)鍵的幾個(gè)類,然后我就憑借自己扎實(shí)的功底補(bǔ)出來了,現(xiàn)在藍(lán)牙工作正常,能發(fā)能收!在看這邊文章之前你要先了解一下藍(lán)牙的工作狀態(tài),我的代碼里面可能解釋的不是很詳細(xì),但是我自己是能看懂的!
package com.example.fsl.bluetooth; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class MainActivity extends AppCompatActivity { private Toolbar toolbar; private TextView status; private StringBuilder mstringbuilder; private static final UUID MY_UUID=UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//沒有用到 BluetoothReceiver receiver; BluetoothAdapter mBtAdapter; BluetoothSocket mBtSocket; private BlueToothTool client; private ListView mListView; private List<String> ListDevice; private ArrayAdapter<String> mAdapter; private Button mbutton; private EditText editText; private ProgressBar progressBar; private LoopProgressBar loopProgressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar=(Toolbar)findViewById(R.id.toolbar); status=(TextView)findViewById(R.id.textView2); mListView=(ListView)findViewById(R.id.listView); mbutton=(Button)findViewById(R.id.button); editText=(EditText)findViewById(R.id.editText); progressBar=(ProgressBar)findViewById(R.id.progressBar); progressBar.setVisibility(View.INVISIBLE); loopProgressBar=(LoopProgressBar)findViewById(R.id.loop); ListDevice=new ArrayList<String>(); mstringbuilder=new StringBuilder(); setSupportActionBar(toolbar); enablebluetooth(); mbutton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { BlueToothTool.WriteTask W=client.new WriteTask(editText.getText().toString()); W.start(); } }); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mBtAdapter.cancelDiscovery();//停止搜索 progressBar.setVisibility(View.INVISIBLE); String str = ListDevice.get(position); String macAdress = str.split("\\|")[1]; BluetoothDevice device = mBtAdapter.getRemoteDevice(macAdress); client=new BlueToothTool(device,handler); try{ client.connect(); }catch (Exception e){ e.printStackTrace(); } } }); } /** *開啟藍(lán)牙且被發(fā)現(xiàn) */ private void enablebluetooth(){ mBtAdapter=BluetoothAdapter.getDefaultAdapter(); /** *if(!mBtAdapter.isEnabled()){這里可以先使能,可以在REQUEST_DISCOVERABLE處使能,這樣的話可以連使能和請(qǐng)求被發(fā)現(xiàn)一塊完成 // mBtAdapter.enable(); Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent,REQUEST_ENABLE); } else { show("藍(lán)牙已開啟"); }*/ Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(enable, REQUEST_DISCOVERABLE); } /** * 銷毀事件,注銷廣播 */ @Override protected void onDestroy() { unregisterReceiver(receiver); super.onDestroy(); } private final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case BlueToothTool.CONNECT_FAILED: show("連接失敗"); try { client.connect(); } catch (Exception e) { Log.e("TAG", e.toString()); } break; case BlueToothTool.CONNECT_SUCCESS: show("連接成功"); mListView.setVisibility(View.INVISIBLE); break; case BlueToothTool.READ_FAILED: show("讀取失敗"); break; case BlueToothTool.WRITE_FAILED: show("寫入失敗"); break; case BlueToothTool.DATA: mstringbuilder.append(msg.obj.toString()); show(mstringbuilder.toString()); break; } } }; /** * 請(qǐng)求響應(yīng)結(jié)果 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ /** *case REQUEST_ENABLE: if(requestCode!= Activity.RESULT_OK){ show("藍(lán)牙未開啟"); } else show("藍(lán)牙已開啟"); break;*/ case REQUEST_DISCOVERABLE: if(resultCode==Activity.RESULT_CANCELED){ show("藍(lán)牙未開啟"); } else show("藍(lán)牙已開啟"); break; default: break; } } public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.menu,menu); return true; } private static final int REQUEST_ENABLE=1; private static final int REQUEST_DISCOVERABLE=2; /** * 注冊(cè)廣播事件 */ @Override public void onResume(){ super.onResume(); IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); receiver = new BluetoothReceiver(); registerReceiver(receiver, filter); filter=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(receiver,filter); } /** * 廣播 */ private class BluetoothReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String str = device.getName() + "|" + device.getAddress(); if (ListDevice.indexOf(str) == -1)// 防止重復(fù)添加 ListDevice.add(str); // 獲取設(shè)備名稱和mac地址 if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } showDevices(); } else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ progressBar.setVisibility(View.INVISIBLE); show("已停止尋找"); } } }; /** * 菜單欄點(diǎn)擊事件 * @param item * @return */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.search: if(!mBtAdapter.isEnabled()){ show("藍(lán)牙未開啟"); } else { mBtAdapter.startDiscovery(); show("正在尋找設(shè)備"); progressBar.setVisibility(View.VISIBLE); } break; case R.id.about: Toast.makeText(MainActivity.this,"關(guān)于我們",Toast.LENGTH_SHORT).show(); break; default: } return true; } private void showDevices() { mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, ListDevice); mListView.setAdapter(mAdapter); } /** * 更新UI方法 * @param string */ private void show(final String string){ runOnUiThread(new Runnable() { @Override public void run() { status.setText(string); } }); } }
然后我的讀任務(wù)和寫任務(wù)以及連接任務(wù)是在另一個(gè)類里面實(shí)現(xiàn)的,也就是BlueToothTool類,這個(gè)類一個(gè)原博客是沒有寫的,只是MainActivity中用到了這個(gè)類的一些方法,但是沒有給出,所以就讓一些同學(xué)很蛋疼。我看完之后是自己補(bǔ)全的這個(gè)類!
package com.example.fsl.bluetooth; import android.app.Notification; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Handler; import android.os.Message; import android.support.v4.app.NotificationCompat; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.logging.LogRecord; /** * Created by Fsl on 2017/12/22. */ public class BlueToothTool { private BluetoothDevice device; private Handler mhandler; BluetoothSocket socket; static final int CONNECT_FAILED=1; static final int CONNECT_SUCCESS=5; static final int READ_FAILED=2; static final int WRITE_FAILED=3; static final int DATA=4; private boolean isConnect=false; public BlueToothTool(BluetoothDevice device,Handler handler){ this.device=device; this.mhandler=handler; } /** *開辟連接線程任務(wù) */ public void connect(){ Thread thread = new Thread(new Runnable() { @Override public void run() { BluetoothSocket tmp = null; Method method; try { method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}); tmp = (BluetoothSocket) method.invoke(device, 1); } catch (Exception e) { setState(CONNECT_FAILED); Log.e("TAG", e.toString()); } socket = tmp; try { socket.connect(); isConnect = true; setState(CONNECT_SUCCESS); Readtask readtask = new Readtask(); //連接成功后開啟讀取數(shù)據(jù)的線程 readtask.start(); } catch (Exception e) { setState(CONNECT_FAILED); Log.e("TAG", e.toString()); } } }); new Thread(thread).start(); } /** *開辟線程讀任務(wù) */ public class Readtask extends Thread{ @Override public void run(){ byte[] buffer = new byte[1024]; int bytes; InputStream inputStream ; //建立輸入流讀取數(shù)據(jù) while (true) { try { inputStream = socket.getInputStream(); if ((bytes = inputStream.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 = mhandler.obtainMessage(); msg.what = DATA; msg.obj = s; mhandler.sendMessage(msg); } } catch (IOException e) { setState(READ_FAILED); Log.e("TAG", e.toString()); break; } } if (socket != null) { try { socket.close(); } catch (IOException e) { Log.e("TAG", e.toString()); } } } } /** *開辟線程寫任務(wù) */ public class WriteTask extends Thread{ private String srt; public WriteTask(String str){ this.srt=str; } @Override public void run(){ OutputStream outputStream=null; byte[] st=srt.getBytes(); try{ outputStream=socket.getOutputStream(); outputStream.write(st); }catch (Exception e){ setState(WRITE_FAILED); e.printStackTrace(); } } } private void setState(int mes){ Message message=new Message(); message.what=mes; mhandler.sendMessage(message); } /** *下面這個(gè)方法目前還沒有用到 */ private byte[] getHexBytes(String message) { int len = message.length() / 2; char[] chars = message.toCharArray(); String[] hexStr = new String[len]; byte[] bytes = new byte[len]; for (int i = 0, j = 0; j < len; i += 2, j++) { hexStr[j] = "" + chars[i] + chars[i + 1]; bytes[j] = (byte) Integer.parseInt(hexStr[j], 16); } return bytes; } }
以上就是我的藍(lán)牙與單片機(jī)連接通信的全過程,順便說一下,這個(gè)連接是自動(dòng)連接的,不需要什么秘鑰什么的,直接搜索到HC-05藍(lán)牙直接就可以確定連接,親測有效。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解
這篇文章主要介紹了Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Android開發(fā)必知 九種對(duì)話框的實(shí)現(xiàn)方法
App中少不了與用戶交互的各種dialog,以此達(dá)到很好的用戶體驗(yàn),下面給大家介紹Android開發(fā)必知 九種對(duì)話框的實(shí)現(xiàn)方法,有需要的朋友可以參考下2015-08-08Android 逐幀動(dòng)畫創(chuàng)建實(shí)例詳解
這篇文章主要介紹了Android 逐幀動(dòng)畫創(chuàng)建實(shí)例詳解的相關(guān)資料,這里主要說明Android 動(dòng)畫的創(chuàng)建及使用方法,希望通過此文能幫助到大家,需要的朋友可以參考下2017-08-08Android基礎(chǔ)之使用Fragment適應(yīng)不同屏幕和分辨率(分享)
以下是對(duì)Fragment的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-07-07react native android6+拍照閃退或重啟的解決方案
android 6+權(quán)限使用的時(shí)候需要?jiǎng)討B(tài)申請(qǐng),那么在使用rn的時(shí)候要怎么處理拍照權(quán)限問題呢?本文提供的是一攬子rn操作相冊(cè)、拍照的解決方案,需要的朋友可以參考下2017-11-11Android采取BroadcastReceiver方式自動(dòng)獲取驗(yàn)證碼
這篇文章主要介紹了Android采取BroadcastReceiver方式自動(dòng)獲取驗(yàn)證碼,感興趣的小伙伴們可以參考一下2016-08-08Android應(yīng)用的Material設(shè)計(jì)的布局兼容性的一些要點(diǎn)總結(jié)
這篇文章主要介紹了Android應(yīng)用的Material設(shè)計(jì)的布局兼容性的一些要點(diǎn)總結(jié),文中還給了一個(gè)RecyclerView布局管理的例子,需要的朋友可以參考下2016-04-04淺析Android Studio 3.0 升級(jí)各種坑(推薦)
本文是小編給大家收藏整理的關(guān)于Android Studio 3.0 升級(jí)后遇到的一些坑,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-11-11Android實(shí)現(xiàn)點(diǎn)擊切換視圖并跳轉(zhuǎn)傳值
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)點(diǎn)擊切換視圖并跳轉(zhuǎn)傳值,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01