Phone tracking app using SMS

847 views
Skip to first unread message

Ray Perkins

unread,
Apr 3, 2018, 4:05:27 PM4/3/18
to DroidScript
As I don't have a data plan, I wrote an app to track a phone using SMS messages. It will send an email or text message with a Google Maps link whenever it detects motion greater than 200 meters, with a one minute update. Comments/criticism welcome. Maybe somebody will find it useful. Obviously, put in your own numbers.

// =======================================================
// =  Tracker - send SMS text whenever location changes  =
// =======================================================

// Apr 3, 2018
// app will work if minimized
// app will work if another app is in the foreground
// app will sort of work if phone is in sleep mode - wakes phone up, but possibly flakey!
// Droidscript keeps phone from going to sleep (inhibits screen timeout) no fix!
// will respond to a received text message - turn tracking on/off, send immediate location

var loc
var sms 
var ctr = 0
var oldLocLat = 45.433813  // just to initialize
var oldLocLon = -76.044660
var homeLocLat = 45.433813   
var homeLocLon = -76.044660
var SMSnum = ""
var SMSmsg = ""
var SendEvery
var oneMin = 1000 * 60     // check location every minute
var SendImmediate = 0      // flag to send location immediately
var SendToEmail = 1        // default

function OnStart()
{   
// Create vertical layout that fills the screen
var lay
app.SetOrientation( "Portrait" )
lay = app.CreateLayout( "Absolute", "Vertical,VCenter,FillXY" )
        lay.SetBackGradientRadial(.5,.7,.6, "#3300ffff", "#3300ff00" )  
app.AddLayout( lay )
    // Create location sensor
loc = app.CreateLocator( "GPS" )
loc.SetOnChange( loc_OnChange ) 
loc.SetRate( 4 )  

// Create SMS object
sms = app.CreateSMS()
sms.SetOnMessage( sms_OnMessage )
    
    // Set one minute interrupt 
    CheckGpsEveryMin = setInterval( CheckGpsEveryMin, oneMin )

    // Buttons: Send to email or phone
    btn1 = app.CreateButton( "Send to email" ) 
    btn1.SetPosition( 0.1, 0.1, 0.4, 0.1 ) // left
    btn1.SetOnTouch( btn_Email )
    lay.AddChild( btn1 )
    btn2 = app.CreateButton( "Send to phone" ) 
    btn2.SetPosition( 0.5, 0.1, 0.4, 0.1 ) // right
    btn2.SetOnTouch( btn_Phone )
    lay.AddChild( btn2 )
    }

function btn_Email()
{
    SendToEmail = 1
    app.SetScreenBrightness( 0 ) // dim screen to save battery
    // app.ToBack() // send app to back; screen will immediately return to bright, so not used
}

function btn_Phone()
{
    SendToEmail = 0
    app.SetScreenBrightness( 0 ) // dim screen to save battery
}

// Run gps to see if location has changed
function CheckGpsEveryMin()
{
    app.WakeUp()    // wake up app from sleep
    if( SendToEmail == 1 ) {
        SMSnum = "6245" // unique email number for Bell Canada
        SMSmsg = "mym...@gmail.com "
    }
    else {
        SMSnum = "5555555555" // phone number
        SMSmsg = "" 
    }
    loc.Start()     // start locator and send SMS to fixed email address
}

// Send SMS message once we get a location change
function loc_OnChange( data ) 
    if (SMSnum != "") {
        var dist = loc.GetDistanceTo( oldLocLat, oldLocLon )    // in km
        var home = loc.GetDistanceTo( homeLocLat, homeLocLon )  // distance to home
        if( dist > 200 | SendImmediate == 1 ) { // motion > 200 meters detected or send now
            ctr = ctr + 1  // speed not used as it is useless
        SMSmsg = SMSmsg + " #" + ctr + "  Bearing: " + data.bearing + " Home: " + (home/1000).toFixed(1) + " km away"
        SMSmsg = SMSmsg + " http://maps.google.com/?q=" + data.latitude + "+" + data.longitude
        sms.Send( SMSnum, SMSmsg )
        app.ShowPopup( SMSmsg + " > " + SMSnum)
        oldLocLat = data.latitude 
        oldLocLon = data.longitude
        }
    SMSnum = ""   // clear for next pass
    SMSmsg = ""
}
    loc.Stop()        // stop locator
    SendImmediate = 0
    //app.GoToSleep()   // put phone to sleep - does nothing without root access!
}

// Parse incoming SMS message for trigger words
function sms_OnMessage( number, msg )
{
    var UpperSMSmsg
    var w
    var t
    var x

UpperSMSmsg = msg.toUpperCase()
w = UpperSMSmsg.search("WALDO")     // send location data immediately
t = UpperSMSmsg.search("TRACKON")   // turn tracker on (default at power up)
x = UpperSMSmsg.search("TRACKOFF")  // turn tracker off
if( w >= 0) {         // reply to "Waldo" trigger word...
        app.WakeUp() 
    SendImmediate = 1
        loc.Start()       // start locator     
}
else if( t >= 0) {    // remotely turn on tracking...
        CheckGpsEveryMin = setInterval( CheckGpsEveryMin, oneMin ) 
        SendImmediate = 1 // send immediate response
        loc.Start()       // start locator     
}
else if( x >= 0) {    // remotely turn off tracking...
        clearInterval( CheckGpsEveryMin )
}
    if( SendToEmail == 1 ) {
        SMSnum = "6245" // unique email number for Bell Canada
        SMSmsg = "mym...@gmail.com "
    }
    else {
        SMSnum = "5555555555" // phone number
        SMSmsg = "" 
    }
}

John Constatine

unread,
Jul 27, 2018, 7:29:24 PM7/27/18
to DroidScript
it would be interesting, to leave the service in the background only to be activated when it received an SMS and that the sms was not shown operate me in the background too
so that it does not waste battery, it is activated only when it receives the command via email or sms, it activates and returns the location

Ray Perkins

unread,
Jul 27, 2018, 8:37:58 PM7/27/18
to DroidScript
My new version does just that, I use a service to run the gps and sms functions. The target email address and phone number is read in from a text file, so I don't have to recompile if I change it. I'll attach as text files...
There is an issue with this, as my one minute interrupt often interrupts only every few minutes. I have tried everything to get around it, to no avail. I think it's just how the OS works in sleep mode.
I would also like to suppress the phone's notification when I send a command SMS so the recipient isn't alerted, but I doubt that is possible.
Tracker200.txt
Service.txt

John Constatine

unread,
Jul 27, 2018, 8:51:27 PM7/27/18
to DroidScript
you have the solution for notification of sms in the bar to study how to make a message or status change in firebase, in real time there could have an application to activate in the other cell recovering what needs without needing a web server, but there needs internet, but your project is very interesting I'll study it

Steve Garman

unread,
Jul 27, 2018, 8:52:37 PM7/27/18
to DroidScript
You're not giving your setInterval a chance.

You are using a global function CheckClock and a global variable CheckClock

I am amazed your service runs at all.

Try renaming one of them.

Ray Perkins

unread,
Jul 27, 2018, 8:55:25 PM7/27/18
to DroidScript
Thanks! I'll look into it. It isn't the first time I've done some thing similar. (Aren't you in England? It's early morning over there!)

Steve Garman

unread,
Jul 27, 2018, 8:59:34 PM7/27/18
to DroidScript
Yeah,it's just coming up to 2 a.m.

It's no wonder I'm such a grumpy old man.

Ray Perkins

unread,
Jul 27, 2018, 9:22:59 PM7/27/18
to DroidScript
I tried the fix in a test file. It seems better, but it's still not all that consistent. I'm using a 5 second interrupt to look at the clock...
  • App.WriteFile( ./Test.txt, 21:09:48 , Append, )
  • App.WriteFile( ./Test.txt, 21:10:03 , Append, )
  • App.WriteFile( ./Test.txt, 21:11:24 , Append, )
  • App.WriteFile( ./Test.txt, 21:12:28 , Append, )
  • App.WriteFile( ./Test.txt, 21:13:00 , Append, )
  • App.WriteFile( ./Test.txt, 21:14:29 , Append, )
  • App.WriteFile( ./Test.txt, 21:15:04 , Append, )
  • App.WriteFile( ./Test.txt, 21:16:00 , Append, )
  • App.WriteFile( ./Test.txt, 21:17:23 , Append, )
  • App.WriteFile( ./Test.txt, 21:18:23 , Append, )
function OnStart()
{   
    // Set fast interrupt to check clock
    CheckxxxClock = setInterval( CheckClock, 5000 ) // 5 second interrupt
}  


// Run gps once a minute to see if location has changed (5 sec. interrupt)
function CheckClock()
{
    var d = new Date()
    var NewMin = d.getMinutes()
    if( NewMin != OldMin ) {
        GPSrunning = 0
        app.WriteFile( "./Test.txt", GetTimeStamp() + " \n",  "Append" )
        OldMin = NewMin
    }
}

// Get current time
function GetTimeStamp ()
{
    var timestr
    var d = new Date()
    var hr = (("0" + d.getHours()).slice(-2))
    var min = (("0" + d.getMinutes()).slice(-2))
    var sec =  (("0" + d.getSeconds()).slice(-2))
    timestr = hr + ":" + min + ":" + sec
    return timestr
}

Ray Perkins

unread,
Jul 28, 2018, 6:31:53 AM7/28/18
to DroidScript
Found it! Android has a "Doze mode"; the system gradually reduces it's response time when asleep. https://lifehacker.com/how-android-doze-works-and-how-to-tweak-it-to-save-you-1785921957
This is exactly what I am seeing when I ran a test program overnight in sleep mode. Following plot file shows the number of seconds between responses (60 seconds is the expected response time, I got anything up to 1800 over an 8-hour period).
I turned off battery optimization for Droidscript and am running another test to see if this fixes the issue of slow responses in sleep mode.
Capture.JPG

Ray Perkins

unread,
Jul 28, 2018, 10:55:04 AM7/28/18
to DroidScript
Well, the fix didn't work. Back to the drawing board!

Jared

unread,
Jul 28, 2018, 8:12:15 PM7/28/18
to DroidScript
I didn't look too closely at the code so sorry if this ends up irrelevant, but did you consider try using the accelerometer to detect movement as a way to send the loc update? you could use magnetometer / accelerometer combo or something like that...

Ray Perkins

unread,
Jul 29, 2018, 12:40:58 PM7/29/18
to DroidScript
Issue isn't detecting a location change. Issue is the processor shuts down for too long in sleep mode. I'm running a test to see if I can stop it from doing that by forcing a wakeup if I detect a slow response from the OS.
Reply all
Reply to author
Forward
0 new messages