Android Tutorial Intent Filters - Intercepting SMS messages in the background

Status
Not open for further replies.
Old tutorial. Don't use services. Use receivers.
Broadcast receivers are program components that can handle broadcasted messages. These messages usually notify about a system event.

There are two types of receivers in Android: statically registered receivers and dynamically registered receivers.

Static registered receivers are receivers that are declared in the manifest file.
Dynamic registered receivers are registered at runtime by calling the Java registerReceiver method.

In Basic4android you can register dynamic receivers with the BroadcastReceiver library. PhoneEvents and SmsInterceptor objects from the Phone library also use dynamic registration to listen for common intents.

Difference between static and dynamic receivers
The main difference between the two types of receivers is that dynamic receivers listen to intents as long as the process is running.

Static receivers always work. If the process is not running then it will be created.

Normal processes eventually get killed. This means that you cannot rely on dynamic receivers to intercept intents when your application is in the background. A possible workaround is to call Service.StartForeground in the service. This will prevent the process from being killed. However this will also add an ongoing notification icon (see the Services tutorial for more information).

So if you need to always listen for a specific type of intents then you may prefer to use a static receiver. Note that some intents can only be intercepted with dynamic receivers.

Static receivers
Each service module in Basic4android is made of two components. The service and a receiver. The receiver responsibility is to delegate broadcast intents to the service. For example when you call StartServiceAt, it is the receiver that actually intercepts the intent and wakes the service.

If we want to listen for intents we need to define an intent filter in the manifest file. See this link for more information about intent filters.

For example if we want to listen for intents with the action: android.provider.Telephony.SMS_RECEIVED we will need to add the following manifest editor code:
B4X:
AddPermission(android.permission.RECEIVE_SMS)
AddReceiverText(s1,
<intent-filter>
    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>)
s1 is the name of the service module that the intent will be delegated to.
We also add the RECEIVE_SMS permission which is required in this case.

Once this program is installed the service will be started each time that an Sms message arrives. It doesn't matter whether the process is running or not.

In our Service_Start event we check the intent action. If it fits then the messages will be parsed from the intent. This is done with the help of the Reflection library:
B4X:
'Service module
Sub Process_Globals
   Type Message (Address As String, Body As String)
End Sub
Sub Service_Create

End Sub

Sub Service_Start(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))
      Next
   End If
   Service.StopAutomaticForeground
End Sub

'Parses an SMS intent and returns an array of messages
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")
      Next
   End If
   Return messages
End Sub

Update 2018: Static intent filters will cause the service to start while the app is not in the foreground. This means that on newer devices it will only work with B4A v8+ and that we need to call Service.StopAutomaticForeground once the task has completed.
https://www.b4x.com/android/forum/threads/automatic-foreground-mode.90546/#post-572424
 
Last edited:

ilan

Expert
Licensed User
Longtime User
use the PhoneStateChangedevent from the PHONE lib.

thanx manfred, but i will still need that intent filter right?
i need to add it to the manifest and create a service where the recording start when a call was answered or a call was performed

how would the manifest permission look like?

AddPermission(android.permission.CALL)
AddReceiverText(s1,
<intent-filter>
<action android:name="android.provider.Telephony.CALL_RECEIVED" />
</intent-filter>)

???
 

DonManfred

Expert
Licensed User
Longtime User

susu

Well-Known Member
Licensed User
Longtime User
'Parses an SMS intent and returns an array of messages
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")
Next
End If
Return messages
End Sub

With this code I can get SMS body and sender number, how can I get the date of SMS? Thanks.
 

volond_sespel

New Member
Licensed User
Longtime User
I looked at the phone library:sign0085:, but I do not understand how to catch the action "send message", since I will not get this from the log, but I would like that every time they send is stored in a db, even if the user deletes the sms ...
Found a solution?
 

kisoft

Well-Known Member
Licensed User
Longtime User
This filter does not work when the screen is locked with a password, how to bypass it
 

Croïd

Active Member
Licensed User
Longtime User
is it possible to block the number of sending (only 1 sms) same correspondent or same number phone ?
 
Status
Not open for further replies.
Top