Android Question How to use the same instance of a library and its events both in Activity and in a Service

moster67

Expert
Licensed User
Longtime User
I have a project which works fine in debug but crashes in release-mode with the following crash report:
java.lang.RuntimeException: Unable to create service b4a.example.starter: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2771)
at android.app.ActivityThread.access$1800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1386)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
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:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at b4a.example.starter.onCreate(starter.java:38)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2761)
... 9 more
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at b4a.example.starter.onCreate(starter.java:36)
... 10 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'b4a.example.starter b4a.example.shootingservice._starter' on a null object reference
at b4a.example.main.initializeProcessGlobals(main.java:395)
... 13 more
Caused by: java.lang.NullPointerException: Attempt to read from field 'b4a.example.starter b4a.example.shootingservice._starter' on a null object reference
at b4a.example.shootingservice._process_globals(shootingservice.java:218)
at b4a.example.main.initializeProcessGlobals(main.java:392)
... 13 more
java.lang.RuntimeException: Unable to create service b4a.example.starter: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2771)
at android.app.ActivityThread.access$1800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1386)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
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:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at b4a.example.starter.onCreate(starter.java:38)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2761)
... 9 more
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at b4a.example.starter.onCreate(starter.java:36)
... 10 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'b4a.example.starter b4a.example.shootingservice._starter' on a null object reference
at b4a.example.main.initializeProcessGlobals(main.java:395)
... 13 more
Caused by: java.lang.NullPointerException: Attempt to read from field 'b4a.example.starter b4a.example.shootingservice._starter' on a null object reference
at b4a.example.shootingservice._process_globals(shootingservice.java:218)
at b4a.example.main.initializeProcessGlobals(main.java:392)
... 13 more

I am using a library which requires to be run the first time on an activity since it uses "StartActivityForResult" and I get the result from "onActivityResult" in the activity through an event. In the event, I check if permission was granted and if yes, I call a service which uses the same library.

In order to use the same instance of the library and to be able to call its events in the service, I created a new instance of the library and copy the previous instance. When I do this, the IDE creates a Warning #24 ("Accessing fields from other modules in Sub Process_Globals can be dangerous as the initialization order is not deterministic.") but the code works in debug-mode although it crashes in release-mode.

It is easier to show the problem with some extracts of the code:

Starter:

B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    Public rec As ContinuousScreenShots
End Sub

Sub Service_Create
    rec.Initialize("rec")
End Sub

Main:
B4X:
'initial code
'....................

Sub btnStart_Click
    Starter.rec.GetPermission
End Sub

Sub rec_PermissionResult(Granted As Boolean)
    StartService(ShootingService)
End Sub

ShootingService:
B4X:
#Region  Service Attributes
    #StartAtBoot: False
  
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
  
    Private mRec As ContinuousScreenShots = Starter.rec 'work fine debug-mode
End Sub

Sub Service_Create
    mRec.Initialize("mRec")
End Sub

Sub Service_Start (StartingIntent As Intent)
    mRec.StartShooting(Starter.rec.BITMAP,40,"","",1)
End Sub

Sub Service_Destroy

End Sub

Sub mRec_Result (Success As Boolean) 'I need to get this event to trigger
    If Success Then
        'code goes here
    End If
End Sub

I guess, simply put, how do I use the same instance (and its events) of a library both in Activity and in a Service?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The question should be: "how to use the same object instance in two modules?".

As the warning says, you should never access a variable from a different module in Process_Globals sub as the order is not deterministic.

Why do you need it to be declared in two modules?

I would have removed the ShootingService completely and only use the Starter service. This is the simplest and safest solution.
The second option is to remove it from the starter service and start ShootingService from the starter service.
Initialize ContinuousScreenShots in ShootingService and use CallSubDelayed to call a sub in the main module that will start the UI related task.
Once it completes use CallSubDelayed to call a sub in ShootingService and call StartShooting.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Come potrebbe sapere, la libreria, a quale modulo inviare gli eventi? Li invia al modulo in cui è stata dichiarata.
Inoltre, stai tentando di rendere privata e quindi locale una variabile dichiarata pubblica in precedenza.
Devo leggere la risposa già arrivata e poi tradurre :)


"Devo leggere la risposa già arrivata e poi tradurre :)" means:
"I have to read the answer already arrived and the translate my post"
as I was writing my answer, someone :) else wrote.

My answer means (more or less):
"How the library can decide which module should receive the events?
Also, you're trying to declare as Private - and then local - a variable already declared as Public elsewhere"
 
Last edited:
Upvote 0

moster67

Expert
Licensed User
Longtime User
I would have removed the ShootingService completely and only use the Starter service. This is the simplest and safest solution.
I did as you suggested and indeed it resolved everything. Thanks. Didn't strike me that the Starter-module is actually a Service.
 
Last edited:
Upvote 0
Top