지속적인 디버깅 탐지 (15min ver)
WorkManager의 이슈 발생
- Workmanager의 주기를 15분으로 설정했으나 15분보다 더 짧은 시간에 work 발생
- 앱 실행시 동시다발적으로 여러개의 work 발생
문제상황 인식 및 분석
1. MainActivity에 생성한 detectDebug WorkManager의 WorkInfo의 state를 살펴봄
⇒ 여러개의 work가 한번에 enqueue되고, doWork()가 실행되는 것을 볼 수 있었음.
2. Application에 등록한 createWorkManager가 여러번 실행되는 것인가? 라고 생각 함
⇒ Application의 onCreate(), createWorkManager()의 함수 호출을 확인해 봄
15분보다는 짧은 시간에 수행되어서 장점이라고 생각할 수 있지만. 여러 문제를 일으킬 수 있는 여지가 있다.
- dowork()가 실행되어서 tracerPid를 감지할 때, 만약 tracerPid ≠ 0인 상태라면 문제가 생긴다.
- dowork()가 동시다발적으로 많이 수행되기 때문에 여러번 finish()가 수행되어서 앱이 렉걸린거 처럼 여러번 종료되는 모습이 발생했다.
- 기대하지 않은 workManager의 주기로 프로세스에도 영향을 줄 수 있다.
⇒ 즉 workManager가 제대로된 순서와 주기로 실행되도록 오류를 해결해야한다.
해결방법
- PeriodicWorkRequest의 enqueue 방법 수정
- workManager가 꼬이지 않도록 실행 전 WorkInfo List 확인
- WorkManager 공식문서 바탕으로 stable한 최신 버전으로 업데이트
application onTerminate()시에 All work cancel지속적인 디버깅 탐지 (15min ver)
- -> application의 onTerminate()는 실제 어플이 종료될 때 사용되기보다는 하드웨어가 종료될 때 사용된다고 해서 효과가 없는 방법이였다.
createDetectDebugWorkManager()
이전코드
// 중략
private void createDetectDebugWorkManager(){
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
DebugDetectWorker.class,15, TimeUnit.MINUTES // 주기 15분
).build();
WorkManager.getInstance(this).enqueue(workRequest);
} // WorkManager 생성
수정코드
private void createDetectDebugWorkManager() {
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
DebugDetectWorker.class, 15, TimeUnit.MINUTES
).addTag("detectDebug").build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork("detectDebug", ExistingPeriodicWorkPolicy.KEEP, workRequest);
}
바뀐점
해당 WorkManager는 주기적으로 실행하는 PeriodicWorkManager이다.
따라서 WorkRequest를 생성하고 enqueue하는 방식을 그냥 enqueue가 아닌 enqueueUniquePeriodicWork를 사용해야한다.
또한 enqueue하는 방식의 정책을 ExistingPeriodicWorkPolicy.KEEP으로 설정한다.
→ 이렇게 설정하면 이미 detectDebug work이 있다면 추가적으로 들어오는 enqueue에 대해서 취소 처리를 한다.
checkEnqueue()
WorkList가 꼬이지 않도록, 비어있을 때만 enqueue 하도록 하는 함수이다.
private void checkEnqueue() throws ExecutionException, InterruptedException {
WorkManager workmanager = WorkManager.getInstance(this);
List<WorkInfo> workInfoList = workmanager.getWorkInfosForUniqueWork("detectDebug").get();
if (workInfoList.isEmpty()){
createDetectDebugWorkManager();
Log.e("hyeon","work info list empty");
}
}
해당 함수는 get 하는 과정에서 Exception을 발생시키기 때문에 Application onCreate()에서 실행할 때 Exception처리를 해야한다.
App.onCreate()
@Override
public void onCreate() {
super.onCreate();
UsbConnectionReceiver.registerReceiver(this, usbReceiver);
try {
checkEnqueue();
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} // 발생하는 exception에 따라서 예외를 처리하면 된다.
WorkManager 최신 버전 업데이트
build.gradle
// Workmanager
implementation("androidx.work:work-runtime:2.9.0")
App.onTerminate()
@Override
public void onTerminate() {
super.onTerminate();
UsbConnectionReceiver.unregisterReceiver(this, usbReceiver);
WorkManager.getInstance(this).cancelAllWorkByTag("detectDebug");
// application 종료 시 all wrok cancel
}
구현결과
수정한 결과 15분 간격으로 알맞게 workManager가 실행되는걸 볼 수 있다.
tracerPid =1로 직접 바꿨을 때도 앱이 강제종료되는 것을 볼 수 있었다.
15분보다 더 미만으로 작업을 수행하는 코드는 다음시간에 ..
레퍼런스
Android Developer WorkManager 작업관리
WorkManager | Jetpack | Android Developers
https://github.com/android/codelab-android-workmanager/issues/99
https://velog.io/@shin75492/kotlin-workmanager와-백그라운드-작업
'Android > 트러블슈팅' 카테고리의 다른 글
[Android/트러블슈팅] Kotlin 1.9.0 & Hilt Version Error (2) | 2024.09.27 |
---|---|
[Android] WorkManager를 활용한 주기적인 백그라운드 작업 실행 (less than 15min ver) (0) | 2024.07.27 |
[Android/트러블슈팅] 구글 플레이스토어 키스토어 분실 재설정 방법 (2) | 2024.01.13 |
[Android/트러블슈팅] 앱을 삭제했는데 데이터가 남아있다고요? (2) | 2023.09.11 |
[Android/트러블슈팅] Keystore 정보 확인하는 법 (0) | 2023.09.07 |