Làm thế nào để có được bối cảnh hoạt động tiền cảnh hiện tại trong Android?


171

Bất cứ khi nào chương trình phát của tôi được thực hiện, tôi muốn hiển thị cảnh báo cho hoạt động tiền cảnh.


từ nơi bạn muốn lấy bối cảnh Hoạt động. Đây có phải là hoạt động ứng dụng của bạn hoặc ứng dụng khác.
AAnkit

đây là một hoạt động ứng dụng. Tôi đã thực hiện mã hóa hộp thoại cảnh báo trên hàm Broadcastreceiver ().
Deepali

một hoạt động ứng dụng! đây có phải là ứng dụng của bạn không ?? và tại sao bạn muốn điều này, vì bất kỳ lý do gì, có thể có sự thay thế cho điều tương tự
AAnkit

Tôi muốn hiển thị cảnh báo về hoạt động tiền cảnh của mình. Đây là cách khác để hiển thị cảnh báo cho hoạt động tiền cảnh mà không có ngữ cảnh.
Deepali

1
trong onreceive chỉ bạn nhận COntext làm thông số, bạn có thể nói
bối cảnh.getApplicationContext

Câu trả lời:


39

Biết rằng ActivityManager quản lý Activity , vì vậy chúng tôi có thể lấy thông tin từ ActivityManager . Chúng tôi nhận được hoạt động chạy nền trước hiện tại bằng cách

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

CẬP NHẬT 2018/10/03 getRastyT
Nhiệm vụ () bị ĐỔI . xem các giải pháp dưới đây.

Phương pháp này không được chấp nhận ở cấp độ API 21. Kể từ Build.VERSION_CODES.LOLLIPOP, phương pháp này không còn khả dụng cho các ứng dụng của bên thứ ba: việc giới thiệu các khoảng cách trung tâm tài liệu có nghĩa là nó có thể rò rỉ thông tin cá nhân cho người gọi. Để tương thích ngược, nó vẫn sẽ trả về một tập hợp con dữ liệu nhỏ: ít nhất là các tác vụ riêng của người gọi và có thể một số tác vụ khác như nhà được biết là không nhạy cảm.


16
đừng nghĩ vậy Martin, từ trợ giúp SDK của getRastyT Nhiệm vụ "Lưu ý: phương pháp này chỉ dành cho gỡ lỗi và trình bày giao diện người dùng quản lý tác vụ. Không bao giờ nên sử dụng logic này trong ứng dụng"
ruhalde

3
Rõ ràng điều này chỉ hỗ trợ một tập hợp con hạn chế của các tác vụ đang chạy trong Android 5 / Lollipop.
Sam

7
Tài liệu dành cho ActivityManager.getRastyT task () cho biết "Phương pháp này không được dùng trong API cấp 21".
markshep

210

( Lưu ý: Một API chính thức đã được thêm vào API 14: Xem câu trả lời này https://stackoverflow.com/a/29786451/119733 )

KHÔNG SỬ DỤNG câu trả lời PREVIOUS (waqas716).

Bạn sẽ gặp vấn đề rò rỉ bộ nhớ, vì tham chiếu tĩnh cho hoạt động. Để biết thêm chi tiết, hãy xem liên kết sau http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Để tránh điều này, bạn nên quản lý các hoạt động tham khảo. Thêm tên của ứng dụng trong tệp kê khai:

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

Lớp ứng dụng của bạn:

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

Tạo một hoạt động mới:

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

Vì vậy, bây giờ thay vì mở rộng lớp Activity cho các hoạt động của bạn, chỉ cần mở rộng MyBaseActivity. Bây giờ, bạn có thể nhận hoạt động hiện tại của mình từ ứng dụng hoặc bối cảnh Hoạt động như thế:

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

9
Bạn chỉ có thể sử dụng WeakReference và đạt được kết quả tương tự với ít mã hơn.
Nacho Coloma

5
@Nacho Tôi sẽ không bao giờ khuyến khích sử dụng WeakReferencestrong Android, GC thu thập chúng nhanh hơn bạn nghĩ.
thiệu

4
@MaximKorobov Có thể nếu bạn gọi finish () từ onCreate (), nếu bạn sử dụng hoạt động của mình chỉ để khởi chạy một hoạt động khác và dừng hoạt động này. Trong kịch bản này, nó bỏ qua onPause () và onStoo (). Xem ghi chú dưới cùng của: developer.android.com/training/basics/activity-lifecycle/iêu
Rodrigo Leitão

2
@rekire @NachoColoma Sử dụng WeakReferencekhông được khuyên dùng cho bộ nhớ đệm, đây không phải là bộ nhớ đệm, đó là ý mCurrentActivitychí chỉ có một tham chiếu đến nó khi nó còn tồn tại nên WeakReferencesẽ không bao giờ được thu thập trong khi ở Activitytrên cùng. Tuy nhiên, những gì @NachoColoma đề xuất là sai vì WeakReferencevẫn có thể tham chiếu một hoạt động không được nối lại (không còn sống / không ở trên cùng) nếu biến không bị xóa!
TWiStErRob

14
Bắt đầu từ API Android cấp 14, có thể sử dụng Application .ActivityLifecycleCallbacks, điều này sẽ tập trung hơn và bạn sẽ không phải thêm bất kỳ mã quản lý nào trong tất cả các hoạt động của mình. Đồng thời xem developer.android.com/reference/android/app/
Lần

68

Tôi mở rộng trên đầu câu trả lời của @ gezdy.

Trong mọi Hoạt động, thay vì phải "đăng ký" với Applicationmã hóa thủ công, chúng tôi có thể sử dụng API sau kể từ cấp 14, để giúp chúng tôi đạt được mục đích tương tự với ít mã hóa thủ công hơn.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

http://developer.android.com/reference/android/app/Application.html#registerActivityLifecyclCallbacks%28android.app.Application.ActivityLifecyclCallbacks%29

Trong Application.ActivityLifecycleCallbacks, bạn có thể nhận Activityđược "đính kèm" hoặc "tách rời" này Application.

Tuy nhiên, kỹ thuật này chỉ khả dụng kể từ API cấp 14.


1
Có chuyện gì với tất cả các câu trả lời khác? Rõ ràng đây là API được thiết kế cho mục đích này. Cảm ơn bạn, Cheok Yan Cheng
Michael Bushe

2
@MichaelBushe - vào năm 2012, khi các câu trả lời khác được viết, tùy thuộc vào API cấp 14 không phải là thứ gì đó để dựa vào mọi thiết bị, với điều kiện là API chỉ mới được phát hành gần đây (tháng 10 năm 2011).
ToolmakerSteve

4
Tìm thấy câu trả lời cho thấy cách sử dụng phương pháp này: stackoverflow.com/a/11082332/199364 Lợi ích là không cần phải làm gì cho chính các hoạt động ; mã là tất cả trong lớp gọi lại tùy chỉnh của bạn. Bạn chỉ cần tạo một lớp đó implements Application.ActivityLifecycleCallbacksvà thêm các phương thức để thực hiện điều đó. Sau đó, trong hàm tạo của lớp đó (hoặc onCreate hoặc init hoặc phương thức khác chạy khi cá thể đang hoạt động / sẵn sàng), đặt getApplication().registerActivityLifecycleCallbacks(this);làm dòng cuối cùng.
ToolmakerSteve

Tôi nghĩ câu trả lời của bạn là tốt nhất
burulangtu

2
câu trả lời chính xác. Nhược điểm duy nhất là bạn vẫn cần lưu hoạt động ở một nơi nào đó nếu bạn cần truy vấn lớp của mình cho hoạt động hiện tại. Vì vậy, bạn vẫn cần tránh rò rỉ bộ nhớ và null tham chiếu.
Raphael C

56

Cập nhật 2 : Có một api chính thức được thêm vào cho điều này, vui lòng sử dụng ActivityLifecycleCallbacks thay thế.

CẬP NHẬT:

Như được chỉ ra bởi @gezdy, và tôi rất biết ơn về điều đó. cũng đặt tham chiếu thành null cho hoạt động hiện tại, thay vì chỉ cập nhật trên mỗi onResume đặt thành null trên mọi onDestroy của Activity để tránh sự cố rò rỉ bộ nhớ.

Trước đây tôi cần chức năng tương tự và đây là phương pháp tôi đạt được điều này. Trong mọi hoạt động của bạn ghi đè lên các phương pháp vòng đời.

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

Bây giờ trong lớp phát sóng của bạn, bạn có thể truy cập hoạt động hiện tại để hiển thị cảnh báo về nó.


3
Câu trả lời này thực sự sẽ nhận được nhiều phiếu bầu hơn, giải pháp đơn giản, nhưng mạnh mẽ khi bạn có các lớp cần thao túng các hoạt động, nhưng bản thân chúng không hoạt động.
ryvianstyron

Đó chỉ là một tài liệu tham khảo tĩnh về đối tượng hoạt động của bạn. Bạn có thể tạo nó bất cứ nơi nào bạn muốn :). Nó không thành vấn đề.
Waqas

Đây là btw tương đương với câu trả lời trước đó của bạn. Applicationchỉ được tạo một lần và không bao giờ rác được thu thập chính xác như một biến tĩnh.
zapl

1
Sẽ có vấn đề với các hoạt động phân cấp. Khi bạn trở về từ một hoạt động con cho cha mẹ: (1) được gọi là onPause của con; (2) onResume của cha mẹ; (3) onDestroy của trẻ ==> hoạt động hiện tại sẽ không có giá trị. Bạn nên thực hiện một số kiểm tra như @gezdy trong ví dụ của anh ấy trong phương thức clearReferences.
Nghệ thuật

4
@ waqas716 tôi muốn đề nghị để đơn giản hóa điều kiện trong clearReferences()để (this.equals(currActivity)).
naXa

51

@lockwobr Cảm ơn đã cập nhật

Điều này không hoạt động 100% thời gian trong phiên bản api 16, nếu bạn đọc mã trên github, chức năng "currentActivityThread" đã thay đổi trong Kitkat, vì vậy tôi muốn nói phiên bản 19ish, loại phiên bản api khó khớp với phiên bản api .

Có quyền truy cập vào hiện tại Activitylà rất tiện dụng. Sẽ không tốt nếu có một getActivityphương thức tĩnh trả về Hoạt động hiện tại mà không có câu hỏi không cần thiết?

Các Activitylớp học là rất hữu ích. Nó cho phép truy cập vào luồng UI, khung nhìn, tài nguyên và nhiều thứ khác. Vô số phương thức yêu cầu a Context, nhưng làm thế nào để có được con trỏ? Đây là một số cách:

  • Theo dõi trạng thái của ứng dụng bằng các phương pháp vòng đời bị ghi đè. Bạn phải lưu trữ Hoạt động hiện tại trong một biến tĩnh và bạn cần truy cập vào mã của tất cả các Hoạt động.
  • Theo dõi trạng thái của ứng dụng bằng Thiết bị. Khai báo Thiết bị trong tệp kê khai, triển khai và sử dụng các phương thức của nó để theo dõi các thay đổi Hoạt động. Truyền con trỏ Activity cho các phương thức và lớp được sử dụng trong Hoạt động của bạn. Tiêm con trỏ bằng một trong các thư viện tiêm mã. Tất cả các cách tiếp cận này khá bất tiện ; may mắn thay, có một cách dễ dàng hơn nhiều để có được Hoạt động hiện tại.
  • Có vẻ như hệ thống cần truy cập vào tất cả các Hoạt động mà không có vấn đề nêu trên. Vì vậy, rất có thể có một cách để có được Hoạt động chỉ bằng các cuộc gọi tĩnh. Tôi đã dành rất nhiều thời gian để tìm hiểu các nguồn Android trên grepcode.com và tôi đã tìm thấy những gì tôi đang tìm kiếm. Có một lớp gọi là ActivityThread. Lớp này có quyền truy cập vào tất cả các Hoạt động và, thậm chí còn tốt hơn, có một phương thức tĩnh để có được hiện tại ActivityThread. Chỉ có một vấn đề nhỏ - danh sách Hoạt động có quyền truy cập gói.

Dễ dàng giải quyết bằng phản xạ:

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

Một phương pháp như vậy có thể được sử dụng ở bất cứ đâu trong ứng dụng và nó thuận tiện hơn nhiều so với tất cả các phương pháp được đề cập. Hơn nữa, có vẻ như nó không an toàn như vẻ ngoài của nó. Nó không giới thiệu bất kỳ rò rỉ tiềm năng mới hoặc con trỏ null.

Đoạn mã trên thiếu xử lý ngoại lệ và giả định một cách ngây thơ rằng Hoạt động đầu tiên đang chạy là hoạt động chúng tôi đang tìm kiếm. Bạn có thể muốn thêm một số kiểm tra bổ sung.

Bài viết trên blog


2
trong Kitkat và trên mActivities không phải là HashMap, mà là ArrayMap, vì vậy bạn cần thay đổi dòng này: HashMap HOẠT ĐỘNG = (HashMap) ActivityField.get (ActivityThread); để trông như thế này: ArrayMap Activity = (ArrayMap) activField.get (ActivityThread);
Palejandro

7
@Palejandro để hỗ trợ cả hai cấp độ api (trên 18 trở xuống) nên sử dụng Mapgiao diện thay thế HashMaphoặc ArrayMap. Tôi đã chỉnh sửa câu trả lời @AZ_.
Yuriy Kolbasinskiy

2
Điều này không hoạt động 100% thời gian trong phiên bản api 16 , nếu bạn đọc mã trên github, chức năng "currentActivityThread" đã thay đổi trong Kitkat, vì vậy tôi muốn nói phiên bản 19ish , loại phiên bản api khó khớp với phiên bản api .
lockwobr

@lockwobr cảm ơn, giải pháp được cập nhật với bạn bình luận :)
AZ_

2
Truy cập API nội bộ thông qua phản ánh không được hỗ trợ và có thể không hoạt động trên tất cả các thiết bị hoặc trong tương lai.
Pei

9

Tôi đã làm như sau trong Kotlin

  1. Tạo lớp ứng dụng
  2. Chỉnh sửa lớp ứng dụng như sau

    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. Tạo lớp ActivityLifecyclCallbacks

    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. bây giờ bạn có thể sử dụng nó trong bất kỳ lớp nào bằng cách gọi như sau: FTApplication.currentActivity()


5

getCienActivity () cũng có trong ReactContextBaseJavaModule.
(Vì câu hỏi này ban đầu được hỏi, nhiều ứng dụng Android cũng có thành phần ReactNative - ứng dụng lai.)

lớp ReactContext trong ReactNative có toàn bộ logic để duy trì mCienActivity được trả về trong getCienActivity ().

Lưu ý: Tôi muốn getCienActivity () được triển khai trong lớp Ứng dụng Android.


trong một số trường hợp bối cảnh này từ ReactContextBaseJavaModule là null, bạn có biết tại sao không?
Moxor

4

Tôi không thể tìm ra giải pháp mà nhóm chúng tôi sẽ hài lòng vì vậy chúng tôi tự lăn lộn. Chúng tôi sử dụng ActivityLifecycleCallbacksđể theo dõi hoạt động hiện tại và sau đó phơi bày thông qua một dịch vụ. Thêm chi tiết tại đây: https://stackoverflow.com/a/38650587/10793


2

Để tương thích ngược:

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
Trừ khi có cách để chuyển từ ElementName sang phiên bản hiện tại của Hoạt động, điều này không trả lời câu hỏi IMO.
mũi

@nasch người ta có thể giữ và lấy WeakReferencetay cầm từ một Applicationlớp - trong khi ComponentNameyêu cầu phải xác định xem mong muốn Activitycó nằm trên danh sách tác vụ đang chạy hay không. Và nếu điều này không trả lời đầy đủ câu hỏi, câu trả lời được chấp nhận cũng không.
Martin Zeitler

Tôi đồng ý, câu trả lời được chấp nhận cũng không trả lời đầy đủ câu hỏi.
mũi

1
topActivitychỉ khả dụng từ Android Q
Eugen Martynov

1

Cá nhân tôi đã làm như "Cheok Yan Cheng" đã nói, nhưng tôi đã sử dụng "Danh sách" để có "Backstack" cho tất cả các hoạt động của mình.

Nếu bạn muốn kiểm tra Hoạt động hiện tại nào, bạn chỉ cần lấy lớp hoạt động cuối cùng trong danh sách.

Tạo một ứng dụng mở rộng "Ứng dụng" và thực hiện điều này:

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

}

Trong trường hợp của tôi, tôi đã sử dụng "Application.ActivityLifecyclCallbacks" để:

  • Bind / Unbind Merlin Instance (được sử dụng để nhận sự kiện khi ứng dụng bị mất hoặc nhận kết nối, ví dụ như khi bạn đóng dữ liệu di động hoặc khi bạn mở nó). Nó rất hữu ích sau khi hành động mục đích "OnConnectivityChanged" bị vô hiệu hóa. Để biết thêm thông tin về MERLINE xem: LIÊN KẾT THÔNG TIN MERNET

  • Đóng Trường hợp thực tế cuối cùng của tôi khi đóng ứng dụng; Tôi sẽ khởi tạo nó trong một cơ sở BaseActivity được mở rộng từ tất cả các hoạt động khác và có Instance RealmHelper riêng. Để biết thêm thông tin về REALM, hãy xem: LINK INFO INFO Ví dụ: Tôi có một ví dụ "RealmHelper" tĩnh bên trong lớp "RealmHelper" của tôi, được khởi tạo trong ứng dụng "onCreate" của tôi. Tôi có một dịch vụ đồng bộ hóa trong đó tôi tạo ra "RealmHelper" mới vì Realm là "Liên kết theo luồng" và Trường hợp Realm không thể hoạt động trong một Chủ đề khác. Vì vậy, để tuân theo Tài liệu về Vương quốc "Bạn cần phải đóng tất cả các thực thể đã mở để tránh rò rỉ tài nguyên hệ thống", để thực hiện điều này, tôi đã sử dụng "Application.ActivityLifecyclCallbacks" như bạn có thể thấy.

  • Cuối cùng, tôi có một trình nhận được kích hoạt khi tôi hoàn thành để đồng bộ hóa ứng dụng của mình, sau đó khi kết thúc đồng bộ hóa, nó sẽ gọi phương thức "IEndSyncCallback" "onEndSync" trong đó tôi tìm nếu tôi có Lớp hoạt động cụ thể trong Danh sách ActivityBackStack của mình vì tôi cần để cập nhật dữ liệu trên chế độ xem nếu đồng bộ hóa cập nhật chúng và tôi có thể cần thực hiện các thao tác khác sau khi đồng bộ hóa ứng dụng.

Đó là tất cả, hy vọng điều này là hữu ích. Gặp bạn :)


-1

Câu trả lời của waqas716 là tốt. Tôi đã tạo một cách giải quyết cho một trường hợp cụ thể đòi hỏi ít mã và bảo trì hơn.

Tôi đã tìm thấy một công việc cụ thể xung quanh bằng cách có một phương thức tĩnh tìm nạp một khung nhìn từ hoạt động mà tôi nghi ngờ là ở phía trước. Bạn có thể lặp qua tất cả các hoạt động và kiểm tra nếu bạn muốn hoặc lấy tên hoạt động từ câu trả lời của martin không

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

Sau đó tôi kiểm tra xem khung nhìn không phải là null và lấy bối cảnh thông qua 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"));
}

Tôi đang tìm kiếm vấn đề tương tự ở đây stackoverflow.com/questions/22788289/ từ đó làm thế nào để chúng ta có được "SuspectedActivity"? Đây có phải là API gốc không?
Stella

2
NHƯNG từ các tài liệu cho 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, ..." trong developer.android.com/reference/android/app/,
ToolmakerSteve

3
Tài liệu dành cho ActivityManager.getRastyT task () hiện cho biết "Phương thức này không được dùng trong API cấp 21".
markshep

-2

Tôi không thích bất kỳ câu trả lời nào khác. ActivityManager không có nghĩa là được sử dụng để có được hoạt động hiện tại. Siêu đẳng cấp và tùy thuộc vào onDestroy cũng dễ vỡ và không phải là thiết kế tốt nhất.

Thành thật mà nói, điều tốt nhất tôi nghĩ ra cho đến nay chỉ là duy trì một enum trong Ứng dụng của mình, được đặt khi một hoạt động được tạo.

Một khuyến nghị khác có thể là tránh sử dụng nhiều hoạt động nếu có thể. Điều này có thể được thực hiện bằng cách sử dụng các đoạn hoặc trong chế độ xem tùy chỉnh tùy chọn của tôi.


1
một enum? Làm thế nào để giúp xác định vị trí hoạt động tiền cảnh hiện tại?
ToolmakerSteve

"Siêu phân loại và tùy thuộc vào onDestroy cũng dễ vỡ" Làm thế nào là dễ vỡ?
ToolmakerSteve

-3

Một giải pháp khá đơn giản là tạo một lớp trình quản lý đơn, trong đó bạn có thể lưu trữ một tham chiếu đến một hoặc nhiều Hoạt động hoặc bất kỳ thứ gì khác mà bạn muốn truy cập trong toàn bộ ứng dụng.

Gọi UberManager.getInstance().setMainActivity( activity );trong hoạt động chính của onCreate.

Gọi UberManager.getInstance().getMainActivity();bất cứ nơi nào trong ứng dụng của bạn để lấy nó. (Tôi đang sử dụng điều này để có thể sử dụng Toast từ một luồng không phải UI.)

Đảm bảo bạn thêm một cuộc gọi đến UberManager.getInstance().cleanup();khi ứng dụng của bạn đang bị hủy.

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

Điều này là xâm nhập và yêu cầu thay đổi trong tất cả các hoạt động. Câu trả lời của AZ_ tốt hơn nhiều vì nó hoàn toàn cục bộ và độc lập mà không yêu cầu các thay đổi khác trong cơ sở mã.
markshep

-7

Tôi thích trễ 3 năm nhưng dù sao tôi cũng sẽ trả lời trong trường hợp ai đó thấy điều này giống như tôi.

Tôi đã giải quyết điều này bằng cách sử dụng đơn giản:

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

Lưu ý rằng "getIntent (). ToString ()" bao gồm một loạt các văn bản khác như tên gói của bạn và bất kỳ bộ lọc mục đích nào cho hoạt động của bạn. Về mặt kỹ thuật, chúng tôi đang kiểm tra mục đích hiện tại, không phải hoạt động, nhưng kết quả là như nhau. Chỉ cần sử dụng ví dụ Log.d ("test", getIntent (). ToString ()); nếu bạn muốn xem tất cả các văn bản. Giải pháp này hơi rắc rối nhưng mã của bạn sạch sẽ hơn nhiều và chức năng cũng vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.