Android-如何替代“后退”按钮,使其无法完成我的活动?


199

我目前有一个活动,当它显示时,一个通知也将显示在通知栏中。

这样,当用户按下主页时,活动被推到后台,他们可以通过通知返回活动。

当用户按下“后退”按钮时,会出现问题,我的活动被销毁,但通知仍然保留,因为我希望用户能够按回去,但仍然能够通过通知进入活动。但是,当USER尝试执行此操作时,我会得到Null指针,因为它试图开始一项新活动,而不是恢复旧活动。

所以从本质上讲,我希望“后退”按钮的作用与“主页”按钮完全相同,这是到目前为止我尝试过的方法:


        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event)  {
            if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5
                    && keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) {
                Log.d("CDA", "onKeyDown Called");
                onBackPressed();
            }

            return super.onKeyDown(keyCode, event);
        }

        public void onBackPressed() {
            Log.d("CDA", "onBackPressed Called");
            Intent setIntent = new Intent(Intent.ACTION_MAIN);
            setIntent.addCategory(Intent.CATEGORY_HOME);
            setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(setIntent); 

            return;
        }   

但是,上面的代码似乎仍然允许我的Activity被销毁,如何在按下后退按钮时阻止我的Activity被销毁?


还有一个类似的问题:stackoverflow.com/questions/2459848/...
aleung


此外,我认为你必须更改您的代码`如果(的Integer.parseInt(android.os.Build.VERSION.SDK)> 5 , the <`应该成为一个>
SudoPlz

1
即使解决了这个问题,您仍然必须处理系统杀死您的应用程序的可能性,对吗?我的意思是,空值仍然可行吗?或者,如果系统由于任何原因终止了您的应用程序,是否还会删除您的通知?我认为这一定是一个问题,因为即使应用程序不存在,通知的目的仍然存在。
ToolmakerSteve

Answers:


276

删除您的关键侦听器或true在拥有后返回KEY_BACK

您只需要以下内容即可捕获返回键(请确保不要调用super in onBackPressed())。

另外,如果您打算在后台运行服务,请确保查看startForeground()并确保有正在进行的通知,否则Android如果需要释放内存,则会终止您的服务。

@Override
public void onBackPressed() {
   Log.d("CDA", "onBackPressed Called");
   Intent setIntent = new Intent(Intent.ACTION_MAIN);
   setIntent.addCategory(Intent.CATEGORY_HOME);
   setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(setIntent);
}

70

仅用一行代码即可实现:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}

这应该是公认的答案。这完全符合问题的要求,并且使用的是干净的内置功能。
Shadoninja'4

谢谢:)您能详细说明其背后的概念吗?
Farrukh Faizy '17

1
您只需覆盖onBackPressed()事件,即可将活动移到后面。
Squirrelkiller

1
当您从主屏幕重新启动应用程序时(如果任务堆栈上还有其他活动),此解决方案不会恢复活动。
IgorGanapolsky

12

我认为您想要的不是不要覆盖后退按钮(这似乎不是一个好主意-Android OS定义了该行为,为什么要更改它?),而是要使用“ 活动生命周期”并将您的设置/数据保留在onSaveInstanceState(Bundle)事件。

@Override
onSaveInstanceState(Bundle frozenState) {
    frozenState.putSerializable("object_key",
        someSerializableClassYouWantToPersist);
    // etc. until you have everything important stored in the bundle
}

然后,使用onCreate(Bundle)将所有内容从该持久性捆绑包中取出,并重新创建状态。

@Override
onCreate(Bundle savedInstanceState) {
    if(savedInstanceState!=null){ //It could be null if starting the app.
        mCustomObject = savedInstanceState.getSerializable("object_key");
    }
    // etc. until you have reloaded everything you stored
}

考虑上面的伪代码,可以为您指明正确的方向。阅读活动生命周期应该可以帮助您确定完成所需内容的最佳方法。


嗨Kiswa,这是真的,我不想更改默认行为。我试过使用onSavedInstanceState,但它没有用,但我相信我现在发现了我的错误。感谢
Donal Rafferty 2010年

5
我至少遇到过几种情况,我想模拟标准的活动堆栈行为,而无需实际启动新的活动。在这种情况下,我认为应该覆盖默认的onBackPressed()行为。但总的来说,我同意:避免压倒一切。
MattBriançon

4
我同意@Matt。我目前正在开发使用NDK的跨平台游戏。这样,如果所有事情都是一个活动,那是最简单的。因此,后退按钮的默认行为是退出应用程序,这不是大多数用户期望的。因此,我不得不覆盖默认行为,以使该活动的行为有所不同,就好像用户实际上已去了另一个活动,并且仅在某些情况下才退出该应用程序。
雷夫·安徒生

1
onSaveInstanceState和保存数据不是一个完全不同的问题吗?
Ted

@Ted-如果您说除了onSaveInstanceState之外,还需要保留非UI应用程序数据的代码,那么我同意。放弃前台后,您的应用可能会被杀死,而不会发出进一步的警告。必须始终保存所有重要内容。另一方面,我认为应用程序生命周期方法将被调用,而不管您使用什么技术隐藏应用程序但将其保留在周围,因此不必仅为此情况添加保存逻辑。无论如何,您的应用都需要在所有正确的位置使用该代码。
ToolmakerSteve

11

只需这样做。

@Override
public void onBackPressed() {
    //super.onBackPressed();
}

注释掉//super.onBackPressed(); 会成功的


1
一个有用的观察,但是这不会导致后退按钮什么也不做,好像它坏了吗?那不是一件好事-给用户造成困扰和烦恼。恕我直言,必须从另一个答案中添加逻辑,以像所要求的那样充当“主页”按钮。接受的答案提到他们故意不调用超级方法。
ToolmakerSteve

是的,您绝对正确。它只会覆盖后退按钮,并且在您添加一些逻辑之前不会执行任何操作。可能是双击按钮以关闭应用程序的条件,或者您只想禁用正在进行的操作(进度对话框)等,但这完全符合要求。
androCoder-BD

5

试试这个:

@Override
public void onBackPressed() {
    finish();
}

3

万一您想处理“后退”按钮(在手机底部)和“主页”按钮(操作栏左侧的按钮)的行为,我在项目中使用的此自定义活动可能会对您有所帮助。

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

/**
 * Activity where the home action bar button behaves like back by default
 */
public class BackActivity extends AppCompatActivity {

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

    private void setupHomeButton() {
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onMenuHomePressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    protected void onMenuHomePressed() {
        onBackPressed();
    }
}

在您的活动中使用的示例:

public class SomeActivity extends BackActivity {

    // ....

    @Override
    public void onBackPressed()
    {
        // Example of logic
        if ( yourConditionToOverride ) {
            // ... do your logic ...
        } else {
            super.onBackPressed();
        }
    }    
}

1
@Override
public void onBackPressed() {
// Put your code here.
}

//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() {
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);
}
Just write this above or below the onCreate Method(within the class)

0

在科特林:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    // Handle the back button event
}

有关更多信息,您可以检查一下

还有一个关于在Kotlin中覆盖后退按钮的特定问题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.