Bagaimana cara mendapatkan konteks aktivitas foreground saat ini di android?


171

Setiap kali siaran saya dieksekusi, saya ingin menunjukkan peringatan untuk aktivitas foreground.


dari tempat Anda ingin mendapatkan konteks Kegiatan. Apakah ini akan menjadi aktivitas aplikasi Anda atau aplikasi lain.
AAnkit

ini adalah aktivitas aplikasi. Saya telah melakukan coding dialog peringatan pada fungsi broadcastreceiver onreceive ().
Deepali

sebuah aktivitas aplikasi! apakah ini aplikasi kamu ?? dan mengapa Anda menginginkan ini, alasan apa pun, semoga ada alternatif yang sama
AAnkit

Saya ingin menampilkan lansiran pada aktivitas latar depan saya. Apakah ada cara lain untuk menunjukkan lansiran pada aktivitas latar depan tanpa konteks.
Deepali

1
di onreceive hanya u mendapatkan COntext sebagai param, Anda dapat mengatakan context.getApplicationContext ()
AAnkit

Jawaban:


39

Mengetahui bahwa ActivityManager mengelola Activity , sehingga kami dapat memperoleh informasi dari ActivityManager . Kami mendapatkan foreground running Activity saat ini oleh

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;

PEMBARUAN 2018/10/03
getRunningTasks () DIHAPUSKAN. lihat solusi di bawah ini.

Metode ini sudah tidak digunakan lagi di API level 21. Pada Build.VERSION_CODES.LOLLIPOP, metode ini tidak lagi tersedia untuk aplikasi pihak ketiga: pengenalan terbaru dokumen-sentris berarti dapat membocorkan informasi orang ke pemanggil. Untuk kompatibilitas mundur, masih akan mengembalikan sebagian kecil dari datanya: setidaknya tugas-tugas pemanggil sendiri, dan mungkin beberapa tugas lain seperti rumah yang diketahui tidak sensitif.


16
jangan berpikir begitu Martin, dari bantuan SDK getRunningTasks "Catatan: metode ini hanya dimaksudkan untuk debugging dan menyajikan antarmuka pengguna manajemen tugas. Ini seharusnya tidak pernah digunakan untuk logika inti dalam suatu aplikasi"
ruhalde

3
Rupanya ini hanya mendukung sebagian kecil dari menjalankan tugas di Android 5 / Lollipop.
Sam

7
Dokumentasi untuk ActivityManager.getRunningTasks () mengatakan "Metode ini sudah usang di API level 21".
markshep

210

( Catatan: API resmi ditambahkan di API 14: Lihat jawaban ini https://stackoverflow.com/a/29786451/119733 )

JANGAN GUNAKAN jawaban SEBELUMNYA (waqas716).

Anda akan memiliki masalah kebocoran memori, karena referensi statis untuk aktivitas tersebut. Untuk detail lebih lanjut lihat tautan berikut http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Untuk menghindari hal ini, Anda harus mengelola referensi kegiatan. Tambahkan nama aplikasi dalam file manifes:

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

Kelas aplikasi Anda:

  public class MyApp extends Application {
        public void onCreate() {
              super.onCreate();
        }

        private Activity mCurrentActivity = null;
        public Activity getCurrentActivity(){
              return mCurrentActivity;
        }
        public void setCurrentActivity(Activity mCurrentActivity){
              this.mCurrentActivity = mCurrentActivity;
        }
  }

Buat Aktivitas baru:

public class MyBaseActivity extends Activity {
    protected MyApp mMyApp;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMyApp = (MyApp)this.getApplicationContext();
    }
    protected void onResume() {
        super.onResume();
        mMyApp.setCurrentActivity(this);
    }
    protected void onPause() {
        clearReferences();
        super.onPause();
    }
    protected void onDestroy() {        
        clearReferences();
        super.onDestroy();
    }

    private void clearReferences(){
        Activity currActivity = mMyApp.getCurrentActivity();
        if (this.equals(currActivity))
            mMyApp.setCurrentActivity(null);
    }
}

Jadi, sekarang alih-alih memperluas kelas Aktivitas untuk aktivitas Anda, cukup rentangkan MyBaseActivity. Sekarang, Anda bisa mendapatkan aktivitas Anda saat ini dari aplikasi atau konteks Aktivitas seperti itu:

Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();

9
Anda bisa menggunakan WeakReference dan mencapai hasil yang sama dengan kode lebih sedikit.
Nacho Coloma

5
@Nacho Saya tidak akan pernah merekomendasikan untuk menggunakan WeakReferencesdi Android GC mengumpulkan mereka lebih cepat dari yang Anda pikirkan.
rekire

4
@ MaximKorobov Ya mungkin jika Anda memanggil finish () dari onCreate (), jika Anda menggunakan aktivitas Anda hanya untuk meluncurkan aktivitas lain dan menghentikan yang ini. Dalam skenario ini ia dilewati onPause () dan onStoo (). Lihat catatan bawah: developer.android.com/training/basics/activity-lifecycle/…
Rodrigo Leitão

2
@rekire @NachoColoma Penggunaan WeakReferencetidak disarankan untuk caching, ini bukan caching, yaitu mCurrentActivityhanya akan memiliki referensi untuk itu ketika masih hidup sehingga WeakReferencetidak akan pernah dikumpulkan saat Activityberada di atas. Namun apa yang @NachoColoma sarankan salah karena WeakReferencemasih dapat merujuk aktivitas yang tidak dilanjutkan (tidak hidup / tidak di atas) jika variabel tidak dihapus!
TWiStErRob

14
Mulai dari Android API level 14 seharusnya memungkinkan untuk digunakan Application .ActivityLifecycleCallbacks, yang akan lebih sentral dan Anda tidak perlu menambahkan kode manajemen dalam semua aktivitas Anda. Lihat juga developer.android.com/reference/android/app/…
Filou

68

Saya memperluas bagian atas jawaban @ gezdy.

Di setiap Kegiatan, alih-alih harus "mendaftar" sendiri dengan Applicationpengkodean manual, kita dapat menggunakan API berikut sejak level 14, untuk membantu kami mencapai tujuan yang sama dengan pengkodean manual yang lebih sedikit.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

Di Application.ActivityLifecycleCallbacks, Anda bisa mendapatkan yang Activity"terlampir" atau "terlepas" dari ini Application.

Namun, teknik ini hanya tersedia sejak API level 14.


1
Ada apa dengan semua jawaban lainnya? Jelas ini dirancang API untuk keperluan ini. Terima kasih, Cheok Yan Cheng
Michael Bushe

2
@MichaelBushe - pada tahun 2012, ketika jawaban lain ditulis, tergantung pada level API 14 bukanlah sesuatu yang bisa diandalkan di setiap perangkat, mengingat bahwa API baru saja dirilis (Oktober 2011).
ToolmakerSteve

4
Menemukan jawaban yang menunjukkan bagaimana menggunakan pendekatan ini: stackoverflow.com/a/11082332/199364 Manfaatnya adalah tidak ada yang perlu dilakukan untuk kegiatan itu sendiri ; kode semua dalam kelas panggilan balik kustom Anda. Anda cukup membuat kelas itu implements Application.ActivityLifecycleCallbacks, dan menambahkan metode untuk mengimplementasikannya. Kemudian di konstruktor kelas itu (atau onCreate atau init atau metode lain yang berjalan ketika instance menjadi aktif / siap), masukkan getApplication().registerActivityLifecycleCallbacks(this);sebagai baris terakhir.
ToolmakerSteve

Saya pikir jawaban Anda yang terbaik
burulangtu

2
jawaban yang bagus satu-satunya downside adalah Anda masih perlu menyimpan aktivitas di suatu tempat jika Anda perlu menanyakan kelas Anda untuk aktivitas saat ini. jadi Anda masih perlu menghindari kebocoran memori dan membatalkan referensi.
Raphael C

56

Pembaruan 2 : Ada api resmi yang ditambahkan untuk ini, silakan gunakan ActivityLifecycleCallbacks sebagai gantinya.

MEMPERBARUI:

Seperti yang ditunjukkan oleh @gezdy, dan saya bersyukur untuk itu. atur referensi ke nol juga untuk aktivitas saat ini, alih-alih memutakhirkan pada setiap onResume atur menjadi nol pada onDestroy setiap Aktivitas untuk menghindari masalah kebocoran memori.

Beberapa waktu yang lalu saya membutuhkan fungsi yang sama dan di sini adalah metode bagaimana saya mencapai ini. Dalam setiap aktivitas Anda, ganti metode-metode siklus hidup ini.

@Override
protected void onResume() {
    super.onResume();
    appConstantsObj.setCurrentActivity(this);

}

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

@Override
protected void onDestroy() {        
   clearReferences();
   super.onDestroy();
}

private void clearReferences(){
          Activity currActivity = appConstantsObj.getCurrentActivity();
          if (this.equals(currActivity))
                appConstantsObj.setCurrentActivity(null);
}

Sekarang di kelas siaran Anda, Anda dapat mengakses aktivitas saat ini untuk menunjukkan peringatan padanya.


3
Jawaban ini harus benar-benar mendapatkan lebih banyak suara, solusi sederhana, tetapi kuat ketika Anda memiliki kelas yang perlu memanipulasi kegiatan, tetapi bukan kegiatan itu sendiri.
ryvianstyron

Ini hanya tentang referensi statis dari objek aktivitas Anda. Anda dapat membuatnya di mana pun Anda mau :). Itu tidak masalah.
Waqas

Ini setara dengan jawaban Anda sebelumnya. Applicationhanya dibuat sekali dan tidak pernah sampah dikumpulkan persis seperti variabel statis.
zapl

1
Akan ada masalah dengan kegiatan hierarkis. Ketika Anda kembali dari aktivitas anak ke aktivitas orang tua: (1) disebut child onPause; (2) onResume orang tua; (3) onDestroy anak ==> aktivitas saat ini akan menjadi nol. Anda harus melakukan beberapa pemeriksaan seperti @gezdy dalam contohnya di metode clearReferences.
Seni

4
@ waqas716 Saya sarankan untuk menyederhanakan kondisi clearReferences()menjadi (this.equals(currActivity)).
naXa

51

@lockwobr Terima kasih telah memperbarui

Ini tidak bekerja 100% dari waktu di api versi 16, jika Anda membaca kode di github fungsi "currentActivityThread" diubah di Kitkat, jadi saya ingin mengatakan versi 19ish, agak sulit untuk mencocokkan versi api dengan rilis di github .

Memiliki akses ke arus Activitysangat berguna. Bukankah lebih baik memiliki getActivitymetode statis mengembalikan Kegiatan saat ini tanpa pertanyaan yang tidak perlu?

The Activitykelas sangat berguna. Ini memberi akses ke utas UI aplikasi, tampilan, sumber daya, dan banyak lagi. Banyak metode membutuhkan Context, tetapi bagaimana cara mendapatkan pointer? Berikut ini beberapa cara:

  • Melacak status aplikasi menggunakan metode siklus hidup yang ditimpa. Anda harus menyimpan Aktivitas saat ini dalam variabel statis dan Anda perlu akses ke kode semua Kegiatan.
  • Melacak status aplikasi menggunakan Instrumentasi. Deklarasikan Instrumentasi dalam manifes, implementasikan, dan gunakan metode-metodenya untuk melacak perubahan Kegiatan. Melewati penunjuk Aktivitas ke metode dan kelas yang digunakan dalam Aktivitas Anda. Menyuntikkan pointer menggunakan salah satu pustaka injeksi kode. Semua pendekatan ini agak tidak nyaman ; untungnya, ada cara yang jauh lebih mudah untuk mendapatkan Aktivitas saat ini.
  • Sepertinya sistem memerlukan akses ke semua Kegiatan tanpa masalah yang disebutkan di atas. Jadi, kemungkinan besar ada cara untuk mendapatkan Kegiatan hanya menggunakan panggilan statis. Saya menghabiskan banyak waktu menggali sumber-sumber Android di grepcode.com, dan saya menemukan apa yang saya cari. Ada kelas yang disebut ActivityThread. Kelas ini memiliki akses ke semua Kegiatan dan, apa yang lebih baik, memiliki metode statis untuk mendapatkan arus ActivityThread. Hanya ada satu masalah kecil - daftar Aktivitas memiliki akses paket.

Mudah dipecahkan menggunakan refleksi:

public static Activity getActivity() {
    Class activityThreadClass = Class.forName("android.app.ActivityThread");
    Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
    Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
    activitiesField.setAccessible(true);

    Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread);
    if (activities == null)
        return null;

    for (Object activityRecord : activities.values()) {
        Class activityRecordClass = activityRecord.getClass();
        Field pausedField = activityRecordClass.getDeclaredField("paused");
        pausedField.setAccessible(true);
        if (!pausedField.getBoolean(activityRecord)) {
            Field activityField = activityRecordClass.getDeclaredField("activity");
            activityField.setAccessible(true);
            Activity activity = (Activity) activityField.get(activityRecord);
            return activity;
        }
    }

    return null;
}

Metode seperti itu dapat digunakan di mana saja di aplikasi dan itu jauh lebih nyaman daripada semua pendekatan yang disebutkan. Selain itu, sepertinya itu tidak seaman kelihatannya. Itu tidak memperkenalkan potensi kebocoran baru atau null pointer.

Cuplikan kode di atas tidak memiliki penanganan pengecualian dan secara naif mengasumsikan bahwa Aktivitas berjalan pertama adalah yang kami cari. Anda mungkin ingin menambahkan beberapa cek tambahan.

Posting Blog


2
di Kitkat dan di atas mActivities bukan HashMap, tetapi ArrayMap, jadi Anda perlu mengubah baris ini: HashMap activities = (HashMap) activitiesField.get (activityThread); agar terlihat seperti ini: ArrayMap activities = (ArrayMap) activitiesField.get (activityThread);
Palejandro

7
@ Palejandro untuk mendukung kedua level api (di atas 18 dan di bawah) harus menggunakan Mapantarmuka HashMapatau ArrayMap. Saya sudah mengedit jawaban @AZ_.
Yuriy Kolbasinskiy

2
Ini tidak bekerja 100% dari waktu di api versi 16 , jika Anda membaca kode di github fungsi "currentActivityThread" diubah di Kitkat, jadi saya ingin mengatakan versi 19ish , agak sulit untuk mencocokkan versi api dengan rilis di github .
lockwobr

@lockwobr terima kasih, solusinya diperbarui dengan komentar Anda
:)

2
Mengakses API internal melalui refleksi tidak didukung dan mungkin tidak berfungsi di semua perangkat atau di masa mendatang.
Pei

9

Saya melakukan Mengikuti di Kotlin

  1. Buat Kelas Aplikasi
  2. Edit Kelas Aplikasi sebagai Berikut

    class FTApplication: MultiDexApplication() {
    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
    
    init {
        instance = this
    }
    
    val mFTActivityLifecycleCallbacks = FTActivityLifecycleCallbacks()
    
    override fun onCreate() {
        super.onCreate()
    
        registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
    }
    
    companion object {
        private var instance: FTApplication? = null
    
        fun currentActivity(): Activity? {
    
            return instance!!.mFTActivityLifecycleCallbacks.currentActivity
        }
    }
    
     }
  3. Buat kelas ActivityLifecycleCallbacks

    class FTActivityLifecycleCallbacks: Application.ActivityLifecycleCallbacks {
    
    var currentActivity: Activity? = null
    
    override fun onActivityPaused(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityResumed(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityStarted(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityDestroyed(activity: Activity?) {
    }
    
    override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
    }
    
    override fun onActivityStopped(activity: Activity?) {
    }
    
    override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
        currentActivity = activity
    }
    
    }
  4. Anda sekarang dapat menggunakannya di kelas apa pun dengan memanggil yang berikut: FTApplication.currentActivity()


5

getCurrentActivity () juga ada di ReactContextBaseJavaModule.
(Karena pertanyaan ini awalnya ditanyakan, banyak aplikasi Android juga memiliki komponen ReactNative - aplikasi hybrid.)

class ReactContext di ReactNative memiliki seluruh rangkaian logika untuk mempertahankan mCurrentActivity yang dikembalikan di getCurrentActivity ().

Catatan: Saya berharap getCurrentActivity () diimplementasikan di kelas Aplikasi Android.


dalam beberapa kasus konteks ini dari ReactContextBaseJavaModule adalah nol, tahukah Anda mengapa?
Moxor

4

Saya tidak dapat menemukan solusi yang akan membuat tim kami senang, jadi kami menggulung sendiri. Kami menggunakan ActivityLifecycleCallbacksuntuk melacak aktivitas saat ini dan kemudian mengeksposnya melalui layanan. Lebih detail di sini: https://stackoverflow.com/a/38650587/10793


2

Untuk kompatibilitas mundur:

ComponentName cn;
ActivityManager am = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
    cn = am.getAppTasks().get(0).getTaskInfo().topActivity;
} else {
    //noinspection deprecation
    cn = am.getRunningTasks(1).get(0).topActivity;
}

4
Kecuali jika ada cara untuk mendapatkan dari ComponentName ke instance Kegiatan saat ini, ini tidak menjawab pertanyaan IMO.
nasch

@Nash satu dapat menyimpan dan mendapatkan WeakReferencepegangan dari Applicationkelas - sementara ComponentNamediperlukan untuk menentukan apakah yang diinginkan Activityada di atas daftar tugas yang sedang berjalan. Dan jika ini tidak sepenuhnya menjawab pertanyaan, jawaban yang diterima juga tidak.
Martin Zeitler

Saya setuju, jawaban yang diterima juga tidak sepenuhnya menjawab pertanyaan.
nasch

1
topActivityhanya tersedia dari Android Q
Eugen Martynov

1

Secara pribadi saya melakukan apa yang dikatakan "Cheok Yan Cheng", tetapi saya menggunakan "Daftar" untuk memiliki "Backstack" dari semua kegiatan saya.

Jika Anda ingin memeriksa Yang merupakan Aktivitas Saat Ini, Anda hanya perlu mendapatkan kelas aktivitas terakhir dalam daftar.

Buat aplikasi yang memperluas "Aplikasi" dan lakukan ini:

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks,
EndSyncReceiver.IEndSyncCallback {

private List<Class> mActivitiesBackStack;
private EndSyncReceiver mReceiver;
    private Merlin mMerlin;
    private boolean isMerlinBound;
    private boolean isReceiverRegistered;

@Override
    public void onCreate() {
        super.onCreate();
        [....]
RealmHelper.initInstance();
        initMyMerlin();
        bindMerlin();
        initEndSyncReceiver();
        mActivitiesBackStack = new ArrayList<>();
    }

/* START Override ActivityLifecycleCallbacks Methods */
    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {
        mActivitiesBackStack.add(activity.getClass());
    }

    @Override
    public void onActivityStarted(Activity activity) {
        if(!isMerlinBound){
            bindMerlin();
        }
        if(!isReceiverRegistered){
            registerEndSyncReceiver();
        }
    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {
        if(!AppUtils.isAppOnForeground(this)){
            if(isMerlinBound) {
                unbindMerlin();
            }
            if(isReceiverRegistered){
                unregisterReceiver(mReceiver);
            }
            if(RealmHelper.getInstance() != null){
                RealmHelper.getInstance().close();
                RealmHelper.getInstance().logRealmInstanceCount("AppInBackground");
                RealmHelper.setMyInstance(null);
            }
        }
    }

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

    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        if(mActivitiesBackStack.contains(activity.getClass())){
            mActivitiesBackStack.remove(activity.getClass());
        }
    }
    /* END Override ActivityLifecycleCallbacks Methods */

/* START Override IEndSyncCallback Methods */
    @Override
    public void onEndSync(Intent intent) {
        Constants.SyncType syncType = null;
        if(intent.hasExtra(Constants.INTENT_DATA_SYNC_TYPE)){
            syncType = (Constants.SyncType) intent.getSerializableExtra(Constants.INTENT_DATA_SYNC_TYPE);
        }
        if(syncType != null){
            checkSyncType(syncType);
        }
    }
    /* END IEndSyncCallback Methods */

private void checkSyncType(Constants.SyncType){
    [...]
    if( mActivitiesBackStack.contains(ActivityClass.class) ){
         doOperation()     }
}

}

Dalam kasus saya, saya menggunakan "Application.ActivityLifecycleCallbacks" untuk:

  • Bind / Unbind Merlin Instance (digunakan untuk mendapatkan acara ketika aplikasi kehilangan atau mendapatkan koneksi, misalnya ketika Anda menutup data seluler atau ketika Anda membukanya). Ini berguna setelah tindakan niat "OnConnectivityChanged" dinonaktifkan. Untuk info lebih lanjut tentang MERLIN, lihat: Tautan INFO MERLIN

  • Tutup Instansi Realm saya yang terakhir ketika aplikasi ditutup; Saya akan memasukkannya ke dalam BaseActivity yang diperluas dari semua kegiatan lainnya dan yang memiliki Instance RealmHelper pribadi. Untuk info lebih lanjut tentang REALM, lihat: REALM INFO LINK Misalnya saya punya contoh "RealmHelper" statis di dalam kelas "RealmHelper" saya yang dipakai di dalam aplikasi saya "onCreate". Saya memiliki layanan sinkronisasi tempat saya membuat "RealmHelper" yang baru karena Realm "Linked-Linked" dan Realm Instance tidak dapat bekerja di dalam Thread yang berbeda. Jadi untuk mengikuti Dokumentasi Realm "Anda Harus Menutup Semua Instansi Realm Terbuka untuk menghindari Kebocoran Sumber Daya Sistem", untuk mencapai hal ini saya menggunakan "Application.ActivityLifecycleCallbacks" seperti yang dapat Anda lihat.

  • Akhirnya saya memiliki penerima yang dipicu ketika saya selesai menyinkronkan aplikasi saya, kemudian ketika sinkronisasi berakhir itu akan memanggil metode "IEndSyncCallback" "onEndSync" di mana saya melihat jika saya memiliki Kelas Aktivitas tertentu di dalam daftar ActivitiesBackStack saya karena saya perlu untuk memperbarui data pada tampilan jika sinkronisasi memperbaruinya dan saya perlu melakukan operasi orang lain setelah sinkronisasi aplikasi.

Itu saja, semoga ini membantu. Sampai jumpa :)


-1

Jawaban oleh waqas716 baik. Saya membuat solusi untuk kasus tertentu yang menuntut lebih sedikit kode dan pemeliharaan.

Saya menemukan pekerjaan khusus sekitar dengan memiliki metode statis mengambil pandangan dari aktivitas yang saya curigai berada di latar depan. Anda dapat mengulangi semua aktivitas dan memeriksa apakah Anda menginginkan atau mendapatkan nama aktivitas dari jawaban martin

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity; 

Saya kemudian memeriksa apakah tampilan tidak nol dan mendapatkan konteksnya melalui getContext ().

View v = SuspectedActivity.get_view();

if(v != null)
{
    // an example for using this context for something not 
    // permissible in global application context. 
    v.getContext().startActivity(new Intent("rubberduck.com.activities.SomeOtherActivity"));
}

Saya mencari masalah serupa di sini stackoverflow.com/questions/22788289/... bagaimana kita mendapatkan "SuspectedActivity"? Apakah ini API asli?
Stella

2
TETAPI dari dokumen untuk getRunningTasks: "Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, ..." di developer.android.com/reference/android/app/...
ToolmakerSteve

3
Dokumentasi untuk ActivityManager.getRunningTasks () sekarang mengatakan "Metode ini sudah usang di API level 21".
markshep

-2

Saya tidak suka jawaban yang lain. ActivityManager tidak dimaksudkan untuk digunakan untuk mendapatkan aktivitas saat ini. Super classing dan bergantung pada onDestroy juga rapuh dan bukan desain terbaik.

Jujur, yang terbaik yang saya hasilkan sejauh ini hanya mempertahankan enum di Aplikasi saya, yang akan ditetapkan ketika suatu aktivitas dibuat.

Rekomendasi lain mungkin untuk menghindari menggunakan beberapa kegiatan jika memungkinkan. Ini dapat dilakukan dengan menggunakan fragmen, atau dalam tampilan khusus preferensi saya.


1
enum? Bagaimana itu membantu menemukan instance aktivitas foreground saat ini?
ToolmakerSteve

"Kelas super dan tergantung padaDestroy juga rapuh" Bagaimana itu rapuh?
ToolmakerSteve

-3

Solusi yang agak sederhana adalah membuat kelas manajer tunggal, di mana Anda dapat menyimpan referensi ke satu atau lebih Kegiatan, atau apa pun yang Anda ingin akses ke seluruh aplikasi.

Panggilan UberManager.getInstance().setMainActivity( activity ); onCreate aktivitas utama.

Panggil UberManager.getInstance().getMainActivity();di mana saja di aplikasi Anda untuk mengambilnya. (Saya menggunakan ini untuk dapat menggunakan Toast dari utas non UI.)

Pastikan Anda menambahkan panggilan UberManager.getInstance().cleanup();saat aplikasi Anda dihancurkan.

import android.app.Activity;

public class UberManager
{
    private static UberManager instance = new UberManager();

    private Activity mainActivity = null;

    private UberManager()
    {

    }

    public static UberManager getInstance()
    {
        return instance;
    }

    public void setMainActivity( Activity mainActivity )
    {
        this.mainActivity = mainActivity;
    }

    public Activity getMainActivity()
    {
        return mainActivity;
    }

    public void cleanup()
    {
        mainActivity = null;
    }
}

Ini mengganggu dan membutuhkan perubahan dalam semua kegiatan. The jawaban dengan AZ_ jauh lebih baik seperti itu benar-benar lokal dan mandiri tanpa memerlukan perubahan lain dalam basis kode.
markshep

-7

Saya terlambat 3 tahun tetapi saya tetap akan menjawabnya kalau-kalau ada orang yang menemukan saya seperti ini.

Saya memecahkan ini dengan hanya menggunakan ini:

    if (getIntent().toString().contains("MainActivity")) {
        // Do stuff if the current activity is MainActivity
    }

Perhatikan bahwa "getIntent (). ToString ()" mencakup banyak teks lain seperti nama paket Anda dan filter maksud apa pun untuk aktivitas Anda. Secara teknis kami memeriksa maksud saat ini, bukan aktivitas, tetapi hasilnya sama. Cukup gunakan misalnya Log.d ("test", getIntent (). ToString ()); jika Anda ingin melihat semua teks. Solusi ini agak hacky tetapi jauh lebih bersih dalam kode Anda dan fungsinya sama.

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.