이 글은 .net android webview, 블루투스 기능 과 blazor server를 활용한 프로젝트에서 사용한 기능 정리입니다.
1. 안드로이드 퍼미션 추가
<!--네트워크 상태 퍼미션-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 카메라 퍼미션 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<!-- 5.0 버전 파일업로드 퍼미션 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- 외부 저장소 사용 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--블루투스 권한-->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- 기기 검색을 위한 권한(위치가 필요하지 않고 장비만 검색하기 위해 위치는 무시) -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<!-- 페어링된 기기를 확인하기 위한 권한 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
2. OnCreate 매서드
OnCreate 매서드에서 코드 추가시 동작하는 기능
ㄱ.화면 고정
RequestedOrientation = ScreenOrientation.Landscape; //세로화면 고정
RequestedOrientation = ScreenOrientation.Portrait; //가로화면 고정
ㄴ.웹뷰 id 가져오기
Android.Webkit.WebView webView = (WebView)FindViewById(Resource.Id.webview);
ㄷ.웹뷰에서 JS 사용 허용
webView.Settings.JavaScriptEnabled = true;
ㄹ.웹뷰를 실행하는 디바이스 고유 ID 가져오기
string deviceid = Settings.Secure.GetString(this.ContentResolver, Settings.Secure.AndroidId);
ㅁ.웹뷰 실행
webView.LoadUrl("url");
3.블루투스 연결 다이얼로그
ㄱ. 블루투스 어댑터를 디폴트 어댑터로 설정
//bluetoothAdapter 값이 null 이면 디바이스가 블루투스를 지원하지 않는다는 의미
Android.Bluetooth.BluetoothAdapter bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
ㄴ.블루투스 활성화 상태인지 아닌지 확인
bool bluetoothenable = bluetoothAdapter.Enable();
ㄷ.해당기기에 페어링 되어있는 불루투스 기기 찾기
ICollection<BluetoothDevice> devices = bluetoothAdapter.BondedDevices;
ㄹ. 디바이스에 기기 페어링을 위한 다이얼로그 생성
AlertDialog.Builder builder = new AlertDialog.Builder(Instance);
builder.SetTitle("페어링 되어있는 블루투스 디바이스 목록");
// 페어링 된 각각의 디바이스의 이름과 주소를 저장할 리스트 선언 및 추가
List<string> list = new List<string>();
List<string> listaddress = new List<string>();
foreach (var m in devices)
{
list.Add(m.Name);
listaddress.Add(m.Address);
}
list.Add("취소");
ㅁ. 선택시 이벤트 추가
EventHandler<DialogClickEventArgs> handler = (s, o) => {
if (o.Which != list.Count - 1)
{
if (connectedDevice == "" || connectedDevice != list[o.Which])
{
connectDevice(listaddress[o.Which], list[o.Which]);
}
}};
// 해당 아이템을 눌렀을 때 호출 되는 이벤트 리스너
builder.SetItems(list.ToArray(), handler);
ㅂ. 뒤로가기 버튼 누를 때 창이 안닫히도록 설정
builder.SetCancelable(false);
ㅅ. 다이얼로그 생성
AlertDialog alertDialog = builder.Create();
alertDialog.Show();
4.디바이스와 블루투스 연결
3번 ㅂ항목의 connectDevice(deviceaddress, deviceName)매서드에 관한 내용
ㄱ.디바이스 주소를 이용해서 bluetoothDevice 변수 값 할당
Android.Bluetooth.BluetoothDevice bluetoothDevice = bluetoothAdapter.GetRemoteDevice(deviceaddress);
ㄴ. UUID 생성
UUID uuid = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
블루투스 프로토콜에 해당하는 값에 대한 내용은 아래 링크 참조
https://dsnight.tistory.com/13
[안드로이드] 블루투스 프로토콜 UUID 리스트
안드로이드 블루투스통신 예제는 인터넷에 많이 있을 것이다. 예를들면 블루투스통신 채팅 같은 예제.. 그러나 예제를 수정하여 블루투스 통신을 구현하려고 할 때 연결이 잘 안될수도 있다. 블
dsnight.tistory.com
ㄷ. Rfcomm 채널을 통해 블루투스 디바이스와 통신하는 소켓 생성 및 연결
Android.Bluetooth.BluetoothSocket bluetoothSocket = bluetoothDevice.CreateRfcommSocketToServiceRecord(uuid);
//블루투스 연결 실패 시 아래 코드에서 오류가 발생함.
bluetoothSocket.Connect();
ㄹ. 데이터 송,수신 스트림
System.IO.Stream outputStream = bluetoothSocket.OutputStream;
System.IO.inputStream = bluetoothSocket.InputStream;
ㅁ. 블루투스 수신 시 이벤트를 thread로 실행
ThreadStart ts1 = new ThreadStart(receiveData);
thread = new System.Threading.Thread(ts1);
thread.Start();
5. 블루투스 수신 이벤트
// 데이터를 수신 버퍼 생성
byte[] readBuffer = new byte[1024];
// 데이터를 수신 확인
int byteAvailable = inputStream.Read(readBuffer);
if (byteAvailable > 0)
{
string receivedata = System.Text.Encoding.Default.GetString(readBuffer);
Instance.webView.Post(() => { Instance.webView.LoadUrl("javascript:'웹의js함수명'('" + receivedata + "')"); });
}
6. Web과 .Net Android 연계
ㄱ. Web에서 .Net Android
function CallAndroidMethod() {
" Android 프로젝트명"." Android 매서드";
//AndroidApp1이라는 프로젝트에서 AndroidMethod 라는 매서드를 실행한다.
//AndroidApp1.AndroidMethod();
}
// Android 쪽 매서드 위에 [JavascriptInterface], [Export] 선언해주면 웹에서도 호출 가능하게 한다
[JavascriptInterface]
[Export]
public void AndroidMethod (){
//안드로이드에서 실행하는 내용
}
ㄴ. .Net Android에서 Web
Instance는 oncreate 매서드에서 MainActivity Instance = this; 코드를 전역변수로 선언 후 사용
Instance.webView.Post(() => { Instance.webView.LoadUrl("javascript:'웹의js함수명'('"파라미터"')"); });
7. 파일 다운로드 로직
private class MyDownloadListener : Java.Lang.Object, IDownloadListener
{
public void OnDownloadStart(string url, string userAgent, string contentDisposition, string mimetype, long contentLength)
{
try
{
DownloadManager.Request request = new DownloadManager.Request(Android.Net.Uri.Parse(url)); // [다운로드 매니저 객체 생성]
DownloadManager manager = (DownloadManager)Android.App.Application.Context.GetSystemService(Context.DownloadService);
string[] parts = contentDisposition.Split(";");
var fileName = parts[1].Split("=")[1];
request.SetMimeType(mimetype);
request.AddRequestHeader("User-Agent", userAgent);
request.SetDescription("Downloading File"); // [다운로드 중 표시되는 내용]
request.SetTitle(fileName);// [다운로드 제목 표시]
request.AllowScanningByMediaScanner();
request.SetNotificationVisibility((DownloadVisibility)1); // [앱 상단에 다운로드 상태 표시]
request.SetDestinationInExternalPublicDir(Android.OS.Environment.DirectoryDownloads, fileName);
manager.Enqueue(request);
}
catch
{
}
}
}
코드 작성 후
OnCreate 부분에 아래 코드 추가
webView.SetDownloadListener(new MyDownloadListener());
8.사진 업로드
public class CustomWebChromeClient : WebChromeClient
{
Activity mActivity = null;
public CustomWebChromeClient(Activity activity)
{
mActivity = activity;
}
public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
MainActivity.mUploadCallbackAboveL = filePathCallback;
//TakePhoto();
Java.IO.File imageStorageDir = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures), Guid.NewGuid() + ".jpg");
// Create camera captured image file path and name, add ticks to make it unique
MainActivity.imageUri = FileProvider.GetUriForFile(mActivity,
" "com.companyname.프로젝트명.fileprovider" " , imageStorageDir);
//Create camera capture image intent and add it to the chooser
Intent captureIntent = new Intent(MediaStore.ActionImageCapture);
captureIntent.PutExtra(MediaStore.ExtraOutput, MainActivity.imageUri);
Intent i = new Intent(Intent.ActionGetContent);
i.AddCategory(Intent.CategoryOpenable);
i.SetType("image/*");
Intent chooserIntent = Intent.CreateChooser(i, "Choose image");
chooserIntent.PutExtra(Intent.ExtraInitialIntents, new Intent[] { captureIntent });
MainActivity.Instance.StartActivityForResult(chooserIntent, MainActivity.PHOTO_REQUEST);
return true;
}
}
코드 작성 후
OnCreate 부분에 아래 코드 추가
webView.SetWebChromeClient(new CustomWebChromeClient(this));