Android 5.1.1 और इसके बाद के संस्करण - getRunningAppProcesses () केवल मेरा एप्लिकेशन पैकेज लौटाता है


100

ऐसा लगता है कि Google ने वर्तमान अग्रभूमि अनुप्रयोग पैकेज प्राप्त करने के लिए सभी दरवाजे बंद कर दिए हैं।

लॉलीपॉप अपडेट के बाद, जो मारा गया getRunningTasks(int maxNum)और इस जवाब के लिए धन्यवाद , मैंने इस कोड का इस्तेमाल लॉलीपॉप के बाद से अग्रभूमि अनुप्रयोग पैकेज पाने के लिए किया:

final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
    field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) { 
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
    if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
        app.importanceReasonCode == 0 ) {
        Integer state = null;
        try {
            state = field.getInt( app );
        } catch (Exception ignored) {
        }
        if (state != null && state == PROCESS_STATE_TOP) {
            currentInfo = app;
            break;
        }
    }
}
return currentInfo;

एंड्रॉइड 5.1.1 और ऊपर (6.0 मार्शमैलो), ऐसा लगता है, getRunningAppProcesses()साथ ही मार दिया गया। अब यह आपके स्वयं के एप्लिकेशन पैकेज की सूची लौटाता है।


UsageStatsManager

हम यहां वर्णित केUsageStatsManager रूप में नए एपीआई का उपयोग कर सकते हैं, लेकिन यह सभी अनुप्रयोगों के लिए काम नहीं करता है। कुछ सिस्टम एप्लिकेशन उसी पैकेज को वापस करेंगे

com.google.android.googlequicksearchbox

AccessibilityService (दिसंबर 2017: Google द्वारा उपयोग के लिए प्रतिबंधित किया जा रहा है)

कुछ एप्लिकेशन उपयोग करते हैं AccessibilityService(जैसा कि यहां देखा गया है ) लेकिन इसके कुछ नुकसान हैं।


क्या वर्तमान चल रहे एप्लिकेशन पैकेज प्राप्त करने का एक और तरीका है?


1
दू स्पीड बूस्टर काम लगता है। मुझे यकीन नहीं है कि यह UseStatsManager का उपयोग करता है।
thecr0w

3
ध्यान दें कि कई प्रमुख विक्रेताओं ने सिस्टम गतिविधि को हटा दिया है जो अपने उपकरणों से उपयोगस्टैट एपीआई तक पहुंच प्रदान करता है। इसका मतलब यह है कि उन उपकरणों पर ऐप्स कभी भी आवश्यक अनुमति प्राप्त नहीं कर सकते हैं।
केविन क्रुमविडे

3
सैमसंग उनमें से एक है। यह बाजार का 60% से अधिक है।
केविन क्रुमविडे

3
इस मुद्दे के बारे में Android बग ट्रैकर से एक टिकट दिया गया है: code.google.com/p/android-developer-preview/issues/…
फ्लोरियन बर्थ

2
अगर मैं psकिसी शेल में रन करने के आउटपुट को पार्स करता हूं और पॉलिसी समान है "fg"और /proc/[pid]/oom_adj_scoreबराबर है 0तो ऐप अग्रभूमि एप्लिकेशन है। दुर्भाग्य से, ऐसा लगता है /proc/[pid]/oom_adj_scoreकि अब Android 6.0 पर पढ़ने योग्य नहीं है। gist.github.com/jaredrummler/7d1498485e584c8a120e
Jared Rummler

जवाबों:


93

Android 1.6 - Android 6.0 पर चल रही प्रक्रियाओं की एक सूची प्राप्त करने के लिए आप इस लाइब्रेरी का उपयोग कर सकते हैं जो मैंने लिखा था: https://github.com/jaredrummler/AndroidProcesses लाइब्रेरी में प्रक्रिया की जानकारी प्राप्त करने के लिए लिखा / पढ़ा जाता है।

Google ने एंड्रॉइड नौगट में पहुंच / खरीद को प्रतिबंधित कर दिया है। Android Nougat पर चलने वाली प्रक्रियाओं की सूची प्राप्त करने के लिए आपको UseStatsManager का उपयोग करना होगा या रूट एक्सेस करना होगा।

पिछले वैकल्पिक समाधानों के लिए संपादन इतिहास पर क्लिक करें।


4
@androiddeveloper नहीं, मैंने केवल libsuperuser का उपयोग किया है क्योंकि यह शेल कमांड (गैर-रूट या रूट) को चलाने और आउटपुट प्राप्त करने का एक आसान तरीका प्रदान करता है। यदि पर्याप्त मांग है तो मैं इसे libsuperuser के बिना फिर से लिख सकता हूं।
जेरेड रुम्मलर

1
उसके लिए खेद है। बस तड़प रही थी। :(
एंड्रॉइड डेवलपर

1
@JaredRummler मैं वर्तमान में आपके समाधान को मेरे ऐप में लागू करने की प्रक्रिया में हूं। जहाँ तक मैं बता सकता हूँ ठीक काम कर रहा है
लड़का .gc

1
@androiddeveloper, यदि आप इसे एक अलग विशेषता के आधार पर क्रमबद्ध करना चाहते हैं, तो इसे Processलागू करें Comparableऔर compareToविधि को ओवरराइड करें । फिर, जब आप उपयोग करते हैं Collections.sort(processesList), तो यह आपके द्वारा निर्दिष्ट आदेश का उपयोग करेगा।
श्रीविष्णु

2
@BruceWayne मुझे लगता है कि जेरेड इस लिंक का उल्लेख कर रहे हैं: https://source.android.com/devices/tech/security/selinux/index.html
एडुआर्डो हर्जर

24
 private String printForegroundTask() {
    String currentApp = "NULL";
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
        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();
            }
        }
    } else {
        ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
        currentApp = tasks.get(0).processName;
    }

    Log.e("adapter", "Current App in foreground is: " + currentApp);
    return currentApp;
}

अग्रभूमि कार्य प्राप्त करने के लिए इस विधि का उपयोग करें। U को सिस्टम अनुमति की आवश्यकता होगी "android: get_usage_stats"

public static boolean needPermissionForBlocking(Context context){
    try {
        PackageManager packageManager = context.getPackageManager();
        ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
        return  (mode != AppOpsManager.MODE_ALLOWED);
    } catch (PackageManager.NameNotFoundException e) {
        return true;
    }
}

यदि उपयोगकर्ता इसे उपयोग में सक्षम करता है -> सुरक्षा-> उपयोग पहुंच के साथ ऐप। उसके बाद u को अग्रभूमि कार्य मिलेगा। इसी तरह की प्रक्रिया चीताहम्बल गूगल प्ले लिंक द्वारा क्लीन मैटर


जैसा कि ओपी और टिप्पणियों में बताया गया है, उपयोग के प्रमुख डाउनसाइड हैं UsageStatsManager। सैमसंग ने अनुरोधों को हटा दिया है और उपयोगकर्ता के लिए सिस्टम की अनुमति देना काफी कष्टप्रद है।
जेरेड रुम्मलर

मैंने मोटो ई 2 डिवाइस में परीक्षण किया है। यह ठीक काम कर रहा है और हां, हमें इस अनुमति को लागू करने की आवश्यकता है। हम सभी समान मुद्दों का सामना कर रहे हैं। हम सभी को वास्तव में एक बेहतर दृष्टिकोण की आवश्यकता है। गुड लक दोस्त
तरुण शर्मा 12

2
यह दृष्टिकोण कम से कम एलजी जी 3 पर काम नहीं करता है क्योंकि कोई "सेटिंग्स -> सुरक्षा-> उपयोग एक्सेस के साथ ऐप" मेनू आइटम नहीं है
दिमित्री

2
यह मेरे सवाल का जवाब नहीं है। इसके अलावा, इस जवाब में कोई नई जानकारी नहीं दी गई है।
लोर इलूज

1
ठीक काम कर रहे हैं लेकिन मार्शमॉलो में ठीक से नहीं। यदि अधिसूचना आई, तो वर्तमान में चल रही प्रक्रिया पैकेज अधिसूचना प्राप्त होगी। वास्तव में ऐप अग्रभूमि या पृष्ठभूमि में नहीं चल रहा है :(। समाधान की आवश्यकता है।
WonderSoftwares

6

Https://github.com/ricvalerio/foregroundappchecker पर एक नज़र डालें , यह वही हो सकता है जिसकी आपको आवश्यकता है। नमूना कोड प्रदान करता है, और क्रॉस संस्करण अग्रभूमि डिटेक्टर को लागू करने के दर्द को दूर करता है।

यहाँ दो नमूने हैं:

AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();

या नियमित रूप से जांच करें:

AppChecker appChecker = new AppChecker();
appChecker
    .when("com.other.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .when("com.my.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .other(new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .timeout(1000)
    .start(this);

2
धन्यवाद, लेकिन यहां कुछ भी नया नहीं है। उन्होंने सिर्फ UseStatsManager API को लपेटा जो कि OP में उल्लेखित है। उपयोगकर्ता को एंड्रॉइड 5.1.1 के बाद से अन्य तरीकों के रूप में एक्सेस सक्षम करने की आवश्यकता होगी
लाइर इलूज

@ Jérémy क्या आपने आवश्यक अनुमति का अनुरोध किया था?
rvalerio

लगता है यह भी हर समय, सही मतदान है?
Android डेवलपर

4

Google ने इस कार्यक्षमता को केवल सिस्टम ऐप्स के लिए सीमित कर दिया है। जैसा कि बग टिकट में बताया गया है , आपको वहां पहुंचने के लिए REAL_GET_TASKS अनुमति की आवश्यकता होगी ।

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


मैंने देखा कि ऐपलॉक अभी भी 5.1.1 पर काम कर रहा है, एक बार ऐप को सुरक्षा की अनुमति मिल जाती है -> "उपयोग के साथ ऐप्स" ... यह कुछ हद तक आश्चर्य की बात है
महेश

"सुरक्षा स्तर हस्ताक्षर, विशेषाधिकार प्राप्त या हस्ताक्षर के साथ अनुमतियाँ या सिस्टम सिस्टम केवल सिस्टम ऐप्स को दी जाती हैं। यदि कोई ऐप नियमित गैर-सिस्टम ऐप है, तो वह इन अनुमतियों का उपयोग करने में कभी सक्षम नहीं होगा।" Google को "सिस्टम ऐप" के रूप में स्वीकार किया जाना है।
जेरेमी

2

बस जो मैं कल्पना करता हूं, उसके लिए एक संभावित अनुकूलन बाहर फेंक रहा हूं, जो कि एम पर शीर्ष-सबसे अधिक एप्लिकेशन का पता लगाने के लिए कोड की भारी कॉपी-पेस्ट वाली बिट है।

यह

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
    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();
        }
    }
}

इसके लिए सरलीकरण किया जा सकता है

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    UsageStatsManager usm = (UsageStatsManager) context.getSystemService(
        Context.USAGE_STATS_SERVICE);
    long time = System.currentTimeMillis();
    List<UsageStats> appStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
            time - 1000 * 1000, time);
    if (appStatsList != null && !appStatsList.isEmpty()) {
        currentApp = Collections.max(appStatsList, (o1, o2) ->
            Long.compare(o1.getLastTimeUsed(), o2.getLastTimeUsed())).getPackageName();
    }
}

मैंने अपने आप को 2 सेकंड के लूप में इस कोड का उपयोग करते हुए पाया, और सोचा कि क्यों मैं एक जटिल समाधान का उपयोग कर रहा था जो कि O (n * लॉग (n)) था जब अधिक सरल समाधान Collections.max () में उपलब्ध था जो कि O (n) है )।


0
public class AccessibilityDetectingService 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(final AccessibilityEvent event) {
        if (event == null ) {
            return;
        } else if(event.getPackageName() == null && event.getClassName() == null){
            return;
        }

            if (activityInfo != null){

                Log.d("CurrentActivity", componentName.flattenToShortString());
        }

}

private ActivityInfo tryGetActivity(ComponentName componentName) {
    try {
        return getPackageManager().getActivityInfo(componentName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
}
@Override
public void onInterrupt() {
}                
}
}//`enter code here`uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />

फिर अपनी डिवाइस सेटिंग में सेवा और ऐप एक्सेसिबिलिटी शुरू करें-> एक्सेसिबिलिटी-> उस सेवा पर ऐप।


यह पहले से ही प्रश्न में शामिल है, और आपने स्टैकऑवरफ्लो पर इसके मूल स्रोत से कोड को केवल कॉपी-पेस्ट किया है।
सैम

-2

कृपया विधि के getRunningServices()बजाय उपयोग करने का प्रयास करें getRunningAppProcesses()

 ActivityManager mActivityManager = (ActivityManager) getSy stemService(Context.ACTIVITY_SERVICE);

 List<ActivityManager.RunningServiceInfo> appProcessInfoList = mActivityManager.getRunningServices(Integer.MAX_VALUE);

3
ढेर अतिप्रवाह में आपका स्वागत है! मुझे नहीं लगता कि यह काम करेगा क्योंकि अग्रभूमि ऐप एक सेवा नहीं चला रहा हो सकता है।
सैम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.