एंड्रॉइड: मैं वर्तमान अग्रभूमि गतिविधि (एक सेवा से) कैसे प्राप्त कर सकता हूं?


180

क्या किसी सेवा से वर्तमान में चल रही गतिविधि का संदर्भ प्राप्त करने के लिए एक देशी एंड्रॉइड तरीका है?

मेरे पास पृष्ठभूमि पर चलने वाली सेवा है, और जब कोई घटना (सेवा में) होती है, तो मैं अपनी वर्तमान गतिविधि को अपडेट करना चाहूंगा। क्या ऐसा करने का एक आसान तरीका है (जैसा कि मैंने ऊपर सुझाव दिया है)?


शायद यह आपको एक विचार दे सकता है stackoverflow.com/a/28423385/185022
AZ_

जवाबों:


87

क्या किसी सेवा से वर्तमान में चल रही गतिविधि का संदर्भ प्राप्त करने के लिए एक देशी एंड्रॉइड तरीका है?

आप "वर्तमान में चल रही गतिविधि" के मालिक नहीं हो सकते हैं।

मेरे पास पृष्ठभूमि पर चलने वाली सेवा है, और जब कोई घटना (सेवा में) होती है, तो मैं अपनी वर्तमान गतिविधि को अपडेट करना चाहूंगा। क्या ऐसा करने का एक आसान तरीका है (जैसा कि मैंने ऊपर सुझाव दिया है)?

  1. Intentगतिविधि के लिए एक प्रसारण भेजें - यहां एक नमूना परियोजना है जो इस पैटर्न का प्रदर्शन करती है
  2. गतिविधि की आपूर्ति करें PendingIntent(जैसे, के माध्यम से createPendingResult()) कि सेवा आह्वान करती है
  3. गतिविधि के माध्यम से सेवा के साथ कॉलबैक या श्रोता ऑब्जेक्ट को पंजीकृत करें bindService(), और उस कॉलबैक / श्रोता ऑब्जेक्ट पर सेवा के पास एक इवेंट विधि है
  4. बैकअप के रूप में Intentनिम्न-प्राथमिकता वाले गतिविधि के लिए एक आदेशित प्रसारण भेजें BroadcastReceiver( Notificationयदि गतिविधि ऑन-स्क्रीन नहीं है तो उठाने के लिए ) - यहाँ इस पैटर्न पर अधिक के साथ एक ब्लॉग पोस्ट है

3
धन्यवाद, लेकिन जैसा कि मेरे पास गतिविधियों की एक लूट है, और उन सभी को अपडेट नहीं करना चाहते हैं, मैं अग्रभूमि को प्राप्त करने के लिए एक एंड्रॉइड तरीके की तलाश कर रहा था। जैसा कि आप कहते हैं, मुझे ऐसा करने में सक्षम नहीं होना चाहिए। मतलब मुझे इसके लिए अपना रास्ता निकालना होगा।
जॉर्ज

1
@ जॉर्ज: जो आप चाहते हैं वह आपकी मदद नहीं करेगा, वैसे भी। जैसा कि आप बताते हैं, आपके पास "गतिविधियों की एक लूट" है। इसलिए, वे सभी अलग-अलग वर्ग हैं। इसलिए, कुछ भी नहीं है कि आपकी सेवा उनके साथ कर सकती है या तो एक बड़े पैमाने पर अगर instanceofचेक -ब्लॉक या गतिविधियों को फिर से साझा करने के लिए एक सामान्य सुपरक्लास या इंटरफ़ेस को साझा करना। और अगर आप गतिविधियों को फिर से शुरू करने जा रहे हैं, तो आप इसे इस तरह से कर सकते हैं जो फ्रेमवर्क के साथ बेहतर रूप से फिट बैठता है और अधिक परिदृश्यों को कवर करता है, जैसे कि आपकी कोई भी गतिविधि सक्रिय नहीं है। # 4 शायद सबसे कम काम और सबसे अधिक लचीला है।
कॉमन्सवेयर

2
धन्यवाद, लेकिन मेरे पास एक बेहतर समाधान है। मेरी सभी गतिविधियाँ एक अनुकूलित बेसएक्टिविटी क्लास का विस्तार करती हैं। मैंने एक ContextRegister सेट किया है जो गतिविधि को वर्तमान के रूप में पंजीकृत करता है जब भी यह अग्रभूमि पर होता है, तो मेरे BaseActivity क्लास में साहित्यिक 3 पंक्तियों के साथ। फिर भी, समर्थन के लिए धन्यवाद।
जॉर्ज

3
@ जॉर्ज: स्मृति लीक के लिए बाहर देखो। जहाँ कहीं भी संभव हो, स्थैतिक स्थैतिक डेटा सदस्यों को जावा में टाला जाना चाहिए।
कॉमन्सवेयर

मैंने ऑब्जेक्ट को कसकर समझाया है, हालांकि मैं वास्तव में इसे ध्यान में रखूंगा। धन्यवाद।
जॉर्ज

139

अपडेट : यह अब एंड्रॉइड 5.0 के रूप में अन्य एप्लिकेशन की गतिविधियों के साथ काम नहीं करता है


यहां गतिविधि प्रबंधक का उपयोग करने का एक अच्छा तरीका है। आप मूल रूप से गतिविधि प्रबंधक से रनिंग कार्य प्राप्त करते हैं। यह हमेशा वर्तमान में सक्रिय कार्य को पहले लौटाएगा। वहां से आप शीर्षता प्राप्त कर सकते हैं।

यहाँ उदाहरण है

एक्टिविटी मैनजर सेवा से कार्य चलाने की एक सूची प्राप्त करने का एक आसान तरीका है। आप फोन पर चल रहे कार्यों की एक अधिकतम संख्या का अनुरोध कर सकते हैं, और डिफ़ॉल्ट रूप से, वर्तमान में सक्रिय कार्य पहले वापस कर दिया जाता है।

एक बार आपके पास यह होगा कि आप अपनी सूची से topActivity का अनुरोध करके एक ComponentName ऑब्जेक्ट प्राप्त कर सकते हैं।

यहाँ एक उदाहरण है।

    ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    Log.d("topActivity", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName());
    ComponentName componentInfo = taskInfo.get(0).topActivity;
    componentInfo.getPackageName();

आपके प्रकट होने पर आपको निम्नलिखित अनुमति की आवश्यकता होगी:

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

3
आपका उत्तर 100% सही है। टैनक्स 4 यह। बेहतर है कि आप एक ही उत्तर यहाँ पोस्ट करें
शहज़ाद इमाम

1
@ArtOfWarfare ने सत्यापित नहीं किया है लेकिन हां, आपके पास जितने टुकड़े हैं, वे अप्रासंगिक हैं, क्योंकि वे हमेशा एक ही गतिविधि द्वारा होस्ट किए जाते हैं।
नेल्सन रामिरेज़

2
अगर मुझे वर्तमान गतिविधि की अधिक आवश्यकता है, तो मुझे बहुत बार सही चुनाव करना होगा? जब भी अग्रभूमि गतिविधि बदलती है तो क्या कॉलबैक ईवेंट प्राप्त करने का कोई तरीका है?
nizam.sp

43
बस हर कोई जागरूक है, डॉक्स इस getRunningTasks () विधि के बारे में बताता है। -------- नोट: यह विधि केवल डिबगिंग और कार्य प्रबंधन उपयोगकर्ता इंटरफ़ेस प्रस्तुत करने के लिए है। किसी अनुप्रयोग में मुख्य तर्क के लिए इसका उपयोग कभी नहीं किया जाना चाहिए, जैसे कि यहां मिली जानकारी के आधार पर विभिन्न व्यवहारों के बीच निर्णय लेना। इस तरह के उपयोग समर्थित नहीं हैं, और भविष्य में होने की संभावना है। उदाहरण के लिए, यदि एक ही समय में कई एप्लिकेशन सक्रिय रूप से चल सकते हैं, तो नियंत्रण प्रवाह के प्रयोजनों के लिए यहां डेटा के अर्थ के बारे में की गई धारणाएं गलत होंगी। ------------
रयान

30
एपी 21 पर सेमीफाइकAs of LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.
शेरपा

116

चेतावनी: Google Play उल्लंघन

Google ने प्ले स्टोर से ऐप्स को हटाने की धमकी दी है यदि वे गैर-पहुंच उद्देश्यों के लिए पहुंच सेवाओं का उपयोग करते हैं। हालांकि, इस पर पुनर्विचार किया जा रहा है


एक का उपयोग करें AccessibilityService

लाभ

  • एंड्रॉइड 7.1 (एपीआई 25) के माध्यम से एंड्रॉइड 2.2 (एपीआई 8) में परीक्षण और काम कर रहा है।
  • मतदान की आवश्यकता नहीं है
  • GET_TASKSअनुमति की आवश्यकता नहीं है ।

नुकसान

  • प्रत्येक उपयोगकर्ता को एंड्रॉइड की एक्सेसिबिलिटी सेटिंग्स में सेवा को सक्षम करना होगा।
  • यह 100% विश्वसनीय नहीं है। कभी-कभी ईवेंट्स आउट ऑफ ऑर्डर हो जाते हैं।
  • सेवा हमेशा चल रही है।
  • जब कोई उपयोगकर्ता सक्षम करने का प्रयास करता है AccessibilityService, तो वे ठीक बटन नहीं दबा सकते हैं यदि किसी एप्लिकेशन ने स्क्रीन पर ओवरले रखा है। ऐसा करने वाले कुछ ऐप वेलिस ऑटो ब्राइटनेस और लक्स हैं। यह भ्रामक हो सकता है क्योंकि उपयोगकर्ता यह नहीं जान सकते हैं कि वे बटन क्यों नहीं दबा सकते हैं या इसके चारों ओर कैसे काम कर सकते हैं।
  • AccessibilityServiceपहले जब तक वर्तमान गतिविधि पता नहीं होगा परिवर्तन गतिविधि की।

उदाहरण

सर्विस

public class WindowChangeDetectingService extends AccessibilityService {

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();

        //Configure these here for compatibility with API 13 and below.
        AccessibilityServiceInfo config = new AccessibilityServiceInfo();
        config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
        config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

        if (Build.VERSION.SDK_INT >= 16)
            //Just in case this helps
            config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;

        setServiceInfo(config);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            if (event.getPackageName() != null && event.getClassName() != null) {
                ComponentName componentName = new ComponentName(
                    event.getPackageName().toString(),
                    event.getClassName().toString()
                );

                ActivityInfo activityInfo = tryGetActivity(componentName);
                boolean isActivity = activityInfo != null;
                if (isActivity)
                    Log.i("CurrentActivity", componentName.flattenToShortString());
            }
        }
    }

    private ActivityInfo tryGetActivity(ComponentName componentName) {
        try {
            return getPackageManager().getActivityInfo(componentName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    @Override
    public void onInterrupt() {}
}

AndroidManifest.xml

इसे अपनी अभिव्यक्ति में मिलाएं:

<application>
    <service
        android:label="@string/accessibility_service_name"
        android:name=".WindowChangeDetectingService"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService"/>
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibilityservice"/>
    </service>
</application>

सेवा की जानकारी

इसे इसमें डालें res/xml/accessibilityservice.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
 start in Android 4.1.1 -->
<accessibility-service
    xmlns:tools="http://schemas.android.com/tools"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagIncludeNotImportantViews"
    android:description="@string/accessibility_service_description"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:ignore="UnusedAttribute"/>

सेवा सक्षम करना

एप्लिकेशन के प्रत्येक उपयोगकर्ता को इसका उपयोग करने के लिए स्पष्ट रूप से सक्षम करने की आवश्यकता होगी AccessibilityServiceयह कैसे करें के लिए यह StackOverflow उत्तर देखें ।

ध्यान दें कि यदि एप्लिकेशन ने स्क्रीन पर ओवरले रखा है, जैसे कि वेलिस ऑटो ब्राइटनेस या लक्स, तो एक्सेसिबिलिटी सर्विस को सक्षम करने का प्रयास करते समय उपयोगकर्ता ओके बटन नहीं दबा पाएगा।


1
@lovemint, मेरा क्या मतलब है: मैंने एक उदाहरण निर्दिष्ट किया settingsActivityहै your.app.ServiceSettingsActivity, इसलिए आपको इसे अपनी पहुंच सेवा के लिए अपनी सेटिंग गतिविधि में बदलना चाहिए। मुझे लगता है कि सेटिंग्स गतिविधि वैसे भी वैकल्पिक है, इसलिए मैंने इसे सरल बनाने के लिए अपने उत्तर से उस हिस्से को हटा दिया है।
सैम

1
बहुत बहुत धन्यवाद, केवल आखिरी सवाल। अगर मुझे एपीआई 8 से वर्तमान में निपटने की आवश्यकता है तो मुझे XML का उपयोग करने के बजाय कोड में वह काम करना चाहिए?
पाओलो

1
@lovemint, यह सही है। मैंने ऐसा करने के लिए सिर्फ उदाहरण कोड को अपडेट किया।
सैम

1
@ मैं इस बात की पुष्टि कर सकता हूं कि यह सेवा पूरी तरह से काम करती है। एक अजीब व्यवहार, मैंने एक्सेसिबिलिटी सर्विस को सक्षम करने के लिए मुख्य गतिविधि में एक इरादे का इस्तेमाल किया। इसके बाद पहली बार सक्रिय की गई सेवा इसे सक्रिय कर देती onAccessibilityEventहै, लेकिन किसी भी घटना को प्राप्त नहीं करती है, लेकिन अगर मैं अक्षम करता हूं, और फिर से एक्सेसिबिलिटी सेवा को सक्षम करता है तो यह सेवा फिर से सक्रिय हो जाती है और onAccessibilityEventकाम करना शुरू कर देती है।
पाओलो 2988

2
आपके कोड के लिए धन्यवाद। मैंने आपके लिए यह ऐप बनाया :)
वॉल्ट

20

इसके द्वारा किया जा सकता है:

  1. अपने खुद के आवेदन वर्ग को लागू करें, ActivLifecycleCallbacks के लिए पंजीकरण करें - इस तरह आप देख सकते हैं कि हमारे ऐप के साथ क्या हो रहा है। फिर से शुरू होने पर कॉलबैक स्क्रीन पर वर्तमान दृश्य गतिविधि को असाइन करता है और ठहराव पर यह असाइनमेंट को हटा देता है। यह विधि का उपयोग करता है registerActivityLifecycleCallbacks()जिसे एपीआई 14 में जोड़ा गया था।

    public class App extends Application {
    
    private Activity activeActivity;
    
    @Override
    public void onCreate() {
        super.onCreate();
        setupActivityListener();
    }
    
    private void setupActivityListener() {
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            }
            @Override
            public void onActivityStarted(Activity activity) {
            }
            @Override
            public void onActivityResumed(Activity activity) {
                activeActivity = activity;
            }
            @Override
            public void onActivityPaused(Activity activity) {
                activeActivity = null;
            }
            @Override
            public void onActivityStopped(Activity activity) {
            }
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            }
            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
    }
    
    public Activity getActiveActivity(){
        return activeActivity;
    }
    
    }
  2. अपनी सेवा में कॉल करें getApplication()और इसे अपने ऐप क्लास नाम (इस मामले में ऐप) में डालें। थान से आप कॉल कर सकते हैं app.getActiveActivity()- जो आपको एक वर्तमान दृश्य गतिविधि देगा (या जब कोई गतिविधि दिखाई न दे तो शून्य)। आप कॉल करके गतिविधि का नाम प्राप्त कर सकते हैंactiveActivity.getClass().getSimpleName()


1
मुझे Nullpointer exeception activeActivity.getClass ()। GetSimpleame () पर मिल रही है। क्या आप कृपया मदद कर सकते हैं
शुरुआती

वैसे जैसा कि आप गतिविधिलिफ़साइकल कॉलबैक से देख सकते हैं - यदि गतिविधि दिखाई नहीं दे रही है, तो application.getActiveActivity () रिटर्न शून्य है। इसका मतलब है कि कोई गतिविधि दिखाई नहीं दे रही है। आपको अपनी सेवा में या जहाँ भी आप इसका उपयोग करते हैं, इसके लिए जाँच करनी होगी।
विट वर्स

ठीक है..लेकिन अगर गतिविधि फिर से शुरू हो जाती है तो इसे वापस नहीं लौटना चाहिए ?? मेरी गतिविधि शुरू हो गई थी और इसके फिर से शुरू होने पर मुझे मिला
शुरुआत

अनुमान लगाने में कठिन, ब्रेकपॉइंट्स को लगाने की कोशिश करें onActivityResumed(), onActivityPaused()और getActiveActivity()यह देखने के लिए कि यह कैसे है, अगर यह कभी भी हो।
विट वेर्स

@beginner एक अगर जांच करना चाहिए activityऔर activeActivityअसाइन करने से पहले ही कर रहे हैं activeActivityके साथ nullविभिन्न गतिविधियों के जीवन चक्र के तरीकों में से मिश्रित बुला आदेश के कारण से बचने के त्रुटियों के क्रम में।
राहुल तिवारी

16

मुझे कोई समाधान नहीं मिला कि हमारी टीम खुश हो जाए इसलिए हमने अपना रोल किया। हम ActivityLifecycleCallbacksवर्तमान गतिविधि का ट्रैक रखने के लिए उपयोग करते हैं और फिर एक सेवा के माध्यम से इसे उजागर करते हैं:

public interface ContextProvider {
    Context getActivityContext();
}

public class MyApplication extends Application implements ContextProvider {
    private Activity currentActivity;

    @Override
    public Context getActivityContext() {
         return currentActivity;
    }

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

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityStarted(Activity activity) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityResumed(Activity activity) {
                MyApplication.this.currentActivity = activity;
            }

            @Override
            public void onActivityPaused(Activity activity) {
                MyApplication.this.currentActivity = null;
            }

            @Override
            public void onActivityStopped(Activity activity) {
                // don't clear current activity because activity may get stopped after
                // the new activity is resumed
            }

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

            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                // don't clear current activity because activity may get destroyed after
                // the new activity is resumed
            }
        });
    }
}

फिर उदाहरण के MyApplicationलिए ContextProvider, उदाहरण के लिए , अपने DI कंटेनर को कॉन्फ़िगर करें

public class ApplicationModule extends AbstractModule {    
    @Provides
    ContextProvider provideMainActivity() {
        return MyApplication.getCurrent();
    }
}

(ध्यान दें कि कार्यान्वयन getCurrent()ऊपर दिए गए कोड से छोड़ा गया है। यह सिर्फ एक स्थिर वैरिएबल है जो एप्लिकेशन कंस्ट्रक्टर से सेट है)


4
एक अगर जांच करना चाहिए activityऔर currentActivityअसाइन करने से पहले ही कर रहे हैं currentActivityके साथ nullविभिन्न गतिविधियों के जीवन चक्र के तरीकों में से मिश्रित बुला आदेश के कारण से बचने के त्रुटियों के क्रम में।
राहुल तिवारी

14

उपयोग ActivityManager

यदि आप केवल वर्तमान गतिविधि वाले एप्लिकेशन को जानना चाहते हैं , तो आप इसका उपयोग कर सकते हैं ActivityManager। आपके द्वारा उपयोग की जाने वाली तकनीक Android के संस्करण पर निर्भर करती है:

लाभ

  • सभी Android संस्करणों में काम करना चाहिए।

नुकसान

  • एंड्रॉइड 5.1+ में काम नहीं करता (यह केवल आपका अपना ऐप लौटाता है)
  • इन APIs के दस्तावेज़ कहते हैं कि वे केवल डीबगिंग और प्रबंधन उपयोगकर्ता इंटरफ़ेस के लिए अभिप्रेत हैं।
  • यदि आप वास्तविक समय के अपडेट चाहते हैं, तो आपको मतदान का उपयोग करने की आवश्यकता है।
  • एक छिपे हुए एपीआई पर निर्भर करता है: ActivityManager.RunningAppProcessInfo.processState
  • यह कार्यान्वयन ऐप स्विचर गतिविधि को नहीं उठाता है।

उदाहरण ( KNaito के कोड पर आधारित )

public class CurrentApplicationPackageRetriever {

    private final Context context;

    public CurrentApplicationPackageRetriever(Context context) {
        this.context = context;
    }

    public String get() {
        if (Build.VERSION.SDK_INT < 21)
            return getPreLollipop();
        else
            return getLollipop();
    }

    private String getPreLollipop() {
        @SuppressWarnings("deprecation")
        List<ActivityManager.RunningTaskInfo> tasks =
            activityManager().getRunningTasks(1);
        ActivityManager.RunningTaskInfo currentTask = tasks.get(0);
        ComponentName currentActivity = currentTask.topActivity;
        return currentActivity.getPackageName();
    }

    private String getLollipop() {
        final int PROCESS_STATE_TOP = 2;

        try {
            Field processStateField = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState");

            List<ActivityManager.RunningAppProcessInfo> processes =
                activityManager().getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo process : processes) {
                if (
                    // Filters out most non-activity processes
                    process.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                    &&
                    // Filters out processes that are just being
                    // _used_ by the process with the activity
                    process.importanceReasonCode == 0
                ) {
                    int state = processStateField.getInt(process);

                    if (state == PROCESS_STATE_TOP) {
                        String[] processNameParts = process.processName.split(":");
                        String packageName = processNameParts[0];

                        /*
                         If multiple candidate processes can get here,
                         it's most likely that apps are being switched.
                         The first one provided by the OS seems to be
                         the one being switched to, so we stop here.
                         */
                        return packageName;
                    }
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        return null;
    }

    private ActivityManager activityManager() {
        return (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }

}

प्रकट

GET_TASKSअनुमति इसमें जोड़ें AndroidManifest.xml:

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

10
यह अब Android M पर काम नहीं करता है। getRunningAppProcesses () अब केवल आपके आवेदन का पैकेज लौटाता है
Lior Iluz

1
API स्तर 22 (Android 5.1) के लिए भी काम नहीं करता है। बिल्ड LPB23 पर परीक्षण किया गया
sumitb.mdi

9

मैं अपने परीक्षणों के लिए इसका उपयोग कर रहा हूं। यह एपीआई> 19 है, और केवल आपके ऐप की गतिविधियों के लिए है।

@TargetApi(Build.VERSION_CODES.KITKAT)
public static Activity getRunningActivity() {
    try {
        Class activityThreadClass = Class.forName("android.app.ActivityThread");
        Object activityThread = activityThreadClass.getMethod("currentActivityThread")
                .invoke(null);
        Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
        activitiesField.setAccessible(true);
        ArrayMap activities = (ArrayMap) activitiesField.get(activityThread);
        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);
                return (Activity) activityField.get(activityRecord);
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    throw new RuntimeException("Didn't find the running activity");
}

ArrayMap को Map से बदलें और यह 4.3 पर भी काम करेगा। पहले के Android संस्करणों का परीक्षण नहीं किया गया।
ओलिवर जोनास

2

एपीआई 21 या उससे ऊपर के लिए इस कोड का उपयोग करें। यह काम करता है और अन्य उत्तरों की तुलना में बेहतर परिणाम देता है, यह पूरी तरह से अग्रभूमि प्रक्रिया का पता लगाता है।

if (Build.VERSION.SDK_INT >= 21) {
    String currentApp = null;
    UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
    long time = System.currentTimeMillis();
    List<UsageStats> applist = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time);
    if (applist != null && applist.size() > 0) {
        SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
        for (UsageStats usageStats : applist) {
            mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);

        }
        if (mySortedMap != null && !mySortedMap.isEmpty()) {
            currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
        }
    }

क्या आप इस बारे में विस्तार से बता सकते हैं कि इस पद्धति के परिणाम अन्य उत्तरों से बेहतर कैसे हैं?
सैम

क्या यह अधिसूचना मेनू के साथ भी काम करता है। मैं एक समस्या का सामना कर रहा हूं जिसमें मुझे कॉल या संदेश मिलता है। UseStatsManager ने अपने ऐप के बजाय मुझे systemUi का पैकेज नाम देना शुरू किया।
कुकरेस

@kukroid, एक अलग प्रश्न पोस्ट करें और अपने स्रोत कोड, डिवाइस की जानकारी, और जो मैसेजिंग और फ़ोन ऐप आप उपयोग कर रहे हैं, शामिल करें।
सैम

0

यहाँ मेरा जवाब है कि बस ठीक काम करता है ...

आपको इस तरह से वर्तमान गतिविधि प्राप्त करने में सक्षम होना चाहिए ... यदि आप अपने ऐप को कई अंशों के साथ कुछ गतिविधियों के साथ जोड़ते हैं और आप यह जानना चाहते हैं कि आपकी वर्तमान गतिविधि क्या है, तो यह बहुत काम करेगा। मेरा सेनारियो था मैं एक गतिविधि के साथ कई टुकड़े हैं। इसलिए मैं एप्लिकेशन ऑब्जेक्ट के माध्यम से वर्तमान गतिविधि का ट्रैक रख सकता हूं, जो सभी वैश्विक चर की वर्तमान स्थिति को संग्रहीत कर सकता है।

यहाँ एक तरीका है। जब आप अपनी गतिविधि शुरू करते हैं, तो आप उस गतिविधि को Application.setCurrentActivity (getIntent ()) द्वारा संग्रहीत करते हैं; यह एप्लिकेशन इसे संग्रहीत करेगा। अपने सेवा वर्ग पर, आप बस Intent currentIntent = Application.getCurrentActivity (); । GetApplication () startActivity (currentIntent);


2
यह मानता है कि सेवा गतिविधि के रूप में उसी प्रक्रिया में चलती है, है ना?
हेल्लेय

0

मुझे नहीं पता कि यह एक मूर्खतापूर्ण जवाब है, लेकिन मैंने किसी भी गतिविधि के ऑनक्रिएट () में प्रवेश करने पर हर बार साझा प्राथमिकताओं में एक ध्वज को संग्रहीत करके इस समस्या को हल किया, फिर मैंने शेड्ड वरीयताओं से मूल्य का उपयोग यह पता लगाने के लिए किया कि यह अग्रभूमि गतिविधि क्या है।


1
हम इसे करने के लिए एक देशी तरीके की तलाश कर रहे हैं
इग्नाइटेकोडर्स

-3

अभी हाल ही में इस बारे में पता चला। एपीस के साथ:

  • minSdkVersion 19
  • targetSdkVersion 26

    ActivityManager.getCurrentActivity (संदर्भ)

आशा है कि यह किसी काम का हो।


1
मेरी उम्मीद थी। शायद जब यह उत्तर दिया गया था कि यह अस्तित्व में है, लेकिन अब getCurrentActivity()तक ActivityManagerकक्षा में कोई कार्य नहीं हुआ है ( developer.android.com/reference/android/app/ActivityManager )। मजेदार है कि यह फ़ंक्शन मौजूद है ActivityManager.isUserAMonkey():।
बाइटस्लिंगर

1
यदि आप अपनी गतिविधि का परीक्षण करने के लिए बंदर परीक्षण एजेंट का उपयोग कर रहे हैं तो यह पता लगाता है। हालांकि एक मजाकिया नाम, यह परीक्षण के लिए काफी उपयोगी हो सकता है (और अन्य लोगों को हँसने, obvs बनाने के लिए) डेवलपर
Ken Corey
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.