Android'de mevcut ön plan etkinliği bağlamı nasıl alınır?


171

Yayınım yürütüldüğünde ön plan etkinliğine karşı uyarı göstermek istiyorum.


Etkinlik bağlamını almak istediğiniz yerden. Bu ur uygulama etkinliği veya başka bir uygulama olacak mı.
AAnkit

bu bir uygulama etkinliğidir. Broadcastreceiver onreceive () işlevinde uyarı iletişim kutusu kodlaması yaptım.
Deepali

bir uygulama etkinliği! Bu senin app mı ?? ve bunu neden istiyorsun, herhangi bir sebeple, bunun için alternatif olabilir
AAnkit

Ön plan etkinliğimde uyarı göstermek istiyorum. Bağlamsız ön plan etkinliğine uyarı göstermek için başka bir yol var.
Deepali

1
onreceive içinde sadece u bir parametre olarak COntext olsun, context.getApplicationContext ()
AAnkit

Yanıtlar:


39

Bilerek ActivityManager yöneten Aktivite , bu yüzden bilgi kazanabilir ActivityManager . Şu anki ön planın çalıştığını görebiliyoruz

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

GÜNCELLEME 2018/10/03
getRunningTasks () DEPRECATED. aşağıdaki çözümlere bakın.

Bu yöntem API düzeyi 21'de kullanımdan kaldırılmıştır. Build.VERSION_CODES.LOLLIPOP'tan itibaren, bu yöntem artık üçüncü taraf uygulamaları tarafından kullanılamamaktadır: belge merkezli sonrakların girilmesi, kişi bilgilerini arayan kişiye sızdırabileceği anlamına gelir. Geriye dönük uyumluluk için, yine de verilerinin küçük bir alt kümesini döndürür: en azından arayanın kendi görevleri ve muhtemelen ev gibi hassas olmadığı bilinen diğer bazı görevler.


16
sanmıyorum Martin, SDK getRunningTasks yardım "Not: bu yöntem sadece görev yönetimi kullanıcı arabirimleri hata ayıklama ve sunmak için tasarlanmıştır. Bu asla bir uygulamada çekirdek mantık için kullanılmamalıdır"
ruhalde

3
Görünüşe göre bu, Android 5 / Lollipop'ta yalnızca sınırlı bir çalışan görev alt kümesini destekler.
Sam

7
ActivityManager.getRunningTasks () belgeleri "Bu yöntem API 21 düzeyinde kullanımdan kaldırıldı" diyor.
markshep

210

( Not: API 14'te resmi bir API eklendi: Bu yanıta bakın https://stackoverflow.com/a/29786451/119733 )

ÖNCEKİ (waqas716) yanıtı KULLANMAYIN.

Etkinliğe statik başvuru nedeniyle bellek sızıntısı sorunu yaşarsınız. Daha fazla ayrıntı için aşağıdaki bağlantıya bakın http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Bundan kaçınmak için aktivite referanslarını yönetmelisiniz. Manifest dosyasına uygulamanın adını ekleyin:

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

Uygulama sınıfınız:

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

Yeni bir Etkinlik oluşturun:

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

Bu nedenle, artık faaliyetleriniz için Activity sınıfını genişletmek yerine, MyBaseActivity'yi uzatın. Artık geçerli etkinliğinizi uygulama veya Etkinlik bağlamından şu şekilde alabilirsiniz:

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

9
Sadece WeakReference kullanabilir ve daha az kodla aynı sonucu elde edebilirsiniz.
Nacho Coloma

5
@Nacho asla WeakReferencesGC kullanmak düşündüğünüzden daha hızlı toplar Android kullanmak için tavsiye etmem .
Haziran'da rekor

4
@MaximKorobov Evet onCreate () öğesinden finish () öğesini çağırırsanız, etkinliğinizi yalnızca başka bir etkinlik başlatmak ve bunu durdurmak için kullanırsanız mümkündür. Bu senaryoda onPause () ve onStoo () 'u atlar. Alt nota bakın: developer.android.com/training/basics/activity-lifecycle/…
Rodrigo Leitão

2
Önbellekleme WeakReferenceiçin kullanılması önerilmez, bu önbellekleme değildir, bu mCurrentActivitysadece hayatta olduğunda ona bir referans olacaktır, böylece üstte WeakReferenceiken asla toplanmayacaktır Activity. Ancak @NachoColoma'nın önerdiği yanlıştır, çünkü WeakReferencedeğişken temizlenmezse yine de devam etmeyen (canlı değil / üstte değil) bir aktiviteye başvurabilir!
TWiStErRob

14
Android API seviye 14'ten başlayarak, Application .ActivityLifecycleCallbacksdaha merkezi olacak ve tüm etkinliklerinize herhangi bir yönetim kodu eklemek zorunda kalmayacaksınız. Ayrıca bkz. Developer.android.com/reference/android/app/…
Filou

68

@ Gezdy'nin cevabının en üstünde yer alıyorum.

Her Faaliyette, Applicationmanuel kodlama ile kendini "kayıt altına almak" yerine, daha az manuel kodlama ile benzer bir amaca ulaşmamıza yardımcı olmak için seviye 14'ten bu yana aşağıdaki API'yı kullanabiliriz.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

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

İçinde Application.ActivityLifecycleCallbacks, hangisinin buna Activity"bağlı" veya "ayrılmış" olduğunu elde edebilirsiniz Application.

Bununla birlikte, bu teknik yalnızca API seviye 14'ten beri mevcuttur.


1
Diğer tüm cevapların nesi var? Açıkçası bu amaç için tasarlanmış API. Teşekkür ederim, Cheok Yan Cheng
Michael Bushe

2
@MichaelBushe - 2012'de, diğer cevapların yazıldığı sırada, API seviye 14'e bağlı olarak, API'nın son zamanlarda piyasaya sürüldüğü göz önüne alındığında, her cihazda güvenilecek bir şey değildi (Ekim 2011).
ToolmakerSteve

4
Bu yaklaşımın nasıl kullanılacağını gösteren bir cevap bulundu: stackoverflow.com/a/11082332/199364 Bunun yararı, faaliyetlerin kendileri için hiçbir şey yapılmasına gerek olmamasıdır ; kodun tamamı özel geri arama sınıfınızdadır. Sadece bir sınıf yapın implements Application.ActivityLifecycleCallbacksve bunu uygulamak için yöntemler ekleyin. Daha sonra bu sınıfın yapıcısı (veya örnek etkin / hazır olduğunda çalışan onCreate veya init veya başka bir yöntem) getApplication().registerActivityLifecycleCallbacks(this);son satır olarak koyulur .
ToolmakerSteve

Cevabınızın en iyisi olduğunu düşünüyorum
burulangtu

2
mükemmel cevap. tek dezavantajı, sınıfınızı geçerli etkinlik için sorgulamanız gerekirse, etkinliği bir yere kaydetmeniz gerekir. bu yüzden bellek sızıntısından kaçınmanız ve referansı sıfırlamanız gerekir.
Raphael C

56

Güncelleme 2 : Bunun için resmi bir API eklendi, lütfen bunun yerine ActivityLifecycleCallbacks kullanın.

GÜNCELLEME:

@Gezdy'nin işaret ettiği gibi, bunun için minnettarım. referansı null değerine de ayarlasadece her onResume cihazında güncelleme yapmak yerine mevcut etkinlik için de null değerine ayarlayın bellek sızıntısı sorununu önlemek için her Aktivitenin onDestroy öğesinde null değerine ayarlayın.

Bir süre önce aynı işlevselliğe ihtiyacım vardı ve işte bunu nasıl başardığım yöntemi. Her etkinliğinizde bu yaşam döngüsü yöntemlerini geçersiz kılar.

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

Artık yayın sınıfınızda, üzerinde etkinlik göstermek için geçerli etkinliğe erişebilirsiniz.


3
Bu cevap gerçekten daha fazla oy, basit bir çözüm almalı, ancak faaliyetleri manipüle etmesi gereken, ancak aktivitelerin kendileri olmayan sınıflarınız olduğunda güçlü olmalıdır.
ryvianstyron

Etkinlik nesnenizin statik bir referansı ile ilgilidir. İstediğiniz yerde oluşturabilirsiniz :). Önemli değil.
Waqas

Bu, önceki cevabınıza eşdeğerdir. Applicationyalnızca bir kez oluşturulur ve hiçbir zaman tam olarak statik bir değişken gibi toplanmaz.
zapl

1
Hiyerarşik etkinliklerle ilgili sorunlar olacaktır. Bir alt etkinlikten üst etkinliğe geri döndüğünüzde: (1) çocuğa onPause denir; (2) ebeveynin onResume'u; (3) çocuğun onDestroy ==> geçerli etkinliği boş olacaktır. ClearReferences yöntemindeki örneğinde @gezdy gibi bir kontrol yapmalısınız.
Sanat

4
@ waqas716 ı durumunu basitleştirmek için öneririm clearReferences()için (this.equals(currActivity)).
naXa

51

@lockwobr Güncelleme için teşekkürler

Github'daki kodu okursanız, api sürüm 16'daki zamanın% 100'ü çalışmaz, "currentActivityThread" fonksiyonu Kitkat'te değişti, bu yüzden 19ish sürümünü söylemek istiyorum, api sürümünü github'daki sürümlerle eşleştirmek biraz zor .

Akıma erişime sahip olmak Activityçok kullanışlıdır. Statik olması güzel olmaz mıydıgetActivityMevcut Etkinliği gereksiz bir soruyla döndüren yöntemin ?

ActivitySınıf çok yararlıdır. Uygulamanın kullanıcı arayüzü iş parçacığına, görünümlerine, kaynaklarına ve çok daha fazlasına erişim sağlar. Birçok yöntem a gerektirir Context, ancak işaretçiyi nasıl edinebilirim? İşte bazı yollar:

  • Geçersiz kılınmış yaşam döngüsü yöntemlerini kullanarak uygulamanın durumunu izleme. Geçerli Etkinliği statik bir değişkende depolamanız ve tüm Etkinliklerin kodlarına erişmeniz gerekir.
  • Enstrümantasyon kullanarak uygulamanın durumunu izleme. Manifest'te Enstrümantasyon ilan edin, uygulayın ve Etkinlik değişikliklerini izlemek için yöntemlerini kullanın. Etkinliklerinizde kullanılan yöntemlere ve sınıflara Etkinlik işaretçisi geçirme. Kod enjeksiyon kitaplıklarından birini kullanarak işaretçiyi enjekte etmek. Tüm bu yaklaşımlar oldukça elverişsizdir ; Neyse ki, mevcut Etkinliği almanın çok daha kolay bir yolu var.
  • Sistemin yukarıda belirtilen sorunlar olmadan tüm Etkinliklere erişmesi gerekiyor gibi görünüyor. Bu nedenle, büyük olasılıkla Etkinlikler'i yalnızca statik çağrılar kullanarak almanın bir yolu vardır. Grepcode.com'daki Android kaynaklarını araştırmak için çok zaman harcadım ve aradığım şeyi buldum. Adında bir sınıf var ActivityThread. Bu sınıfın tüm Etkinliklere erişimi vardır ve daha da iyisi, akımı elde etmek için statik bir yöntemi vardır ActivityThread. Yalnızca küçük bir sorun var - Etkinlik listesinde paket erişimi var.

Yansıma kullanarak çözmek kolay:

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

Böyle bir yöntem uygulamanın herhangi bir yerinde kullanılabilir ve bahsedilen tüm yaklaşımlardan çok daha uygundur. Dahası, göründüğü kadar güvenli değil gibi görünüyor. Herhangi bir yeni potansiyel sızıntı veya boş gösterici getirmez.

Yukarıdaki kod snippet'inde istisna yönetimi yoktur ve ilk çalışan Etkinliğin aradığımız faaliyet olduğunu saf bir şekilde varsayar. Bazı ek denetimler eklemek isteyebilirsiniz.

Blog yazısı


2
Kitkat ve üstü mActivities içinde HashMap değil, ArrayMap olduğundan, bu satırı değiştirmeniz gerekir: HashMap activities = (HashMap) activitiesField.get (activityThread); şöyle görünmek için: ArrayMap activities = (ArrayMap) activitiesField.get (activityThread);
Palejandro

7
@Palejandro her iki api seviyesini desteklemek için (18 ve altı) veya Mapbunun yerine arayüz kullanmalıdır . @AZ_ yanıtı düzenledim. HashMapArrayMap
Yuriy Kolbasinskiy

2
Github'daki kodu okursanız, api sürüm 16'daki zamanın% 100'ü çalışmaz , "currentActivityThread" fonksiyonu Kitkat'te değişti, bu yüzden 19ish sürümünü söylemek istiyorum , api sürümünü github'daki sürümlerle eşleştirmek biraz zor .
lockwobr

@lockwobr teşekkürler, çözüm sizinle güncellenmiştir yorum
:)

2
Dahili API'lere yansıtma yoluyla erişilmesi desteklenmez ve tüm cihazlarda veya gelecekte çalışmayabilir.
Pei

9

Kotlin'de aşağıdakileri yaptım

  1. Uygulama Sınıfı Oluştur
  2. Uygulama Sınıfını Aşağıdaki gibi Düzenleyin

    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. ActivityLifecycleCallbacks sınıfını oluşturma

    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. artık aşağıdakileri arayarak herhangi bir sınıfta kullanabilirsiniz: FTApplication.currentActivity()


5

getCurrentActivity (), ReactContextBaseJavaModule öğesinde de bulunur.
(Bu soru başlangıçta sorulduğundan, birçok Android uygulamasının da ReactNative bileşeni - hibrit uygulaması vardır.)

ReactNative içindeki class ReactContext, getCurrentActivity () içinde döndürülen mCurrentActivity'yi korumak için tüm mantık kümesine sahiptir.

Not: Keşke getCurrentActivity () Android Uygulama sınıfında uygulanır.


bazı durumlarda ReactContextBaseJavaModule'den gelen bu bağlam null, neden biliyor musunuz?
Moxor

4

Ekibimizin mutlu olacağı bir çözüm bulamadık, bu yüzden kendi ekibimizi yuvarladık. Biz kullanmak ActivityLifecycleCallbacksmevcut etkinlik izlemek ve daha sonra bir hizmet aracılığıyla mazur bırakmayın. Daha fazla ayrıntı burada: https://stackoverflow.com/a/38650587/10793


2

Geriye dönük uyumluluk için:

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
BileşenAdı'ndan Etkinliğin geçerli örneğine ulaşmanın bir yolu yoksa, bu IMO sorusunu yanıtlamaz.
nasır

@nasch WeakReferencebir Applicationsınıf tutabilir ve bir tanıtıcı elde edebilirsiniz - ComponentNameistenen Activityise çalışan görevler listesinin üstünde olup olmadığını belirlemek için gereklidir . Ve eğer bu soruya tam olarak cevap vermezse, kabul edilen cevap da cevap vermez.
Martin Zeitler

Kabul ediyorum, kabul edilen cevap da soruyu tam olarak cevaplamıyor.
Nasch

1
topActivitysadece Android Q'dan kullanılabilir
Eugen Martynov

1

Şahsen "Cheok Yan Cheng" dediği gibi yaptım, ama tüm faaliyetlerimin bir "Backstack" için bir "Liste" kullandım.

Geçerli Etkinliğin Hangisi olduğunu kontrol etmek istiyorsanız, listedeki son etkinlik sınıfını almanız yeterlidir.

"Uygulama" yı genişleten bir uygulama oluşturun ve bunu yapın:

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()     }
}

}

Benim durumumda "Application.ActivityLifecycleCallbacks" kullandım:

  • Bağlama / Açma Merlin Örneği (uygulama mobil bağlantıyı kapattığınızda veya açtığınızda uygulama kaybedildiğinde veya bağlantı kurulduğunda olay almak için kullanılır). "OnConnectivityChanged" niyet eylemi devre dışı bırakıldıktan sonra yararlıdır. MERLIN hakkında daha fazla bilgi için bkz: MERLIN INFO LINK

  • Uygulama kapandığında son Bölge örneğimi kapat; Diğer tüm etkinliklerden genişletilmiş ve özel bir RealmHelper Eşgörünümüne sahip olan bir BaseActivity içinde başlatacağım. REALM hakkında daha fazla bilgi için bakınız: REALM INFO LINK Örneğin, "onCreate" uygulamamın içinde başlatılan "RealmHelper" sınıfımın içinde statik bir "RealmHelper" örneğim var. Ben yeni "RealmHelper" oluşturduğum bir senkronizasyon hizmetim var, çünkü Realm "Thread-Linked" ve bir Realm Örneği farklı bir Thread içinde çalışamıyor. Bu yüzden "Sistem Kaynakları Sızıntılarını önlemek için Tüm Açılmış Bölge Örneklerini Kapatmanız Gerekiyor" Bölgesel Belgeleri takip etmek için, bu şeyi gerçekleştirmek için gördüğünüz gibi "Application.ActivityLifecycleCallbacks" kullandım.

  • Sonunda benim uygulama senkronize etmek için bitirdiğinde tetiklenen bir alıcı var, sonra senkronizasyon sona erdiğim zaman "IEndSyncCallback" "onEndSync" yöntemini arayacağım, çünkü benim ActivitiesBackStack Listemde belirli bir Aktivite Sınıfı varsa bakacağım senkronizasyon güncellendiyse görünümdeki verileri güncellemek için ve uygulama senkronizasyonundan sonra başka işlemler yapmam gerekebilir.

Hepsi bu, umarım bu yardımcı olur. Görüşürüz :)


-1

Waqas716'nın cevabı iyidir. Daha az kod ve bakım gerektiren belirli bir durum için bir geçici çözüm oluşturdum.

Statik bir yöntem ön planda olduğundan şüphelendiğim bir etkinlik bir görünüm getirerek etrafında özel bir çalışma buldum. Tüm aktiviteleri tekrarlayabilir ve martin cevabından aktivite adını isteyip istemediğinizi kontrol edebilirsiniz.

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

Sonra görünüm null olmadığını kontrol edin ve getContext () üzerinden bağlam olsun.

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"));
}

Burada benzer bir sorun arıyorum stackoverflow.com/questions/22788289/… "SuspectedActivity" nasıl edinebiliriz? Bu yerel API mı?
Stella

2
ANCAK için dokümanlar 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, ..." ama geliştirici.android.com
reference/

3
ActivityManager.getRunningTasks () belgeleri artık "Bu yöntem API 21 düzeyinde kaldırıldı" diyor.
markshep

-2

Diğer cevaplardan hiç hoşlanmıyorum. ActivityManager'ın mevcut etkinliği almak için kullanılması amaçlanmamıştır. Süper sınıflandırma ve onDestroy'a bağlı olarak en iyi tasarım değil kırılgandır.

Dürüst olmak gerekirse, şimdiye kadar bulduğum en iyi şey, Uygulamamda bir etkinlik oluşturulduğunda ayarlanan bir numaralandırmayı korumaktır.

Başka bir öneri, mümkünse birden fazla etkinlik kullanmaktan kaçınmak olabilir. Bu, parçaların kullanılmasıyla veya tercih edilen özel görünümlerimde yapılabilir.


1
bir numaralandırma? Bu, geçerli ön plan etkinliği örneğinin bulunmasına nasıl yardımcı olur?
ToolmakerSteve

"Süper sınıflandırma ve onDestroy'a bağlı olarak da kırılgan" Nasıl kırılgan?
ToolmakerSteve

-3

Oldukça basit bir çözüm, bir veya daha fazla Faaliyete veya uygulama boyunca erişmek istediğiniz herhangi bir şeye referans depolayabileceğiniz tekli bir yönetici sınıfı oluşturmaktır.

Aramak UberManager.getInstance().setMainActivity( activity );Ana etkinliğin onCreate'sini .

Aramak UberManager.getInstance().getMainActivity(); için uygulamanızın herhangi bir yerini . (UI olmayan bir iş parçacığından Tost kullanabilmek için bunu kullanıyorum.)

UberManager.getInstance().cleanup();Uygulamanız yok edilirken bir arama eklediğinizden emin olun .

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

Bu müdahaleci ve tüm faaliyetlerde değişiklik gerektirir. AZ_ tarafından cevap kod temeli diğer değişiklik gerektirmeden çok tamamen yerelleştirilmiş oluyor olarak daha iyi ve bağımsız olduğunu.
markshep

-7

3 yıl geç kaldım ama birisinin bunu benim yaptığım gibi bulması durumunda yine de cevaplayacağım.

Bunu sadece bunu kullanarak çözdüm:

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

"GetIntent (). ToString ()" öğesinin paket adınız ve etkinliğiniz için herhangi bir niyet filtresi gibi bir grup metni içerdiğini unutmayın. Teknik olarak şu andaki amacı kontrol ediyoruz, faaliyeti değil, sonuç aynı. Sadece Log.d ("test", getIntent (). ToString ()); tüm metni görmek istiyorsanız. Bu çözüm biraz hileli ama kodunuzda çok daha temiz ve işlevsellik aynı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.