source

앱이 다시 시작되지 않고 다시 시작됨

lovecheck 2023. 10. 29. 19:49
반응형

앱이 다시 시작되지 않고 다시 시작됨

누군가가 해결책은 아니더라도 최소한 행동에 대한 설명이라도 알아내는데 도움을 줄 수 있기를 바랍니다.

문제:

일부 장치에서는 런처 아이콘을 누르면 현재 작업이 재개되고, 다른 장치에서는 초기 실행 의도가 실행(앱을 효과적으로 재시작)됩니다.왜 이런 일이 일어날까요?

세부 정보:

Launcher 아이콘을 누르면 앱이 정상적으로 시작됩니다. 즉, 첫번째 이름으로 Intent가 실행됩니다.Activity행동으로android.intent.action.MAIN그리고 카테고리android.intent.category.LAUNCHER 항상 그러나 항상 그런 것은 아닙니다.

대부분의 장치에서 앱이 이미 실행된 후 런처 아이콘을 누르면 해당 프로세스에서 현재 실행 중인 활동이 재개됩니다(초기가 아님).ActivityOS 메뉴의 "Recent Tasks"에서 선택한 것과 동일한 방법으로 재개됩니다.이것이 제가 모든 기기에서 원하는 행동입니다.

그러나 선택한 다른 장치에서는 다음과 같은 다른 동작이 발생합니다.

  • 모토로라 줌에서 런처 아이콘을 누르면 이 항상 초기 실행을 시작합니다.Activity현재 실행 중인 것과 관계없이런처 아이콘은 항상 "런처" 의도를 시작한다고 가정합니다.

  • 삼성 탭 2에서 런처 아이콘을 누르면 앱을 설치한 지 얼마 안 된 경우 항상 초기화가 실행됩니다.Activity(Xoom과 동일) - 그러나 설치 후 장치를 다시 시작하면 실행기 아이콘이 대신 앱을 다시 시작합니다.이러한 장치는 장치 시작 시 검색 테이블에 "설치된 앱"을 추가하여 런처 아이콘이 실행 중인 작업을 올바르게 재개할 수 있다고 가정합니다.

저는 제 문제와 비슷하게 들리는 답변을 많이 읽었지만, 단순히 덧붙입니다.android:alwaysRetainTaskState="true"또는 사용하기launchMode="singleTop"Activity정답이 아닙니다.

편집:

가장 최근에 이 앱을 실행한 후에, 우리는 이 동작이 처음 다시 시작한 후에 모든 기기에서 발생하기 시작했다는 것을 알게 되었습니다.제가 보기에는 미친 것 같지만, 다시 시작하는 과정을 보면 실제로 무엇이 잘못되고 있는지 찾을 수가 없습니다.

사용자가 경험하고 있는 동작은 API 1 이후 일부 Android 런처에 존재하는 문제로 인해 발생합니다. 이 버그에 대한 자세한 내용은 물론 가능한 해결책도 여기 https://code.google.com/p/android/issues/detail?id=2373 에서 확인할 수 있습니다.

맞춤형 런처/스킨을 사용하는 다른 제조사뿐만 아니라 삼성 기기에서도 비교적 흔한 문제입니다.안드로이드 런처 재고에서 문제가 발생한 것을 본 적이 없습니다.

기본적으로 앱이 완전히 다시 시작되는 것은 아니지만, 런처에서 앱이 다시 시작될 때 당신의 런처 액티비티가 시작되고 액티비티 스택의 맨 위에 추가됩니다.앱을 다시 시작하고 실행 활동이 표시되면 뒤로 버튼을 클릭하면 이러한 상황임을 확인할 수 있습니다.그런 다음 앱을 다시 시작할 때 표시될 것으로 예상되는 활동으로 이동해야 합니다.

이 문제를 해결하기 위해 구현하기로 한 해결 방법은 의도를 확인하는 것입니다.CARECTORY_Launcher 카테고리 및 의도.ACTION_MAIN 동작은 초기 Activity를 시작하는 intent에 있습니다.이 두 개의 플래그가 있는데 활동이 작업의 루트(앱이 이미 실행 중임을 의미)에 없으면 초기 활동에서 finish()를 호출합니다.그 정확한 해결책은 당신에게 효과가 없을 수도 있지만, 비슷한 것이 있어야 합니다.

다음은 초기/시작 활동의 Create()에서 수행하는 작업입니다.

    if (!isTaskRoot()
            && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
            && getIntent().getAction() != null
            && getIntent().getAction().equals(Intent.ACTION_MAIN)) {

        finish();
        return;
    }

이 질문은 2016년에도 여전히 유효합니다.오늘 QA 테스터가 안드로이드 M의 스톡 런처에서 다시 시작하는 것이 아니라 다시 시작하는 앱을 보고했습니다.

실제로 시스템은 시작된 작업을 현재 작업 스택에 추가하고 있었지만 사용자에게 다시 시작된 작업이 발생하여 작업이 중단된 처럼 보였습니다.순서는 다음과 같습니다.

  1. 플레이 스토어(또는 사이드로드 랩)에서 다운로드
  2. Playstore에서 앱 실행 대화상자: A 활동이 나타납니다 [태스크 스택: A]
  3. 활동 B로 이동 [태스크 스택: A -> B]
  4. 홈' 버튼을 누릅니다.
  5. 앱 드로어에서 앱을 시작합니다: A 활동이 나타납니다![태스크 스택: A -> B -> A] (사용자는 '뒤로' 버튼을 눌러 여기서 'B' 활동으로 이동할 수 있습니다)

참고: ADB를 통해 배포된 디버그 APK의 경우에는 이 문제가 나타나지 않으며, Play Store에서 다운로드하거나 사이드 로드된 APK에서만 발생합니다.후자의 경우, 5단계의 발사 의도가 깃발을 포함하고 있었습니다.Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT, 디버그의 경우에는 그렇지 않습니다.런처에서 앱을 콜드 스타트하면 문제가 사라집니다.제가 의심하는 것은 작업이 완전히 삭제될 때까지 올바른 시작 동작을 방해하는 잘못된 형식(더 정확하게는 표준이 아닌) 의도로 작업이 시드된다는 것입니다.

다양한 활동 시작 모드를 시도했지만, 이러한 설정은 사용자가 예상하는 표준 동작(활동 B에서 작업 재개)에서 너무 벗어납니다.작업 및 백스택 안내서의 '작업 시작' 아래 페이지 하단에 있는 예상 동작에 대한 다음 정의를 참조하십시오.

이런 종류의 의도 필터는 활동의 아이콘과 레이블을 응용프로그램 실행기에 표시하게 하여 활동을 실행하고 활동이 실행된 후 언제든지 작성한 작업으로 돌아갈 수 있도록 합니다.

저는 이 답변이 적합하다는 것을 알고 사용자가 애플리케이션을 열 때 적절하게 재개되도록 제 루트 활동(A)의 'onCreate' 메서드에 다음을 삽입했습니다.

                    /**
     * Ensure the application resumes whatever task the user was performing the last time
     * they opened the app from the launcher. It would be preferable to configure this
     * behavior in  AndroidMananifest.xml activity settings, but those settings cause drastic
     * undesirable changes to the way the app opens: singleTask closes ALL other activities
     * in the task every time and alwaysRetainTaskState doesn't cover this case, incredibly.
     *
     * The problem happens when the user first installs and opens the app from
     * the play store or sideloaded apk (not via ADB). On this first run, if the user opens
     * activity B from activity A, presses 'home' and then navigates back to the app via the
     * launcher, they'd expect to see activity B. Instead they're shown activity A.
     *
     * The best solution is to close this activity if it isn't the task root.
     *
     */

    if (!isTaskRoot()) {
        finish();
        return;
    }

업데이트: 이 솔루션을 의도 플래그 파싱에서 작업의 루트에 작업이 직접 있는지 쿼리하는 방식으로 이동했습니다.의도 플래그는 메인 활동을 여는 여러 가지 방법으로 예측하고 테스트하기 어렵습니다(집에서 시작, '위' 버튼에서 시작, 플레이 스토어에서 시작 등).

아하! (tldr; 하단 굵은 글씨로 문장 보기)

문제를 발견했습니다...생각합니다.

자, 그럼 일단 추정부터 해보겠습니다.런처를 누르면 기본값으로 시작됩니다.Activity아니면, 만약에Task이전 출시로 시작된 제품이 열려 있습니다. 이 제품이 전면으로 나옵니다.다른 방법으로 이동 - 탐색 단계에서 새 항목을 작성하는 경우Task그리고.finish이전의 런처는 이제 더 이상 당신의 앱을 재개하지 않을 것입니다.

만약 그 추측이 사실이라면, 저는 그것이 버그가 되어야 한다고 확신합니다, 각각의 사람들이Task동일한 프로세스에 있으며 처음 작성한 이력서와 동일한 유효한 이력서 후보자입니까?

내 문제는 몇개의 깃발을 제거함으로써 해결되었습니다.Intents:

i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );

아주 분명하지만,FLAG_ACTIVITY_NEW_TASK새것을 만듭니다.Task, 나는 위의 가정이 유효하다는 것을 인정하지 않았습니다.저는 이것을 범죄자로 간주하고 테스트하기 위해 제거했고 저는 여전히 문제가 있어서 그것을 기각했습니다.하지만 저는 여전히 다음과 같은 조건을 가지고 있었습니다.

i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

내 스플래시 화면이 "메인"을 시작하고 있었습니다.Activity위의 깃발을 사용하는 제 앱에서.결국, 내가 내 앱을 다시 시작하고,Activity아직도 운영 중이라 상태 정보를 보존하고 싶습니다.

문서에 새로 시작하는 것에 대한 언급이 없다는 것을 알게 될 것입니다.Task:

설정되어 있고 실행 중인 활동이 현재 작업에서 이미 실행 중인 경우, 해당 활동의 새 인스턴스를 실행하는 대신 해당 활동의 다른 모든 활동이 종료되고 이 활동이 새로운 활동으로 이전 활동(현재 맨 위)에 전달됩니다.

예를 들어, A, B, C, D 활동으로 구성된 작업을 생각해 보겠습니다. 만약 D가 활동 B의 구성 요소로 해결하는 Intent로 Activity()를 시작하면, C와 D는 끝나고 B는 주어진 Intent를 받게 되며, 결과적으로 스택은 A, B가 됩니다.

위의 예에서 현재 실행 중인 활동 B 인스턴스는 여기서 시작하는 새 의도를 새 의도() 메서드에서 수신하거나 새 의도로 완료하고 다시 시작합니다.실행 모드를 "multiple"(기본값)로 선언하고 FLAG_ACTIVE_SINGLE_TOP을 동일한 의도로 설정하지 않은 경우 실행 모드가 완료되어 다시 생성됩니다. 다른 모든 실행 모드에 대해 또는 FLAG_ACTIVE_SINGLE_TOP이 설정된 경우 이 의도가 NewIntent()의 현재 인스턴스로 전달됩니다.

이 실행 모드는 FLAG_ACTIVE_NEW_TASK와 함께 사용할 수도 있습니다. 작업의 루트 활동을 시작하는 데 사용되는 경우 해당 작업의 현재 실행 중인 인스턴스를 포그라운드로 가져온 다음 루트 상태로 지웁니다.이 기능은 예를 들어 알림 관리자에서 작업을 시작할 때 특히 유용합니다.

그래서 저는 다음과 같은 상황에 처했습니다.

  • A출시된B와 함께FLAG_ACTIVITY_CLEAR_TOP,A마무리를 짓습니다.
  • B서비스를 재시작하기를 원하므로 사용자를 에 보냅니다.A서비스 재시작 로직 및 UI(플래그 없음)가 있습니다.
  • A발사들B FLAG_ACTIVE_CLEAR_와 TOP 으로,A마무리를 짓습니다.

이 단계에서 두번째.FLAG_ACTIVITY_CLEAR_TOP플래그가 다시 시작되고 있습니다.B작업 스택에 있습니다.이번 사건은 그들을 파괴할 것이라고 생각합니다Task그리고 새로운 문제를 일으켜서 제 문제를 일으키고 있습니다. 저에게 묻는다면 발견하기 매우 어려운 상황입니다!

그렇다면, 제 추측이 모두 맞다면,

  • Launcher처음에 만든 작업만 다시 시작합니다.
  • FLAG_ACTIVITY_CLEAR_TOPwill, 만약 그것이 유일하게 남아있는Activity, 또한 새것을 다시 만듭니다.Task

삼성 기기에서도 같은 문제가 있었습니다.많은 것을 검색해 본 결과, 이 중 어떤 것도 제게 맞지 않았습니다.Android Manifest.xml 파일에서,launchMode로 설정됩니다.singleInstance(android:launchMode="singleInstance"제거 중입니다.launchMode속성이 내 문제를 해결했습니다.

Cats60에서 Developer 옵션에서 "Don't keep activities"(활동 유지 안 함)를 활성화하여 다시 비활성화하면 앱의 상태를 잃지 않고 앱을 전환할 수 있습니다.

이 솔루션은 제게 효과적이었습니다.

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Intent startMain = new Intent(Intent.ACTION_MAIN);
            startMain.addCategory(Intent.CATEGORY_HOME);
            startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(startMain);
            return false;
        }
        else
            return super.onKeyUp(keyCode, event);
    }

credit : back button 클릭시 안드로이드 어플리케이션을 최소화해야 합니다.

일부 장치에서는 작동하지 않지만 뒤로 버튼을 누르면 홈 버튼 동작이 성공적으로 생성되므로 작업을 완료하는 대신 중지할 수 있습니다.

저도 같은 문제가 있었습니다. 그 원인은 다음과 같습니다.

(Kotlin 코드, 주 활동)

override fun onBackPressed() {
    finish()
}

로그인 활동에서 기본 활동으로 이동할 때 다음을 사용합니다.

    val intent = Intent(this, MainActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    startActivity(intent)

이 플래그를 사용할 때 기본 활동에서 onBackPressed()를 사용할 필요가 없습니다. 백클릭 시 앱이 자연스럽게 종료됩니다.그리고 홈 버튼을 누르고 앱으로 돌아가면 다시 시작되지 않습니다.

프로그래밍에 대해 전혀 모르고 안드로이드 폰에서 이 문제를 경험하는 사람들을 위한 해결책.이것은 대부분 안드로이드 버전의 업그레이드 때문에 발생합니다.업그레이드 후에는 모든 앱이 배터리 사용량이 적도록 최적화됩니다.그러나 이 경우 장치 속도가 느려집니다.

해결할 방법.

설정으로 이동>>앱스>>앱스 설정(화면의 어느 곳에서나 설정 기호를 찾습니다-기기마다 다릅니다)>배터리 최적화(또는 이와 유사한 opti[여기에 이미지 설명 입력][1]on]>>모든 앱을 '최적화되지 않음' 상태로 이동합니다(수동으로 1씩 해야 함-일부 전화에서는 허용/불허가될 수 있음).런처 앱은 '최적화되지 않음'이 필요합니다(제 경우 Zen UI 런처 - 이것이 범인입니다- 시간이 있으면 다른 앱을 최적화하고 다시 시작하지 않음).이제 전화를 다시 시작합니다.(데이터/안전 모드 또는 문제를 재설정할 필요가 없음)

지금 멀티태스킹을 시도해보세요.:) 이제 Launcher 아이콘을 누르면 현재 작업이 재개됩니다.:) 기기가 배터리 걱정하지 마세요 어차피 방전되니까요.

사용자에게 값을 매길 수 없습니다.최근에 사용한 앱 목록에 몇 주를 앉아도 완벽한 이력서.

사용자에게는 이력서처럼 보이지만 실제로는 완전한 시작입니다.

배경:작업을 시작하지 않은 주요 활동에 있는 앱에서 사용하는 메모리는 회수하기 쉽습니다.OS는 원래 번들을 create에 전달하여 앱을 다시 시작하기만 하면 됩니다.그러나 에서 원래 번들에 추가할 수 있습니다.onSaveInstanceState따라서 OS에서 앱을 다시 시작할 때 인스턴스 상태를 복원할 수 있으며 앱을 다시 시작할지, 다시 시작할지에 대해 더 현명한 사람은 아무도 없습니다.고전적인 지도 프로그램을 예로 들겠습니다.사용자가 지도의 위치로 이동한 다음 홈 키를 누릅니다.2주 후에도 이 지도 제작 앱은 페이스북, 판도라, 캔디 크러쉬와 함께 여전히 최근 앱 목록에 있습니다.OS는 최근에 사용한 앱의 이름만 저장하는 것이 아니라 앱을 시작하는 데 사용된 원래 번들도 저장합니다.하지만 프로그래머가 코드화한 것은onSaveInstanceStatemethod so original bundle은 앱을 구성하는 데 필요한 모든 자료와 정보를 포함하고 있어서 그것이 재개된 것처럼 보입니다.

예: 앱이 언로드되고 몇 주 후에 최근 앱 목록에서 다시 시작해야 할 경우를 대비해 SaveInstanceState에 현재 카메라 위치를 저장합니다.

@Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        // save the current camera position;
        if (mMap != null) {
            savedInstanceState.putParcelable(CAMERA_POSITION,
                    mMap.getCameraPosition());
        }
    }



@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // get the exact camera position if the app was unloaded.
        if (savedInstanceState != null) {
            // get the current camera position;
            currentCameraPosition = savedInstanceState
                    .getParcelable(CAMERA_POSITION);
        }

참고: 다음을 사용할 수도 있습니다.onRestoreInstanceStatemethod 하지만 인스턴스를 복원하는 것이 더 쉽다고 생각합니다.onCreate.

이것은 당신의 앱에서 일어나고 있는 일일 가능성이 높습니다.일부 장치에서는 앱이 언로드되어 메모리를 확보할 수 있습니다.네, 도움이 되는 플래그들이 있지만, 플래그들은 당신의 앱의 모든 뉘앙스를 감지하지 못할 것이고, 플래그들은 몇 주 동안 당신을 살려두지 못할 것입니다.onSaveInstanceState2주 후 이력서를 완벽하게 작성해야 합니다복잡한 앱에서 쉬운 일은 아니겠지만 우리는 당신의 뒤에 있고 도움을 주기 위해 여기에 있습니다.

행운을 빌어요

언급URL : https://stackoverflow.com/questions/19545889/app-restarts-rather-than-resumes

반응형