Mendeteksi tekan tombol home di android


94

Ini telah membuatku gila untuk sementara waktu sekarang.

Adakah cara yang andal untuk mendeteksi jika tombol beranda telah ditekan di aplikasi Android?

Jika tidak, apakah ada cara yang tepat untuk mengetahui apa yang menyebabkan aktivitas masuk ke onPause? yaitu Bisakah kita mendeteksi apakah itu disebabkan oleh peluncuran aktivitas baru atau dengan menekan kembali / beranda.

Satu saran yang telah saya lihat adalah mengganti onPause () dan memanggil isFinishing () tetapi ini akan mengembalikan false saat menekan tombol beranda sama seperti jika aktivitas baru dimulai, jadi ini gagal untuk membedakan keduanya.

Setiap bantuan sangat dihargai.

** Pembaruan **: Terima kasih kepada @ android-hung untuk tautan ini: https://nishandroid.blogspot.com/

Mengatasi metode berikut:

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);           
}

Kemudian acara berikut AKAN dipicu untuk penekanan tombol beranda:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME)
    {
       //The Code Want to Perform. 
    }
});

Saya tidak yakin apakah ada efek samping dengan baris ini:

this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);   

Jadi tampaknya bertentangan dengan kepercayaan populer, Anda sebenarnya dapat mendengarkan kunci rumah. Yang mengkhawatirkan, Anda dapat mengembalikan false dan kunci beranda tidak melakukan apa pun.

Pembaruan : Seperti yang diharapkan, ada beberapa efek samping dengan ini - tampaknya video yang disematkan dan peta Google tidak terlihat dengan mode ini diaktifkan.

Pembaruan : Seharusnya peretasan ini tidak lagi berfungsi mulai Android 4.0 dan seterusnya


Masalah saya bukan untuk menyamarkan antara tombol belakang dan rumah tetapi saya ingin menyelesaikan aplikasi pada kedua kasus. Yang saya gunakan Activity.onUserLeaveHint().
harisme

Satu-satunya masalah adalah onUserLeaveHint () juga akan aktif saat saya memulai aktivitas dari aktivitas tersebut, saya hanya ingin tahu apakah kembali atau beranda telah ditekan. Terima kasih atas sarannya
Dean Wild

Itu benar, tapi sayangnya, sejauh yang saya tahu, itu satu-satunya tempat untuk menerima informasi tentang penggunaan -key Home. Membuat lebih menjadi masalah untuk mengeluarkan positif-palsu, dari banyak yang dapat dikenali dengan mudah, tetapi tetap membuat tugas yang terdengar mudah agak rumit.
harisme

2
@DeanWild: apakah kamu membaca ini: nisha113a5.blogspot.com
Pratik Bhat

2
Konstanta TYPE_KEYGUARD telah dihapus dari WindowManager.LayoutParams di Android 5.0
theb1uro

Jawaban:


136

Kode berikut berfungsi untuk saya :)

HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
    @Override
    public void onHomePressed() {
        // do something here...
    }
    @Override
    public void onHomeLongPressed() {
    }
});
mHomeWatcher.startWatch();
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

public class HomeWatcher {

    static final String TAG = "hg";
    private Context mContext;
    private IntentFilter mFilter;
    private OnHomePressedListener mListener;
    private InnerReceiver mReceiver;

    public HomeWatcher(Context context) {
        mContext = context;
        mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    }

    public void setOnHomePressedListener(OnHomePressedListener listener) {
        mListener = listener;
        mReceiver = new InnerReceiver();
    }

    public void startWatch() {
        if (mReceiver != null) {
            mContext.registerReceiver(mReceiver, mFilter);
        }
    }

    public void stopWatch() {
        if (mReceiver != null) {
            mContext.unregisterReceiver(mReceiver);
        }
    }

    class InnerReceiver extends BroadcastReceiver {
        final String SYSTEM_DIALOG_REASON_KEY = "reason";
        final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
        final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (reason != null) {
                    Log.e(TAG, "action:" + action + ",reason:" + reason);
                    if (mListener != null) {
                        if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                            mListener.onHomePressed();
                        } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                            mListener.onHomeLongPressed();
                        }
                    }
                }
            }
        }
    }
}
public interface OnHomePressedListener {
    void onHomePressed();
    void onHomeLongPressed();
}

3
Anda onHomeLongPressedsebenarnya tampaknya sesuai dengan pembukaan aktivitas sistem "Terbaru". Di ponsel saya, itu dipicu dengan menekan tombol terbaru di sebelah tombol beranda, jadi asumsi kode Anda tentang itu sebagai pers lama di rumah tidak selalu benar.
Sam

mengapa tidak berhasil untuk saya, saya melakukan hal yang sama kecuali mendaftarkan siaran melalui manifes.
Farhan

Terdaftar di kelas aplikasi, Bekerja sejauh ini .. +1, saya ingin tahu apa yang menarik? Maksud saya, kasus asli apa yang akan kita lewatkan ..: ^)
Farhan

1
terkadang intent.getStringExtra (SYSTEM_DIALOG_REASON_KEY); mengembalikan nol. Saya ingin tahu apa yang terjadi ??
Fakher

1
Alasan pers yang lama sekarang disebutfinal String SYSTEM_DIALOG_REASON_LONG_PRESS = "assist"
JWqvist

49

Ini adalah pertanyaan lama tapi mungkin bisa membantu seseorang.

@Override
protected void onUserLeaveHint()
{
    Log.d("onUserLeaveHint","Home button pressed");
    super.onUserLeaveHint();
}

Menurut dokumentasi, metode onUserLeaveHint () dipanggil saat pengguna mengklik tombol beranda ATAU ketika sesuatu mengganggu aplikasi Anda (seperti panggilan telepon masuk).

Ini bekerja untuk saya .. :)


26
Tidak benar !!! Itu berfungsi saat tombol beranda ditekan tetapi juga berfungsi saat Menggeser Aktivitas dengan Maksud !!
Nikunj Paradva

Ini akan selalu dijalankan sebelum onStop (), meskipun aktivitas lain muncul di atas atau pengguna secara paksa meninggalkan aktivitas atau mengklik tombol beranda ...
Navas pk

7

Tidak mungkin mendeteksi dan / atau mencegat tombol HOME dari dalam aplikasi Android. Ini dibangun ke dalam sistem untuk mencegah aplikasi berbahaya yang tidak dapat keluar.


periksa jawaban yang diterima, itu mungkin. Belum diuji pada banyak perangkat.
Dean Wild

Ya ... aplikasi crash pada saya.
Jeremy Logan

bagaimana dengan peluncur / aplikasi pengganti rumah? Saya sedang membangunnya dan saya ingin membuka layar pertama saat pengguna mengeklik beranda
lisovaccaro

Untuk Peluncur, gunakan ini: @Override protected void onNewIntent (Intent intent) {super.onNewIntent (intent); / * Lakukan apa yang Anda inginkan * /}
Ton

Peluncur @lisovaccaro dan atau pengganti rumah masih belum didukung oleh google (src diane hackborn) dan oleh karena itu Anda tidak dapat mencegah pengguna untuk mengklik tombol beranda. Anda masih bisa menambahkan tampilan Anda sebagai dialog peringatan sistem, yang akan menutupi semuanya. Tetapi klik tombol beranda akan melewatinya.
JacksOnF1re

7

Saya perlu memulai / menghentikan musik latar di aplikasi saya saat aktivitas pertama dibuka dan ditutup atau saat aktivitas apa pun dijeda oleh tombol beranda dan kemudian dilanjutkan dari pengelola tugas. Pemutaran murni berhenti / melanjutkan Activity.onPause()dan Activity.onResume()mengganggu musik untuk sementara waktu, jadi saya harus menulis kode berikut:

@Override
public void onResume() {
  super.onResume();

  // start playback here (if not playing already)
}

@Override
public void onPause() {
  super.onPause();

  ActivityManager manager = (ActivityManager) this.getSystemService(Activity.ACTIVITY_SERVICE);
  List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(Integer.MAX_VALUE);
  boolean is_finishing = this.isFinishing();
  boolean is_last = false;
  boolean is_topmost = false;
  for (ActivityManager.RunningTaskInfo task : tasks) {
    if (task.topActivity.getPackageName().startsWith("cz.matelier.skolasmyku")) {
      is_last = task.numRunning == 1;
      is_topmost = task.topActivity.equals(this.getComponentName());
      break;
    }
  }

  if ((is_finishing && is_last) || (!is_finishing && is_topmost && !mIsStarting)) {
    mIsStarting = false;
    // stop playback here
  }
}

yang menyela pemutaran hanya ketika aplikasi (semua aktivitasnya) ditutup atau ketika tombol beranda ditekan. Sayangnya saya tidak berhasil mengubah urutan pemanggilan onPause()metode aktivitas awal dan aktivitas onResume()yang dimulai saat Activity.startActivity()dipanggil (atau mendeteksi onPause()aktivitas tersebut meluncurkan aktivitas lain dengan cara lain) sehingga kasus ini harus ditangani secara khusus:

private boolean mIsStarting;

@Override
public void startActivity(Intent intent) {
  mIsStarting = true;
  super.startActivity(intent);
}

Kelemahan lainnya adalah membutuhkan GET_TASKSizin yang ditambahkan ke AndroidManifest.xml:

<uses-permission
  android:name="android.permission.GET_TASKS"/>

Memodifikasi kode ini sehingga hanya bereaksi pada penekanan tombol home sangatlah mudah.


4

Timpa onUserLeaveHint()dalam aktivitas. Tidak akan pernah ada panggilan balik ke aktivitas ketika aktivitas baru datang atau pengguna menekan kembali tekan.


4
itu juga disebut juga saat
berpindah

3

onUserLeaveHint ();

ganti metode kelas aktivitas ini. Ini akan mendeteksi klik tombol beranda. Metode ini dipanggil tepat sebelum callback onPause () aktivitas. Namun metode ini tidak akan dipanggil saat aktivitas diinterupsi seperti aktivitas dalam panggilan masuk ke latar depan, selain interupsi itu akan dipanggil saat pengguna mengklik tombol beranda.

@Override
protected void onUserLeaveHint() {
    super.onUserLeaveHint();
    Log.d(TAG, "home key clicked");
}

2

Cobalah membuat penghitung untuk setiap layar. Jika pengguna menyentuh HOME, maka penghitung akan menjadi nol.

public void onStart() {
  super.onStart();
  counter++;
}

public void onStop() {
  super.onStop();
  counter--;    
  if (counter == 0) {
      // Do..
  }
}

3
Jika yang Anda maksud adalah penghitung aplikasi global, itu akan menjadi nol pada saat satu aktivitas dipindahkan ke back-stack dan yang lain dipindahkan ke atas atau ketika aktivitas puncak selesai dan aktivitas back-stack dipindahkan ke atas yang merupakan tempat biasa ketika Anda ingin bereaksi saat menekan tombol home. Jika yang Anda maksud adalah penghitung seluruh aktivitas, nilainya akan nol setiap kali aktivitas tidak terlihat (tidak harus disebabkan oleh penekanan tombol beranda). Satu-satunya solusi adalah menunda reaksi Anda menggunakan pengatur waktu untuk melewati transisi ini tetapi penundaan yang diperlukan mungkin tidak dapat diprediksi atau diinginkan.
Blackhex


1

Saya mengalami masalah ini, dan karena menimpa metode onKeyDown () tidak mencapai apa-apa karena sistem android yang mendasarinya tidak memanggil metode ini, saya menyelesaikannya dengan mengganti onBackPressed (), dan saya menetapkan nilai boolean di sana ke false , karena saya menekan kembali, izinkan saya menunjukkan kepada Anda apa yang saya maksud dalam kode:

import android.util.Log;
public class HomeButtonActivity extends Activity {
    boolean homePressed = false;
    // override onCreate() here.

    @Override
    public void onBackPressed() {
        homePressed = false; // simply set homePressed to false
    }

    @Overide
    public void onResume() {
        super.onResume();
        homePressed = true; // default: other wise onBackPressed will set it to false
    }

    @Override
    public void onPause() {
        super.onPause();
        if(homePressed) { Log.i("homePressed", "yay"); }
    }

Jadi alasan mengapa ini berhasil adalah karena satu-satunya cara untuk menavigasi di luar aktivitas ini adalah dengan menekan kembali atau beranda jadi jika kembali ditekan maka saya tahu penyebabnya bukan di rumah, tetapi sebaliknya penyebabnya adalah rumah, oleh karena itu saya menetapkan boolean default nilai untuk homePressed menjadi benar. Namun ini hanya akan bekerja dengan satu instance aktivitas dalam aplikasi Anda karena jika tidak, Anda memiliki lebih banyak kemungkinan untuk menyebabkan metode onPause () dipanggil.


sebenarnya saat Anda pergi ke aktivitas lain, metode jeda disebut
Fakher

Itu sebabnya saya secara eksplisit menyatakan bahwa ini hanya akan berfungsi jika aplikasi Anda hanya memasukkan satu aktivitas!
Moshe Rabaev

Dan bagaimana jika beberapa aktivitas yang tidak terkait berjalan pada waktu yang sama, dan pengguna hanya beralih di antaranya? Perangkat Android modern mendukung multi-tasking. Dengan kode ini, sepertinya beralih kembali ke aplikasi Anda akan disetel homePressedke true, lalu beralih ke aplikasi lain akan menganggap Beranda ditekan padahal sebenarnya tidak.
Remy Lebeau

1

Sejak API 14 Anda dapat menggunakan fungsi tersebut onTrimMemory()dan memeriksa benderanya TRIM_MEMORY_UI_HIDDEN. Ini akan memberi tahu Anda bahwa Aplikasi Anda menuju ke latar belakang.

Jadi di kelas Aplikasi kustom Anda, Anda dapat menulis sesuatu seperti:

override fun onTrimMemory(level: Int) {
    if (level == TRIM_MEMORY_UI_HIDDEN) {
        // Application going to background, do something
    }
}

Untuk studi mendalam tentang ini, saya mengundang Anda untuk membaca artikel ini: http://www.developerphil.com/no-you-can-not-override-the-home-button-but-you-dont-have -untuk/


1
Artikel bagus - alternatif berguna yang mungkin memenuhi kebutuhan kebanyakan orang
Dean Wild

Solusi bagus. Apakah Anda tahu cara menyetel ulang bendera saat aplikasi kembali dari latar belakang? Misalnya jika saya membuat isInBackground boolean, saya ingin mengatur ulang ke setelah kita kembali dari latar belakang.
MikeOscarEcho


0

Karena Anda hanya ingin aktivitas root ditampilkan kembali saat aplikasi diluncurkan, mungkin Anda bisa mendapatkan perilaku ini dengan mengubah mode peluncuran, dll. Di manifes?

Misalnya, pernahkah Anda mencoba menerapkan atribut android: clearTaskOnLaunch = "true" ke aktivitas peluncuran Anda, mungkin bersama-sama dengan android: launchMode = "singleInstance" ?

Tasks and Back Stack adalah sumber yang bagus untuk menyempurnakan perilaku semacam ini.


Ini akan tampak seperti solusi yang paling elegan tetapi menurut saya solusi ini tidak dapat diandalkan. Setelah beberapa siklus buka / tutup / jeda, aplikasi akan mulai melanjutkan daripada memulai ulang sepenuhnya
Dean Wild

0

Merupakan ide yang buruk untuk mengubah perilaku kunci rumah. Inilah mengapa Google tidak mengizinkan Anda mengganti kunci rumah. Saya tidak akan mengacaukan kunci rumah secara umum. Anda perlu memberi pengguna cara untuk keluar dari aplikasi Anda jika aplikasi tersebut masuk ke gulma karena alasan apa pun.

Saya membayangkan pekerjaan apa pun di sekitar akan memiliki efek samping yang tidak diinginkan.


1
Anda benar-benar tepat tetapi beberapa klien tidak akan menerima jawaban tidak dan tidak mengerti mengapa mereka tidak boleh melanggar pedoman.
Dean Wild

Masalahnya adalah bahwa meskipun Anda tidak ingin mengubah perilaku tombol beranda, Anda terkadang harus bereaksi secara berbeda pada situasi di mana aplikasi dipindahkan ke belakang karena penekanan tombol beranda berbeda dari pada situasi di mana aktivitas Anda saat ini dijeda untuk apa pun. alasan. Masalah yang sama ada pada fakta bahwa Application.onDestroy () tidak dapat digunakan untuk build poduction. Contoh seperti itu adalah menjeda game saat pengguna menyembunyikan aplikasi, menghentikan musik latar, dll.
Blackhex

0

Baru-baru ini saya mencoba mendeteksi tombol home press, karena saya membutuhkannya untuk melakukan hal yang sama dengan metode " onBackPressed () ". Untuk melakukan ini, saya harus mengganti metode " onSupportNavigateUp () " seperti ini:

override fun onSupportNavigateUp(): Boolean {
    onBackPressed()
    return true
}

Ini bekerja dengan sempurna. =)


0

Jawaban Jack berfungsi sempurna untuk clickacara sementara yang longClicksedang dipertimbangkan adalah sebagai menuklik tombol.

Ngomong-ngomong, jika ada yang bertanya-tanya bagaimana caranya melalui kotlin,

class HomeButtonReceiver(private var context: Context,private var listener: OnHomeButtonClickListener) {
    private val mFilter: IntentFilter = IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
    private var mReceiver: InnerReceiver = InnerReceiver()

    fun startWatch() {
        context.registerReceiver(mReceiver, mFilter)
    }

    fun stopWatch() {
        context.unregisterReceiver(mReceiver)
    }

    inner class InnerReceiver: BroadcastReceiver() {
        private val systemDialogReasonKey = "reason"
        private val systemDialogReasonHomeKey = "homekey"
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action
            if (action == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) {
                val reason = intent.getStringExtra(systemDialogReasonKey)
                if (reason != null && reason == systemDialogReasonHomeKey) {
                    listener.onHomeButtonClick()
                }
            }
        }
    } 
}

0

masukkan deskripsi gambar di sini Android Home Key ditangani oleh lapisan kerangka kerja, Anda tidak dapat menangani ini di tingkat lapisan aplikasi. Karena aksi tombol beranda sudah ditentukan di tingkat di bawah ini. Tetapi Jika Anda mengembangkan ROM khusus Anda, maka itu mungkin saja. Google membatasi fungsi TOMBOL HOME karena alasan keamanan.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.