Всем привет, сегодня я хотел бы показать вам, как написать приложение для Android, которое будет использовать Bluetooth для подключения к Arduino.
Блютуз подключение в Android проект для Arduino
Блютуз подключение в Android проект для Arduino
Блютуз подключение в Android проект для Arduino
В частности, это в рамках моего проекта связи Android устройства с Arduino, поскольку меня недавно с АлиЭкспресс пришел модуль hc-06, это модуль Bluetooth для подключения.
Давайте напишем небольшой проект, большой небольшой, ну посмотрим, и в середине, когда дойдём до графической части написания layout для приложения, я вам покажу интересный эмулятор который я думаю вас заинтересует и решит Ваши проблемы с производительностью.
Давайте создадим новый проект, это как обычно EmptyActivity, дадим названием, допустим Bt-hc-06, да будет так.
Делаем под минимальную, под пятую версию, там разберемся.
Завершилось создание проекта, давайте перейдём в наш проект в манифест, нам нужно будет добавить строки для разрешение работы с блютузом.
Обратите внимание, в примерах кода для AndroidManifest.xml и activity_main.xml после угловой скобки я добавил пробел, чтобы на сайте теги разметки не перемешались с тегами самой статьи. В своем коде < uses-permission, < TextView, < ListView, < FrameLayout, < ToggleButton и т.д., а так же закрывающие теги пишите слитно!!!
< uses-permission android:name="android.permission.BLUETOOTH" /> < uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Будет 2 строки в 2 разрешения Bluetooth и Bluetooth_ADMIN также давайте сделаем чтобы наша MainActivity располагалась в портретном виде.
< activity android:name=".MainActivity" android:screenOrientation="portrait">
Манифест больше нам не понадобится перейдём в ActivityMain.xml в слой LayOut, поскольку код у меня уже в принципе набран, сверстан, я буду лишь добавлять блоками фрагменты кода и буду где-то походу пояснять, так сказать, что у нас к чему и зачем.
Закрываем RelativeLayout это будет у нас общая так сказать рамка, канва.
< TextView
android:id="@+id/textInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:textSize="22dp"
android:visibility="visible" />
Добавляем textview с Id textinfo, добавим listview, список куда у нас будут подгружаться данные об найденных устройствах, далее мы добавим FrameLayout, он будет нужен для отображение всех устройств, которые мы будем видеть, к которым вернее мы подключимся.
< ListView
android:id="@+id/list"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="@+id/textInfo"
android:layout_alignParentStart="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="30dp"
android:visibility="visible" />
< FrameLayout
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#e7e7e5"
android:visibility="gone">
/// **************///
< /FrameLayout>
Также во внутрь FrameLayout мы добавим RelativerLayout для позиционирования элементов внутри.
< RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
/// **************///
< /RelativeLayout>
Я хочу показать вам на примере четырех канального включателя-выключателя, который будет подключаться к Bluetooth адаптеру и передавать команды, которые Arduino будет принимать и соответственно на этих 4 пинах Arduino будет выполняться какие-либо действия.
Это может быть, как включение реле, как мигание светодиодов, различное, то есть мы конкретно здесь в коде и не прописываем, что мы на самом деле будем подключать в Arduino, но в принципе у нас будет кнопка 1, кнопка 2, кнопка 3, кнопка 4, типа ToggleButton, которая фиксирует нажатое состояние.
< ToggleButton
android:id="@+id/toggleButton1"
android:layout_width="264dp"
android:layout_height="70dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="71dp"
android:layout_marginEnd="70dp"
android:text="D10"
android:textOff="D10 OFF"
android:textOn="D10 ON " />
< ToggleButton
android:id="@+id/toggleButton2"
android:layout_width="211dp"
android:layout_height="70dp"
android:layout_below="@+id/toggleButton1"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="70dp"
android:text="D11"
android:textOff="D11 OFF"
android:textOn="D11 ON" />
< ToggleButton
android:id="@+id/toggleButton3"
android:layout_width="211dp"
android:layout_height="70dp"
android:layout_below="@+id/toggleButton2"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="70dp"
android:text="D12"
android:textOff="D12 OFF"
android:textOn="D12 ON" />
< ToggleButton
android:id="@+id/toggleButton4"
android:layout_width="211dp"
android:layout_height="70dp"
android:layout_below="@+id/toggleButton3"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginLeft="70dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="70dp"
android:text="D13"
android:textOff="D13 OFF"
android:textOn="D13 ON" />
С RelativeLayout мы практически закончили, давайте теперь перейдем в дизайн, и обратите внимание, в виде компонентов получается следующая картина: надпись, список, и вот это вся панель.
На данный момент кнопки у нас не видны, когда мы выберем какой-то пункт из списка сопряженных устройств, а это будет наша Arduino с Bluetooth модулем, то мы должны будем увидеть список с кнопками.
Давайте мы переключим listView, мы его сделаем невидимым,
android:visibility="gone"
а для FrameLayout напишем
android:visibility="visible"
сделав его видимым, сохраним, и вот у нас просто будут располагаться кнопки.
Эти кнопки типа ToggleButton, при нажатии на которые они фиксируют, свое состояние, при повторном нажатии, естественно меняется цвет, меняются названия.
По поводу кнопок, я хотел вам показать, как у меня проставлены названия кнопок, здесь событии нажатия свойство textOff примет значение название кнопки + OFF, при повторном нажатии textOn примет значение название кнопки + ON, кнопки я называл по номеру используемых пинов в ардуинке.
Всё здесь позиционировано, отступы по 70 единиц от краев, и 48 друг от друга, поскольку то устройство на котором будут тестировать немножко не совпадает по размерам и скорей всего съедет в сторону…)
Давайте теперь посмотрим, что у нас получилось по поводу эмулятора, я хочу вам представить очень удобный, на мой взгляд, эмулятор называется LDPlayer (не путать с ЛДПР)…)
Смотрите видео: Найдена лучшая замена эмулятора Android!!! (для Android Studio)
Так же дополнительная информация есть в основном видео к этой статье. А в двух словах - стоит попробовать!
Переключим обратно значения видимости для ListView и FrameLayout с кнопками: скроем как это было и вернёмся всё-таки к написанию кода.
Список у нас пока пустой, собственно тут есть кнопки, но они будут скрыты, пока не произойдет соединение по блютуз и никакие данные в него не передаются.
Займемся теперь самой большой частью кода, скопируйте весь текст MainActivity.java, изменив только имя пакета, если оно отличается от моего.
package ru.maxfad.bt_hc_06;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
import static android.R.layout.simple_list_item_1;
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener{
ToggleButton tb1,tb2,tb3,tb4;
private static final int REQUEST_ENABLE_BT = 1;
public TextView textInfo;
BluetoothAdapter bluetoothAdapter;
ArrayList< String> pairedDeviceArrayList;
ListView listViewPairedDevice;
FrameLayout ButPanel;
ArrayAdapter< String> pairedDeviceAdapter;
ThreadConnectBTdevice myThreadConnectBTdevice;
ThreadConnected myThreadConnected;
private UUID myUUID;
private StringBuilder sb = new StringBuilder();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tb1 = (ToggleButton) findViewById(R.id.toggleButton1);
tb2 = (ToggleButton) findViewById(R.id.toggleButton2);
tb3 = (ToggleButton) findViewById(R.id.toggleButton3);
tb4 = (ToggleButton) findViewById(R.id.toggleButton4);
tb1.setOnCheckedChangeListener(this);
tb2.setOnCheckedChangeListener(this);
tb3.setOnCheckedChangeListener(this);
tb4.setOnCheckedChangeListener(this);
final String UUID_STRING_WELL_KNOWN_SPP = "00001101-0000-1000-8000-00805F9B34FB";
textInfo = (TextView)findViewById(R.id.textInfo);
listViewPairedDevice = (ListView)findViewById(R.id.list);
ButPanel = (FrameLayout) findViewById(R.id.panel);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)){
Toast.makeText(this, "BLUETOOTH NOT support", Toast.LENGTH_LONG).show();
finish();
return;
}
myUUID = UUID.fromString(UUID_STRING_WELL_KNOWN_SPP);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not supported on this hardware platform", Toast.LENGTH_LONG).show();
finish();
return;
}
String stInfo = bluetoothAdapter.getName() + " " + bluetoothAdapter.getAddress();
textInfo.setText(String.format("Это устройство: %s", stInfo));
}
@Override
protected void onStart() { // Запрос на включение Bluetooth
super.onStart();
if (!bluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
setup();
}
private void setup() { // Создание списка сопряжённых Bluetooth-устройств
Set< BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) { // Если есть сопряжённые устройства
pairedDeviceArrayList = new ArrayList<>();
for (BluetoothDevice device : pairedDevices) { // Добавляем сопряжённые устройства - Имя + MAC-адресс
pairedDeviceArrayList.add(device.getName() + "\n" + device.getAddress());
}
pairedDeviceAdapter = new ArrayAdapter<>(this, simple_list_item_1, pairedDeviceArrayList);
listViewPairedDevice.setAdapter(pairedDeviceAdapter);
listViewPairedDevice.setOnItemClickListener(new AdapterView.OnItemClickListener() { // Клик по нужному устройству
@Override
public void onItemClick(AdapterView< ?> parent, View view, int position, long id) { //тут пробел после скобки !!!!
listViewPairedDevice.setVisibility(View.GONE); // После клика скрываем список
String itemValue = (String) listViewPairedDevice.getItemAtPosition(position);
String MAC = itemValue.substring(itemValue.length() - 17); // Вычленяем MAC-адрес
BluetoothDevice device2 = bluetoothAdapter.getRemoteDevice(MAC);
myThreadConnectBTdevice = new ThreadConnectBTdevice(device2);
myThreadConnectBTdevice.start(); // Запускаем поток для подключения Bluetooth
}
});
}
}
@Override
protected void onDestroy() { // Закрытие приложения
super.onDestroy();
if(myThreadConnectBTdevice!=null) myThreadConnectBTdevice.cancel();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_ENABLE_BT){ // Если разрешили включить Bluetooth, тогда void setup()
if(resultCode == Activity.RESULT_OK) {
setup();
}
else { // Если не разрешили, тогда закрываем приложение
Toast.makeText(this, "BlueTooth не включён", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private class ThreadConnectBTdevice extends Thread { // Поток для коннекта с Bluetooth
private BluetoothSocket bluetoothSocket = null;
private ThreadConnectBTdevice(BluetoothDevice device) {
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(myUUID);
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() { // Коннект
boolean success = false;
try {
bluetoothSocket.connect();
success = true;
}
catch (IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Нет коннекта,
проверьте Bluetooth-устройство с которым хотите соединица!", Toast.LENGTH_LONG).show();
listViewPairedDevice.setVisibility(View.VISIBLE);
}
});
try {
bluetoothSocket.close();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
if(success) { // Если законнектились, тогда открываем панель с кнопками и запускаем поток приёма и отправки данных
runOnUiThread(new Runnable() {
@Override
public void run() {
ButPanel.setVisibility(View.VISIBLE); // открываем панель с кнопками
}
});
myThreadConnected = new ThreadConnected(bluetoothSocket);
myThreadConnected.start(); // запуск потока приёма и отправки данных
}
}
public void cancel() {
Toast.makeText(getApplicationContext(), "Close - BluetoothSocket", Toast.LENGTH_LONG).show();
try {
bluetoothSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
} // END ThreadConnectBTdevice:
private class ThreadConnected extends Thread { // Поток - приём и отправка данных
private final InputStream connectedInputStream;
private final OutputStream connectedOutputStream;
private String sbprint;
public ThreadConnected(BluetoothSocket socket) {
InputStream in = null;
OutputStream out = null;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
}
catch (IOException e) {
e.printStackTrace();
}
connectedInputStream = in;
connectedOutputStream = out;
}
@Override
public void run() { // Приём данных
while (true) {
try {
byte[] buffer = new byte[1];
int bytes = connectedInputStream.read(buffer);
String strIncom = new String(buffer, 0, bytes);
sb.append(strIncom); // собираем символы в строку
int endOfLineIndex = sb.indexOf("\r\n"); // определяем конец строки
if (endOfLineIndex > 0) {
sbprint = sb.substring(0, endOfLineIndex);
sb.delete(0, sb.length());
runOnUiThread(new Runnable() { // Вывод данных
@Override
public void run() {
switch (sbprint) {
case "D10 ON":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D10 OFF":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D11 ON":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D11 OFF":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D12 ON":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D12 OFF":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D13 ON":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
case "D13 OFF":
Toast.makeText(MainActivity.this, sbprint, Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
});
}
} catch (IOException e) {
break;
}
}
}
public void write(byte[] buffer) {
try {
connectedOutputStream.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
switch (compoundButton.getId()) {
case R.id.toggleButton1:
if(isChecked){
if(myThreadConnected!=null) {
byte[] bytesToSend = "a".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D10 ON", Toast.LENGTH_SHORT).show();
}else{
if(myThreadConnected!=null) {
byte[] bytesToSend = "A".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D10 OFF", Toast.LENGTH_SHORT).show();
}
break;
case R.id.toggleButton2:
if(isChecked){
if(myThreadConnected!=null) {
byte[] bytesToSend = "b".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D11 ON", Toast.LENGTH_SHORT).show();
}else{
if(myThreadConnected!=null) {
byte[] bytesToSend = "B".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D11 OFF", Toast.LENGTH_SHORT).show();
}
break;
case R.id.toggleButton3:
if(isChecked){
if(myThreadConnected!=null) {
byte[] bytesToSend = "c".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D12 ON", Toast.LENGTH_SHORT).show();
}else{
if(myThreadConnected!=null) {
byte[] bytesToSend = "C".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D12 OFF", Toast.LENGTH_SHORT).show();
}
break;
case R.id.toggleButton4:
if(isChecked){
if(myThreadConnected!=null) {
byte[] bytesToSend = "d".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D13 ON", Toast.LENGTH_SHORT).show();
}else{
if(myThreadConnected!=null) {
byte[] bytesToSend = "D".getBytes();
myThreadConnected.write(bytesToSend );
}
Toast.makeText(MainActivity.this, "D13 OFF", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
Поясню идею в целом: при соединении телефона с блютуз модулем станут видны кнопки, при нажатии на них будет меняться их состояние, вид, текст. Функция Toast будет писать, какая кнопка нажата и по блютуз будут передаваться команды – буква a – (английская, маленькая)- нажата кнопка D10 – включить, на выход Arduino 10 десятый идет напряжение. Буква A - (английская, большая)- повторно кнопка D10, выключить, на выход Arduino десятый пин напряжение перестает подаваться.
То же самое правило действует и для остальных кнопок: D11, D12, D13, - b/B, c/C, d/D – вкл/выкл.
Статью со скетчем для Arduino выложу в ближайшее время, так что посещайте сайт чаще, добавляйтесь в группы в Одноклассниках, вКонтакте, или на facebook, в них я всегда публикую анонсы новых статей. Подписывайтесь на канал в ютубе, чтобы не пропустить выход видео, исходники проекта вы можете скачать по ссылке ниже.
Cкачать архив для ознакомления - проект Блютуз подключение Android и Arduino:
Блютуз подключение в Android проект для Arduino
Рекомендуем смотреть видео в полноэкранном режиме, в настойках качества выбирайте 1080 HD, не забывайте подписываться на канал в YouTube, там Вы найдете много интересного видео, которое выходит достаточно часто. Приятного просмотра!
С уважением, авторы сайта Компьютерапия
Понравилось? Поделись этим видео с друзьями!
Блютуз подключение в Android проект для Arduino
Рекомендуем смотреть видео в полноэкранном режиме, в настойках качества выбирайте 1080 HD, не забывайте подписываться на видео ВКонтакте, там Вы найдете много интересного, которое выходит достаточно часто. Приятного просмотра!
С уважением, авторы сайта Компьютерапия
Понравилось? Поделись этим видео с друзьями!
Блютуз подключение в Android проект для Arduino
Рекомендуем смотреть видео в полноэкранном режиме, в настойках качества выбирайте 1080 HD, не забывайте подписываться на канал в Рутубе, там Вы найдете много интересного, которое выходит достаточно часто. Приятного просмотра!
С уважением, авторы сайта Компьютерапия
Понравилось? Поделись этим видео с друзьями!