Android Tutorial Intent Filters - Intercepting SMS messages in the background

Discussion in 'Tutorials & Examples' started by Erel, Aug 2, 2012.

Thread Status:
Not open for further replies.
  1. Erel

    Erel Administrator Staff 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:
    Code:
    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:
    Code:
    '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 IntentAs 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: Mar 12, 2018
  2. sconlon

    sconlon Active Member Licensed User

    Thanks for the info Erel it seems to be what I need. However, when I added an S1 service module to my app with the code you gave and made the changes to the manifest file I got the following java error in the log:

    java.lang.Exception: Sub service_create signature does not match expected signature.

    and a msgbox on screen saying "Sorry!" The application has stopped unexpectedly, Please try again.

    What have I done wrong or failed to do?

    Thanks.
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    Please start a new thread for this question and also upload your project (File - Export as zip).
     
  4. flyingbag

    flyingbag Member Licensed User

    Using this method of SMS interception: I am wondering if there is a way to "trap" the intercepted message and not display to the user in the SMS manager

    Just like in SMS Interceptor, you can return "True" from the handling sub to prevent this SMS being shown to the user...

    Thanks
    flyingbag
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    You will not be able to abort the broadcast with the static intent filter.
     
  6. lymey

    lymey Active Member Licensed User

    Intercepting multi part sms

    I am working on a project that will receive large sms messages..i.e multipart messages.
    Since the interceptor receives one part at a time as a separate SMS, is there a way of looking at the UDH so that I can piece the messages together or some way that the interceptor can concatenate the messages into a single message?

    Thanks!
    :sign0104:
     
  7. asillato

    asillato New Member Licensed User

    SMS over 160 chars

    Hi guys,

    do you know if Phone Library implements SMS_Interceptor for sms with most of 160 chars?

    TX
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    It is not documented. You will need to test it. It seems from the native source code that it should handle multipart messages correctly.
     
  9. djpero

    djpero Member Licensed User

    Hi Erel,

    it is late to initialize sms interceptor on intent action SMS_RECEIVED? I cannot get into SI_MessageReceived Sub.

    Thnx
     
  10. djpero

    djpero Member Licensed User

    Yes it is possible but another app is blocking sms_intercept to work.
     
  11. airblaster

    airblaster Active Member Licensed User

    Hi Erel,

    I'm trying to use your method to intercept Share Intents (android.intent.action.SEND) and search intents (android.intent.action.SEARCH).
    But for some reason I don't get it working.

    I've added the following Code to the manifest editor:
    Code:
    AddReceiverText(SuchIntent, 
    <
    intent-filter>
        <action android:name=
    "android.intent.action.SEND" />
        <category android:name=
    "android.intent.category.DEFAULT" />
       <data android:mimeType=
    "text/plain" />
    </
    intent-filter>)
    AddReceiverText(SuchIntent, 
    <
    intent-filter>
        <action android:name=
    "android.intent.action.SEARCH" />
        <category android:name=
    "android.intent.category.DEFAULT" />
    </
    intent-filter>)
    The service Module "SuchIntent" contains the following code:
    Code:
    'Service module
    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

    End Sub

    Sub Service_Start (StartingIntent As Intent)
       
    Dim keyword As String
       
    If StartingIntent.Action = "android.intent.action.SEND" Then
          keyword = StartingIntent.GetExtra(
    "android.intent.extra.TEXT")
           
    Log("Extras:"&StartingIntent.ExtrasToString)
          
    Log("GetData:"&StartingIntent.GetData)
          
    Log("GetExtra"&StartingIntent.GetExtra("android.intent.extra.TEXT"))
          
    Log(StartingIntent.HasExtra("EXTRA_TEXT"))
       
    Else If StartingIntent.Action = "android.intent.action.SEARCH" Then
          keyword = StartingIntent.GetExtra(
    "query")
       
    Else
          
    Return
        
    End If   
       Suche.SearchState = Suche.SS_RESULT_SUCCESS
       Suche.SearchResult = keyword
       DB.AddVerlauf(keyword)
       
    StartActivity(Suche)   
    End Sub

    Sub Service_Destroy

    End Sub
    If I open the phones browser, select some text and the either click on Share or Search my Application isn't shown in the list.

    Is there something wrong with my code, or is this a Bug in B4A?
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    The SEND intent is sent to an activity not receiver. You should add the intent filter to an activity.
     
  13. airblaster

    airblaster Active Member Licensed User

    Hi Erel,

    thanks for pointing this out. I changed the Manifest text to:
    Code:
    AddActivityText(SuchIntent, 
    <
    intent-filter>
        <action android:name=
    "android.intent.action.SEND" />
        <category android:name=
    "android.intent.category.DEFAULT" />
       <data android:mimeType=
    "text/plain" />
    </
    intent-filter>)
    AddActivityText(SuchIntent, 
    <
    intent-filter>
        <action android:name=
    "android.intent.action.SEARCH" />
        <category android:name=
    "android.intent.category.DEFAULT" />
    </
    intent-filter>)
    For some reason, the Application still doesn't appear in the Share popup.
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    Is SuchIntent an activity? Try to change the mimeType to text/* or */*.
     
  15. airblaster

    airblaster Active Member Licensed User

    Just figured it out myself: The intent doesn't work in Service Modules, but it works in Activity Modules.
     
  16. zekigultekin

    zekigultekin Member Licensed User

    SmsInterceptor problem

    when i received new sms i have this error. how can i solve it ??


    java.lang.RuntimeException: Error receiving broadcast Intent { act=android.provider.Telephony.SMS_RECEIVED flg=0x30 (has extras) } in anywheresoftware.b4a.phone.PhoneEvents$SMSIntercep tor$1@426deee8

    :sign0085:
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    Please start a new thread for this question. And also include the full error message from the logs.
     
  18. guidoarfini

    guidoarfini Member Licensed User

    android.provider.Telephony.SMS_SENT

    i have add in manifest

    <action android:name="android.provider.Telephony.SMS_SENT" />

    AddPermission(android.permission.RECEIVE_SMS)
    AddReceiverText(SerSMS,
    <intent-filter>
    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    <action android:name="android.provider.Telephony.SMS_SENT" />
    </intent-filter>)

    but.... how do intercept sms sent in Service?
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    Where did you see this action? I don't think that there is such an intent in Android. Note that the updated Phone library allows you to track outgoing messages (when your process is running).
     
  20. guidoarfini

    guidoarfini Member Licensed User

Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice