Android Question Problem with SMS reception

Filippo

Expert
Licensed User
Longtime User
Hi,

I have written an app just for my private use, with which I can make phone calls and write and receive text messages.
Everything works very well, but occasionally the SMS reception does not work if the app is not used for a longer period of time.
This usually happens when PayPal sends me an SMS to confirm a purchase.
The first SMS is not received, I have to ask PayPal to send a second SMS.
Am I doing something wrong or is something missing?

It would be nice if someone has encountered the same problem and found a solution.

This is the manifest:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.basic4ppc.com/forum/showthread.php?p=78136
AddManifestText(
'<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
'SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

AddPermission(android.permission.READ_CONTACTS)
AddPermission(android.permission.WRITE_CONTACTS)
AddPermission(android.permission.READ_SMS)
AddPermission(android.permission.WRITE_SMS)
AddPermission(android.permission.SMS_DELIVER)
AddPermission(android.permission.SEND_SMS)

'Einstellung für Adaptive-icon
SetApplicationAttribute(android:icon, "@mipmap/ic_launcher")
CreateResource(mipmap-anydpi-v26, ic_launcher.xml,
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@mipmap/background"/>
    <foreground android:drawable="@mipmap/foreground"/>
</adaptive-icon>
)

'************ Android-Themen ************
SetApplicationAttribute(android:theme, "@style/MyAppTheme")
CreateResource(values, theme.xml,
<resources>
    <style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">#3f51b5</item>
        <item name="colorPrimaryDark">#303f9f</item>
        <item name="colorAccent">#448aff</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>

<style name="ToolbarMenu" parent="Base.ThemeOverlay.AppCompat.ActionBar">
    <item name="android:textColorPrimary">#fff</item>
    <item name="android:colorBackground">#0098FF</item>
   </style>
</resources>
)

'********* TabStrip ***********************
CreateResource(drawable, background_tab.xml,
<selector xmlns:android="http://schemas.android.com/apk/res/android"
   android:exitFadeDuration="@android:integer/config_shortAnimTime">
  <item android:state_pressed="true" android:drawable="@color/background_tab_pressed" />
  <item android:state_focused="true" android:drawable="@color/background_tab_pressed"/>
  <item android:drawable="@android:color/transparent"/>
</selector>)
CreateResource(values, colors.xml,
<resources>
  <color name="background_tab_pressed">#6633B5E5</color>
</resources>)
'******************************************


'Turns out you need to manage all the options or it will not be listed. You need to have three services and add this code:
AddPermission(android.permission.RECEIVE_SMS)
AddReceiverText(svSMS,
<intent-filter>
    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>)

SetReceiverAttribute(service1, android:permission, "android.permission.BROADCAST_SMS")
AddReceiverText(service1, <intent-filter>
  <action android:name="android.provider.Telephony.SMS_DELIVER" />
  </intent-filter>
)
SetReceiverAttribute(service2, android:permission, "android.permission.BROADCAST_WAP_PUSH")
AddReceiverText(service2,  <intent-filter>
  <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
  <data android:mimeType="application/vnd.wap.mms-message" />
  </intent-filter>
)
SetServiceAttribute(service3, android:permission, "android.permission.SEND_RESPOND_VIA_MESSAGE")
SetServiceAttribute(service3, android:exported, "true")
AddServiceText(service3,  <intent-filter>
  <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:scheme="sms" />
  <data android:scheme="smsto" />
  <data android:scheme="mms" />
  <data android:scheme="mmsto" />
  </intent-filter>
)
AddActivityText(main,
 <intent-filter>
  <action android:name="android.intent.action.SEND" />   
  <action android:name="android.intent.action.SENDTO" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="sms" />
  <data android:scheme="smsto" />
  <data android:scheme="mms" />
  <data android:scheme="mmsto" />
  </intent-filter>
)

My Receiver-Service:
B4X:
Sub Process_Globals
    Type Message (Address As String, Body As String, Date As Long)
End Sub

'Called when an intent is received.
'Do not assume that anything else, including the starter service, has run before this method.
Private Sub Receiver_Receive (FirstTime As Boolean, StartingIntent As Intent)
    If StartingIntent.Action = "android.provider.Telephony.SMS_RECEIVED" Then
        Dim messages() As Message
        messages = ParseSmsIntent(StartingIntent)
        For i = 0 To messages.Length - 1
'            Log(messages(i))
            SMS_Notification(Starter.getTelefonNumber(messages(i).Address), messages(i).Body)
            InsertSMS(messages(i))
        Next
    End If
End Sub

'Parses an SMS intent and returns an array of messages
Private Sub ParseSmsIntent (in As Intent) As Message()
    Dim messages() As Message
    If in.HasExtra("pdus") = False Then Return messages
    Dim pdus() As Object
    Dim r As Reflector
    pdus = in.GetExtra("pdus")
    If pdus.Length > 0 Then
        Dim messages(pdus.Length) As Message
        For i = 0 To pdus.Length - 1
            r.Target = r.RunStaticMethod("android.telephony.SmsMessage", "createFromPdu", _
            Array As Object(pdus(i)), Array As String("[B"))
            messages(i).Body = r.RunMethod("getMessageBody")
            messages(i).Address = r.RunMethod("getOriginatingAddress")
            messages(i).Date = r.RunMethod("getTimestampMillis")
            messages(i).Date = r.RunMethod("getTimestampMillis")
        Next
    End If
    Return messages
End Sub

private Sub SMS_Notification(contact As String, message As String)
    Dim n As NB6
    n.Initialize("default", Application.LabelName, "HIGH").AutoCancel(True).SmallIcon(Application.Icon)
    n.Build(contact, message, "tag1", mReadSMS).Notify(4) 'It will be Main (or any other activity) instead of Me if called from a service.
End Sub

private Sub InsertSMS(sms As Message)
    Dim resolver As ContentResolver
    resolver.Initialize("res")
    Dim values As ContentValues
    values.Initialize
    values.PutString("address", sms.Address)
    values.PutString("body", sms.Body)
    values.PutString("read", "1")
    values.PutString("subject", "subject")
    values.PutLong("date", sms.date)

    Dim Uri1 As Uri
    Uri1.parse("content://sms/inbox")

    Try
        resolver.Insert(Uri1, values).ParseId
    Catch
        MsgboxAsync(LastException,"")
    End Try
End Sub

My Starter-Service:
B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    '...
End Sub

Sub Service_Create
    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.
    '...
End Sub

Sub Service_Start (StartingIntent As Intent)
    Service.StopAutomaticForeground 'Starter service can start in the foreground state in some edge cases.
End Sub

Sub Service_TaskRemoved
    'This event will be raised when the user removes the app from the recent apps list.
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub
 

Filippo

Expert
Licensed User
Longtime User
MsgboxAsync(LastException,"") <-- this will not work in a receiver or service. It will cause the process to crash.

Worth checking the logs, immediately after missing a message. Maybe there will be an error there.
Thank you Erel for the answer.
The “MsgboxAsync” can also cause a crash, but that is not the case here.

Here is the log file:
Logger connected to: CTLGAP1890703438
--------- beginning of crash
--------- beginning of system
--------- beginning of main
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
** Activity (msms) Create (first time) **
** Activity (msms) Resume **
*** Service (smsendsms) Create ***
** Service (smsendsms) Start **
** Service (smsendsms) Destroy **
** Activity (msms) Pause, UserClosed = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
** Service (starter) Destroy (ignored)**
** Receiver (service1) OnReceive **
*** Receiver (svsms) Receive (first time) ***
starter_vvv6 (java line: 190)
java.lang.RuntimeException: Object should first be initialized (List).
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
at anywheresoftware.b4a.objects.collections.List.getSize(List.java:129)
at fg.PhoneForOver40.starter._vvv6(starter.java:190)
at fg.PhoneForOver40.svsms._receiver_receive(svsms.java:218)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
at fg.PhoneForOver40.svsms.onReceive(svsms.java:42)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3789)
at android.app.ActivityThread.access$1400(ActivityThread.java:220)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1871)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
java.lang.RuntimeException: Unable to start receiver fg.PhoneForOver40.svsms: java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (List).
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3798)
at android.app.ActivityThread.access$1400(ActivityThread.java:220)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1871)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (List).
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:258)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
at fg.PhoneForOver40.svsms.onReceive(svsms.java:42)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3789)
... 8 more
Caused by: java.lang.RuntimeException: Object should first be initialized (List).
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
at anywheresoftware.b4a.objects.collections.List.getSize(List.java:129)
at fg.PhoneForOver40.starter._vvv6(starter.java:190)
at fg.PhoneForOver40.svsms._receiver_receive(svsms.java:218)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
... 11 more
*** Service (starter) Create ***
stopping spontaneous created service
** Service (starter) Start **
** Service (starter) Destroy (ignored)**

The error I have now found is in this code:
The error that I have now found is in the sub “Receiver_Receive” in this function "Starter.getTelefonNumber"

Function in Starter-Service:
B4X:
Public Sub getTelefonNumber(Number As String) As String
    Dim Info As Kinfo
    Dim kontakts As kontakt
    Dim TelefonNumber As String = NormalizeNumber(Number)
    For I = 0 To myContactList.Size - 1
        Info = myContactList.get(I)
        kontakts = myContactMap.get(Info.contact_id)
        'Log(NormalizeNumber(kontakts.Number) & "=" & TelefonNumber)
        If NormalizeNumber(kontakts.Number) = TelefonNumber Then
            Return kontakts.DisplayName
        End If
    Next
    Return Number
End Sub

Private Sub NormalizeNumber(Number As String) As String
    Dim str As String = Number.Replace(" ", "")
    If Number.StartsWith("+") Then
        Return "0" & str.SubString(3)
    End If
    Return str
End Sub

The list “myContactList” and the map “myContactMap” are initialized in the starter service, but this is not started when receiving SMS, so the first SMS is not received. Only when I start the app normally, the 2 variables (myContactList and myContactMap) are initialized in the starter service.

Now I have to find a new way to initialize the 2 variables, or do you have a suggestion?
 
Upvote 0
Top