B4A Library OS metrics: MSOS lib and OSStats and GetForegroundApp

Discussion in 'Additional libraries, classes and official updates' started by thedesolatesoul, Nov 25, 2013.

  1. thedesolatesoul

    thedesolatesoul Expert Licensed User

    MSOS Library

    This library contains many OS functions from the Activity Manager.
    This library is constantly evolving.
    It consists of 2 librarys now. MSOS is java code, OSStats is B4A code. Both are packed jars.

    Requirements:
    At the moment getSystemTotalMemorySize works only on API 16+ thanks to google for implementing incomplete API. Courtesy testing (read bashing) of NJDude.

    MSOS
    Author:
    thedesolatesoul
    Version: 0.01
    • MSOS
      Fields:
      • IMPORTANCE_FOREGROUND As Int
      • IMPORTANCE_VISIBLE As Int
      Methods:
      • getForegroundApp (pImportance As Int) As List
      • getForegroundTask As List
      • getFormattedSystemAvailabeMemorySize As String
      • getFormattedSystemTotalMemorySize As String
      • getProcessMemoryInfo (pid As Int) As Int
      • getSystemAvailabeMemorySize As Long
      • getSystemTotalMemorySize As Long
      Permissions:
      • android.permission.GET_TASKS
      Properties:
      • NumCores As Int [read only]
        Gets the number of cores available in this device, across all processors.
        Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
    OSStats
    • Class_Globals
      Class module
    • EndStats
      Stop collecting the stats
      Call this in Activity_Pause
    • Initialize (Interval As Int, BufferSize As Int, Module As Object, EventName As String)
      Initializes the object.
      Interval is the gap to keep between capturing stats
      Buffer size is size of buffer to store stats (for graphing etc)
      Module is the parent object where the events will be delivered
      Eventname is th prefix of the events raised
    • StartStats
      Start collecting stats
      The eventname_Update(CpuEfficientcy() as Float,RAMUsage as Float) will be raised
    • getNumCores As Int
      Returns the number of CPU cores


    It calculated the CPU Usage and Memory Usage.
    You can start/stop tracking the OSStats.
    This is stored in a buffer for graphing/smoothing etc.

    I am trying to figure out out how to get which app is in the foreground or is visible.
    This is so that I can use either a transparent activity or a service, and find out which app is on top.

    //Ignore
    getRunningApps: Uses this to find which apps have IMPORTANCE_FOREGROUND or IMPORTANCE_VISIBLE set
    getRunningTasks: Uses this to find running tasks. tasks(0) will be the most recent one.
    You can run these in a service and see what values they return.
    I am still not sure which method is more accurate depending on what a 'task' and what an 'app' is.
    For instance the last 'task' may have ended itself, whereas IMPORTANCE_VISIBLE will return whatever the user is viewing however this returns a number of items.
    If someone could test this, and figure out what is doing what it would be great!
    //
     

    Attached Files:

    Last edited: Nov 30, 2013
  2. NJDude

    NJDude Expert Licensed User

    The attached sample shows a simple way of using this library.

    You need to install the MSOS and OSStats library.
     

    Attached Files:

  3. bsnqt

    bsnqt Active Member Licensed User

    Thanks for the library.
    I try to run the sample from NJDude but got error...
    Is this related to what thedesolatesould mentioned "getSystemTotalMemorySize works only on API 16+"?
    My test device is Xperia S (Android 4.1.2)
    When I run the sample, it just stopped with error "Unfortunately, MSOS Example has stopped".
     
  4. NJDude

    NJDude Expert Licensed User

    Yes, the lib seems to work on 4.2 and up.
     
  5. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I have 4.1.1 and it is working for me.
    API16 = 4.1 , I am not sure how it doesnt work on your 4.1.2
    Nevertheless I am implementing an alternative method. Initially I was using the API version to determine which method to use, but may be I shall use try/catch and catch the NoSuchField exception and then use the alternate method (which may be blocked by Google in the future!)
     
  6. thedesolatesoul

    thedesolatesoul Expert Licensed User

    I have update the library to be working with API16 and lesser too.
    getSystemTotalMemorySize should work now.
    It would be great if someone could test it.
    Thanks
     
    NJDude likes this.
  7. NJDude

    NJDude Expert Licensed User

    Excellent!, it seems to work on all versions, I tried even on Froyo and it works, however, the RAM usage on older versions gives the wrong results, see THIS
     
  8. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Okay, it was returning the info in KB. I fixed and re-uploaded.
    Thanks
     
    NJDude likes this.
  9. NJDude

    NJDude Expert Licensed User

    Ok, it's fine now.
     
    thedesolatesoul likes this.
  10. bsnqt

    bsnqt Active Member Licensed User

    It works now Sir :)
    Thank you.
     
    thedesolatesoul likes this.
  11. cambopad

    cambopad Active Member Licensed User

    @thedesolatesoul, @NJDude , and @Erel


    How can I use this in a service? I tried to use it in a service, but MSOS seems to be an activity object. As a result I got the following message:

    Code:
    Error description: Cannot access activity object from sub Process_Globals.
    Occurred on line: 
    10
    Dim xmsos As MSOS
    Word: 
    msos
    Does anyone know how to fix this and get it working in a service? I need this feature for my upcoming project :(


    Thanks you!
     
  12. thedesolatesoul

    thedesolatesoul Expert Licensed User

    It doesnt need to be an ActivityObject. I have definitely used it in a service.
    I might fix it one day.
    Although be wary as most of this API is deprecated by Google in Android5, so I dont see a lot of point in putting any effort into this.
     
    cambopad likes this.
  13. cambopad

    cambopad Active Member Licensed User

    @thedesolatesoul Thanks you! But are these two features also deprecated?

    • getForegroundApp
    • getForegroundTask
    I really need this two features :(
     
  14. cambopad

    cambopad Active Member Licensed User

    Can you provide sample code to use it in a service? Or does the lib need to be fixed by you first before I can use it in a service?
     
  15. thedesolatesoul

    thedesolatesoul Expert Licensed User

    Yes they are deprecated:
    http://developer.android.com/reference/android/app/ActivityManager.html#getRecentTasks(int, int)
    http://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int)

    I would need to fix the lib.
    Try the one attached.
     

    Attached Files:

    Multiverse app and cambopad like this.
  16. cambopad

    cambopad Active Member Licensed User

    Thank you so much! I will try this :D
     
  17. G-ShadoW

    G-ShadoW Active Member Licensed User

    Android 5.1.1 not working

    Code:
    ** Activity (main) Create, isFirst = true **
    main_activity_create (B4A line: 
    68)
    xOSStats.Initialize(
    40050, Me, "myStats")
    java.lang.IncompatibleClassChangeError: The method 
    'int com.maximussoft.msos.MSOS.getNumCores()' was expected to be of type virtual but instead was found to be of type static (declaration of 'java.lang.reflect.ArtMethod' appears in /system/framework/core-libart.jar)
        at b4a.example.osstats._initialize(osstats.java:208)
        at njdude.msos.sample.main._activity_create(main.java:
    396)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:
    372)
        at anywheresoftware.b4a.BA.raiseEvent2(BA.java:
    187)
        at njdude.msos.sample.main.afterFirstLayout(main.java:
    100)
        at njdude.msos.sample.main.access$
    100(main.java:17)
        at njdude.msos.sample.main$WaitForLayout.run(main.java:
    78)
        at android.os.Handler.handleCallback(Handler.java:
    739)
        at android.os.Handler.dispatchMessage(Handler.java:
    95)
        at android.os.Looper.loop(Looper.java:
    135)
        at android.app.ActivityThread.main(ActivityThread.java:
    5289)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:
    372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:
    904)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:
    699)
    ** 
    Activity (main) Resume **
    WakeLock already held.
    ---- 
    1 ----
    ---- 
    2 ----
    ---- 
    3 ----
    ---- 
    4 ----
    ---- 
    In onAdFailedToLoad ----Server Message: no results. Try again in 10 seconds
     
  18. Rick Harris

    Rick Harris Well-Known Member Licensed User

    I can also confirm that MSOS does not work in Android 5.0 and higher. Pity Google deprecates (=messes up) good working code. What can I use in stead to determine which application is running in the foreground (i.e. has the focus)?
     
    Last edited: May 25, 2016
  19. Rick Harris

    Rick Harris Well-Known Member Licensed User

    To answer my own question: A good solution can be found under:
    https://www.b4x.com/android/forum/threads/get-the-currently-running-activity.39387/#content

    In particular I recommend thread #7.

    I slightly modified the code:
    Code:
    Sub Timer1_Tick
        
    Dim AppName1 As String
        
    Dim n As Long
        AppName1 = GET_RUNNINGTASK1                        
    '25-05-2016
        If AppName1.trim="" Then Return
        AppName1 = AppName1.Replace(
    "ComponentInfo{","")   'Example: "ComponentInfo(blindnav1.dsh/blindnav1.dsh.main)"
        n=AppName1.IndexOf("/")                            'Need to strip superfluous info to get the real app name!
        If n=-1 Then n=AppName1.length
        AppName1 = AppName1.SubString2(
    0,n)                'Gives: "blindnav1.dsh"
        'Do something with the derived foreground appname (in AppName1)
    end sub

    Sub GET_RUNNINGTASK1 As String
        
    Private RunList1 As List = OS1.getRunningTasks(1)
        
    Private RunTask1 As String = ""
        
    Private r1 As Reflector
        RunTask1=
    ""
        
    If RunList1.Size > 0 Then
          r1.Target = RunList1.Get(
    0)
          RunTask1  = r1.getField(
    "topActivity")
        
    End If
        
    Return RunTask1
    End Sub
    Use Dim OS1 As OperatingSystem under Process Globals and OS1.Initialize("") under ServiceCreate or ActivityCreate.
    The sub GET_RUNNINGTASKS1 returns too much information about the running foreground app and therefore needs to be filtered (as shown above). I prefer the use of the OS library. It also does not require any permissions in the Manifest.
     
    Last edited: May 25, 2016
  20. Rick Harris

    Rick Harris Well-Known Member Licensed User

    Update (June 2016): The above GET_RUNNINGTASKS function sadly also no longer works (at least not in Android 5.0 and higher).
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice