닫을 수 없는 Android POS 앱 빌드

게시 됨: 2022-03-11

모바일 앱 개발의 세계는 거의 매일 새로운 프레임워크와 기술이 등장하면서 방대하고 끊임없이 진화하고 있습니다. 모바일 장치에 대해 생각할 때 스마트폰만큼 인기 있는 제품은 아니지만 휴대폰이나 태블릿을 생각할 수 있습니다.

애플의 iOS와 구글의 안드로이드는 지난 10년 동안 각각 우여곡절을 겪었던 모바일 시장을 지배하고 있다. 오늘은 Android와 반드시 모바일이 아닌 기기에서 사용하는 방법에 대해 더 자세히 설명하겠습니다.

오픈 소스가 된다는 것은 Google의 모바일 운영 체제에 정말 흥미로운 부작용이 있었습니다. 물론 다양한 스마트폰 회사의 다양한 Android 포크를 생각할 수 있지만 모바일이 아닌 Android를 실행하는 모든 장치는 어떻습니까? 냉장고, 스마트 오븐, 도어록, 심지어 POS(Point of Sale) 기기에 이르기까지 모든 것이 오늘날 Android를 실행할 수 있습니다. 내가 이 글을 쓰게 된 이유는 후자 때문이다.

현재 POS(Point of Sale) 기기에서 Android를 실행할 수 있습니다.

안드로이드 POS 시스템

약 1년 전에 나는 평범하지 않은 Android 기기를 가지고 놀게 되었고 대부분의 사람들이 사용하지 않을 것입니다. 문제의 기기는 통합 열전사 프린터(매장이나 ATM에서 영수증을 인쇄하는 데 사용되는 것과 같은)가 있는 중국 공급업체의 Android 기반 POS 시스템입니다.

하지만 가장 놀라운 점은 소프트웨어였습니다. Android의 뼈대 버전을 실행하고 있었습니다. 제 기억이 맞다면 당시에는 안드로이드 8이 실행되고 있었고 구글 코드명을 선호한다면 안드로이드 오레오가 실행되고 있었습니다. 장치 자체는 구식 휴대용 POS 장치처럼 보이지만 PIN을 입력하는 물리적 키보드 대신 작년의 Android 휴대폰에 사용된 것과 같은 정전식 터치스크린을 자랑합니다.

내 요구 사항은 간단했습니다. 우리가 개발 중인 앱을 실행하면서 열전사 프린터와 같은 이 장치의 기능을 사용할 수 있는 방법이 있는지 확인해야 했습니다. 요구 사항 자체가 가능하다는 것을 깨달았을 때 또 다른 문제가 발생했습니다. 바로 보안 입니다.

문제는 카드 결제 및 기타 종류의 거래를 처리하는 장치가 있는 경우 동일한 장치에서 TikTok, Gmail 또는 Snapchat을 실행하는 것을 원하지 않을 수 있다는 것입니다. 이 기기는 태블릿과 똑같이 작동했으며 Google Play 스토어가 사전 설치된 상태로 제공되었습니다. 작은 편의점에 가서 계산원이 셀카를 찍고, 나이지리아 왕자가 보낸 이메일을 열고, 멀웨어가 득실거리는 이상한 웹사이트를 탐색하는 것을 상상해 보십시오.

그런 다음 계산원은 PIN을 입력할 수 있는 동일한 장치를 제공합니다. 개인적으로, 나는 그러한 장치를 통해 내 신용 카드 정보를 제공하는 것이 안전하지 않다고 생각합니다.

Android 메뉴에서 사용자 잠금

보안을 제쳐두고 나는 훨씬 더 중요한 문제를 해결해야 했습니다. 내 앱 내에서 Android POS 기기를 사용하는 사람을 잠궈야 했습니다. 이러한 장치는 비기술자에게 제공되었기 때문에 운영 체제를 어지럽히는 것은 선택 사항이 아니었습니다.

물론 계산원은 응용 프로그램을 설치할 수 있는 능력 이상을 가지고 있지만 대부분은 사용자 지정 ROM을 플래시하거나 다른 하위 수준 작업을 처리할 수 없습니다. 이 컨텍스트에서는 관련이 없지만 앱 자체는 React Native로 작성되었습니다. 내가 만든 모든 수정 사항은 기본 Java 코드이므로 기본 응용 프로그램을 개발하는 데 무엇을 사용하든 이러한 조정이 작동해야 합니다.

약간의 면책 조항으로 이 절차 는 Android 앱에만 적용됩니다 . Apple은 iPhone 또는 iPad에서 이와 같은 작업을 쉽게 수행하는 데 필요한 제어를 제공하지 않습니다. 이는 iOS의 폐쇄적인 특성을 감안할 때 이해할 수 있습니다.

사용자가 응용 프로그램을 종료할 수 있는 네 가지 방법이 있습니다.

  • 버튼을 사용하세요.
  • 뒤로 버튼을 사용합니다.
  • 최근 버튼을 사용합니다.
  • 알림 표시줄 을 통해 앱을 종료합니다.

최근 알림을 클릭하거나 해당 표시줄에서 설정으로 이동하면 사용자가 애플리케이션을 종료하게 됩니다. 제스처도 있지만 하루가 끝나면 이러한 제스처는 일반 버튼 누름과 똑같은 동작을 트리거합니다.

또한 응용 프로그램의 잠금을 해제하기 위한 PIN 시스템이 있으면 누군가가 장치를 관리하는 데 매우 유용할 수 있습니다. 이렇게 하면 PIN을 보유한 사람만 최종 사용자에게 더 깊은 액세스 권한을 제공하지 않고 다른 버전의 애플리케이션을 설치할 수 있습니다.

홈 버튼

사용자가 홈 버튼을 누르지 못하도록 하기 위해 실제로 비활성화할 필요는 없습니다.

Android의 유용한 기능 중 하나는 다양한 런처를 사용할 수 있다는 것입니다. 일반적으로 이러한 앱은 다양한 홈 화면, 앱 서랍 및 다양한 UI 사용자 정의에 대한 액세스를 제공합니다. 모든 Android 기기에는 제조업체에서 미리 설치한 기기가 있습니다. 궁극적으로 이들은 작지만 중요한 예외가 하나 있는 정상적인 일반 앱입니다.

이것이 의미하는 바는 운영 체제가 우리 애플리케이션을 런처로 인식할 수 있다면 기본 런처로 설정할 수 있다는 것입니다. 이것의 부작용은 홈 버튼을 누를 때마다 장치가 홈 런처로 이동한다는 것입니다. 그리고 우리 애플리케이션이 홈 런처라면 기본적으로 이 홈 버튼은 쓸모가 없게 됩니다. 그렇게 하려면 Android 프로젝트에서 AndroidManifest XML 파일을 편집하고 다음 두 줄의 코드를 추가해야 합니다.

 <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>

첫 번째 줄은 사용자가 홈 버튼을 눌렀을 때 앱을 선택할 수 있도록 하고 두 번째 줄은 이 작업이 발생할 때마다 앱을 기본값으로 설정할 수 있도록 합니다.

이제 현장 에이전트가 애플리케이션을 클라이언트에 전달할 때 디바이스에 설치하는 일만 남았습니다. 런처가 될 가능성이 있는 앱을 설치할 때마다 Android는 다른 런처를 사용할지와 해당 런처를 기본값으로 설정할지 묻습니다.

이제 홈 버튼을 누르거나 최근 응용 프로그램을 모두 지우면 장치가 자동으로 내 응용 프로그램으로 안내합니다.

닫을 수 없는 Android POS 앱 빌드

뒤로 버튼

다음으로 뒤로 버튼을 처리해야 합니다. 특히 많은 장치에 전용 "뒤로" 키가 없기 때문에 모바일 앱은 일반적으로 화면을 통해 화면으로 돌아갈 수 있는 방법을 제공합니다.

몇 년 전에는 화면 아래에 하나의 물리적 버튼이 있는 이미 아이코닉한 디자인을 특징으로 하는 Apple의 iOS 기기가 있었습니다. 그러나 최근 몇 년 동안 대부분의 Android 기기에서 물리적 홈 버튼도 삭제되었습니다. 첫째, 그들은 온스크린 버튼으로 옮겨갔고, 이제는 휴대폰 제조업체가 작은 베젤과 턱이 있는 전체 화면 장치로 이동함에 따라 제스처 대신 전화기에서 단계적으로 사라지는 것을 보고 있습니다.

이것이 의미하는 바는 Android가 기본적으로 제공하는 뒤로 버튼은 실제로 필요하지 않으며 이 버튼을 완전히 쓸모없게 만들려면 활동에 간단한 코드 블록을 추가하기만 하면 됩니다.

 @Override public void onBackPressed() { } 

닫을 수 없는 Android POS 앱 빌드

이것은 매우 간단한 코드 블록입니다. 주요 활동을 통해 사용자가 뒤로 버튼을 누를 때마다 가로챌 수 있습니다. 우리의 경우 사용자가 앱을 종료하기 위해 해당 버튼을 너무 많이 누르는 것을 원하지 않기 때문에 기본 메서드를 아무 작업도 수행하지 않는 메서드로 덮어쓰면 됩니다. 버튼이 눌렸습니다.

이것은 일부 응용 프로그램이 실수로 너무 많이 돌아가서 종료하기 전에 확인을 요청하는 방법입니다.

최근 버튼

우리는 여전히 최근 버튼을 처리해야 하며 이것이 가장 까다로운 버튼입니다. 또한 이것은 확실히 모범 사례나 Play 스토어에 푸시해야 하는 것이 아니지만 여기에서 우리의 틈새 사례에는 효과가 있습니다.

메인 액티비티를 통해 뒤로 버튼이 눌렸는지 알 수 있는 것과 같은 방식으로 앱이 일시 중지된 시간도 알 수 있습니다. 이것은 무엇을 의미 하는가? 이 코드는 앱이 포그라운드 애플리케이션에서 백그라운드로 전환될 때마다 트리거됩니다.

이 이벤트를 가로챌 때 현재 응용 프로그램의 작업 ID를 가져와 활동 관리자에게 이 작업을 앞으로 이동하도록 지시합니다. 이렇게 하려면 이전에 편집한 동일한 Android 매니페스트 파일에 하나의 특별 권한이 필요합니다.

 <manifest xmlns:andro package="com.johnwick"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.REORDER_TASKS" /> <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> </application> </manifest>

이렇게 하면 진행 중인 작업을 읽고 이러한 작업을 변경할 수 있습니다. 또한 애플리케이션이 백그라운드로 전송되는 순간을 가로채야 합니다. 활동에서 onPause 메소드를 다시 재정의할 수 있습니다.

여기에서 작업 관리자를 가져와 특정 작업을 포그라운드로 이동하도록 합니다. 우리의 경우 해당 특정 작업은 방금 백그라운드(우리 애플리케이션)로 전송된 작업입니다.

 @Override public void onPause() { super.onPause(); ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); activityManager.moveTaskToFront(getTaskId(), 0); }

이제 최근 메뉴로 이동하려고 할 때마다 응용 프로그램이 자동으로 다시 초점을 맞춥니다. 물론 때때로 화면이 약간 깜박일 수 있지만 이 응용 프로그램을 종료할 수는 없습니다. 그리고 여기에 한 가지 더 멋진 사실이 있습니다. 알림을 클릭하거나 알림 트레이를 통해 설정으로 직접 이동하여 종료할 수도 있다고 제가 말한 것을 기억하십니까? 글쎄, 이러한 작업을 수행하면 앱이 백그라운드에 배치되어 코드가 트리거되고 사용자가 바로 다시 들어가게 됩니다.

이 모든 일이 너무 빨리 일어나서 사용자는 백그라운드에서 일어나는 일을 눈치채지 못할 것입니다. 또한 이 접근 방식의 또 다른 좋은 점은 빠른 토글을 계속 사용할 수 있다는 것입니다. 예를 들어 여전히 Wi-Fi 네트워크를 선택하거나 소리를 비활성화할 수 있지만 실제 설정 앱으로 이동해야 하는 것은 허용되지 않습니다.

닫을 수 없는 Android POS 앱 빌드

해결책

이것이 최선의 방법인지 확신할 수 없지만 그럼에도 불구하고 가능한지조차 몰랐던 주제를 연구하면서 정말 흥미로운 과정이었습니다. 그리고 그것은 작동합니다! 경고: 이 시점에서 개발자로서 애플리케이션을 종료할 수 있는 방법은 운영 체제를 다시 설치하거나 ADB를 통해 앱을 종료/제거하는 두 가지 방법뿐입니다.

어떻게 해서든 장치에 대한 ADB 연결이 끊어지면 쉽게 빠져나올 수 있는 방법을 모르겠습니다. 이를 피하기 위해 결국 PIN 시스템을 구축하게 되었습니다.

엣지 케이스

확인해야 하는 몇 가지 상황이 있습니다. 우선 기기가 재부팅되면 어떻게 될까요? 수동으로 재부팅할 필요는 없으며 운영 체제가 충돌할 수도 있습니다.

이전에 애플리케이션을 기본 런처로 설정했기 때문에 운영 체제가 백업되자마자 자동으로 애플리케이션을 시작해야 합니다. 그러나 Android는 부팅 시 홈 화면을 로드하는 방법을 알고 있습니까? 기본적으로 기본 실행 프로그램을 로드하기 때문입니다. 이 시점에서 우리는 기본 런처이므로 재부팅은 문제가 되지 않습니다. 그리고 안드로이드가 어느 시점에서 우리 애플리케이션을 죽일 수 있을까요? 이론적으로 RAM 메모리가 가득 차면 앱을 종료할 수 있지만 현실에서는 거의 불가능합니다. 우리 앱은 닫을 수 없기 때문에 아무도 다른 앱을 열 수 없으므로 RAM 메모리가 채워지지 않아야 합니다.

꽉 찼다고 생각할 수 있는 유일한 방법은 애플리케이션에 막대한 메모리 누수가 있는 경우이지만, 이 경우 사용자를 애플리케이션 내부에 유지하는 것보다 더 큰 문제가 발생합니다. 그럼에도 불구하고 Android가 어떻게든 애플리케이션에 킬 신호를 트리거하더라도 집으로 돌아가려고 할 때마다 OS는 기본 런처이기 때문에 앱을 다시 시작하려고 시도하므로 사용자를 잠긴 상태로 유지합니다.

뒷문 만들기

간단히 설명하자면, 앱 설정에 PIN을 입력하여 앱 잠금을 해제할 수 있는 곳이 있었습니다. PIN이 정확하면 간단한 조건문을 수행하여 onPause 및 onBackPressed 메서드에서 설정한 제한을 비활성화합니다. 거기에서 사용자는 빠른 토글 메뉴를 통해 설정을 입력할 수 있습니다. 그 후에는 언제든지 기본 런처를 다시 기본 런처로 설정할 수 있으며, 그러면 앱에서 완전히 벗어날 수 있습니다. 이 부분을 처리할 수 있는 방법은 여러 가지가 있지만, 동일한 제한을 해제하는 메커니즘이 있는 것이 좋습니다. 잠금 해제를 위해 지문 인증을 할 수도 있습니다. 가능성은 거의 무한합니다.

닫을 수 없는 Android POS 앱 빌드

마무리

결국 아무도 닫거나 죽일 수 없는 응용 프로그램이 남았습니다. 장치를 재부팅해도 현재 응용 프로그램인 기본 실행 프로그램으로 직접 전원이 다시 켜지므로 도움이 되지 않습니다. 그것은 우리 프로젝트에 유용한 것으로 판명되었으며, 너무 엉뚱하고 엉뚱한 것을 시도하는 만족감은 참으로 위대하고 매우 동기를 부여합니다.

Android가 개발자의 삶을 쉽게 만들어준 많은 기기와 사용 사례가 있습니다. 요즘에는 Android 애플리케이션을 작성하는 것이 다양한 플랫폼별 언어와 도구를 사용하는 것보다 훨씬 쉽습니다. IoT 장치, 키오스크 애플리케이션, POS 시스템, 택시용 내비게이션 및 결제 게이트웨이 등을 생각해 보십시오.

이는 Android가 앱 개발을 더 쉽게 만든 사용 사례이지만 이 기사에서 설명한 것과 유사한 방식으로 액세스를 제한하려는 틈새 사용 사례이기도 합니다.