Android Question java.lang.NullPointerException

Arnaud

Active Member
Licensed User
Longtime User
Hello,


I have the same error several times in the analyze in Google Play. Unfortunately I can not reproduce and know where this error comes from. I have try on several and different devices, different version of Android, all works fine on my devices.

to have an idea I have 106 times this same error (on different brand of smartphone) for about 4000 installations of the APP.

Can you help me or advice please?

java.lang.NullPointerException:
java.lang.NullPointerException:
  at sun.misc.FloatingDecimal.readJavaFormatString (FloatingDecimal.java:1838)
  at sun.misc.FloatingDecimal.parseDouble (FloatingDecimal.java:110)
  at java.lang.Double.parseDouble (Double.java:538)
  at anywheresoftware.b4a.keywords.Common.IsNumber (Common.java:810)
  at b4a.ALFANO_6.codedivers._wordandroidcsv (codedivers.java:1358)
  at b4a.ALFANO_6.choixsession._activity_create (choixsession.java:803)
  at java.lang.reflect.Method.invoke (Native Method)
  at anywheresoftware.b4a.BA.raiseEvent2 (BA.java:213)
  at b4a.ALFANO_6.choixsession.afterFirstLayout (choixsession.java:105)
  at b4a.ALFANO_6.choixsession.access$000 (choixsession.java:17)
  at b4a.ALFANO_6.choixsession$WaitForLayout.run (choixsession.java:83)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8669)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1135)

Activity_Create:
Sub Activity_Create(FirstTime As Boolean)

        Activity.LoadLayout("LayoutChoixSessionDesign")
'        ProgressDialogShow2(CodeDivers.WordAndroidCSV(72),False)

        LabelTitre.TextSize=20*Main.Scale
        LabelTitre.Text=CodeDivers.WordAndroidCSV(78)

        height=35dip
        height_isolation=5dip

        '--------------------------- entete ----------------------------------------------
       
        ScrollViewEnteteSession.Initialize(0%x, 0, "ScrollViewEnteteSession")
        pnl_session_entete_dans_le_chrono.Initialize(0)
        ScrollViewEnteteSession.Panel.AddView(pnl_session_entete_dans_le_chrono,0%x,0%y,165%x,0%y)
        PanelChoixSession.AddView(ScrollViewEnteteSession, 0%x, 5%y, PanelChoixSession.Width, 10%y)

        ScrollViewEnteteSession.Color=Colors.transparent
        ScrollViewEnteteSession.Panel.Height=10%y
        ScrollViewEnteteSession.Panel.Width=165%x
   
        ScrollViewEnteteSession.ScrollbarsVisibility(False,False)
        ScrollViewEnteteSession.Enabled=False
        affichage_entete_session

        '--------------------------- session ----------------------------------------------
       
        ScrollViewSession.Initialize(0%x, 0, "ScrollViewSession")
        pnl_session_dans_le_chrono.Initialize(0)
        ScrollViewSession.Panel.AddView(pnl_session_dans_le_chrono,0%x,0%y,165%x,0%y)
        PanelChoixSession.AddView(ScrollViewSession, 0%x,ScrollViewEnteteSession.Top+ScrollViewEnteteSession.Height, PanelChoixSession.Width, PanelChoixSession.Height-5%y-ScrollViewEnteteSession.Height-ScrollViewEnteteSession.Top)

        ScrollViewSession.Color=Colors.transparent
        '----------------------------------------------------------------------------------

        ButtonAnnuler.TextSize=24*Main.Scale
        ButtonValider.TextSize=24*Main.Scale

        filtre_track.Initialize
        filtre_track.liste_Filtre_partiel.Initialize
        filtre_track.liste_Filtre_partiel.Clear
        filtre_track.liste_Filtre_complete.Initialize
        filtre_track.liste_Filtre_complete.Clear
   
        filtre_pilote.Initialize
        filtre_pilote.liste_Filtre_partiel.Initialize
        filtre_pilote.liste_Filtre_partiel.Clear
        filtre_pilote.liste_Filtre_complete.Initialize
        filtre_pilote.liste_Filtre_complete.Clear

        filtre_TestType.Initialize
        filtre_TestType.liste_Filtre_partiel.Initialize
        filtre_TestType.liste_Filtre_partiel.Clear
        filtre_TestType.liste_Filtre_complete.Initialize
        filtre_TestType.liste_Filtre_complete.Clear

        filtre_categorie.Initialize
        filtre_categorie.liste_Filtre_partiel.Initialize
        filtre_categorie.liste_Filtre_partiel.Clear
        filtre_categorie.liste_Filtre_complete.Initialize
        filtre_categorie.liste_Filtre_complete.Clear

        filtre_classeur.Initialize
        filtre_classeur.liste_Filtre_partiel.Initialize
        filtre_classeur.liste_Filtre_partiel.Clear
        filtre_classeur.liste_Filtre_complete.Initialize
        filtre_classeur.liste_Filtre_complete.Clear
           
        filtre_annee.Initialize
        filtre_annee.liste_Filtre_partiel.Initialize
        filtre_annee.liste_Filtre_partiel.Clear
        filtre_annee.liste_Filtre_complete.Initialize
        filtre_annee.liste_Filtre_complete.Clear

        filtre_TypeAlfano.Initialize
        filtre_TypeAlfano.liste_Filtre_partiel.Initialize
        filtre_TypeAlfano.liste_Filtre_partiel.Clear
        filtre_TypeAlfano.liste_Filtre_complete.Initialize
        filtre_TypeAlfano.liste_Filtre_complete.Clear


        filtre_date.Initialize
        filtre_date.liste_Filtre_partiel.Initialize
        filtre_date.liste_Filtre_partiel.Clear
        filtre_date.liste_Filtre_complete.Initialize
        filtre_date.liste_Filtre_complete.Clear

           
        DateTime.DateFormat = "dd-MM-yyyy"
        DateTime.TimeFormat = "HH:mm:ss"
   
        Main.menu="recuperation des sessions"

End Sub

WordAndroidCSV:
Sub WordAndroidCSV(ID As Int) As String

    If IsNumber(Main.configuration.language)=False Then
        Main.configuration.language=3      
    End If

    Private su As StringUtils
    Dim l As List
    l.Initialize
    l = su.LoadCSV(File.DirAssets, "WordAndroidCSV.csv", ";")

    If ID>=l.size Then
        Return ""
    End If
   
    Dim line() As String
    line=l.Get(ID)
   
    If Main.configuration.language<line.Length-1 Then
        Return line(Main.configuration.language+1)
    Else
       
        Dim TextReader1 As TextReader
        If Main.configuration.language=line.Length-1 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "hongrois.txt"))
        else If Main.configuration.language=line.Length Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "japan.txt"))
        else If Main.configuration.language=line.Length+1 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "grec.txt"))
        else If Main.configuration.language=line.Length+2 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "russe.txt"))
        Else If Main.configuration.language=line.Length+3 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "chinois.txt"))
        else If Main.configuration.language=line.Length+4 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "thailandais.txt"))
        Else If Main.configuration.language=line.Length+5 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "polonais.txt"))
        Else If Main.configuration.language=line.Length+6 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "arabe.txt"))
        Else If Main.configuration.language=line.Length+7 Then
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "danois.txt"))
        Else
            TextReader1.Initialize(File.OpenInput(File.DirAssets, "turc.txt"))
        End If
       
        Dim s As String
            s = TextReader1.ReadLine  
        For i=0 To ID-1
              s = TextReader1.ReadLine
        Next
        TextReader1.Close
 
         Return s
    End If

End Sub
 

agraham

Expert
Licensed User
Longtime User
That's a bit weird. The error seems to be in the IsNumber keyword call but IsNumber looks like this
Java:
  public static boolean IsNumber(String Text) {
    try {
      Double.parseDouble(Text);
      return true;
    } catch (NumberFormatException e) {
      return false;
    }
  }
From what I can see on the web FloatingDecimal.readJavaFormatString throws a NullPointerException if asked to parse a null value. However the parseDouble call is protected by a try...catch block which should swallow any exception. I cannot explain why it appears not to in this situation.
EDIT: Oh Yes I can!. See the next post.

Unless Erel can come up with something I would suggest a hack like the following
B4X:
    If Main.configuration.language = Null OR IsNumber(Main.configuration.language)=False Then
        Main.configuration.language=3    
    End If
If the Null check succeeds the OR should short circuit the logical evaluation and not try the IsNumber call hopefully avoiding the exception,
 
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
Ah! Silly me - I failed to notice

catch (NumberFormatException e)

So it won't catch the NullPointerException so you need that extra Null test to avoid passing Null to IsNumber. I can't reproduce it within B4A as it changes the value of Null to "null" when casting values to strings.

What is Main.configuration.language that appears to sometimes be a null?

EDIT: You could also put your own Try...Catch around the IsNumber call.
 
Last edited:
Upvote 0

Arnaud

Active Member
Licensed User
Longtime User
Thanks for your feedback.

Main.configuration.language must have always have a value beetwen 0 and 15.

I had add the line by precaution

Main.configuration.language:
    If IsNumber(Main.configuration.language)=False Then
        Main.configuration.language=3     
    End If

Main.configuration.language=3 give then all text in the APP in "English" .

I have try to force Main.configuration.language=Null for test and at Main.configuration.language="" also for test, the code above works fine and correct the code at
Main.configuration.language=3.

So, in all case, impossible for me to reproduce the error and the crash of APP. I will compile a new version with the function "catch" and I will see the result in Google Play Console.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
Main.configuration.language is a string
As a string value that explain why it can have a null value. But where is it declared? I assume it must be in a Java library because any attempt to declare it and assign a null will not work within B4A. And it's puzzling as to why on a very few occasions it does have that null value!
 
Upvote 0

Arnaud

Active Member
Licensed User
Longtime User
The configuration just below is declared in Sub Process_Globals in the Main module
The configuration contains for example the language, the unit (°C or °F), unit speed (kmh or mph), color of the graph etc..., all setting for the customer.
I initialize the variable configuration.language when the APP start in the Activity_Create in the Main module, with Sub detection_language .

I don't know if this can be usefulI don't know if this can be use...


Main:
Sub Process_Globals
    
    Dim configuration As configuration_

end sub



The type "configuration_" is declared in a other code module

configuration:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    
    Type configuration_ (FastDownload As String,Unit_pression As String,gforce_lie As String,DataDynamique As String,canal_vitesse_conversion_distance As String, type_connection As String, echelle_kart_distance As String,echelle_kart_temps As String, disposition As String, mode_professionel As String,trieLap As String,nbre_lap_analyser_par_defaut As Int ,amplitude_optimisee As Boolean,dip_axe As Int,vehicule As String,couleur_session(20) As Int,name As String,filtre_gear_box As Int,couleur_de_fond As Int,time_distance As String,orientation As Int,mapping As Boolean,Quadrillage As Int,  Auto_disposition As Boolean, Unit_Degree_fahrenheit As Int,Unit_kmh_mph As Int,language As String,format_date_heure As Int, canal_channel(5) As canal_)

    Private su As StringUtils
    Dim rp As RuntimePermissions

End Sub

selection automatic of the language in the main:
Sub detection_language


       Log("Langue "& GetDefaultLanguage)
 
    Dim langue As Int
    If GetDefaultLanguage.Contains("fr") Then
        langue=0
    else If GetDefaultLanguage.Contains("it") Then
        langue=1
    else If GetDefaultLanguage.Contains("de") Then
        langue=2
    else If GetDefaultLanguage.Contains("es") Then
        langue=4
    else If GetDefaultLanguage.Contains("pt") Then
        langue=5
    else If GetDefaultLanguage.Contains("nl") Then
        langue=6
    else If GetDefaultLanguage.Contains("sv") Then
        langue=7
    else If GetDefaultLanguage.Contains("no") Then
        langue=8
    else If GetDefaultLanguage.Contains("fi") Then
        langue=9
    else If GetDefaultLanguage.Contains("hu") Then
        langue=10
    else If GetDefaultLanguage.Contains("jp") Then
        langue=11
    else If GetDefaultLanguage.Contains("el") Then
        langue=12
    else If GetDefaultLanguage.Contains("ru") Then
        langue=13
    else If GetDefaultLanguage.Contains("cn") Then
        langue=14
    else If GetDefaultLanguage.Contains("th") Then
        langue=15
    else If GetDefaultLanguage.Contains("pl") Then
        langue=16
    Else
        langue=3  'en
    End If 

    Main.configuration.language=langue   

End Sub
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I've managed to reproduce the IsNumber null error within B4A. If you don't initialize a type instance the string items contain null rather than empty strings.
B4X:
Sub Button1_Click
    Dim x As configuration_
    If IsNumber(x.language)=False Then ' NullPointerException here
        Log("False")
    End If
End Sub
Is there any chance that under some circumstance your Sub detection_language is not being called before your IsNumber test? Like a Wait For in Activity_Create?
 
Upvote 0

Arnaud

Active Member
Licensed User
Longtime User
Thanks @agraham ,

I have reproduce also the bug with your help.

I have a Wait For in the Activity_Create for the permission, below the code :

But if you don't accept the permission, you cannot continue in the APP, you cannot then access to the Sub WordAndroidCSV(ID As Int) As String

I don't see how the type configuration can be not initialized in the sub WordAndroidCSV.

Activity_Create in the Main:
Sub Activity_Create(FirstTime As Boolean)

    If FirstTime Then
 
    End If

    menu="main first time"

    Activity.LoadLayout("LayoutMenuPrincipal")
    
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result=False Then
        ToastMessageShow("No permission...", False)
        Return
    End If

    rp.CheckAndRequest(rp.PERMISSION_READ_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result=False Then
        ToastMessageShow("No permission...", False)
        Return
    End If

    rp.CheckAndRequest(rp.PERMISSION_ACCESS_FINE_LOCATION)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result = False Then
        ToastMessageShow("No permission...", False)
        Return
    End If
    

    configuration.Initialize
    configuration.canal_channel(0).Initialize   
    configuration.canal_channel(1).Initialize   
    configuration.canal_channel(2).Initialize   
    configuration.canal_channel(3).Initialize   
    configuration.canal_channel(4).Initialize   

    SaveParametre.detection_language

    ......
    
end sub
 
Upvote 0

Arnaud

Active Member
Licensed User
Longtime User
to improve also this, I will move the code below

configuration Initialize:
    configuration.Initialize
    configuration.canal_channel(0).Initialize   
    configuration.canal_channel(1).Initialize   
    configuration.canal_channel(2).Initialize   
    configuration.canal_channel(3).Initialize   
    configuration.canal_channel(4).Initialize   

    SaveParametre.detection_language

before the permission and the Wait For.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
If you do a Wait For in Activity_Create then it will exit Activity_Create and immediately run Activity_Resume before re-entering Activity_Create later so this is a timing 'hole' that gives an opportunity for Activity_Resume or possibly another event to access something that isn't initialised before Wait For is called so this is a 'feature' to be aware of.

Moving the initialisation before any Wait For is a good protective measure.
 
Upvote 0

Arnaud

Active Member
Licensed User
Longtime User
Thank you very much for your help agraham, I will modify and compile a new version the next month, I will see then the feedback.
 
Upvote 0
Top