Bagaimana cara memeriksa apakah aktivitas berada di latar depan atau di latar belakang yang terlihat?

104

Saya memiliki layar splash pada pengatur waktu. Masalah saya adalah bahwa sebelum finish()saya melakukan aktivitas, saya perlu memeriksa bahwa aktivitas berikutnya telah dimulai karena kotak dialog sistem muncul dan saya hanya ingin finish(); setelah pengguna memilih opsi dari kotak dialog?

Saya tahu bahwa ada banyak pertanyaan tentang bagaimana melihat apakah aktivitas Anda berada di latar depan, tetapi saya tidak tahu apakah ini juga memungkinkan adanya kotak dialog di atas aktivitas.

Inilah masalahnya, warna merah adalah aktivitas saya yang ada di latar belakang sementara dialog berada di latar depan:

merah adalah aktivitas saya yang berada di latar belakang sementara dialog berada di latar depan

EDIT: Saya telah mencoba hanya untuk tidak menggunakan finish()tetapi kemudian aktivitas saya dapat kembali ke tumpukan aplikasi yang saya coba hindari.

Nick
sumber
Mungkin relevan: stackoverflow.com/questions/4414171/…
jarmod
Untuk memperjelas, Anda ingin meluncurkan pemilih maksud dan menunggu aplikasi Anda selesai () hingga pengguna mengetuk salah satu pilihan? Sepertinya Anda membutuhkan Intent.createChooser () dan startActivityForResult () diikuti oleh finish () saat hasilnya diterima.
alanv
kemungkinan duplikat Memeriksa apakah aplikasi Android sedang berjalan di latar belakang
Douglas Nassif Roma Junior
ProcessLifecycleOwner adalah solusi terbaru
SR

Jawaban:

189

Inilah yang direkomendasikan sebagai solusi yang tepat :

Solusi yang tepat (kredit diberikan ke Dan, CommonsWare dan NeTeInStEiN) Lacak visibilitas aplikasi Anda sendiri menggunakan metode Activity.onPause, Activity.onResume. Simpan status "visibilitas" di kelas lain. Pilihan yang baik adalah penerapan Anda sendiri atas Aplikasi atau Layanan (ada juga beberapa variasi dari solusi ini jika Anda ingin memeriksa visibilitas aktivitas dari layanan).

Contoh Implementasikan kelas Aplikasi khusus (perhatikan metode statis isActivityVisible ()):

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Daftarkan kelas aplikasi Anda di AndroidManifest.xml:

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Tambahkan onPause dan onResume ke setiap Aktivitas dalam proyek (Anda dapat membuat leluhur yang sama untuk Aktivitas Anda jika Anda mau, tetapi jika aktivitas Anda sudah diperluas dari MapActivity / ListActivity dll. Anda masih perlu menulis yang berikut ini secara manual) :

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

Dalam finish()metode Anda, Anda ingin menggunakan isActivityVisible()untuk memeriksa apakah aktivitas terlihat atau tidak. Di sana Anda juga dapat memeriksa apakah pengguna telah memilih opsi atau tidak. Lanjutkan saat kedua kondisi terpenuhi.

Sumber tersebut juga menyebutkan dua solusi yang salah ... jadi hindari melakukan itu.

Sumber: stackoverflow

Tapi Aku Bukan Kelas Pembungkus
sumber
Ada satu momen kecil antara selesai dan memulai aktivitas dan saya sedikit perlu menambahkan beberapa penundaan dan kontra
sagus_helgy
28
Ini tidak bekerja dengan andal. Anda mungkin mengalami situasi berikut: Lanjutkan A Lanjutkan B Jeda A. Sekarang activityVisible salah sedangkan aplikasi terlihat. Mungkin Anda menggunakan penghitung visibilitas: visibleCounter ++ di onResume dan visibleCounter - di onPause.
Joris Weimar
4
Sependapat dengan Joris Weimar bahwa ini bukanlah solusi yang sangat mudah. Salah satu skenario adalah jika pengguna ditarik ke bawah panel notifikasi, maka tidak dengan onPause, onStop, maupun onResumeacara disebut. Jadi apa yang Anda lakukan jika tidak ada peristiwa ini yang dipecat ?!
1
Faktanya, tidak ada jawaban lain yang berhasil 100%.
2
Jika aplikasi memiliki lebih dari satu Aktivitas, skema ini tidak akan berfungsi. Ganti dengan penghitung setidaknya
ruX
70

Jika menargetkan API level 14 atau lebih tinggi, seseorang dapat menggunakan android.app.Application.ActivityLifecycleCallbacks

public class MyApplication extends Application implements ActivityLifecycleCallbacks {
    private static boolean isInterestingActivityVisible;

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

        // Register to be notified of activity state changes
        registerActivityLifecycleCallbacks(this);
        ....
    }

    public boolean isInterestingActivityVisible() {
        return isInterestingActivityVisible;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = true;
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = false;
        }
    }

    // Other state change callback stubs
    ....
}
silvermouse
sumber
18
Anda bisa melakukan ini dalam callback siklus hidup aktivitas biasa (onResume (), onStop ()) juga saya akan katakan.
Daniel Wilson
5
@DanielWilson Saya pikir intinya bukanlah membangun sistem untuk melakukan sesuatu yang sudah ada. IMHO ini harus menjadi jawaban yang diterima.
Jeffrey Blattman
26

UPD : diperbarui ke status Lifecycle.State.RESUMED. Terima kasih kepada @htafoya untuk itu.

Di 2019 dengan bantuan pustaka dukungan baru 28+atau AndroidX, Anda cukup menggunakan:

val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)

Anda dapat membaca lebih lanjut di dokumentasi untuk memahami apa yang terjadi di balik terpal.

Alex Misiulia
sumber
2
Tidak juga, mungkin lebih baik menempatkan activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) atau MEMULAI. INITIALIZEDtidak menjamin bahwa itu di latar depan.
htafoya
11

Activity :: hasWindowFocus () mengembalikan Anda boolean yang Anda butuhkan.

public class ActivityForegroundChecker extends TimerTask
{
    private static final long FOREGROUND_CHECK_PERIOD = 5000;
    private static final long FIRST_DELAY             = 3000;

    private Activity m_activity;
    private Timer    m_timer;

    public ActivityForegroundChecker (Activity p_activity)
    {
        m_activity = p_activity;
    }

    @Override
    public void run()
    {
        if (m_activity.hasWindowFocus() == true) {
            // Activity is on foreground
            return;
        }
        // Activity is on background.
    }

    public void start ()
    {
        if (m_timer != null) {
            return;
        }
        m_timer = new Timer();
        m_timer.schedule(this, FIRST_DELAY, FOREGROUND_CHECK_PERIOD);
    }

    public void stop ()
    {
        if (m_timer == null) {
            return;
        }
        m_timer.cancel();
        m_timer.purge();
        m_timer = null;
    }
}

Berikut adalah contoh kelas untuk memeriksa visibilitas aktivitas Anda dari mana pun Anda berada.

Ingatlah bahwa jika Anda menampilkan dialog , hasilnya akan salah karena dialog akan memiliki fokus utama. Selain itu, ini sangat berguna dan lebih dapat diandalkan daripada solusi yang disarankan.

Burak Day
sumber
1
Terima kasih telah mengubah jawaban @Burak Day, ini sebenarnya adalah jawaban sekarang
Nick
Ini tidak berhasil, saya lebih suka menggunakan properti boolean di kelas, disetel ke true di OnResume, dan disetel ke false di OnPause ();
Chandler
@Chandler apa masalah sebenarnya yang Anda alami dengan kode ini? Juga versi yang mana?
Hari Burak
@Chandler juga, bagaimana jika Anda tidak memiliki akses ke metode siklus hidup aktivitas. Pertimbangkan Anda hanya memeriksa visibilitas aktivitas dari perpustakaan.
Hari Burak
Masalah sebenarnya dari jawaban ini adalah TIDAK berfungsi, activity.hasWindowFocus benar tidak dapat menjamin aktivitas berada di antara status onResume dan onPause. Saya lebih suka merekomendasikan menambahkan properti isResumed bool dalam aktivitas itu, secara manual mengatur nilainya dan menambahkan metode get.
Chandler
10

Itulah tepatnya perbedaan antara onPausedan onStopkejadian aktivitas seperti yang dijelaskan dalam dokumentasi kelas Aktivitas .

Jika saya memahami Anda secara benar, yang ingin Anda lakukan adalah memanggil finish()dari aktivitas Anda onStopuntuk menghentikannya. Lihat gambar terlampir dari Aplikasi Demo Siklus Hidup Aktivitas . Ini adalah tampilannya ketika Aktivitas B diluncurkan dari Aktivitas A. Urutan kejadian adalah dari bawah ke atas sehingga Anda dapat melihat bahwa Aktivitas A onStopdipanggil setelah Aktivitas B onResumesudah dipanggil.

Demo siklus hidup aktivitas

Jika dialog ditampilkan, aktivitas Anda diredupkan di latar belakang dan hanya onPausedipanggil.

Muzikant
sumber
7

Dua solusi yang mungkin:

1) Panggilan Balik Siklus Hidup Aktivitas

Gunakan Aplikasi yang mengimplementasikan ActivityLifecycleCallbacks dan menggunakannya untuk melacak kejadian daur hidup Aktivitas di aplikasi Anda. Perhatikan bahwa ActivityLifecycleCallbacks adalah untuk Android api> = 14. Untuk api Android sebelumnya, Anda harus mengimplementasikannya sendiri di dalam semua aktivitas Anda ;-)

Gunakan Aplikasi ketika Anda perlu membagikan / menyimpan status di seluruh aktivitas.

2) Periksa informasi proses yang sedang berjalan

Anda dapat memeriksa status proses yang berjalan dengan kelas ini RunningAppProcessInfo

Ambil daftar proses yang sedang berjalan dengan ActivityManager.getRunningAppProcesses () dan filter daftar hasil untuk memeriksa RunningAppProcessInfo yang diinginkan dan periksa "pentingnya"

avianey
sumber
4

Saya telah membuat proyek di github app-foreground-background-listen

yang menggunakan logika yang sangat sederhana dan berfungsi dengan baik dengan semua level API Android.

kiran boghra
sumber
3

Gunakan jeda waktu antara jeda dan lanjutkan dari latar belakang untuk menentukan apakah itu terjaga dari latar belakang

Dalam Aplikasi Kustom

private static boolean isInBackground;
private static boolean isAwakeFromBackground;
private static final int backgroundAllowance = 10000;

public static void activityPaused() {
    isInBackground = true;
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (isInBackground) {
                isAwakeFromBackground = true;
            }
        }
    }, backgroundAllowance);
    Log.v("activity status", "activityPaused");
}

public static void activityResumed() {
    isInBackground = false;
    if(isAwakeFromBackground){
        // do something when awake from background
        Log.v("activity status", "isAwakeFromBackground");
    }
    isAwakeFromBackground = false;
    Log.v("activity status", "activityResumed");
}

Di Kelas BaseActivity

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}
Kit
sumber
3

Saya rasa saya punya solusi yang lebih baik. Karena Anda bisa membangun hanya dalam MyApplication.activityResumed (); untuk setiap Kegiatan dengan satu perluasan.

Pertama, Anda harus membuat (seperti CyberneticTwerkGuruOrc)

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Selanjutnya, Anda harus menambahkan kelas Aplikasi ke AndroidManifest.xml

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Kemudian, buat kelas ActivityBase

public class ActivityBase extends Activity {

    @Override
    protected void onPause() {
        super.onPause();
        MyApplication.activityPaused();
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyApplication.activityResumed();
    }
}

Terakhir, saat Anda membuat Activity baru, Anda cukup memperluasnya dengan ActivityBase alih-alih Activity.

public class Main extends ActivityBase {
    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }
}

Bagi saya Ini metode yang lebih baik karena Anda harus ingat tentang perluasan oleh ActivityBase. Selain itu, Anda dapat memperluas fungsi basis Anda di masa mendatang. Dalam kasus saya, saya menambahkan penerima untuk layanan saya dan peringatan tentang jaringan dalam satu kelas.

Jika Anda ingin memeriksa visibilitas Aplikasi Anda, Anda cukup menelepon

MyApplication.isActivityVisible()
Eliasz Kubala
sumber
Bagaimana jika saya membutuhkan Aktivitas saya untuk memperluas AppCombatActivity?
winklerrr
2

Ini bisa mencapai ini dengan cara yang efisien dengan menggunakan Application.ActivityLifecycleCallbacks

Sebagai contoh, mari kita ambil nama kelas Activity karena ProfileActivity memungkinkan menemukan apakah itu di latar depan atau latar belakang

pertama kita perlu membuat kelas aplikasi kita dengan memperluas Kelas Aplikasi

yang mengimplementasikan

Application.ActivityLifecycleCallbacks

Mari menjadi kelas Aplikasi saya sebagai berikut

Kelas aplikasi

public class AppController extends Application implements Application.ActivityLifecycleCallbacks {


private boolean activityInForeground;

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

//register ActivityLifecycleCallbacks  

    registerActivityLifecycleCallbacks(this);

}



public static boolean isActivityVisible() {
    return activityVisible;
}

public static void activityResumed() {
    activityVisible = true;
}

public static void activityPaused() {
    activityVisible = false;
}

private static boolean activityVisible;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {

}

public boolean isActivityInForeground() {
    return activityInForeground;
}
}

di kelas di atas ada metode override onActivityResumed dari ActivityLifecycleCallbacks

 @Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

di mana semua instance aktivitas yang saat ini ditampilkan di layar dapat ditemukan, cukup periksa apakah Aktivitas Anda ada di Layar atau tidak dengan metode di atas.

Daftarkan kelas Aplikasi Anda di manifest.xml

<application
    android:name=".AppController" />

Untuk memeriksa cuaca, Aktivitas di Latar Depan atau latar belakang sesuai solusi di atas, panggil metode berikut di tempat-tempat yang perlu Anda periksa

AppController applicationControl = (AppController) getApplicationContext();
    if(applicationControl.isActivityInForeground()){
     Log.d("TAG","Activity is in foreground")
    }
    else
    {
      Log.d("TAG","Activity is in background")
    }
Ramz
sumber
1

Jika Anda ingin mengetahui apakah ada aktivitas aplikasi Anda yang terlihat di layar, Anda dapat melakukan sesuatu seperti ini:

public class MyAppActivityCallbacks implements Application.ActivityLifecycleCallbacks {
private Set<Class<Activity>> visibleActivities = new HashSet<>();

@Override
public void onActivityResumed(Activity activity) {
    visibleActivities.add((Class<Activity>) activity.getClass());
}

@Override
public void onActivityStopped(Activity activity) {
     visibleActivities.remove(activity.getClass());
}

public boolean isAnyActivityVisible() {
    return !visibleActivities.isEmpty();
}

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityStarted(Activity activity) {}

@Override
public void onActivityPaused(Activity activity) {}

@Override
public void onActivityDestroyed(Activity activity) {}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}}

Buat saja satu tunggal kelas ini dan setel dalam contoh Aplikasi Anda seperti di bawah ini:

class App extends Application{
     @Override
     public void onCreate() {
         registerActivityLifecycleCallbacks(myAppActivityCallbacks);
     }
}

Kemudian Anda bisa menggunakan metode isAnyActivityVisible () dari instance MyAppActivityCallbacks Anda di mana saja!

Vasil Stolyarchuk
sumber
0

apakah Anda mencoba untuk tidak memanggil finish, dan meletakkan "android: noHistory =" true "dalam manifes? ini akan mencegah aktivitas masuk ke tumpukan.

shaish
sumber
0

Saya harus mengatakan alur kerja Anda tidak dengan cara Android standar. Di Android, Anda tidak perlu melakukan finish()aktivitas jika ingin membuka aktivitas lain dari Intent. Untuk kenyamanan pengguna, Android memungkinkan pengguna untuk menggunakan tombol 'kembali' untuk kembali dari aktivitas yang Anda buka ke aplikasi Anda.

Jadi biarkan sistem menghentikan aktivitas Anda dan menyimpan apa pun yang diperlukan saat aktivitas Anda dipanggil kembali.

Owen Zhao
sumber
3
"buu ini bukan android" cara jawaban melelahkan dan jangan menjawab pertanyaan yang diajukan sejak awal. selanjutnya, ada alasan yang sah untuk menyelesaikan (); - misalnya bisa dibayangkan bahwa kembali ke sana setelah tindakan tersebut dilakukan tidak ada gunanya sama sekali. dengan kata lain, apakah menurut Anda mereka meletakkan finish () di sana untuk bersenang-senang? itu tetap di tumpukan persis apa yang penanya pertanyaan ingin menghindari
Lassi Kinnunen
"buu ini bukan android" cara jawaban melelahkan dan jangan menjawab pertanyaan yang diajukan sejak awal. Pujian Anda tidak adil. Meskipun saya menunjukkan bahwa ini bukan cara Android, saya memberikan jawaban setelah kalimat ini bukannya tidak sama sekali. Saya hanya tidak memberikan jawaban dalam kode karena itu tidak perlu. Jadi tidak adil mengatakan saya tidak menjawab pertanyaan itu sejak awal.
Owen Zhao
0

Simpan bendera jika Anda dijeda atau dilanjutkan. Jika Anda melanjutkan, itu berarti Anda berada di latar depan

boolean  isResumed = false;

@Override
public void onPause() {
  super.onPause();    
  isResumed = false;
}

@Override
public void onResume() {
  super.onResume();    
  isResumed = true;
}

private void finishIfForeground() {
  if (isResumed) {
    finish();
  }
}
yoah
sumber
0

Salah satu solusi yang mungkin mungkin adalah menyetel tanda saat menampilkan dialog sistem dan kemudian di metode onStop dari siklus hidup aktivitas, periksa tanda tersebut, jika benar, selesaikan aktivitas.

Misalnya, jika dialog sistem dipicu oleh beberapa klik tombol, maka pendengar onclick mungkin akan menyukainya

private OnClickListener btnClickListener = new OnClickListener() {

    @Override
    public void onClick(View v) {           
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("text/plain");
        CheckActivity.this.startActivity(Intent.createChooser(intent, "Complete action using"));
        checkFlag = true;  //flag used to check

    }
};

dan di onstop aktivitas:

@Override
protected void onStop() {
    if(checkFlag){
        finish();
    }
    super.onStop();
}
Diya
sumber
0

Mengapa tidak menggunakan siaran untuk ini? aktivitas kedua (yang perlu di up) bisa mengirim siaran lokal seperti ini:

//put this in onCreate(..) or any other lifecycle method that suits you best
//notice the string sent to the intent, it will be used to register a receiver!
Intent result = new Intent("broadcast identifier");
result.putString("some message");//this is optional
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result);

kemudian tulis penerima sederhana dalam aktivitas splash:

//this goes on the class level (like a class/instance variable, not in a method) of your splash activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //kill activity here!!!
        //mission accomplished!
    }
};

dan daftarkan penerima baru Anda dengan LocalBroadcastManager untuk mendengarkan siaran dari aktivitas kedua Anda:

//notice the string sent to the intent filter, this is where you tell the BroadcastManager which broadcasts you want to listen to!
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter("broadcast identifier"));

CATATAN bahwa Anda dapat menggunakan konstanta atau sumber daya string untuk string "pengenal siaran".


sumber
Untuk keamanan yang lebih baik, gunakan efisiensi iklan di LocalBroadcastManagersini
Alexander Farber
0

Jika Anda menggunakan finish()hanya untuk menghindari aplikasi baru untuk dimulai dalam tumpukan (tugas) aplikasi Anda, Anda dapat menggunakan Intent.FLAG_ACTIVITY_NEW_TASKbendera, saat memulai aplikasi baru dan tidak memanggil finish()sama sekali. Menurut dokumentasi , ini adalah tanda yang akan digunakan untuk mengimplementasikan perilaku gaya "peluncur".

// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
sergej shafarenka
sumber
0

Gunakan metode ini di dalam file Activity.

isDestroyed()

Ditambahkan dalam Api 17
Mengembalikan nilai true jika panggilan onDestroy () terakhir telah dilakukan pada Aktivitas, jadi instance ini sekarang mati.

isFinishing()

Ditambahkan dalam Api 1
Periksa untuk melihat apakah aktivitas ini sedang dalam proses penyelesaian, baik karena Anda memanggil finish () di atasnya atau orang lain telah memintanya untuk diselesaikan. Ini sering digunakan di onPause () untuk menentukan apakah aktivitas hanya berhenti sebentar atau selesai sepenuhnya.


Dari Memory Leaks Documentation

Kesalahan umum dengan AsyncTaskadalah menangkap referensi yang kuat ke tuan rumah Activity(atau Fragment):

class MyActivity extends Activity {
  private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
    // Don't do this! Inner classes implicitly keep a pointer to their
    // parent, which in this case is the Activity!
  }
}

Ini menjadi masalah karena AsyncTaskdapat dengan mudah hidup lebih lama dari induknya Activity, misalnya jika terjadi perubahan konfigurasi saat tugas sedang berjalan.

Cara yang tepat untuk melakukannya adalah dengan membuat tugas Anda menjadi statickelas, yang tidak menangkap induknya, dan memegang referensi yang lemah ke host Activity:

class MyActivity extends Activity {
  static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<MyActivity> weakActivity;

    MyTask(MyActivity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      MyActivity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }
}
Sanket Berde
sumber
0

Berikut adalah solusi menggunakan Applicationkelas.

public class AppSingleton extends Application implements Application.ActivityLifecycleCallbacks {

private WeakReference<Context> foregroundActivity;


@Override
public void onActivityResumed(Activity activity) {
    foregroundActivity=new WeakReference<Context>(activity);
}

@Override
public void onActivityPaused(Activity activity) {
    String class_name_activity=activity.getClass().getCanonicalName();
    if (foregroundActivity != null && 
            foregroundActivity.get().getClass().getCanonicalName().equals(class_name_activity)) {
        foregroundActivity = null;
    }
}

//............................

public boolean isOnForeground(@NonNull Context activity_cntxt) {
    return isOnForeground(activity_cntxt.getClass().getCanonicalName());
}

public boolean isOnForeground(@NonNull String activity_canonical_name) {
    if (foregroundActivity != null && foregroundActivity.get() != null) {
        return foregroundActivity.get().getClass().getCanonicalName().equals(activity_canonical_name);
    }
    return false;
}
}

Anda cukup menggunakannya seperti berikut,

((AppSingleton)context.getApplicationContext()).isOnForeground(context_activity);

Jika Anda memiliki referensi ke Aktivitas yang diperlukan atau menggunakan nama kanonik Aktivitas, Anda bisa mencari tahu apakah itu ada di latar depan atau tidak. Solusi ini mungkin tidak selalu mudah. Oleh karena itu, komentar Anda sangat kami terima.

TMtech
sumber
0

Saya tidak tahu mengapa tidak ada yang berbicara tentang sharedPreferences, untuk Aktivitas A, menyetel SharedPreference seperti itu (misalnya di onPause ()):

SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();

Saya pikir ini adalah cara yang dapat diandalkan untuk melacak visibilitas aktivitas.

HZDI
sumber
0

Akan Activity.onWindowFocusChanged(boolean hasFocus)berguna di sini? Itu, ditambah bendera tingkat kelas, sesuatu seperti isFocuseditu onWindowFocusChangedset, akan menjadi cara mudah untuk mengatakan pada setiap titik dalam aktivitas Anda jika terfokus atau tidak. Dari membaca dokumen, sepertinya ini akan disetel dengan benar ke "false" dalam situasi apa pun di mana aktivitas tidak secara langsung berada di "latar depan" fisik, seperti jika dialog sedang ditampilkan atau baki notifikasi ditarik ke bawah.

Contoh:

boolean isFocused;
@Override
void onWindowFocusChanged (boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    isFocused = hasFocus;
}

void someMethod() {
    if (isFocused) {
        // The activity is the foremost object on the screen
    } else {
        // The activity is obscured or otherwise not visible
    }
}
InsanityOnABun
sumber
0

Jika Anda menggunakan EventBus , itu sebagai metode yang disebut hasSubscriberForEventyang dapat digunakan untuk memeriksa apakah sebuah Activityfokus.

Kris B
sumber
-3

Saya dulu suka,

jika aktivitas tidak di latar depan

getIntent ()

akan mengembalikan nol. : = P

Jacob Abraham
sumber