Android Tutorial Intent Filters - Intercepting SMS messages in the background

Status
Not open for further replies.
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:

DonManfred

Expert
Licensed User
But I want to know what code i need to write in Service_Destroy if I wanted to stop the service by calling StopService () (if it is possible to stop the service...)
Thanks a lot.
Maybe this thread could be of interest for your issue?
 

Bangdido

Member
Licensed User
Hello Erel.

i have problems with this inssue,
following the tutorial, I made an application to intercept sms,
BUT it seems that is not working,

the SMS arrives first (i see the OS notification) and then the interceptor get the sms, how can i hide the notification?

this is my code.
p.d. the device have android 4.4.2

B4X:
Main Activity
Sub Activity_Create(FirstTime As Boolean)
  StartService(Servicio)
End Sub

Service
#Region  Service Attributes
   #StartAtBoot: True
#End Region

Sub Process_Globals
  Dim N As Notification
  Dim SI As SmsInterceptor
End Sub

Sub Service_Create
  Log("Servicio SMS Interceptor Creado")
  ' Establecimiento de las Propiedades de Notificación
  N.Initialize
  N.Icon  = "icon"
  N.Sound  = False
  N.Vibrate  = False
  N.Light  = False
  N.OnGoingEvent = True
  N.SetInfo("GPS Guardian", "GPS Guardian v1.0", Main)
  N.Notify(1)
   Service.StartForeground(1,N)
   SI.Initialize2("SI",2147483647)
End Sub

Sub Service_Start (StartingIntent As Intent)
  Log("Servicio SMS Interceptor Iniciado")
End Sub

Sub Service_Destroy
  Log("Servicio SMS Interceptor Destruido")
  N.Cancel(1)
End Sub

Sub SI_MessageReceived (From As String, Body As String) As Boolean
  Dim Rst As Boolean
   Rst = False
  If From="5050" Then  ' Is the SMS what i need ?
    Rst = True
    Log("Interceptando SMS desde " & From & " - " & Body)
   Else
    Log("SMS desde "  & From & " - " & Body)
   End If
   Return(Rst)
End Sub
 
Last edited:

fransvlaarhoven

Active Member
Licensed User
Hallo,

is there a way to register an app in such a way that it becomes "the home app", the first app to start after the system boots?

Maybe with a static receiver in the manifest?
 

koaunglay

Member
Licensed User
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
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

Hi Erel! I'm trying block incoming sms. But I can't.
Please see this post
http://stackoverflow.com/questions/11194330/block-incoming-texts-android
And teach me please how to use in B4a. I don't understand Eclipse code. So help me Erel or somebody. Please!
 

John Decowski

Member
Licensed User
I want to check my database for updates even while the app is closed and then send a notification to user of a new message. What is the best approach using this technique?
 

John Decowski

Member
Licensed User
I notice this example for phone sms intent. How can i modify manifest to call program every so often? I want my app to refresh its data every 5 minutes even when app is closed. I know a lot of users close apps. I noticed the manifest file listed above calls upon phone sms how would i modify to call my app after a time delay instead?
Thanks really appreciate it guys!
 

BarryW

Active Member
Licensed User
can we intercept message even if the service is been stop on android settings (force stop)... Tnx...
 

haddad

Member
Licensed User
hello ,

i want to send data ( login an password ) from activity A to activity B with intent how can i do ?

thinks
 
Status
Not open for further replies.
Top