로그 아웃시 활동 기록 스택을 지우고 “뒤로”버튼이 로그인 한 활동을 열지 못하도록합니다. 로그인 활동을 열려고 FLAG_ACTIVITY_CLEAR_TOP했지만 로그인 활동을 기록

내 응용 프로그램의 모든 활동을 보려면 사용자가 로그인해야합니다. 사용자는 거의 모든 활동에서 로그 아웃 할 수 있습니다. 이것은 응용 프로그램의 요구 사항입니다. 사용자가 로그 아웃하면 언제든지 사용자를 Login으로 보내려고합니다 Activity. 이 시점에서이 활동이 히스토리 스택의 맨 아래에 있기를 원하므로 “뒤로”단추를 누르면 사용자가 Android 홈 화면으로 돌아갑니다.

나는이 질문이 몇 가지 다른 장소를 요구하는 것을 보았습니다. 모두 비슷한 대답으로 대답했습니다.

설명서에 설명 된 것처럼 Intent플래그를 설정하여 로그인 활동을 열려고 FLAG_ACTIVITY_CLEAR_TOP했지만 로그인 활동을 기록 스택의 맨 아래에 배치하고 사용자가 다시 탐색하지 못하게하는 목표를 달성하지 못했습니다. 이전에 본 로그인 활동 또한 android:launchMode="singleTop"매니페스트에서 Login 활동에 사용해 보았지만 이것이 목표를 달성하지 못합니다 (어쨌든 효과가없는 것 같습니다).

나는 역사 스택을 지우거나 이전에 열었던 모든 활동을 끝내야한다고 생각합니다.

한 가지 옵션은 각 활동의 onCreate확인 상태를 finish()로그인하고 로그인하지 않은 경우입니다. 이 옵션이 마음에 들지 않습니다. 뒤로 버튼을 계속 사용할 수 있으므로 활동이 닫힐 때 뒤로 돌아갑니다.

다음 옵션은 LinkedList모든 곳에서 정적으로 액세스 할 수있는 모든 열린 활동 (아마도 약한 참조를 사용)에 대한 참조 를 유지하는 것입니다. 로그 아웃하면이 목록에 액세스하여 이전에 열었던 모든 활동을 반복 finish()하여 각 활동을 호출 합니다. 아마이 방법을 곧 구현하기 시작할 것입니다.

Intent그러나 오히려 이것을 달성 하기 위해 깃발 속임수를 사용하고 싶습니다 . 위에서 설명한 두 가지 방법 중 하나를 사용하지 않고도 응용 프로그램 요구 사항을 충족시킬 수 있다는 사실을 알게되어 기쁩니다.

Intent설정 또는 매니페스트 설정 을 사용하여이 작업을 수행 할 수있는 방법이 있습니까? 아니면 두 번째 옵션 LinkedList인 열린 활동을 유지하는 것이 최선의 옵션입니까? 아니면 내가 완전히 간과하는 또 다른 옵션이 있습니까?



답변

IMHO가 더 강력한 다른 접근법을 제안 할 수 있습니다. 기본적으로 로그인 상태를 유지해야하는 모든 활동에 로그 아웃 메시지를 브로드 캐스트해야합니다. 그래서 당신은 모든 활동에를 사용 sendBroadcast하고 설치할 수 있습니다 BroadcastReceiver. 이 같은:

/** on your logout method:**/
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_LOGOUT");
sendBroadcast(broadcastIntent);

수신자 (보안 활동) :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /**snip **/
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("com.package.ACTION_LOGOUT");
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("onReceive","Logout in progress");
            //At this point you should start the login activity and finish this one
            finish();
        }
    }, intentFilter);
    //** snip **//
}


답변

새로운 안드로이드 프로그래머가이 문제를 연구하고이 모든 StackOverflow 스레드를 읽는 데 하루를 보내는 것은 통과의 의례처럼 보입니다. 나는 지금 새로 시작했고 나는 미래의 순례자를 돕기 위해 겸손한 경험의 흔적을 남깁니다.

첫째, 명백한 또는 즉시 내 연구에 따라이 작업을 수행하는 방법이 없습니다 (as of September 2012).당신이 간단 할 수 생각하지 거라고 startActivity(new Intent(this, LoginActivity.class), CLEAR_STACK)하지만 .

당신은 할 수 startActivity(new Intent(this, LoginActivity.class))FLAG_ACTIVITY_CLEAR_TOP– 이것은 스택을 검색 LoginActivity 당신의 이전 원본 인스턴스를 찾아 다시 작성하고 (위쪽으로) 스택의 나머지 부분을 취소 프레임 워크의 원인이됩니다. 로그인은 스택의 맨 아래에있을 것으로 예상되므로 이제 빈 스택이 있고 뒤로 버튼은 응용 프로그램을 종료합니다.

그러나 이것은 이전에 LoginActivity의 원래 인스턴스를 스택 기반에 남겨둔 경우에만 작동합니다. 많은 프로그래머처럼, 당신이 선택, 경우 finish()LoginActivity사용자가 성공적으로 다음 스택의 기초에 더 이상의와,에 기록되면 FLAG_ACTIVITY_CLEAR_TOP의미가 적용되지 않습니다 … 새를 만들어 결국 LoginActivity기존의 스택의 상단에. 거의 확실하게 원하는 것이 아닙니다 (사용자가 이전 화면에 로그인하지 못하게하는 이상한 행동).

이전 그래서 만약 finish()‘는 d는 LoginActivity당신이 당신의 스택을 삭제하고 새로운 시작을위한 몇 가지 메커니즘을 추구해야합니다 LoginActivity. @doreamon이 스레드에서 답변 이 가장 좋은 해결책 인 것 같습니다 (적어도 내 겸손한 눈에).

https://stackoverflow.com/a/9580057/614880

LoginActivity를 활성 상태로 두 었는지 여부에 대한 까다로운 영향으로 인해 많은 혼란이 초래 될 것입니다.

행운을 빕니다.


답변

최신 정보

슈퍼 finishAffinity()메소드는 코드를 줄이는 데 도움이되지만 동일한 결과를 얻을 수 있습니다. 스택의 모든 활동뿐만 아니라 현재 활동을 완료합니다 getActivity().finishAffinity(). 조각 상태 인 경우 사용 하십시오.

finishAffinity();
startActivity(new Intent(mActivity, LoginActivity.class));

원래 답변

LoginActivity-> HomeActivity-> …-> SettingsActivity 호출 signOut ()이라고 가정하십시오.

void signOut() {
    Intent intent = new Intent(this, HomeActivity.class);
    intent.putExtra("finish", true);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
    startActivity(intent);
    finish();
}

활동 :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    boolean finish = getIntent().getBooleanExtra("finish", false);
    if (finish) {
        startActivity(new Intent(mContext, LoginActivity.class));
        finish();
        return;
    }
    initializeView();
}

이것은 나를 위해 작동합니다, 그것이 당신에게도 도움이되기를 바랍니다. 🙂


답변

API 11 이상을 사용하는 경우 다음을 시도해보십시오 FLAG_ACTIVITY_CLEAR_TASK.-문제를 정확하게 해결하는 것 같습니다. 분명히 API 11 이전의 군중은 @doreamon이 제안했듯이 다른 모든 활동을 추가로 확인하는 조합을 사용해야합니다.

(또한 참고 : 이것을 사용하려면 전달해야합니다 FLAG_ACTIVITY_NEW_TASK)

Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("finish", true); // if you are checking for this in your other Activities
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                Intent.FLAG_ACTIVITY_CLEAR_TASK |
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();


답변

나는 이것에도 몇 시간을 보냈다 … 그리고 FLAG_ACTIVITY_CLEAR_TOP 은 당신이 원하는 것처럼 들린다 는 것에 동의합니다 : 시작되는 활동을 제외하고 전체 스택을 지우면 뒤로 버튼이 응용 프로그램을 종료합니다. 그러나 Mike Repass가 언급했듯이 FLAG_ACTIVITY_CLEAR_TOP은 실행중인 활동이 이미 스택에있는 경우에만 작동합니다. 활동이 없으면 플래그는 아무것도하지 않습니다.

무엇을해야합니까? 와 스택의 활동 존재 발사를 넣어 FLAG_ACTIVITY_NEW_TASK 그 활동을 역사의 스택에 새 작업의 시작을한다. 그런 다음 FLAG_ACTIVITY_CLEAR_TOP 플래그를 추가하십시오.

이제 FLAG_ACTIVITY_CLEAR_TOP이 스택에서 새로운 활동을 찾으면 모든 것이 지워지기 전에 거기에 있고 풀려납니다.

여기 내 로그 아웃 기능이 있습니다. View 매개 변수는 기능이 첨부 된 버튼입니다.

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}


답변

많은 답변. 이것도 도움이 될 것입니다-

Intent intent = new Intent(activity, SignInActivity.class)
                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
this.finish();

코 틀린 버전

Intent(this, SignInActivity::class.java).apply {
    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}.also { startActivity(it) }
finish()


답변

이것을 사용하면 도움이 될 것입니다. 약간 수정 된 xbakesx 답변.

Intent intent = new Intent(this, LoginActivity.class);
if(Build.VERSION.SDK_INT >= 11) {
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
} else {
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivity(intent);