[MAUI] 안드로이드 블루투스 Native? 개발(작성 중입니다)

안녕하세요.
Android native 개발을 처음 어떻게 진행 할수 있는지 그 과정에 대해 말해보려고 합니다.
[잡다한 내용]


(사실 native라고하면 저는 감이 잘 안잡힙니다. 지금부터 설명하려는 것이 native인지도 조금 의문이 들기도하구요)
부족하지만 가이드 해주시는 분이 있어서 native로 개발 할수 있었습니다.


Android native 개발에 대해 알아보겠습니다.
native는 원주민, 본래의 등의 뜻을 가집니다. 어떠한 것의 원조라는 느낌이드네요.
native 개발 이라고하면 '플랫폼에서 지원하는 특정 언어로 개발한다’라는 느낌이네요
Android에서 자바, 코틀린 / iOS에서는 Object-C, Swift 로 개발하는 것입니다.
이 글에서 .Net MAUI에서 Java 코드를 랩핑 후 사용하는 방법에 대해 알아 볼 것입니다.
랩핑설명
우선 Java 코드를 랩핑해야하는데 이미 대부분 되어 있는거 같습니다.

Xamarin Aandroid SDK입니다. (랩핑된 코드를 보실 수 있습니다.)

Android java, Kotlin에 대한 문서입니다.
필요한 Native 코드는 Android developers에서 찾고 해당하는 코드를 Xamarin Android SDK에서 래핑된 것을 찾아 사용하 실 수 있습니다.

.Net에서 Android Native로 개발하려면 Java 코드를 랩핑해야한다. => MS에서 Android Code가 랩핑된 문서를 볼 수있다. => 랩핑된 코드를 사용하면 된다.

제가 느낀 Native 개발에서 장점은 ‘자료가 많고 개발이 자유롭다’ 입니다.
Android developers에서 블루투스에 대한 가이드를 제공합니다. 문서를 보고 따라만하면 어느정도 개발이 가능합니다.
Bluetooth 가이드 문서

Java와 C# 코드의 차이점

단순 Java Vs C#에 대한 것이 아니라 Java로 개발하는 문서를 보고 C#으로 랩핑된 코드로 개발했을 때 느낀점에 대해 말씀 드리려고 합니다.
C#에서 보통 파스칼식으로 명명하는 것을 Java에서는 카멜식으로 표현하더군요.

Java code Vs C# 랩핑된 코드
getRemoteDeviceJava 코드는 C#에서 GetRemoteDevice로 표현합니다.
(첫 알파벳이 대문자냐 소문자냐의 차이입니다.)

Java에서는 인스턴트하면서 Override를 할수 있습니다.
image
참조 문서
Android Developers Bluetooth 가이드 문서를 보면 자주 보이는 방식입니다.
이러한 방식은 C#에서 못본거 같습니다. 저는 C#에서 Class를 새로생성해서 사용했습니다.

++++++++++
예제를 추가해 설명하기
메소드에 어떠한 설정에 대한 것을 파라미터로 넣은 부분이 있습니다. 이러한 경우 C#에서는 enum을 좀 다른 이름으로 정의되어있고 이 부분은 문서를 통해 찾기가 좀 어려운 부분이 있습니다.
이 경우 매소드의 파라미터를 확인하고 필요한 enum 이름을 알아내어 추척하는 방식이 편합니다.
설명을 위한 가짜 예시) [Java 코드] SearchBluetoothDevice( ???, ???, Set.LowEnergy)

[C#] enum ScanMode
{ LowEnergy, …}
++++++++++

++ 에뮬레이터에서 블루투스 검색이 됩니다. (실질적인 검색은 안되지만, Dummy device가 잡히는 것 같아요)


[본문]

본 글은 Bluetooth Low Energy에 관한 내용입니다.
(Bluetooth는 Bluetooth Classic, Bluetooth Low Energy로 나뉩니다.)

개발 방법

  1. Android developers 문서를 보고 학습하기 Android developers - Android 가이드 문서, Reference 문서
  2. Java 코드를 MS문서를 통해 적용하기 MS - Android SDK 문서

Bluetooth 개발

  1. Bluetooth 앱 권한 설정
  2. Bluetooth device 검색

:one: Bluetooth 앱 권한 설정 참조 문서
앱에서 블루투스를 사용하러면 권한이 필요합니다.
(보안상의 이유로 앱에서 기능을 사용하려면 권한이 필요하지 않나 생각합니다.)
Platforms/Android/AndroidManifest.xml에서 설정 할수 있습니다.
image

AndroidManifest.xml에서 ‘~~이러한 권한이 필요하다’ 정도로 설정 할 수 있습니다.(권한 선언)
특정 권한은 사용자에게 직접 권한 요청을해서 동적으로 받아야합니다.
(android:protectionLevel="dangerous" 특정 레벨의 권한은 사용자의 동의가 필요합니다.)
(종종 보셨을 겁니다. 앱을 다운 받으면 마이크, 사진, 전화, 연락처 등등 권한을 요청하는 것을 말이죠.
이와 같이 Bluetooth도 사용자에게 동의를 받아야하는 권한이 있습니다.)
참조 - 권한 만들기(권한에 설정하는 보안 레벨이 있습니다.)
Bluetooth의 경우 위치 권한을 사용자에게 요청해야합니다.
Bluetooth로 위치에 대한 값을 얻을 수 있기 때문인 것 같습니다.
Ex) 비콘 - 전시장에서 주로 사용되며 사용자와 일정 거리 안에 들어오면 통신을 시작한다.
전시품에 대한 설명창을 기기에 보여줄 때 사용한다. (정확한 예시인 지는 좀 의문입니다. 신호의 세기를 감지하는 것인지 거리를 어느 정도 가늠하는 것인지 애매하네요)

그리고 Android에 버전에 따라 필요한 권한이 다릅니다.
API 12 기준으로 근처기기, 탐색, 연결에 대한 권한이 필요합니다.
단순히 근처기기에 대한 권한을 요청해도 Bluetooth를 사용할 수 있습니다만… 함정이 있습니다.
근처기기에 대한 권한만 요청 했을 때 권한 요청이 잘 안됩니다. (50번 배포하면 1번 정도??)
그래서 수동으로 모바일 기기에서 권한 설정하여 사용하기도 했습니다.
근처기기, 연결, 탐색 3가지 모두를 같이 사용자에게 권한을 요청하면 잘 동작했습니다.

위치권한은 사용자에게 요청할 권한이 정의 되어 있습니다만,
Android API 12에서 Bluetooth에 대한 권한은 직접 생성해야 합니다.(사용자에게 동적으로 요청할 때 필요합니다. AndroidManifest.xml에서 권한 선언은 따로 정의 할 필요없이 가능합니다.)

MAUI Android Permissions 클래스 파일입니다. IsDeclaredInManifest은 권한이 선언 되었나 확인할 수 있는 매소드구요. 그 외 여러가지 매소드와 어떻게 권한이 정의되는지 보실수 있습니다.

// Android API 12 
// Define Custom Permissions
internal class AndroidApi12Permissions : Permissions.BasePlatformPermission
{
	public override (string androidPermission, bool isRuntime)[] RequiredPermissions
	{
		get
		{
			List<(string, bool)> permissions = new();

			permissions.Add((Manifest.Permission.BluetoothConnect, true));
			permissions.Add((Manifest.Permission.BluetoothScan, true));
			permissions.Add((Manifest.Permission_group.NearbyDevices, true));
		
			return permissions.ToArray();
		}
	}
}

(왜 이걸 제공해주지 않고 직접 구현해서 사용해야하는 지는 의문입니다.)
(하고나면 별거 아닌듯 하지만 이거 하나에 비용이 너무 컸습니다;; )

// 앱이 실행 될 때 권한을 요청하면 될 것 같습니다.
// 저는 `MainActivity`에서 요청 했습니다.
await Permissions.RequestAsync<AndroidApi12Permissions>()

Permissions.RequestAsync<>()를 통해서 사용자에게 권한 동의를 받으면 됩니다.

:two: Bluetooth Low Energy device 검색
참조 - Bluetooth Low Energy - OverView
참조 - Bluetootth Classic - Set up Bluetooth
참조 - Android Developers Reference
참조 - MS Xamarin Android SDK

(Bluetooth device 검색의 경우 탐색(Scan)을 시작하면 Callback으로 탐색결과가 들어오는 방식입니다.)

2-1 Set up bluetooth
image
Java code를 MAUI 프로젝트에 복붙 합니다.

image
당연하게 빨간줄로 맞이해줍니다 ^^

image
참조 - MS Xamarin Android SDK에서 getSystemService를 검색합니다.

image
[검색 결과] Namespace가 Android.Content라는 걸 알수 있으며 메소드 이름이 대문자로 시작합니다.
getSystemService() => Context.GetSystemService()

.

.

Context.GetSystemService(BluetoothManager.class) => Context.GetSystemService(Context.BluetoothService)
BluetoothManager.class가 무엇인지 짐작하기도 힘드네요;;
이럴 때 Android developers Reference에서 검색을하면 좋습니다.

image
[Android developers Reference 검색 결과]
GetSystemService에 string 값을 넣어주면 되고 그 값은 Context Bluetooth_Service에 있다고 하네요 ^^

image
[Android developers Reference 검색 결과]
Context.BLUETOOTH_SERVICE은 string 값으로 "bluetooth"라는 걸 확인 할수 있습니다.

image
(Visual studio에서 Context를 추적해보면BluetoothService가 같은 값을 가지며 BLUETOOTH_SERVICE에서 생성 되었다고 하네요)

bluetoothManager.getAdapter() => bluetoothManager.Adapter`
이 경우 변경 사항이 많아서 그런지 찾기가 쉽지 않았습니다.

image
[Xamarin SDK 검색 결과]
Xamarin Android SDK에서 getAdapter에 대한 검색결과가 나오지 않습니다 ㅠㅠ
대신 BluetoothManager에 대해 검색하면 Adapter가 보입니다.
관련 있어보이니 한번 확인 해보겠습니다.

image
[Xamarin SDK 검색 결과]
설명글 "Get the BLU~~~"이 있으며 Register("getAdapter")라는 문구가 보이네요.

image
[Android developers Reference 검색 결과]
설명글도 완전히 동일한 것으로 보아 getAdapter()은 C#에서 Adapter로 되어 있는것 같습니다. ^^

image
[before]

image
[after]
이러한 방식으로 Java 코드를 C#에서 사용하는 방법을 찾습니다.

(다음에 이어서 가겠습니다. 생각보다 시간이 오래걸리고 정리가 잘 안되네요)

6개의 좋아요

@Stupid 앗 저도 조만 간에 필요한 작업인데 좋은 글 감사드립니다.!! :smile:

2개의 좋아요