안드로이드

안드로이드 서비스 앱 삭제 및 강제종료 방지하기

2020. 8. 24. 16:04

일단 기본적으로 꽤 위험할 수 있는 내용이라고 생각한다. 그럼에도 불구하고 부득이하게 이런 기술을 사용해야 하는 경우도 있으므로 내가 구현한 방법에 대해 정리해보려고 한다.

 

전체적인 루틴은 아래와 같다.

디바이스 관리자 권한 받음 -> UsageStatsManager를 이용한 현재 최상단의 화면 정보 가져옴 -> 디바이스 관리자 권한 제거 액티비티가 올라왔을 때 화면 전환

 

* 디바이스 관리자 권한을 얻으면? - 해당 디바이스를 제어할 수 있는 권한을 얻음 - 디바이스 관리자 권한을 받으면 강제종료 버튼이 비활성화 됨

 

* UsageStatsManager란? - 디바이스의 사용 기록 및 현재 상태에 대한 정보를 가지고 있는 Class - 이를 이용해 현재 최상단에 있는 액티비티의 클래스명을 가져올 수 있음

 

디바이스 관리자 권한을 획득하는 코드는 아래와 같다.

DevicePolicyManager mDPM;
ComponentName mAdminName;

mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
mAdminName = new ComponentName(this, AmayalockAdminReceiver.class);

if (!mDPM.isAdminActive(mAdminName)) {
  Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
  intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName);
  intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "안전한 환경을 위해 실행 버튼을 클릭해주세요");
  startActivityForResult(intent, 0);
}

 

아래는 현재 최상단에 있는 클래스명을 구하는 메소드이다.

public String getForegroundPackageNameClassNameByUsageStats() {
  String packageNameByUsageStats = "";
  String classByUsageStats = null;
  if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    @SuppressLint("WrongConstant") UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");
    final long INTERVAL = 1000;
    final long end = System.currentTimeMillis();
    final long begin = end - INTERVAL;
    final UsageEvents usageEvents = mUsageStatsManager.queryEvents(begin, end);
    
    while (usageEvents.hasNextEvent()) {
      UsageEvents.Event event = new UsageEvents.Event();
      usageEvents.getNextEvent(event);
      
      if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
        packageNameByUsageStats = event.getPackageName();
        classByUsageStats = event.getClassName();
        Log.d("asdf", "packageNameByUsageStats is " + packageNameByUsageStats + ", classByUsageStats is " + classByUsageStats);
      }
    }
  }
  if(classByUsageStats!= null) {
    if (classByUsageStats.equals("com.android.settings.DeviceAdminAdd")) {
      return "exit";
    }
  }
  else{
    return "null";
  }
}

위 코드 23번째 줄에서 보이는 "com.android.settings.DeviceAdminAdd" 가 디바이스 관리자를 해제하는 화면의 클래스명이다.

 

최초 디바이스 관리자 권한을 부여받고 난 뒤, 해당 앱을 삭제하기 위해선 반드시 디바이스 관리자를 해제한 후 삭제하게 되는데 이 디바이스 관리자 해제 창이 뜨는지 상시 체크한다면 해제 창이 떴을 때 다른 화면으로 전환하는 등의 조치를 통해 앱 삭제를 방지할 수 있다.