Android Question Best practive to know if Activity_Create or Activty_Resume will be run?

JohnC

Expert
Licensed User
Longtime User
I need to call a routine in an activty from a service, but I need to make sure that only the routine will run and that no code in the Acitivty_Create sub will run.

From what I understand, if I try to use IsPaused(Main) it will return TRUE for either of these possible states:

1) Activity is loaded, but it is paused.
2) Activity is not loaded at all.

If it is in state #1 above, then I know when I do a CallSubDelayed(Main,"MyRoutine"), just the Activity_Resume and the MyRoutine subs will run, which is what I want.

But if it is in state #2 above, then when I call CallSubDelayed(Main,"MyRoutine"), the Activity_Create, (and maybe also Activity_Resume) and then MyRoutine subs will run, which is not good because I don't want the code in the Activity_Create to run.

So, how can I know which state Main is in?

(p.s. I don't know if a b4xpages app would work better for this issue, but at this point in time it is not practical to convert the app to a b4xpages app)
 

drgottjr

Expert
Licensed User
Longtime User
can't say this is the best. or even the only way.
but here's something you might try in your service. basically, it gave a list of running
processes. nowadays it only lists your app or, presumably, nothing if your app isn't
loaded. hard for me to test since i don't have a service ready to go and, mainly,
you can't restart an activity from a service anymore (if i understand correctly).
but if you query the activitymanager and you see your app, then you know it's in
memory. if you don't see it, then it's dead. anyway, that's how i read it.

note the "importance" field. this indicates the state of any processes listed. you can
also get the names of the running processes to compare against your own app's name.
as i say, nowadays you can only see your own app. if you're running the app on an
older device with your b4a v9, you might see more.

you can look up the constant values for "importance" in google's documentation for
android.app.ActivityManager.RunningAppProcessInfo

B4X:
    Dim jo As JavaObject
    Activity.LoadLayout("Layout")
    jo.Initializecontext
    Dim activitymanager As JavaObject
    activitymanager = jo.RunMethod("getSystemService",Array("activity"))
    Dim processlist As JavaObject = activitymanager.RunMethod("getRunningAppProcesses",Null)

    Log(jo.RunMethod("getPackageName",Null))

    If processlist.IsInitialized Then
        For Each p As JavaObject In processlist.As(List)
            Log(p.GetField("importance"))    ' you can look 'em up
            Log(p.GetField("processName"))  ' compare with getPackageName above
            
        Next
    Else
        Log("failed")
    End If

i ran it on android 12 + b4a 12.2. ran as expected under google's current conditions.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
It's giving me a bunch of different errors for the line:

B4X:
For Each p As JavaObject In processlist.As(List)
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I also found out that doing a CallSubDelayed("Main", "MyRoutine") did not start the activity from the service if the activity was not already loaded.

I am setting the TargetSDK to 22, so it should be possible to do this.

The Log even indicated that it submitted the request to the que, but the main activity was never shown.

When I did this test, my app was setup to run a service for the BOOT_COMPLETE intent, so only this service was running after a bootup - meaning at this point the Main activity was never loaded/displayed at all - only the service was started. So, I don't know if that was the reason for why it didn't get displayed.

Maybe there is some conflict with FireOS that prevents CallSubDelay to fully work correctly.

What did work was this:
B4X:
If IsPaused(Main) = True Then
    StartActivity(Main)
End if
CallSubDelayed(Main,"MyRoutine")
 
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i forgot; you don't have As comes with b4a 11 or 12. let me think a bit.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
At this point I'm thinking of maybe just using a Global Boolean var named "DontRunActivityCreateCode".

So, the service will set this to TRUE before starting the Main activity, and the Activity_Create sub in Main will simply check this var, and if true, it will skip over the code I don't want running.

This way it won't matter if Main is in either State #1 or #2.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
still with my suggestion here. removed the As and did it the old, roundabout way:

B4X:
    If processlist.IsInitialized Then
        Dim i As Int
        For i = 0 To processlist.runmethod("size",Null) - 1

'      original way **********************
'        For Each p As JavaObject In processlist.As(List)
'            Log(p.GetField("importance"))
'            Log(p.GetField("processName"))
'      end of original way ******************

            Dim processinfo As JavaObject = processlist.RunMethod("get",Array(i))
            Log("running: " & processinfo.GetField("processName"))
            Log("status: " & processinfo.GetField("importance"))
        Next
    Else
        Log("failed")
    End If

i'm too far gone to outthink android; i tend to go with what it gives me. you could be on to something with what you're trying.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
That routine is only returning my own app's package name :(

Maybe my global var idea is a workaround for now.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
that's what it's supposed to do.
if the activity was loaded and still had a process, it's in some active state.
if it's not loaded (and, presumably, has no process), you should probably get an empty list. that's how you would tell if you were loaded or not.

i see where you're going with the process global variable. sounds doable.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I do already have that permission in the manifest and I know that permission is working because my app does display an overlay.

It's weird because the description for CallSubDelay says that it's a combination of StartActivty and CallSub so that if the activity/service is not already open, it will open it and then call the subroutine.

But by just calling CallSubDelay alone, it did add a "adding request to que" in the log events, but it did not cause the activity to load and I waited over a minute.

I had to first call StartActivity, then CallSubDelay, then that worked. So, my code looks like this:
B4X:
If IsPaused(Main) = True Then
    StartActivity(Main)
End If
            
CallSubDelayed(Main,"MyRountine")

Like I said, it might be a FireOS bug because I did not test this on a normal andorid device.
 
Upvote 0
Top