<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dahun.log</title>
        <link>https://velog.io/</link>
        <description>기록을 남기는 걸 좋아하는 안드로이드 개발자입니다.</description>
        <lastBuildDate>Mon, 02 May 2022 17:18:14 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dahun.log</title>
            <url>https://images.velog.io/images/dahun_kim/profile/bbedc1fa-d421-4cad-b461-cf588ab0a213/IMG_1392.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dahun.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dahun_kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Android BLE 파헤치기 _ Auto Connect 편]]></title>
            <link>https://velog.io/@dahun_kim/BLE-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-Auto-Connect-%ED%8E%B8</link>
            <guid>https://velog.io/@dahun_kim/BLE-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-Auto-Connect-%ED%8E%B8</guid>
            <pubDate>Mon, 02 May 2022 17:18:14 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dahun_kim/post/10eccbd5-4de8-466d-9ea7-7033200de1b1/image.png" alt=""></p>
<h1 id="서론">서론</h1>
<p>나는 현재 회사에서 블루투스 SDK 관련 업무를 맡고 있다. 그래서 블루투스 관련 문서를 많이 보는 편인데, 안드로이드 공식 사이트에 나와있는 블루투스 관련 설명이 하나같이 다 불친절하다고 느꼈다.</p>
<p>사실 문서만이 아니다. 실제로 API를 사용해보면 에러 코드가 별 다른 구분 없이 다 동일한 코드로 떨어진다던가, 블루투스 전송 시 API 레벨에서 일련의 큐 구조와 같은 메시지 관리 로직이 없어 성공, 실패 등등의 응답이 떨어지기 전에 전송하면 문제가 발생한다던가 ...</p>
<p>사실 이러한 내용들은 난 공식 문서에서 알려줘야 하는 부분이라고 생각하는데, 공식 문서에는 하나같이 내용들이 부실하며, 그냥 단순한 코드 스니펫만 줄줄 나와있다.</p>
<p>그래서 답답했던 나머지 내가 여태껏 안드로이드의 Bluetooth API를 사용하면서 이해가 되지 않거나, 궁금했던 내용, 삽질했던 내 기록들을 담은 BLE 시리즈를 준비해보았다.</p>
<p>오늘은 그 첫번째 이야기, Auto Connect에 관한 내용이다.</p>
<h1 id="살펴보기">살펴보기</h1>
<p><a href="https://developer.android.com/guide/topics/connectivity/bluetooth-le?hl=ko#connect">안드로이드 공식 문서</a>를 확인해보면 다음과 같은 코드 스니펫을 볼 수 있다.</p>
<pre><code class="language-kotlin">var bluetoothGatt: BluetoothGatt? = null
...
bluetoothGatt = device.connectGatt(this, false, gattCallback)</code></pre>
<p>매개변수는 앞에서부터 <code>Context</code>, <code>boolean</code>, <code>BluetoothGattCallback</code> 를 입력받는다.</p>
<p>Context와 BluetoothGattCallback은 그렇다 쳐도, 2번째 값인 <code>autoConnect(boolean)</code>은 어떤 친구일까?</p>
<blockquote>
<p><strong>autoConnect</strong> : 이용 가능한 즉시 블루투스 기기에 자동 연결할지 나타내는 부울
<em>Android Developer</em></p>
</blockquote>
<p>그렇다. 번역된거라 이해가 바로 되지는 않지만, 여러 번 읽다 보면 뭔가 자동으로 다시 연결해주고 싶을 때 사용하는 플래그 같다.</p>
<p>이 플래그를 설정하면 어떠한 매커니즘이 동작할까?</p>
<h1 id="auto-connect와-direct-connect">Auto Connect와 Direct Connect</h1>
<p>위의 매개변수 <code>autoConnect</code>에 전달하는 값에 따라</p>
<ul>
<li><code>true</code> : <strong>Auto Connect</strong></li>
<li><code>false</code> : <strong>Direct Connect</strong></li>
</ul>
<p>로 동작한다.</p>
<h2 id="direct-connect">Direct Connect</h2>
<p>용어에서도 알 수 있듯이, 직접 연결을 의미한다.</p>
<ul>
<li>이 연결은 시스템 설정 앱에서 블루투스 스캔 후 터치하여 직접 연결하는 것과 동일하다.</li>
<li>Direct Connect를 이용해 BLE 연결 시도 시, 안드로이드 OS는 30초의 시간 제한을 둔다.</li>
<li>30초 이내 연결이 되지 않을 경우 실패로 간주해, 더 이상 연결을 시도하지 않고 <code>Callback</code>으로 에러를 반환한다.</li>
</ul>
<p>또한 Direct Connect는 Auto Connect에 비해 우선순위가 높게 처리되기 때문에 만약 Auto Connect를 시도하고 있는 연결이 있다면 잠시 중단하고 Direct Connect를 우선적으로 처리하게 된다.</p>
<h2 id="auto-connect">Auto Connect</h2>
<p>이건 자동 연결을 의미하며, Direct Connect의 반대 성격을 가진다.</p>
<ul>
<li>우선 연결에 시간 제한이 없다. 주변 장치를 계속 스캔하며 연결이 가능해지면 연결을 시도한다.</li>
<li>한 번 연결됐던 디바이스는 사용자의 별 다른 상호작용 없이도 계속 연결을 시도한다.</li>
</ul>
<p>또한 동시에 여러 개의 Auto Connect 연결을 가질 수 있다. 그래서 디바이스 신호가 약해졌거나, 꺼졌거나 하는 등의 이유로 Connection을 Lost 해도 끊임없이 재연결을 시도한다.</p>
<p>근데, 만약 이 때 <code>disconnect()</code> 또는 <code>close()</code>를 호출하여 연결이 끊어지면 다시 연결을 시도하지 않는다.</p>
<h2 id="차이점">차이점</h2>
<p>이 외에도 연결할 때 차이가 있다. Direct Connect가 30초라는 시간 제한을 가진 대신 우선순위가 더 높기 때문에 더 짧은 주기로 연결 가능한 <code>Advertising Packet</code>을 검색한다. 그래서 Auto Connect보다 연결이 더 빠르게 성립된다.</p>
<blockquote>
<p>사실 이 차이는 Android 10 부터는 줄어들었다고 한다. Direct Connect를 처리하는 동안 Auto Connect는 멈추지 않고, Direct Connect에도 <code>Whitelist</code> 개념이 도입되어 Auto Connect와 비슷하게 동작된다고 한다.</p>
</blockquote>
<h1 id="auto-connect의-동작-방식">Auto Connect의 동작 방식</h1>
<p><code>autoConnect = true</code> 로 연결이 성립된다면 연결된 디바이스에 대한 정보가 캐시되어 저장된다. 이게 <code>WhiteList</code>에 등록되는 것인데, 무조건 등록되는 것은 아니고 아래의 조건 중 하나 이상을 만족해야 한다.</p>
<ul>
<li>블루투스 기기와 bind 되어야 한다.</li>
<li>블루투스 기기의 주소가 public 해야 한다.</li>
<li>블루투스 기기의 주소가 random static address 여야 한다.</li>
</ul>
<p>이 중에 한 가지의 조건도 성립되지 않는다면 <code>whiteList</code>에 추가되지 못하고, 재연결을 시도하지 않게 된다.</p>
<h1 id="auto-connect의-활용">Auto Connect의 활용</h1>
<p>백그라운드에서 지속적인 연결이 필요한 경우에 사용할 수 있겠다. 나와 같은 경우 개발 중인 SDK 중 백그라운드에서도 지속적인 데이터 수신이 필요한 기능이 있는데, Connection이 항상 유지될 수가 없으므로 이럴 때 Auto Connect를 이용해 다시 연결을 시도하는 방식을 생각해보았다.</p>
<p>다만 백그라운드에서 블루투스 Connection을 유지하기 위해 Foreground Service를 이용해 백그라운드에서도 연결이 유지되도록 작업해주었다.</p>
<h1 id="결론">결론</h1>
<p>Auto Connect가 연결이 해제되어도 다시 연결을 해주기 때문에 더 좋아보일 수도 있지만, Direct Connect 보다 우선순위가 낮아 연결이 늦게 성립된다.</p>
<p>또, 앱이 종료되면 디바이스 정보를 캐시했던 WhiteList가 날아가서 재연결을 시도하지 않는다. 이는 활용에서도 언급했듯이 Foreground Service를 이용해 백그라운드에서도 어느 정도의 연결 유지는 가능하다. 다만 이 Service도 시스템에 의하여 종료되는 등의 이유로 앱의 프로세스가 완전히 kill 된다면 재연결을 다시 시도하지 않는다. 이는 단말기가 Shutdown 해도 동일하다.</p>
<p>나와 같은 경우 위의 상황을 대비해 MAC Address를 따로 저장하여 BroadcastReceiver를 통해 부팅 이벤트를 수신받고, Foreground Service를 이용해 재연결 하도록 작업하려고 했다.</p>
<hr>
<h1 id="참고">참고</h1>
<p><a href="https://stackoverflow.com/questions/40156699/which-correct-flag-of-autoconnect-in-connectgatt-of-ble">https://stackoverflow.com/questions/40156699/which-correct-flag-of-autoconnect-in-connectgatt-of-ble</a></p>
]]></description>
        </item>
    </channel>
</rss>