안드로이드·윈도우 유틸 앱을 혼자 만들고 있습니다. 그중 AutoStart+는 재부팅하면 골라 둔 앱을 자동으로 열어 주는 앱인데, "부팅되면 앱 하나 띄우기"가 생각보다 함정이 많아서 정리해 봅니다. 대상은 minSdk 26 / targetSdk 36 입니다.

 

1. BOOT_COMPLETED가 늦게 옵니다

BOOT_COMPLETED는 우선순위 순으로 배달됩니다. intent-filter priority를 기본값 0으로 뒀더니 갤럭시 A34에서 부팅 후 71~148초 뒤에야 도착했습니다. 그래서 priority="999"를 줬고, 일부 제조사의 빠른 부팅 모드는 QUICKBOOT_POWERON만 보내서 그것도 같이 받습니다.

 

반대로 "부팅 후 5분 안에만 처리" 같은 시간 제한은 넣지 않았습니다. 늦게 오면 아무것도 안 하게 되니까요. 대신 Settings.Global.BOOT_COUNT를 키로 "부팅 1회에 1번만" 처리하도록 중복을 막습니다(값이 없는 기기는 부팅 시각 ±30초로 대신).

 

2. 잠금 해제 전(Direct Boot)에 깨어나는 문제

directBootAware로 하면 잠금 해제 전에 LOCKED_BOOT_COMPLETED로 깨어납니다. 이때는 CE 저장소가 닫혀 있어서 일반 SharedPreferences를 못 읽습니다.

 

  • 판정에 KeyguardManager.isDeviceLocked()를 쓰면 틀립니다. 스와이프 잠금 기기는 false인데 CE 저장소는 아직 닫혀 있습니다. UserManager.isUserUnlocked()로 바꿨습니다.
  • 잠금 해제 전 호출에서 "이번 부팅은 처리함"으로 표시하면 안 됩니다. 먼저 온 LOCKED_BOOT_COMPLETED가 중복 방지 칸을 써 버려서 진짜 BOOT_COMPLETED가 막혔습니다. 지금은 잠금 해제 전이면 아무것도 소비하지 않고 return 합니다.
  • 중복 방지 카운터만 잠금 중에도 읽히도록 DE 저장소(createDeviceProtectedStorageContext)에 두고, 사용자 데이터는 CE 그대로입니다.
  • 잠금 중 Application.onCreate에서 설정 초기화가 예외를 던져 프로세스째 죽고 BootReceiver까지 못 가는 일도 있었습니다. 실패하면 false만 돌려주고 잠금 해제 후 지연 초기화하게 바꿨습니다.

 

USER_UNLOCKED / USER_PRESENT를 매니페스트로 받는 것도 해 봤는데, USER_UNLOCKED는 동적 등록 리시버에만 오고 USER_PRESENT는 Android 8 이후 암시적 브로드캐스트 제한으로 안 왔습니다(갤럭시 A34 / Android 16 확인).

 

3. Android 10 이후 백그라운드에서 Activity 실행

백그라운드 서비스에서 startActivity()를 하면 원칙적으로 막힙니다. 그것도 예외 없이 조용히 무시됩니다.

 

"다른 앱 위에 표시(SYSTEM_ALERT_WINDOW)" 권한을 백그라운드 실행 가능 조건으로 보고, 권한이 없어도 일단 시도합니다(제조사에 따라 통하는 경우가 있어서). 실패하면 "지금 실행 / 설정" 버튼을 띄워 사용자가 누른 Activity에서 실행합니다. 버튼은 오버레이 권한이 있으면 화면 배너, 없으면 알림입니다.

 

알림 권한(Android 13 POST_NOTIFICATIONS)까지 거부돼 있으면 재부팅 후 아무것도 안 보이게 됩니다. 이때는 결과를 기록해 뒀다가 다음에 앱을 열면 카드로 보여 줍니다. 아무것도 안 보인 채 실패하면 사용자는 "안 되네" 하고 지우더라고요.

 

4. 포그라운드 서비스 타입은 shortService

실행 작업은 몇 초면 끝나서 dataSync 대신 shortService(API 34+)를 썼습니다. 전용 권한이 필요 없고 약 3분 제한 안에 끝나는 작업용입니다. 배너 대기도 2분까지로 맞췄습니다. 다만 Android 15 일부 기기에서 BOOT_COMPLETED에서 startForeground()를 부르면 예외가 나는 경우가 있어서, 그때는 포그라운드 없이 스레드로 같은 작업을 이어가는 폴백을 넣었습니다.

 

5. 강제 종료 후 "재배달"

Android 16 탭 A9+에서 사용자가 강제 종료한 뒤 프로세스가 깨어나 부팅 처리가 돌아버리는 일이 있었습니다. ApplicationStartInfo.wasForceStopped()와 프로세스 시작 시각(10초 이내)을 보고 그 경우엔 아무것도 하지 않습니다.

 

6. 제조사별 자동 실행 설정

샤오미·오포·비보·화웨이는 OS와 별개로 "자동 실행" 허용이 있고, 꺼져 있으면 BOOT_COMPLETED 자체가 안 옵니다. 각 설정 화면으로 바로 여는 버튼을 두고, 못 열면 배터리 최적화 설정으로 보냅니다. 이 허용 상태는 앱에서 읽을 수가 없어서 사용자가 "켰다"고 하는 걸 믿는 구조입니다.

 

정리하면

  • BOOT_COMPLETED는 늦게 온다고 보고, 시간으로 자르지 말고 "부팅 1회 1번"으로 중복을 막는다
  • 잠금 해제 전은 isUserUnlocked()로 판정하고 아무것도 소비하지 않고 돌아간다
  • 백그라운드 실행은 조용히 실패하니까, 실패했을 때 보이는 길(배너·알림·다음 실행 카드)을 꼭 만든다

 

혹시 부팅 자동 실행이나 Direct Boot 쪽 만들어 보신 분들, 특정 제조사에서 겪은 문제가 있으면 듣고 싶습니다. 특히 제조사 자동 실행 허용 상태를 확인할 방법이 정말 없는지 궁금합니다.

 

앱은 여기 있습니다. 무료로 앱 1개 자동 실행, Pro는 여러 개입니다.

https://play.google.com/store/apps/details?id=com.codedac.autostart