사용자가 Android 활동을 종료 할 것인지 확인하는 대화 상자를 표시하는 방법은 무엇입니까?


274

"종료 하시겠습니까?"를 표시하려고했습니다. 사용자가 활동을 종료하려고 할 때 대화 상자 유형.

그러나 적절한 API 후크를 찾을 수 없습니다. Activity.onUserLeaveHint()처음에는 유망한 것처럼 보였지만 활동이 끝나는 것을 막을 수있는 방법을 찾을 수 없습니다.


39
이 프롬프트가 반드시 있어야합니까? 사용자가 활동을 마치려면 즉시 수행 할 수 있어야합니다. 전략을 다시 생각할 수도 있습니다.
Tom R

4
종료 확인 옵션을 표시하는 것은 Samsung의 App Store에 상장해야합니다. 내 앱 중 하나가 이것을 거부하여 거부되었습니다.
존 애쉬모어

6
@ 삼성.
dokkaebi

3
종료 할 때 수행 할 작업에 따라 다릅니다. 상태가 유지되고 뒤로 탐색 할 수 있으면 대화 상자를 표시하지 않아도됩니다. 그러나 내 응용 프로그램 중 하나에서 최종 데이터 커밋으로 쿠키, 데이터 및 연결을 정리합니다. 특히 오늘날 모바일 애플리케이션에서 최종성을 갖는 것은 드물기 때문에 사용자는 자신이 선택한 최종성을 알고 있어야합니다.
Eric

15
@ Tom R : 완전히 동의하지 않습니다. 실수로 끝내고 싶지 않은 앱이 있습니다. 그들은 비즈니스 환경 등에서 일합니다.
TomeeNS

답변:


390

Android 2.0 이상에서는 다음과 같습니다.

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle("Closing Activity")
        .setMessage("Are you sure you want to close this activity?")
        .setPositiveButton("Yes", new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            finish();    
        }

    })
    .setNegativeButton("No", null)
    .show();
}

이전 버전에서는 다음과 같습니다.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    //Handle the back button
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        //Ask the user if they want to quit
        new AlertDialog.Builder(this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setTitle(R.string.quit)
        .setMessage(R.string.really_quit)
        .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                //Stop the activity
                YourClass.this.finish();    
            }

        })
        .setNegativeButton(R.string.no, null)
        .show();

        return true;
    }
    else {
        return super.onKeyDown(keyCode, event);
    }

}

15
또한 2.0 이상에서는 onKeyDown developer.android.com/intl/zh-TW/reference/android/app/를 통해 권장되는 새로운 onBackPressed 이벤트가 있습니다. 여기에는 변경 사항 및 새로운 권장 접근 방식에 대한 섹션이 있습니다. developer.android.com/intl/zh-TW/sdk/android-2.0.html
Patrick Kafka 2019

3
뒤로 키를 잡는 방법에 대한 블로그 게시물 : android-developers.blogspot.com/2009/12/… 이렇게하면 사용자가 앱을 떠날 수있는 다른 방법 (집을 누르거나 알림 선택, 전화 받기)을 잡을 수는 없습니다. 전화 등
hackbod

이것은 완벽하게 작동하지만 사용자에게 코드 실행이 표시되는 동안 어떻게 코드 실행을 강제로 중지합니까?
anon58192932

그것을 발견, 이것은 여기에 훌륭한 솔루션입니다 : stackoverflow.com/questions/4381296/…
anon58192932

1
이것은 내가 찾고있는 method ()이지만이 method ()를 어디에서 호출 해야할지 모르겠습니다.
user2841300

186
@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
           .setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   ExampleActivity.super.onBackPressed();
               }
           })
           .setNegativeButton("No", null)
           .show();
}

5
elBradford의 의견 : onBackPressed가 finish () 만 호출한다고 가정하는 것보다 super onBackPressed를 호출하는 것이 좋습니다. 그 지금 사실하더라도, 그것은 미래의 API에 진실하지 않을 수 있습니다CustomTabActivity.super.onBackPressed
mplungjan

@mplungjan 댓글을 명확히 할 수 있습니까 ? finish()코드 를 바꾸는 것이 더 낫다고 말씀 super.onBackPressed()하십니까?
금지 지오 엔지니어링

댓글은 3 살입니다. 나는 2015 년에 좋은 연습이 무엇인지 전혀 모른다
mplungjan

@mplungjan 귀하의 의견은 미래의 API를 언급했지만 어쨌든 명확하게 설명하면 도움이 될 것입니다.
금지 지오 엔지니어링

문제 없다. 글쎄, 나는 방금 시도 MyActivity.super.onBackPressed();했고 그것은 나에게 잘 작동한다. 사용자가 "아니오"를 누를 때 표준 동작을 원하는 경우 재정의하는 메소드를 호출하는 것이 가장 논리적 인 접근 방식 인 것 같습니다.
금지 지오 엔지니어링

33

@ user919216 코드를 수정하여 WebView와 호환되도록 만들었습니다.

@Override
public void onBackPressed() {
    if (webview.canGoBack()) {
        webview.goBack();

    }
    else
    {
     AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                finish();
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
AlertDialog alert = builder.create();
alert.show();
    }

}

22

종료 대화 상자보다 뒤로 버튼을 두 번 탭하여 종료하고 싶습니다.

이 솔루션에서는 처음으로 돌아갈 때 토스트를 표시하고 다시 한 번 더 누르면 앱이 닫힙니다. 이 예에서는 4 초 미만입니다.

private Toast toast;
private long lastBackPressTime = 0;

@Override
public void onBackPressed() {
  if (this.lastBackPressTime < System.currentTimeMillis() - 4000) {
    toast = Toast.makeText(this, "Press back again to close this app", 4000);
    toast.show();
    this.lastBackPressTime = System.currentTimeMillis();
  } else {
    if (toast != null) {
    toast.cancel();
  }
  super.onBackPressed();
 }
}

토큰 : http://www.androiduipatterns.com/2011/03/back-button-behavior.html


대화 상자가 성 가실 수 있기 때문에 이것은 내가 가장 좋아하는 것입니다. 나는 그것을 3 초로 만들기 위해 약간 변경했으며 그 마커로 조금 더 자연스럽게 보입니다. 게시물 주셔서 감사합니다.
PGMacDesign

더블 백 프레스에서 이상적으로 응용 프로그램을 종료해야하지만 코드에서 로그인 활동을 엽니 다 (스피너가 활성화 된 활동을 의미합니다)
techDigi

21

"back"에 대한 호출이 앱을 종료하는지 또는 사용자를 다른 활동으로 안내 할 것인지 확실하지 않은 경우 위의 답변을 확인하여 isTaskRoot ()를 수행 할 수 있습니다. 주 활동을 백 스택에 여러 번 추가하거나 백 스택 기록을 조작하는 경우에 발생할 수 있습니다.

if(isTaskRoot()) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
       .setCancelable(false)
       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                YourActivity.super.onBackPressed;
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
           }
       });
    AlertDialog alert = builder.create();
    alert.show();

} else {
    super.onBackPressed();
}

5

Lambda 사용 :

    new AlertDialog.Builder(this).setMessage(getString(R.string.exit_msg))
        .setTitle(getString(R.string.info))
        .setPositiveButton(getString(R.string.yes), (arg0, arg1) -> {
            moveTaskToBack(true);
            finish();
        })
        .setNegativeButton(getString(R.string.no), (arg0, arg1) -> {
        })
        .show();

gradle.build에서 java 8을 지원하도록 레벨 언어를 설정해야합니다.

compileOptions {
       targetCompatibility 1.8
       sourceCompatibility 1.8
}

5

중국에서는 대부분의 앱이 '두 번 클릭'하여 종료를 확인합니다.

boolean doubleBackToExitPressedOnce = false;

@Override
public void onBackPressed() {
    if (doubleBackToExitPressedOnce) {
        super.onBackPressed();
        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;                       
        }
    }, 2000);
} 

5

먼저 코드보다 아래의 메소드 super.onBackPressed();에서 제거하십시오 onbackPressed().

@Override
public void onBackPressed() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    MyActivity.this.finish();
               }
           })
           .setNegativeButton("No", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
               }
           });
    AlertDialog alert = builder.create();
    alert.show();

}

2

나는 @GLee 접근법을 좋아하고 아래와 같이 조각과 함께 사용합니다.

@Override
public void onBackPressed() {
    if(isTaskRoot()) {
        new ExitDialogFragment().show(getSupportFragmentManager(), null);
    } else {
        super.onBackPressed();
    }
}

조각을 사용하는 대화 상자 :

public class ExitDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.exit_question)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getActivity().finish();
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    getDialog().cancel();
                }
            })
            .create();
    }
}

2
Just put this code in your first activity 

@Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.END)) {
            drawerLayout.closeDrawer(GravityCompat.END);
        }
        else {
// if your using fragment then you can do this way
            int fragments = getSupportFragmentManager().getBackStackEntryCount();
            if (fragments == 1) {
new AlertDialog.Builder(this)
           .setMessage("Are you sure you want to exit?")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    finish();
               }
           })
           .setNegativeButton("No", null)
           .show();


            } else {
                if (getFragmentManager().getBackStackEntryCount() > 1) {
                    getFragmentManager().popBackStack();
                } else {

           super.onBackPressed();
                }
            }
        }
    }

y 첫 번째 활동, 중간에 활동에 넣을 수 없습니다. 왜냐하면 그것은 현재 활동을 닫고 이전 활동을 보여주기 때문입니다
shareef

1

또 다른 대안은 첫 번째 백 프레스 에서 Toast/Snackbar표시하여 다시 종료하도록 다시 요청 하는 것입니다. 이는 AlertDialog사용자가 앱을 종료하려고하는지 확인 하는 것보다 훨씬 덜 방해 입니다.

를 사용하여 DoubleBackPress Android Library몇 줄의 코드로 이것을 달성 할 수 있습니다 . 유사한 행동을 보여주는 GIF 예.

시작하려면 응용 프로그램에 종속성을 추가하십시오.

dependencies {
    implementation 'com.github.kaushikthedeveloper:double-back-press:0.0.1'
}

그런 다음 활동에서 필요한 동작을 구현하십시오.

// set the Toast to be shown on FirstBackPress (ToastDisplay - builtin template)
// can be replaced by custom action (new FirstBackPressAction{...})
FirstBackPressAction firstBackPressAction = new ToastDisplay().standard(this);

// set the Action on DoubleBackPress
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
    @Override
    public void actionCall() {
        // TODO : Exit the application
        finish();
        System.exit(0);
    }
};

// setup DoubleBackPress behaviour : close the current Activity
DoubleBackPress doubleBackPress = new DoubleBackPress()
        .withDoublePressDuration(3000)     // msec - wait for second back press
        .withFirstBackPressAction(firstBackPressAction)
        .withDoubleBackPressAction(doubleBackPressAction);

마지막으로, 이것을 다시 언론의 행동으로 설정하십시오.

@Override
public void onBackPressed() {
    doubleBackPress.onBackPressed();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.