Android - Как переопределить кнопку «Назад», чтобы она не заканчивала () мою активность?

199

В настоящее время у меня есть действие, которое, когда оно отображается, уведомление также отображается на панели уведомлений.

Это делается для того, чтобы, когда пользователь нажимал кнопку «Домой», а действие переместилось в фоновый режим, они могли вернуться к действию через уведомление.

Проблема возникает, когда пользователь нажимает кнопку «Назад», моя активность уничтожается, но уведомление остается, так как я хочу, чтобы пользователь мог нажимать назад, но при этом получать доступ к активности через уведомление. Но когда ПОЛЬЗОВАТЕЛЬ пытается это сделать, я получаю нулевые указатели как попытку начать новую деятельность, а не вернуть старую.

По сути, я хочу, чтобы кнопка «Назад» действовала точно так же, как кнопка «Домой», и вот как я пытался это сделать:


        @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;
        }   

Однако приведенный выше код все еще позволяет уничтожить мою активность. Как я могу остановить уничтожение моей активности при нажатии кнопки «Назад»?

Донал Рафферти
источник
Есть похожий вопрос: stackoverflow.com/questions/2459848/…
aleung
1
Аналогичный ответ .. stackoverflow.com/questions/5914040/…
Zar E Ahmer
Также я думаю, что вы должны изменить свой код на `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <` должен стать >.
SudoPlz
1
Даже если вы решите это, вы все равно должны учитывать возможность того, что система убьет ваше приложение, верно? Я имею в виду, нулевой случай все еще возможен? Или если система по какой-либо причине убивает ваше приложение, это также приведет к удалению вашего уведомления? Я думаю, что это должно быть проблемой, поскольку цель уведомления - существовать, даже если приложение не существует.
ToolmakerSteve
Посмотрите здесь пример кода приложения freakyjolly.com/how-to-add-back-arrow-in-android-activity
Code Spy

Ответы:

276

Удалить ваш ключевой слушатель или вернуться, trueкогда у вас есть KEY_BACK.

Вам просто нужно следующее, чтобы поймать клавишу возврата (убедитесь, что не вызывать супер в 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);
}
ekawas
источник
70

Это было проще реализовать только одной строкой кода:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}
Тео Инке
источник
Это должен быть принятый ответ. Это делает именно то, что задает вопрос, и использует чистый встроенный функционал.
Шадониня,
Спасибо :) Можете ли вы разработать концепцию этого?
Фаррух Файзи
1
Вы просто переопределяете событие onBackPressed (), заставляя его переместить действие назад.
Белка
1
Это решение не вернет активность, когда вы перезапустите приложение с главного экрана (если в стеке задач есть другое действие).
Игорь Ганапольский
12

Я думаю, что вам нужно не переопределить кнопку «назад» (это не кажется хорошей идеей - ОС Android определяет это поведение, зачем менять его?), А использовать жизненный цикл активности и сохранить свои настройки / данные в Событие 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, и он не работал, но я думаю, что я заметил свою ошибку сейчас. Спасибо
Донал Рафферти
5
Я сталкивался, по крайней мере, с несколькими ситуациями, когда я хотел имитировать стандартное поведение стека действий без фактического запуска новых действий. В этих случаях, я думаю, целесообразно переопределить поведение onBackPressed () по умолчанию. В целом, однако, я согласен: избегать переопределения.
Мэтт Бриансон
4
Я согласен с @Matt. В настоящее время я работаю над кроссплатформенной игрой, в которой используется NDK. Таким образом, проще всего, если все является одним видом деятельности. Из-за этого поведение кнопки «Назад» по умолчанию - выход из приложения, чего не ожидает большинство пользователей. Поэтому мне пришлось перезаписать поведение по умолчанию, чтобы действие стало другим, как если бы пользователь фактически перешел к другому действию и выходил из приложения только в определенных обстоятельствах.
Лейф Андерсен
1
Разве onSaveInstanceState и сохранение данных - это совсем другой вопрос?
Тед
@Ted - если вы говорите, что в дополнение к onSaveInstanceState также должен присутствовать код, который сохраняет данные приложений, не относящиеся к пользовательскому интерфейсу, тогда я согласен. Как только вы покидаете передний план, ваше приложение может быть убито без предупреждения. Всегда нужно сохранять все, что имеет значение. С другой стороны, я думаю, что методы жизненного цикла приложения будут вызываться независимо от того, какую технику вы используете для скрытия приложения, но сохраняете его, поэтому не нужно добавлять логику сохранения только для этого случая. Ваше приложение нуждается в этом коде во всех нужных местах независимо от.
ToolmakerSteve
11

просто сделай это ..

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

комментирование //super.onBackPressed (); сделает свое дело

androCoder-BD
источник
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)
user3156040
источник
0

В Котлине:

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

Для получения дополнительной информации вы можете проверить это .

Существует также конкретный вопрос о переопределении кнопки возврата в Kotlin.

solaza
источник