728x90
https://twinparadox.tistory.com/132
위 링크에 올린 블루투스 리모컨으로 조종하는 아두이노 선풍기에 어플리케이션 코드가 없었다.
프로젝트를 정리해 올리면서 아두이노 스케치 코드는 올렸는데, 어플리케이션 코드는 찾지 못해서 올리지 못한 상태였는데 최근 코틀린을 배우면서, 코틀린도 연습할 겸, 잃어버린 프로젝트의 주권(?)을 되찾을 겸, 리모컨을 다시 만들었다.
소스에 대해 간략히 설명하자면, SelectDeviceActivity는, 블루투스 장치를 검색 및 선택하는 액티비티고, ControlActivity는 해당 장치를 컨트롤하는 액티비티로, 여기서는 리모컨 역할을 하는 액티비티다.
build.gradle
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 27 defaultConfig { applicationId "twinparadox.bluetoothremotecontroller" minSdkVersion 21 targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' compile "org.jetbrains.anko:anko-common:0.8.3" } | cs |
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="twinparadox.bluetoothremotecontroller"> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".SelectDeviceActiviy"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ControlActivity" android:screenOrientation="portrait" > </activity> </application> </manifest> | cs |
control_layout.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.constraint.ConstraintLayout android:id="@+id/wind_power" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp"> <Button android:id="@+id/wind_high" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/high" app:layout_constraintRight_toRightOf="parent"/> <Button android:id="@+id/wind_mid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/mid" app:layout_constraintLeft_toLeftOf="@+id/wind_low" app:layout_constraintRight_toRightOf="@+id/wind_high" /> <Button android:id="@+id/wind_low" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/low" app:layout_constraintLeft_toLeftOf="parent"/> </android.support.constraint.ConstraintLayout> <android.support.constraint.ConstraintLayout android:id="@+id/wind_stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" app:layout_constraintTop_toBottomOf="@+id/wind_power" > <Button android:id="@+id/wind_off" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/windstop"/> </android.support.constraint.ConstraintLayout> <android.support.constraint.ConstraintLayout android:id="@+id/rotation_angle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" app:layout_constraintTop_toBottomOf="@+id/wind_stop"> <Button android:id="@+id/angle_60" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/angle60" app:layout_constraintLeft_toLeftOf="parent"/> <Button android:id="@+id/angle_120" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/angle120" app:layout_constraintLeft_toLeftOf="@+id/angle_60" app:layout_constraintRight_toRightOf="@+id/angle_180" /> <Button android:id="@+id/angle_180" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/angle180" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout> <android.support.constraint.ConstraintLayout android:id="@+id/rotation_stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" app:layout_constraintTop_toBottomOf="@+id/rotation_angle"> <Button android:id="@+id/rotation_off" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/rotationstop"/> </android.support.constraint.ConstraintLayout> <android.support.constraint.ConstraintLayout android:id="@+id/disconnect" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" app:layout_constraintTop_toBottomOf="@+id/rotation_stop"> <Button android:id="@+id/disconnect_device" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/disconnect"/> </android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout> | cs |
ControlActivity.kt
package twinparadox.bluetoothremotecontroller import android.app.ProgressDialog import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothSocket import android.content.Context import android.os.AsyncTask import android.os.Bundle import android.os.PersistableBundle import android.support.v7.app.AppCompatActivity import android.util.Log import kotlinx.android.synthetic.main.control_layout.* import java.io.IOException import java.util.* class ControlActivity: AppCompatActivity() { companion object { var m_myUUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") var m_bluetoothSocket: BluetoothSocket? = null lateinit var m_progress:ProgressDialog lateinit var m_bluetoothAdapter:BluetoothAdapter var m_isConnected:Boolean = false lateinit var m_address:String } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.control_layout) m_address=intent.getStringExtra(SelectDeviceActiviy.EXTRA_ADDRESS) ConnectToDevice(this).execute() wind_off.setOnClickListener{ sendCommand("off") } wind_low.setOnClickListener{ sendCommand("on1") } wind_mid.setOnClickListener { sendCommand("on2") } wind_high.setOnClickListener { sendCommand("on3") } rotation_off.setOnClickListener { sendCommand("off4") } angle_60.setOnClickListener { sendCommand("on4") } angle_120.setOnClickListener { sendCommand("on5") } angle_180.setOnClickListener { sendCommand("on6") } disconnect_device.setOnClickListener{ disconnect() } } private fun sendCommand(input:String) { if(m_bluetoothSocket != null) { try { m_bluetoothSocket!!.outputStream.write(input.toByteArray()) } catch (e:IOException) { e.printStackTrace() } } } private fun disconnect() { if(m_bluetoothSocket != null) { try { m_bluetoothSocket!!.close() m_bluetoothSocket = null m_isConnected = false } catch (e:IOException) { e.printStackTrace() } } finish() } private class ConnectToDevice(c: Context): AsyncTask<Void, Void, String>() { private var connectSuccess:Boolean = true private val context:Context init { this.context=c } override fun onPreExecute() { super.onPreExecute() m_progress= ProgressDialog.show(context,"Connecting...","please wait") } override fun doInBackground(vararg params: Void?): String? { try { if(m_bluetoothSocket == null || !m_isConnected) { m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() val device:BluetoothDevice = m_bluetoothAdapter.getRemoteDevice(m_address) m_bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(m_myUUID) BluetoothAdapter.getDefaultAdapter().cancelDiscovery() m_bluetoothSocket!!.connect() } } catch(e:IOException) { connectSuccess=false e.printStackTrace() } return null } override fun onPostExecute(result: String?) { super.onPostExecute(result) if(!connectSuccess) { Log.i("data","coudln't connect") } else { m_isConnected=true } m_progress.dismiss() } } } | cs |
select_device_layout.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=".SelectDeviceActiviy"> <ListView android:id="@+id/select_device_list" android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@id/select_device_refresh" app:layout_constraintTop_toTopOf="parent" android:layout_marginBottom="10dp"/> <Button android:id="@+id/select_device_refresh" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginStart="20dp" android:layout_marginEnd="20dp" android:layout_marginBottom="20dp" android:text="@string/refresh"/> </android.support.constraint.ConstraintLayout> | cs |
SelectDeviceActivity.kt
package twinparadox.bluetoothremotecontroller import android.app.Activity import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.content.Intent import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.AdapterView import android.widget.ArrayAdapter import kotlinx.android.synthetic.main.select_device_layout.* import org.jetbrains.anko.toast class SelectDeviceActiviy : AppCompatActivity() { private var m_bluetoothAdapter:BluetoothAdapter? = null private lateinit var m_pairedDevices:Set<BluetoothDevice> private val REQUEST_ENABLE_BLUETOOTH = 1 companion object { val EXTRA_ADDRESS: String = "Device_address" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.select_device_layout) m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() if(m_bluetoothAdapter == null) { toast("This device dosen't support bluetooth") return } if(!m_bluetoothAdapter!!.isEnabled) { val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH) } select_device_refresh.setOnClickListener{ pairedDeviceList() } } private fun pairedDeviceList() { m_pairedDevices = m_bluetoothAdapter!!.bondedDevices val deviceList : ArrayList<BluetoothDevice> = ArrayList() val nameList : ArrayList<String> = ArrayList() if(!m_pairedDevices.isEmpty()) { for(device:BluetoothDevice in m_pairedDevices) { deviceList.add(device) nameList.add(device.name+"("+device.address+")") Log.i("device",""+device.name) } } else { toast("Paired devices not found") } val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1,nameList) select_device_list.adapter = adapter select_device_list.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> val device: BluetoothDevice = deviceList[position] val address: String = device.address val intent = Intent(this, ControlActivity::class.java) intent.putExtra(EXTRA_ADDRESS,address) startActivity(intent) } } override fun onActivityResult(requestCode:Int, resultCode:Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if(requestCode == REQUEST_ENABLE_BLUETOOTH) { if(resultCode == Activity.RESULT_OK) { if(m_bluetoothAdapter!!.isEnabled) { toast("Bluetooth has been enabled") } else { toast("Bluetooth has benn disabled") } } else if(resultCode == Activity.RESULT_CANCELED) { toast("Bluetooth enabling has benn canceled") } } } } | cs |
728x90
'정리가 필요한 카테고리(추후 정리) > Android, iOS' 카테고리의 다른 글
안드로이드] 안드로이드에서 HttpURLConnection을 이용해 POST 방식으로 데이터 전송하기 (0) | 2019.06.03 |
---|---|
안드로이드의 이미지버튼(ImageButton)과 이미지뷰(ImageView)의 차이 (0) | 2018.10.09 |
코틀린(Kotlin) 조건문(When, if) (0) | 2018.07.26 |
코틀린(Kotlin)을 이용하면 findViewById()를 사용할 필요가 없다 (0) | 2018.07.25 |
안드로이드 예제 - 코틀린으로 로그인-메뉴 화면 만들기 (0) | 2018.07.22 |