Intro
테블릿 안에 앱을 설치해서 테블릿을 사용자에게 판매해야(인앱 시스템) 할 때가 있습니다.
하지만 PlayStore에 앱을 등록하지 않았기 때문에 여러가지 문제가 발생합니다.
예를 들면 사용자가 앱을 삭제했거나 아니면 업데이트 하는 경우 등 추후 유지보수에 대해
문제가 발생할 수 있습니다.
그래서 이번에는 제가 회사에서 인앱 시스템을 구축하면서 알게된 것들에 대해서 정리하겠습니다.
1.Device policy Manager
https://developer.android.com/reference/android/app/admin/DevicePolicyManager
-안드로이드 앱 소유자 권한을 가져야만 사용할 수 있는 기능들을 제공해주는 클래스 입니다.
-앱 삭제 방지, 공장초기화, 개발자 모드 비활성화 등의 기능들을 제공해줍니다.
-Device Policy Manger를 사용하기 위해서는 최상위 앱 권한인 소유자(Owner)
권한이 필요합니다.
2.안드로이드 소유자(Owner) 권한
-안드로이드 앱 권한 중 가장 상위에 있는 권한입니다.
-이 권한을 얻기 위해서는 관리자 권한이 먼저 필요합니다.
1)관리자 권한(Admin)을 얻는 방법
예제
https://github.com/mcsong/SimpleKioskDemo
1. MainActivity
-DevicePolicyManager 객체를 생성합니다.
private DevicePolicyManager devicePolicyManager;
devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
-관리자 권한을 얻을 화면으로 이동하는 코드를 작성합니다.
private void adminActive() {
ComponentName componentName = new ComponentName(this, AppDeviceAdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
startActivityForResult(intent, DEVICE_ADMIN_ADD_RESULT_ENABLE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == DEVICE_ADMIN_ADD_RESULT_ENABLE) {
// setCameraDisabled(true);
}
if (requestCode == 10 && resultCode == RESULT_OK) {
// 앱이 기기 소유자로 설정됨
}
super.onActivityResult(requestCode, resultCode, data);
}
3. AppDeviceAdminReceiver
public class AppDeviceAdminReceiver extends DeviceAdminReceiver {
private static final String TAG = AppDeviceAdminReceiver.class.getSimpleName();
@Override
public void onEnabled(Context context, Intent intent) {
super.onEnabled(context, intent);
Log.d(TAG, "Admin onEnabled");
}
@Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
Log.d(TAG, "Admin onDisabled");
}
}
3-1)manifest
<receiver
android:name=".AppDeviceAdminReceiver"
android:description="@string/device_admin_description"
android:directBootAware="true"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN"
tools:targetApi="26">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_receiver" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
4. device_admin_receiver.xml
<device-admin>
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
</uses-policies>
</device-admin>
1-2)소유자 권한(Admin)을 얻는 방법
-관리자 권한을 얻어야만 소유자 권한을 얻을 수 있습니다.
-소유자 권한을 얻기 위해서는 adb 설정을 해야 합니다.
안드로이드 터미널로 이동 후 adb shell dpm set-device-owner 패키지이름/.리시버이름 이 명령어를 입력합니다.
소유자 권한을 얻는데 성공하면 위와 같은 메세지를 받게된다.
* 에러 케이스
1. java.lang.IllegalStateException: Not allowed to set the device owner because there are already several users on the device
-이미 등록된 계정이 있어서 발생하는 에러 입니다.
-설정 -> 계정 -> 등록된 계정 삭제를 진행해주세요.
2.java.lang.RuntimeException: Can't set package ComponentInfo{app.example.deviceadmin/app.example.deviceadmin.AppDeviceAdminReceiver} as device owner.
-앱의 컴포넌트 이름이 맞지 않아서 발생하는 오류일 확률이 높습니다.
-저의 경우에는 디바이스를 공장 초기화 하니 해결되었습니다.
* 주의 사항
- 소유자 권한을 얻은 상태에서 안드로이드 스튜디오로 앱을 빌드 할 수 없습니다.
- 왠만하면 개발용 폰으로 하시는 것을 추천합니다.
1-3)소유자 권한(Admin)을 해제 하는 방법
-안드로이드 터미널로 이동 후 adb shell dpm remove-active-admin 패키지이름/.리시버이름 이 명령어를 입력합니다.
인앱 시스템 구축 시 필요한 기능
1)테블릿의 고유한 키 값
- 테블릿의 WIFI-Mac 주소를 저는 키 값으로 사용했습니다.
- 이 주소는 테블릿 내의 고유한 16진수로된 주소로 Device Policy Manager를 통해 앱에서도 사용할 수 있습니다.
-이 Unique한 Key 값을 앱에서 조회할 수 있음으로써 고객의 현재 보유한 테블릿의 개수를 알 수
있었습니다.
btnWifiMac.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
btnWifiMac.setText(devicePolicyManager.getWifiMacAddress(componentName));
}
}
}
});
2)앱 삭제 방지
-사용자가 실수로 앱을 삭제하는 상황을 방지하기 위해서 사용했습니다.
findViewById(R.id.btnStopUninstall).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
devicePolicyManager.setUninstallBlocked(componentName, "패키지이름", true);
}
}
});
- 소유자 권한이 있는 앱의 다운 링크를 QRCODE에 담은 후 디바이스 초기 환경 세팅 시 이 앱을 시스템 앱으로 만드는 방법에 대해서 포스팅 하겠습니다.
참고
https://daisyleh.blogspot.com/2019/03/devicepolicymanager.html
https://developer.android.com/reference/android/app/admin/DevicePolicyManager
'안드로이드 공부 & 앱' 카테고리의 다른 글
안드로이드 인앱 시스템 구축[2편] QR 코드를 통한 시스템 앱 배포 방법 (1) | 2023.07.28 |
---|---|
[안드로이드/Kotlin] 의존성 주입 및 Hilt 프레임워크 사용 과정 (0) | 2022.05.17 |
[안드로이드/Kotlin] DiffUtill + RecyclerView 개념 정리 및 Tip (0) | 2022.05.14 |
안드로이드 CleanArchitecture 개념 정리 및 구현 (0) | 2022.04.21 |
[안드로이드] JetPack Navigation 개념 정리 및 예제 (0) | 2022.04.16 |
댓글