아두이노, 안드로이드 블루투스 통신하기
아두이노로 미세먼지 측정기를 만들던 도중 안드로이드와 연동하여 데이터를 주고 받고 싶어 제작하던 중 유용한 정보가 될 것 같아 포스팅 합니다.
이번 개발환경은 DESKTOP과 TEST DEVICE를 동시에 사용합니다. 여러분의 개발에 착오 없으시길 바랍니다. 자세한 개발환경에 대해서는 공지사항을 참고해 주시기 바랍니다.
미리 알아두면 좋은 것
준비하기
- HC-06모듈이 달린 아두이노
- 안드로이드 기기
- Android Studio (IDE)
제작하기
compile 'com.akexorcist:bluetoothspp:1.0.0'
블루투스를 사용할 것이기 때문에 블루투스 관련 권한을 manifest에 넣어줍니다.
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
activity_main.xml에다가 아래 레이아웃 소스코드를 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context="space.codejun.btcommunicatoin.MainActivity">
<Button
android:id="@+id/btnConnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="연결"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="보내기"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnConnect" />
</android.support.constraint.ConstraintLayout>
MainActivity.java로 가서 아래 소스코드를 추가해 줍니다.
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import app.akexorcist.bluetotohspp.library.BluetoothSPP;
import app.akexorcist.bluetotohspp.library.BluetoothState;
import app.akexorcist.bluetotohspp.library.DeviceList;
public class MainActivity extends AppCompatActivity {
private BluetoothSPP bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = new BluetoothSPP(this); //Initializing
if (!bt.isBluetoothAvailable()) { //블루투스 사용 불가
Toast.makeText(getApplicationContext()
, "Bluetooth is not available"
, Toast.LENGTH_SHORT).show();
finish();
}
bt.setOnDataReceivedListener(new BluetoothSPP.OnDataReceivedListener() { //데이터 수신
public void onDataReceived(byte[] data, String message) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
bt.setBluetoothConnectionListener(new BluetoothSPP.BluetoothConnectionListener() { //연결됐을 때
public void onDeviceConnected(String name, String address) {
Toast.makeText(getApplicationContext()
, "Connected to " + name + "\n" + address
, Toast.LENGTH_SHORT).show();
}
public void onDeviceDisconnected() { //연결해제
Toast.makeText(getApplicationContext()
, "Connection lost", Toast.LENGTH_SHORT).show();
}
public void onDeviceConnectionFailed() { //연결실패
Toast.makeText(getApplicationContext()
, "Unable to connect", Toast.LENGTH_SHORT).show();
}
});
Button btnConnect = findViewById(R.id.btnConnect); //연결시도
btnConnect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (bt.getServiceState() == BluetoothState.STATE_CONNECTED) {
bt.disconnect();
} else {
Intent intent = new Intent(getApplicationContext(), DeviceList.class);
startActivityForResult(intent, BluetoothState.REQUEST_CONNECT_DEVICE);
}
}
});
}
public void onDestroy() {
super.onDestroy();
bt.stopService(); //블루투스 중지
}
public void onStart() {
super.onStart();
if (!bt.isBluetoothEnabled()) { //
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, BluetoothState.REQUEST_ENABLE_BT);
} else {
if (!bt.isServiceAvailable()) {
bt.setupService();
bt.startService(BluetoothState.DEVICE_OTHER); //DEVICE_ANDROID는 안드로이드 기기 끼리
setup();
}
}
}
public void setup() {
Button btnSend = findViewById(R.id.btnSend); //데이터 전송
btnSend.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
bt.send("Text", true);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == BluetoothState.REQUEST_CONNECT_DEVICE) {
if (resultCode == Activity.RESULT_OK)
bt.connect(data);
} else if (requestCode == BluetoothState.REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_OK) {
bt.setupService();
bt.startService(BluetoothState.DEVICE_OTHER);
setup();
} else {
Toast.makeText(getApplicationContext()
, "Bluetooth was not enabled."
, Toast.LENGTH_SHORT).show();
finish();
}
}
}
}
중간중간 주석을 달아놓았습니다. 라이브러리가 잘 되어있기 때문에 크게 어려움은 없으리라 믿습니다. 그래도! 알려드릴건 알려드려야죠. 몇 가지 중요한 부분만 알려드리도록 하겠습니다.
bt.setOnDataReceivedListener(new BluetoothSPP.OnDataReceivedListener() { //데이터 수신
public void onDataReceived(byte[] data, String message) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
이 부분은 아두이노에서 넘어오는 데이터를 수신하는 부분입니다. 아두이노는 우리가 원하는대로 문자열, 정수 등등을 바로바로 던져주지 않고 1바이트씩 (...) 줍니다. 따라서 data에 아두이노에서 온 데이터를 넣어 바이트를 모두 합친 후 message를 통해 return 됩니다. 결론적으로 우리가 사용해야 할 것은 message 입니다. 저 소스코드에서는 토스트를 통해 띄워주고 있네요.
bt.startService(BluetoothState.DEVICE_OTHER); //DEVICE_ANDROID는 안드로이드 기기 끼리
저기 보이시는 DEVICE_OTHER은 아두이노와 같은 기기들과 연결할 때 사용하는 것입니다.
만약 안드로이드 기기끼리 통신하고 싶으시다면, DEVICE_ANDROID로 변경해 주세요.
public void setup() {
Button btnSend = findViewById(R.id.btnSend); //데이터 전송
btnSend.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
bt.send("Text", true);
}
});
}
이 부분은 블루투스 서비스가 시작되고 난 뒤에 실행되는 것인데요, 전송 버튼을 누르면 Text라는 글자가 아두이노에게 전송됩니다.
실행
위와 같이 기기가 뜨면 눌러서 아두이노와 연결을 해 줍니다.
그 다음 보내기 버튼을 누르게 되면 아두이노에 위의 소스코드 처럼 Text라는 글자가 전송되게 됩니다. 시리얼 모니터를 연 후 보내기 버튼을 눌러보세요.
Text라는 글자가 정상적으로 수신 되었습니다.
이제 끝입니다! 나머지는 여러분들의 입맛대로 쓰시면 됩니다.
질문은 언제나 환영입니다! 댓글 남겨주세요!
참고사항
Copyright (c) 2014 Akexorcist
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
'Android' 카테고리의 다른 글
Google I/O Extended Seoul 참가 후기 (0) | 2018.06.12 |
---|---|
Android Studio에서 Firebase Assistant 사용하기 (With. Dynamic Links) (2) | 2018.06.03 |
ML Kit 을 사용하여 간편하게 머신러닝 사용하기 (1) | 2018.05.25 |
Gradle용 Android 플러그인 업데이트 (0) | 2018.05.05 |
안드로이드 FCM(Firebase Cloud Messaging) 사용하기 (22) | 2018.05.04 |
댓글
이 글 공유하기
다른 글
-
Android Studio에서 Firebase Assistant 사용하기 (With. Dynamic Links)
Android Studio에서 Firebase Assistant 사용하기 (With. Dynamic Links)
2018.06.03 -
ML Kit 을 사용하여 간편하게 머신러닝 사용하기
ML Kit 을 사용하여 간편하게 머신러닝 사용하기
2018.05.25 -
Gradle용 Android 플러그인 업데이트
Gradle용 Android 플러그인 업데이트
2018.05.05 -
안드로이드 FCM(Firebase Cloud Messaging) 사용하기
안드로이드 FCM(Firebase Cloud Messaging) 사용하기
2018.05.04