Android Question SEND_SMS location in background / SDK35 / FLAG_MUTABLE ?

Armani

Member
Hello All,

I'm making a really simple app to geolocalize my son phone on request (only with SMS - NO mobile data plan)
Not to be use in Google Play store, only personal use.

Application expected behavior:
Boot with phone and run 'forever' in background.
Intercept incoming SMS, if SMS coming from Authorize number and contain expected Keyword, then send back location by SMS

I use this tutorial as starting point; https://www.b4x.com/android/forum/threads/background-location-tracking.99873/#content
I add permissions and code for SEND_SMS / RECEIVE_SMS

Everything working perfectly on my Android 13 / SDK33 😁

But I got issues with my son phone Android 15 / SDK35 😭

As a temporary fix, I put targetSdkVersion = 33 in Manifest and it's working 🙏, but I immagine this will not work for long ??

- Please help me, give me a direction to solve this, FLAG_MUTABLE ???
- Or let me know if my temporary fix, targetSdkVersion = 33 is sufficient for a personnal use for long time ?

Many thanks !


Start of Error log:
tracker_gps_locationchanged (java line: 181)
java.lang.IllegalArgumentException: GetGPS.adu: Targeting U+ (version 34 and above) disallows creating or retrieving a PendingIntent with FLAG_MUTABLE, an implicit Intent within and without FLAG_NO_CREATE and FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for security reasons. To retrieve an already existing PendingIntent, use FLAG_NO_CREATE, however, to create a new PendingIntent with an implicit Intent use FLAG_IMMUTABLE.
 

Armani

Member
Hi Erel, thanks for your support.

Here, the full project and full error log.
I do not use notification.




Manifest:
'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: https://www.b4x.com/forum/showthread.php?p=78136

AddManifestText(   
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="35"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
CreateResourceFromFile(Macro, Themes.DarkTheme)
'End of default text.
SetServiceAttribute(Tracker, android:foregroundServiceType, "location")

AddPermission(android.permission.FOREGROUND_SERVICE_LOCATION)
AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)
AddPermission(android.permission.RECEIVE_BOOT_COMPLETED)

AddPermission(android.permission.RECEIVE_SMS)
AddPermission(android.permission.SEND_SMS)

AddReceiverText(StartAtBootReceiver,
<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>)


Main:
#Region  Project Attributes
    #ApplicationLabel: GetGPS
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
#BridgeLogger: true
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 Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Dim Permissions As List

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("main")

    Permissions.Initialize
    Permissions.Add(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
    Permissions.Add(Starter.rp.PERMISSION_SEND_SMS)
    Permissions.Add(Starter.rp.PERMISSION_RECEIVE_SMS)
    
    Permissions.Add(Starter.BACKGROUND_LOCATION_PERMISSION)
    
End Sub

Sub Activity_Resume
    
    For Each Permission As String In Permissions
        If Starter.rp.Check(Permission) = False Then
            Sleep(200)
            Starter.rp.CheckAndRequest(Permission)
            Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
            Log(Permission)
            If Result = False Then
                ToastMessageShow("No permission " & Permission, True)
                Starter.rp.CheckAndRequest(Permission)
                Sleep(200)
                Return
            End If
        End If
    Next
    

    
    
    
    
    
    ' TBC /
    Wait For (CheckAndRequestNotificationPermission) Complete (HasPermission As Boolean)
    If HasPermission = False Then
        Log("no permission")
        ToastMessageShow("no permission", True)
        Return
    End If
    
    
    ' TBC /
    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result Then
        If Starter.phone.SdkVersion >= 34 Then
            'This is only required for the case where the Tracker service is started after boot.
            'In other cases it is considered to be running in the foreground.
            If Starter.rp.Check(Starter.BACKGROUND_LOCATION_PERMISSION) = False Then
                MsgboxAsync("Please allow app to always allow location services", "")
                Wait For Msgbox_Result (unused As Int)
                Dim in As Intent
                in.Initialize("android.settings.LOCATION_SOURCE_SETTINGS", "")
                StartActivity(in)
                'catch the Activity_Resume event to prevent an endless loop if the user denies the permission.
                Wait For Activity_Resume
            End If
        End If
        StartService(Tracker)
    Else
        ToastMessageShow("No permission...", True)
    End If




End Sub

' TBC /
Private Sub CheckAndRequestNotificationPermission As ResumableSub
    Dim p As Phone
    If p.SdkVersion < 33 Then Return True
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    Dim targetSdkVersion As Int = ctxt.RunMethodJO("getApplicationInfo", Null).GetField("targetSdkVersion")
    If targetSdkVersion < 33 Then Return True
    Dim NotificationsManager As JavaObject = ctxt.RunMethod("getSystemService", Array("notification"))
    Dim NotificationsEnabled As Boolean = NotificationsManager.RunMethod("areNotificationsEnabled", Null)
    If NotificationsEnabled Then Return True
    Dim rp As RuntimePermissions
    rp.CheckAndRequest(rp.PERMISSION_POST_NOTIFICATIONS)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean) 'change to B4XPage_PermissionResult if B4XPages project
    Log(Permission & ": " & Result)
    Return Result
    
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

StartAtBootReceiver:
Sub Process_Globals
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 Starter.phone.SdkVersion >= 34 Then
        If Starter.rp.Check(Starter.BACKGROUND_LOCATION_PERMISSION) = False Then
            Dim s As String = "Background location permission is missing."
            Log(s)
            ToastMessageShow(s, True)
            Return
        End If
    End If
    StartForegroundService(Tracker)
End Sub

Private Sub StartForegroundService(Service As Object)
    Dim p As Phone
    If p.SdkVersion <= 26 Then
        StartService(Service)
        Return
    End If
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    Dim intent As JavaObject
    intent.InitializeNewInstance("android.content.Intent", Array(ctxt, Service))
    ctxt.RunMethod("startForegroundService", Array(intent))
End Sub

Starter:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    Public rp As RuntimePermissions
    Public Const BACKGROUND_LOCATION_PERMISSION As String = "android.permission.ACCESS_BACKGROUND_LOCATION"
    Public phone As Phone
    

    
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)
    

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

Sub Service_Destroy

End Sub

Tracker:
#Region  Service Attributes
    #StartAtBoot: False
#End Region

Sub Process_Globals
    Private nid As Int = 1
    Private GPS As GPS
    Private Tracking As Boolean
    Private LastUpdateTime As Long
    Private lock As PhoneWakeState
    
    
    'Starter
'    Dim rp As RuntimePermissions
    Private PE As PhoneEvents
    Private SmsIncoming As SmsInterceptor
    Private PhoneId As PhoneId
        
    Private MySms As PhoneSms
    Private FromNumber As String

    Private MySms As PhoneSms
    Private Dad As String,Mum As String,KeyWord As String
    Dad="+xx123456789"
    Mum="+xx987654321"
    KeyWord = "GETGPS" 'Trim comparison
    
End Sub

Sub Service_Create
    Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_NEVER 'we are handling it ourselves
'    GPS.Initialize("gps")
    lock.PartialLock
    
    'Starter
    PE.InitializeWithPhoneState("PE",PhoneId)
    SmsIncoming.Initialize("SmsInterceptor")
    
    
End Sub

Sub Service_Start (StartingIntent As Intent)
    
    Service.StartForeground(nid, CreateNotification("..."))
'    Track
End Sub

Public Sub Track
    Log("Sub Track 1 Tracking: " & Tracking)
    If Tracking Then Return
    If Starter.rp.Check(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION) = False Then
        Log("No permission")
        Return
    End If
    GPS.Start(0, 0)
    Tracking = True
    Log("Sub Track 2 Tracking: " & Tracking)
End Sub

Sub GPS_LocationChanged (Location1 As Location)
    If DateTime.Now > LastUpdateTime + 10 * DateTime.TicksPerSecond Then
'        Dim MyLocation As String = $"$2.5{Location1.Latitude} , $2.5{Location1.Longitude}"$
        
        Dim MyLocation As String = "https://maps.google.com/?q=" & $"$2.5{Location1.Latitude},$2.5{Location1.Longitude}"$
        Log(MyLocation)
        
        
        
'        Dim n As Notification = CreateNotification(body)
'        n.Notify(nid)
        
    
        MySms.Send(FromNumber,MyLocation)
        Tracking = False
        Log("Sub GPS_LocationChanged Tracking: " & Tracking)
        GPS.Stop
        
        
        DateTime.DateFormat="yyyy-MM-dd [h:mm:ss a]"
        Log("Timestamp : " & DateTime.Date(DateTime.Now))
        
        Log(MyLocation)
        LastUpdateTime = DateTime.Now
        
        
        
    End If
End Sub

Sub CreateNotification (Body As String) As Notification
    Dim notification As Notification
    notification.Initialize2(notification.IMPORTANCE_LOW)
    notification.Icon = "icon"
    notification.SetInfo("Tracking location", Body, Main)
    Return notification
End Sub

Sub Service_Destroy
    If Tracking Then
        GPS.Stop
    End If
    Tracking = False
    Log("Sub Service_Destroy Tracking: " & Tracking)
    
    
    
    lock.ReleasePartialLock
End Sub




'Starter
Sub SmsInterceptor_MessageReceived (From As String, Body As String) As Boolean
    FromNumber=From
    Log("MessageReceived: From = " & FromNumber & ", Body = " & Body)
    
    
    
    
    
    
    
    
'    If (FromNumber=Dad Or FromNumber=Mum) And Body=KeyWord  Then
    If (FromNumber=Dad Or FromNumber=Mum) And Body.Trim=KeyWord  Then
        
        Log("Good")
        GPS.Initialize("gps")
        Track
        
    End If
    
    
    
    
    
    Return True
End Sub



Full Error Log (with SDK35):
tracker_gps_locationchanged (java line: 181)
java.lang.IllegalArgumentException: GetGPS.adu: Targeting U+ (version 34 and above) disallows creating or retrieving a PendingIntent with FLAG_MUTABLE, an implicit Intent within and without FLAG_NO_CREATE and FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for security reasons. To retrieve an already existing PendingIntent, use FLAG_NO_CREATE, however, to create a new PendingIntent with an implicit Intent use FLAG_IMMUTABLE.
    at android.os.Parcel.createExceptionOrNull(Parcel.java:3260)
    at android.os.Parcel.createException(Parcel.java:3240)
    at android.os.Parcel.readException(Parcel.java:3223)
    at android.os.Parcel.readException(Parcel.java:3165)
    at android.app.IActivityManager$Stub$Proxy.getIntentSenderWithFeature(IActivityManager.java:7387)
    at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:767)
    at android.app.PendingIntent.getBroadcast(PendingIntent.java:750)
    at anywheresoftware.b4a.phone.Phone$PhoneSms.Send2(Phone.java:681)
    at anywheresoftware.b4a.phone.Phone$PhoneSms.Send(Phone.java:664)
    at GetGPS.adu.tracker._gps_locationchanged(tracker.java:181)
    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 anywheresoftware.b4a.gps.GPS$1.onLocationChanged(GPS.java:65)
    at android.location.LocationListener.onLocationChanged(LocationListener.java:63)
    at android.location.LocationManager$LocationListenerTransport$1.operate(LocationManager.java:3309)
    at android.location.LocationManager$LocationListenerTransport$1.operate(LocationManager.java:3306)
    at com.android.internal.listeners.ListenerExecutor.lambda$executeSafely$0(ListenerExecutor.java:127)
    at com.android.internal.listeners.ListenerExecutor$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:249)
    at android.os.Looper.loop(Looper.java:337)
    at android.app.ActivityThread.main(ActivityThread.java:9600)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.am.ActivityManagerService.getIntentSenderWithFeatureAsApp(ActivityManagerService.java:6212)
    at com.android.server.am.ActivityManagerService.getIntentSenderWithFeature(ActivityManagerService.java:6154)
    at android.app.IActivityManager$Stub.onTransact$getIntentSenderWithFeature$(IActivityManager.java:13527)
    at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3654)
    at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3090)
 
Upvote 0
Top