Creați un scaner Bluetooth cu Bluetooth API-ul Android

Bluetooth a devenit o tehnologie foarte populară, în special pe dispozitivele mobile. Este o tehnologie pentru a descoperi și a transfera date între dispozitivele din apropiere. Practic, fiecare dispozitiv mobil modern are capabilități Bluetooth în aceste zile. Dacă doriți să creați o interfață de aplicație cu un alt dispozitiv compatibil Bluetooth, de la telefoane la difuzoare, trebuie să știți cum să utilizați API-ul Bluetooth al Android.

În acest tutorial, vom face o aplicație asemănătoare cu aplicația Bluetooth încorporată în setările Android. Acesta va include următoarele caracteristici:

  • activați Bluetooth pe un dispozitiv
  • afișați o listă de dispozitive asociate
  • descoperiți și listați dispozitive Bluetooth din apropiere

De asemenea, vom trece peste elementele de bază pentru a conecta și a trimite date către un alt dispozitiv Bluetooth. Am creat un proiect pentru a ne începe, pe care îl puteți descărca de la GitHub. Imaginea de mai jos ilustrează ce arată proiectul de pornire. Dacă te blochezi sau te confrunți cu probleme, poți să te uiți la proiectul finalizat pe GitHub.

1. Activarea funcției Bluetooth

Înainte de a putea activa Bluetooth pe un dispozitiv Android, trebuie să solicităm permisiunile necesare. Facem asta în manifestul aplicației. BLUETOOTH permisiunea permite aplicației noastre să se conecteze, să deconecteze și să transfere date cu un alt dispozitiv Bluetooth. BLUETOOTH_ADMIN permisiunea permite aplicației noastre să descopere noi dispozitive Bluetooth și să modifice setările Bluetooth ale dispozitivului.

  

Vom folosi adaptorul Bluetooth pentru a interfața cu Bluetooth. Inițializăm adaptorul în ListActivity clasă. Dacă adaptorul este nul, acest lucru înseamnă că Bluetooth nu este acceptat de dispozitiv și că aplicația nu va funcționa pe dispozitivul curent. Ne ocupăm de această situație prin afișarea unui dialog de alertă către utilizator și prin ieșirea din aplicație.

@Override protejat void onCreate (Bundle savedInstanceState) ... BTAdapter = BluetoothAdapter.getDefaultAdapter (); // Telefonul nu acceptă Bluetooth, astfel încât utilizatorul să știe și să iasă. dacă (BTAdapter == null) new AlertDialog.Builder (this) .setTitle ("Incompatibil") .setMessage ("Telefonul nu suportă Bluetooth") .setPositiveButton void onClick (dialog DialogInterface, int care) System.exit (0);) .setIcon (android.R.drawable.ic_dialog_alert) .show (); 

Dacă Bluetooth este disponibil pe dispozitiv, trebuie să-l activați. Pentru a activa Bluetooth, începem o intenție oferită de SDK Android, BluetoothAdapter.ACTION_REQUEST_ENABLE. Aceasta va prezenta un dialog către utilizator, cerându-i permisiunea de a activa Bluetooth pe dispozitiv. REQUEST_BLUETOOTH este un număr întreg static pe care l-am stabilit pentru a identifica solicitarea de activitate.

clasa publica ListActivity extinde ActionBarActivity implementează DeviceListFragment.OnFragmentInteractionListener public static int REQUEST_BLUETOOTH = 1; ... protejat void onCreate (Bundle savedInstanceState) ... if (! BTAdapter.isEnabled ()) Intenție enableBT = Intenție nouă (BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult (enableBT, REQUEST_BLUETOOTH); 

2. Obținerea unei liste de dispozitive asociate

În acest pas, scanăm dispozitivele Bluetooth asociate și le afișăm într-o listă. În contextul unui dispozitiv mobil, un dispozitiv Bluetooth poate fi:

  • necunoscut
  • împerecheat
  • conectat

Este important să cunoașteți diferența dintre un dispozitiv Bluetooth asociat și unul conectat. Dispozitivele asociate sunt conștiente de existența celuilalt și partajează o cheie de legătură, care poate fi utilizată pentru autentificare, rezultând o conexiune. Dispozitivele sunt asociate automat odată ce se stabilește o conexiune criptată.

Dispozitivele conectate împart un canal RFCOMM, permițându-le să trimită și să primească date. Un dispozitiv poate avea mai multe dispozitive asociate, dar poate fi conectat la un singur dispozitiv la un moment dat.

Dispozitivele Bluetooth sunt reprezentate de BluetoothDevice obiect. O listă de dispozitive asociate poate fi obținută invocând getBondedDevices () , care returnează un set de BluetoothDevice obiecte. Invocăm getBondedDevices () metodă în DeviceListFragment„s onCreate () metodă.

public void onCreate (bundle savedInstanceState) super.onCreate (savedInstanceState); Log.d ("DEVICELIST", "Super solicitat pentru DeviceListFragment onCreate \ n"); deviceItemList = noul ArrayList(); A stabilit pairDevices = bTAdapter.getBondedDevices (); 

Noi folosim getName () și getAddress ()  pentru a obține mai multe informații despre dispozitivele Bluetooth. getName () metoda returnează identificatorul public al dispozitivului în timp ce getAddress () metoda returnează adresa MAC a dispozitivului, un identificator care identifică în mod unic dispozitivul.

Acum, când avem o listă de dispozitive asociate, vom crea o DeviceItem obiect pentru fiecare BluetoothDevice obiect. Apoi adăugăm fiecare DeviceItem obiect la un numit matrice deviceItemList. Vom utiliza această matrice pentru a afișa lista de dispozitive Bluetooth asociate în aplicația noastră. Codul pentru afișarea listei de DeviceItem obiectele sunt deja prezente în proiectul de pornire.

dacă (perecheDevices.size ()> 0) pentru (Dispozitiv BluetoothDevice: perechiDevice) DeviceItem newDevice = DeviceItem nou (device.getName (), device.getAddress (), "false"); deviceItemList.add (newDevice); 

3. Descoperiți dispozitive Bluetooth apropiate

Următorul pas este să descoperiți dispozitivele pe care dispozitivul nu le-a încorporat încă, necunoscut și adăugați-le în lista dispozitivelor asociate. Facem acest lucru când utilizatorul pune butonul de scanare. Codul pentru a gestiona acest lucru este situat în DeviceListFragment.

Mai întâi trebuie să facem BroadcastReceiver și suprascrie onReceive () metodă. onReceive () metoda este invocată ori de câte ori este găsit un dispozitiv Bluetooth.

 onReceive () metoda are ca scop al doilea argument. Putem verifica ce fel de intenție este transmisă invocând getAction (). Dacă acțiunea este BluetoothDevice.ACTION_FOUND, atunci știm că am găsit un dispozitiv Bluetooth. Când se întâmplă acest lucru, vom crea un DeviceItem utilizând numele dispozitivului și adresa MAC. În cele din urmă, adăugăm DeviceItem obiecte față de ArrayAdapter pentru a le afișa în aplicația noastră.

class public DeviceListFragment extinde Fragment implementează AbsListView.OnItemClickListener ... final privat BroadcastReceiver bReciever = nou BroadcastReceiver () public void onReceive (Context context, intent intent) String action = intent.getAction (); dacă (BluetoothDevice.ACTION_FOUND.equals (acțiune)) dispozitiv BluetoothDevice = intent.getParcelableExtra (BluetoothDevice.EXTRA_DEVICE); // Creați un element de dispozitiv nou DeviceItem newDevice = DeviceItem nou (device.getName (), device.getAddress (), "false"); // Adăugați-l la adaptorul nostru mAdapter.add (newDevice); ; 

Când butonul de scanare este pornit, trebuie doar să înregistram receptorul pe care tocmai l-am făcut și să-l invocăm startDiscovery () metodă. Dacă butonul de scanare este oprit, dezarhivează receptorul și invocă cancelDiscovery (). Rețineți că descoperirea ocupă o mulțime de resurse. Dacă aplicația dvs. se conectează cu un alt dispozitiv Bluetooth, trebuie să anulați descoperirea înainte de conectare.

De asemenea, clarificăm ArrayAdapter obiect, mAdapter, când începe descoperirea. Când începem să scanăm, nu vrem să includem dispozitive vechi care ar putea să nu mai fie în raza dispozitivului.

public Vizualizare onCreateView (LayoutInflater inflater, Container ViewGroup, Bundle savedInstanceState) Vizualizare vedere = inflater.inflate (R.layout.fragment_deviceitem_list, container, false); ToggleButton scan = (ToggleButton) view.findViewById (R.id.scan); ... scan.setOnCheckedChangeListener (new CompoundButton.OnCheckedChangeListener () public void onCheckedChanged CompoundButton buttonView, boolean isChecked) IntentFilter filter = new IntentFilter (BluetoothDevice.ACTION_FOUND) dacă este (esteChecked) mAdapter.clear (); getActivity () .regReceptor (bReciever, filter); bTAdapter.startDiscovery (); altceva getActivity () unregisterReceiver (bReciever) bTAdapter.cancelDiscovery ); 

Asta e. Am terminat scanerul Bluetooth.

4. Conectarea la un dispozitiv

Conexiunile Bluetooth funcționează ca orice altă conexiune. Există un server și un client, care comunică prin prize RFCOMM. Pe Android, prizele RFCOMM sunt reprezentate ca a BluetoothSocket obiect. Din fericire pentru noi, cea mai mare parte a codului tehnic pentru servere este gestionată de SDK-ul Android și disponibilă prin Bluetooth API.

Conectarea ca client este simplă. Prima dată obțineți mufa RFCOMM de la cea dorită BluetoothDevice sunând createRfcommSocketToServiceRecord (), trecând într-un UUID, o valoare de 128 de biți pe care o creați. UUID este similar cu un număr de port.

De exemplu, să presupunem că faceți o aplicație de chat care utilizează Bluetooth pentru a discuta cu alți utilizatori din apropiere. Pentru a găsi alți utilizatori în chat, doriți să căutați alte dispozitive cu aplicația dvs. de chat instalată. Pentru a face acest lucru, am căuta UUID în lista de servicii a dispozitivelor din apropiere. Utilizarea unui UUID pentru a asculta și a accepta conexiuni Bluetooth adaugă automat UUID la lista de servicii a telefonului sau la protocolul de descoperire a serviciului.

Odata ce BluetoothSocket este creat, sunați conectați() pe BluetoothSocket. Aceasta va inițializa o conexiune cu BluetoothDevice prin mufa RFCOMM. Odată ce dispozitivul nostru este conectat, putem folosi soclul pentru a schimba datele cu dispozitivul conectat. Acest lucru este similar cu orice implementare standard a serverului.

Menținerea unei conexiuni Bluetooth este costisitoare, așa că trebuie să închidem soclul când nu mai avem nevoie de el. Pentru a închide soclul, sunăm închide() pe BluetoothSocket.

Următorul fragment de cod arată cum să vă conectați la un anumit articol BluetoothDevice:

clasa publică ConnectThread extinde Thread private BluetoothSocket bTSocket; conexiune publică boolean (BluetoothDevice bTDevice, UUID mUUID) BluetoothSocket temp = null; încercați temp = bTDevice.createRfcommSocketToServiceRecord (mUUID);  captură (IOException e) Log.d ("CONNECTTHREAD", "Nu s-a putut crea socketul RFCOMM:" + e.toString ()); return false;  încercați bTSocket.connect ();  captură (IOException e) Log.d ("CONNECTTHREAD", "Nu s-a putut conecta:" + e.toString ()); încercați bTSocket.close ();  captură (IOException închide) Log.d ("CONNECTTHREAD", "Nu s-a putut închide conexiunea:" + e.toString ()); return false;  return true;  public boolean anula () try bTSocket.close ();  captură (IOException e) Log.d ("CONNECTTHREAD", "Conectarea nu a putut fi închisă:" + e.toString ()); return false;  return true; 

Conectarea ca server este ceva mai dificilă. În primul rând, de la dvs. BluetoothAdapter, trebuie să obțineți a BluetoothServerSocket, care va fi folosit pentru a asculta o conexiune. Aceasta se utilizează numai pentru a obține conexiunea RFCOMM partajată a conexiunii. Odată ce conexiunea este stabilită, soclul serverului nu mai este necesar și poate fi închis prin apelare închide() pe el.

Instalați o socket de server apelând listenUsingRfcommWithServiceRecord (numele șirului, UUID mUUID). Această metodă are doi parametri, un nume de tip Şir și un identificator unic de tip UUID. Parametrul nume este numele pe care îl oferim serviciului când acesta este adăugat la intrarea SDP (Service Discovery Protocol) din telefon. Identificatorul unic ar trebui să se potrivească cu UUID pe care îl utilizează clientul care încearcă să se conecteze.

Apoi sunăm Accept() pe nou obținut BluetoothServerSocket să așteptați o conexiune. Cand Accept() apelul returnează ceva care nu este nul, noi îi atribuim BluetoothSocket, pe care le putem apoi utiliza pentru a face schimb de date cu dispozitivul conectat.

Următorul fragment de cod arată cum se acceptă o conexiune ca server:

clasa publică ServerConnectThread extinde Thread private BluetoothSocket bTSocket; public ServerConnectThread ()  public void acceptConnect (BluetoothAdapter bTAdapter, UUID mUUID) BluetoothServerSocket temp = null; încercați temp = bTAdapter.listenUsingRfcommWithServiceRecord ("Service_Name", mUUID);  captură (IOException e) Log.d ("SERVERCONNECT", "Nu am putut obține un BluetoothServerSocket:" + e.toString ());  în timp ce (adevărat) try bTSocket = temp.accept ();  captură (IOException e) Log.d ("SERVERCONNECT", "Nu s-a putut accepta o conexiune primită"); pauză;  dacă (bTSocket! = null) try temp.close ();  captură (IOException e) Log.d ("SERVERCONNECT", "ServerSocket nu a putut fi închis:" + e.toString ());  pauză;  void public closeConnect () încercați bTSocket.close ();  captură (IOException e) Log.d ("SERVERCONNECT", "Conexiunea nu a putut fi închisă:" + e.toString ()); 

Citirea și scrierea la conexiune se face folosind fluxuri, InputStream și OutputStream. Putem trimite o referință la aceste fluxuri sunând getInputStream () și getOutputStream () pe BluetoothSocket. Pentru a citi și scrie în aceste fluxuri, sunăm citit() și scrie() respectiv.

Următorul fragment de cod arată cum se face acest lucru pentru un singur întreg:

clasa publica ManageConnectThread extinde Subiectul public ManageConnectThread ()  public void sendData (socket BluetoothSocket, int date) arunca IOException ByteArrayOutputStream output = new ByteArrayOutputStream (4); output.write (date); Ieșire OutputStreamStream = socket.getOutputStream (); outputStream.write (output.toByteArray ());  public int receiveData (socket BluetoothSocket) aruncă IOException byte [] buffer = nou octet [4]; Intrare ByteArrayInputStream = ByteArrayInputStream (buffer) nou; InputStream inputStream = socket.getInputStream (); inputStream.read (tampon); întoarcere input.read (); 

Puteți găsi ambele exemple în proiectul finalizat pe GitHub.

Concluzie

Am realizat cu succes propriul scaner Bluetooth și am învățat următoarele:

  • solicitați permisiunile Bluetooth necesare
  • activați Bluetooth pe telefon
  • obțineți o listă de dispozitive asociate
  • scanați și afișați o listă de dispozitive Bluetooth din apropiere
  • stabiliți o conexiune Bluetooth între două dispozitive
  • să trimiteți și să primiți date printr-o conexiune Bluetooth

Simțiți-vă libertatea de a utiliza codul în proiectul finalizat pe GitHub și modificați-l în propriile aplicații.

Cod