Android에서 스 와이프하여 앱이 종료 될 때 코드를 처리하는 방법은 무엇입니까?


104

내 앱이 실행 중이고 홈 버튼을 누르면 앱이 백그라운드로 전환됩니다. 이제 홈 버튼을 길게 누르고 최근 앱 목록에서 앱을 스 와이프하여 앱을 종료하면 onPause(), onStop()또는 같은 이벤트가 발생 onDestroy()하지 않고 오히려 프로세스가 종료됩니다. 서비스를 중지하고 알림을 종료하고 리스너를 등록 취소하려면 어떻게해야합니까? 나는 꽤 많은 기사와 블로그를 읽었지만 유용한 정보를 얻지 못했고 그것에 대한 문서를 찾지 못했습니다. 어떤 도움을 주시면 감사하겠습니다. 미리 감사드립니다.


내 문제를 해결합니다. 확인
MysticMagicϡ 2014

@MysticMagic 서비스에서 작동합니다. 알림 취소 및 리스너 등록 취소는 어떻습니까?
CodeWarrior 2014

onTaskRemoved에서 리스너 등록을 취소 할 수 있습니다. 안돼? 알림 취소도 동일합니다.
MysticMagicϡ 2014

@ MysticMagicϡ 앱 업데이트에서 같은 일을하고 싶다면 어떻게해야하나요?
reji

답변:


150

비슷한 종류의 문제를 방금 해결했습니다.

최근 앱 목록에서 스 와이프하여 애플리케이션이 종료 될 때 서비스를 중지 하는 경우 다음을 수행 할 수 있습니다 .

매니페스트 파일 내 에서 서비스 플래그 stopWithTask를 유지하십시오 true. 처럼:

<service
    android:name="com.myapp.MyService"
    android:stopWithTask="true" />

그러나 리스너 등록을 취소하고 알림을 중지하고 싶다고 말했듯이이 방법을 제안합니다.

  1. 매니페스트 파일 내 에서 서비스 플래그 stopWithTask를 유지하십시오 false. 처럼:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
  2. 이제 MyService서비스에서 method를 재정의 하십시오 onTaskRemoved. (이로 stopWithTask설정된 경우에만 실행됩니다 false).

    public void onTaskRemoved(Intent rootIntent) {
    
        //unregister listeners
        //do any other cleanup if required
    
        //stop service
        stopSelf();  
    }

코드의 다른 부분도 포함하는 자세한 내용은 내 질문 을 참조하십시오 .

도움이 되었기를 바랍니다.


감사. 이 방법이 스 와이프 킬을 식별하는 데 사용될 수 있는지 생각합니다. 간단한 빈 서비스?
Kiran 2014

예 @Kiran 당신은 시도 할 수 있습니다. :)
MysticMagicϡ 2014

1
@ MysticMagicϡ 안녕하세요, 한 가지 질문입니다. 솔루션을 사용해 보았지만 서버에 데이터를 전송하고 Google에 분석을 보내는 것과 같은 긴 작업이 때때로 완전히 진행되지 않는 것 같습니다. 이 방법이 완전히 완료되기 전에 프로세스가 종료 될 수 있습니까? Huawei 장치에서도이 방법을 시도해 보셨습니까? onTaskRemoved는 해당 장치에서 호출되지 않는 것 같습니다. 이유는 무엇입니까?
아론 Minski

2
@ MysticMagicϡ 공공 무효 onTaskRemoved (..) 메소드하지 안드로이드 O. 안드로이드 O. 작동 다른 OS에서 미세하지만 점점 문제에 전화
제이 파텔

2
이 코드는 백그라운드 서비스 제한으로 인해 Android O에서 작동하지 않습니다. 모든 Android 기기에서이를 처리 할 수있는 방법이 있습니까?
Aanal Mehta

33

이 작업을 수행하는 한 가지 방법을 찾았습니다.

이렇게 하나의 서비스를

public class OnClearFromRecentService extends Service {

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d("ClearFromRecentService", "Service Started");
    return START_NOT_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d("ClearFromRecentService", "Service Destroyed");
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    Log.e("ClearFromRecentService", "END");
    //Code here
    stopSelf();
}

}

2) manifest.xml에이 서비스 등록

<service android:name="com.example.OnClearFromRecentService" android:stopWithTask="false" />

3) 그런 다음 스플래시 활동에서이 서비스를 시작하십시오.

startService(new Intent(getBaseContext(), OnClearFromRecentService.class));

그리고 이제 안드로이드에서 앱을 지울 때마다 onTaskRemoved () 메서드가 실행됩니다.


1
이 답변에서 일대일 복사 및 붙여 넣기 : stackoverflow.com/questions/21040339
Flot2011

17

비슷한 문제를 해결했습니다. 최근 작업에서 스 와이프 한 후 다음에 실행할 때 제대로 작동하려면 아래 단계를 따르세요.

1) 공유 기본 설정에 프로세스 ID 저장 :

SharedPreferencesUtils.getInstance().putInt(SharedPreferencesUtils.APP_PROCESS_ID, android.os.Process.myPid());

2) 최근 작업에서 지운 후 런처에서 응용 프로그램이 시작되면 다음을 수행하십시오.

int previousProcessID = mSharedPreferencesUtils.getInt(SharedPreferencesUtils.APP_PROCESS_ID);

int currentProcessID = android.os.Process.myPid();

if ((previousProcessID == currentProcessID)) {
    // This ensures application not killed yet either by clearing recent or anyway
} else {
    // This ensures application killed either by clearing recent or by anyother means
}

확인 됨-service.onTaskRemoved ()없이 Android 8에서 사용됨-잘하셨습니다
Gal Rom

4
응용 프로그램을 다시 시작할 경우이 솔루션은 감지하지만, 앱을 살해 할 때 정확한 순간을 감지 할 수 없습니다
바딤 Kotov

6

당신이 집을 누를 때- onPause그리고 onStop당신의 활동이 호출 될 때, 그래서 지금 당신은 모든 절약과 정리를해야합니다. 왜냐하면 안드로이드 플랫폼은 더 이상 onDestroy다른 라이프 사이클 메소드가 호출 될 것이라는 것을 보장하지 않기 때문에 프로세스가 종료 될 수 있습니다. 통지없이.


12
제안 주셔서 감사합니다,하지만 난 내 알림 서비스와 청취자를 죽이고 싶지 않아,에 onPause()그리고 onstop()그들은 사용자가 응용 프로그램 즉, 로그 아웃 종료하는 경우에만 살해 될 필요가있다.
CodeWarrior

1

on onPause()이 호출 되면 데이터를 저장해야합니다 . 이 수명주기 다이어그램을보십시오. Android 개발자

onPause()또는 이후에 앱이 종료 될 수 있음을 알 수 있습니다 onStop().

거기에서 데이터를 처리하고 onRestart()\ 에서 복구하십시오 onCreate().

행운을 빕니다!


1

시스템은 콜백을 호출하지 않고 메모리에서 프로세스를 제거하기 때문에 스 와이프를 처리 할 수 ​​없습니다.

사용자가 "최근 앱"화면을 호출하기 전에 항상 onPause ()가 호출되는지 확인했습니다. 따라서 isFinishing ()을 확인하지 않고 모든 데이터를 onPause 메서드에 저장해야합니다.

뒤로 버튼을 확인하려면 onBackPressed 메서드를 사용하십시오.


1
나는 이것이 모든 안드로이드 버전에 대한 유일한 안전한 방법이라고 생각합니다.
Sergio

@Sergio 예, 가장 안전한 방법이며 대규모 응용 프로그램에서 테스트했습니다.
Ahmad

1

ViewModel.onCleared ()는 사용자가 "중지"또는 버튼을 누르는 대신 스 와이프하여 깜짝 종료를 실행할 때 일부 리소스 (네트워크의 다른 곳에서 실행중인 시스템)를 해제하는 것이 목표 인 경우 유용 할 수 있습니다. [원래이 질문에 도달 한 방법입니다].

응용 프로그램이 알림을받지 못하고 Activity.onDestroy ()가 방향 변경과 같은 구성 변경에 대해 호출되므로 대답이 없습니다. 그러나 ViewModel.onCleared는 애플리케이션이 스 와이프 될 때 (및 사용자가 활동에서 돌아올 때) 호출됩니다. 사용하려는 리소스가 스택의 둘 이상의 활동과 연결되어있는 경우 참조 횟수 또는 다른 메커니즘을 추가하여 ViewModel.onClear가 리소스를 해제할지 여부를 결정할 수 있습니다.

이것은 ViewModel을 사용하는 또 다른 좋은 이유입니다.

-밥


1

위의 방법은 심지어 내가 세트 내 경우에 작동하지 않는 이유를 정말 모르는 android:stopWithTask="false"onTaskRemoved()호출되지 않습니다.

또 다른 좋은 접근 방식은 AndroidViewModel. 이것은 사용자가 뒤로 버튼을 눌러 응용 프로그램을 종료하는 경우에도 작동합니다.

ViewModel클래스를 바인딩 MainActivity한 다음 작업 onCleared()콜백 을 수행하십시오 .

예:

public class MainViewModel extends AndroidViewModel {
    public MainViewModel(@NonNull Application application) {
        super(application);
    }

    @Override
    protected void onCleared() {
        // Do your task here
        Log.e("MainViewModel", "OnCleared mainViewModel");
        super.onCleared();
    }
}

그런 다음 MainActivity에 바인딩하십시오.

MainViewModel viewModel = new ViewModelProvider(this).get(MainViewModel.class);

~ 짜잔!


다른 댓글 작성자가 언급했듯이 Android O 이상으로 인해 서비스 접근 방식으로 작동하지 않을 수 있습니다. 이것은 뷰 모델을 활용하는 흥미로운 솔루션 인 것 같습니다. 응용 프로그램이 강제 종료 된 경우에도 여전히 트리거됩니까 (앱 전환기 화면에서 스 와이프 됨)? 편집 : Bob의 답변은 이러한 경우에 작동한다고 제안합니다
William Reed

네 작동합니다. 내가 만난 경우입니다
droidhs

0

이것은 안드로이드 6,7,8,9에서 나를 위해 일했습니다.

다음과 같이 하나의 서비스를 만드십시오.

 public class OnClearFromRecentService extends Service {

 @Override public IBinder onBind(Intent intent) {
     return null; }

 @Override public int onStartCommand(Intent intent, int flags, int
 startId) {
     Log.d("ClearFromRecentService", "Service Started");
     return START_NOT_STICKY; }

 @Override public void onDestroy() {
     super.onDestroy();
     Log.d("ClearFromRecentService", "Service Destroyed"); }

 @Override public void onTaskRemoved(Intent rootIntent) {
     Log.e("ClearFromRecentService", "END");
     //Code here
     stopSelf(); } }

2)이 서비스 등록 manifest.xml:

<service android:name="com.example.OnClearFromRecentService"
 android:stopWithTask="false" />

3) 그런 다음 스플래시 활동에서이 서비스를 시작하십시오.

 startService(new Intent(getBaseContext(),
 OnClearFromRecentService.class));

1
서비스가 Android 8 이상에서 계속 실행되는 이유는 무엇입니까? Android 8 이후 Started Services에 제한이 있다는 것을 알고 있습니까?
rahil008

0

Bob Cram이 그의 답변에서 언급했듯이 View Model의 onCleared () 메서드가 답입니다. 두 경우 모두 작동합니다.

  1. 사용자가 백그라운드에서 앱을 스 와이프하여 앱을 제거 할 때.
  2. 사용자가 목록 지우기 버튼을 사용하여 모든 앱을 지울 때.

서비스의 onTaskRemoved ()는 사용자가 백그라운드에서 앱을 스 와이프하면 작동하지만 모두 죽이기 버튼을 사용하여 앱을 지울 때는 작동하지 않습니다.

그러나 viewModel의 onCleared () 메서드는 두 경우 모두에서 작동합니다. 진행중인 프로세스를 중지하거나 원격 서버에서 작업을 지우려면 if를 사용할 수 있습니다.

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.