More Phone API (Contacts-specific)

NeoTechni

Well-Known Member
Licensed User
Longtime User
KillCall, SendCall, SendSMS aren't mine, the rest are.

Some of the contacts API from the Phone library didn't work, so I was forced to replace it. Now my first versions were slow (+1 minute for some) so I had to do a bunch of clever caching to speed it up. As such, I am sharing that.

I may have used API from other modules of mine, so tell me if I missed anything

B4X:
Sub Process_Globals
   Dim YourName As String ,UnreadThreads As Int , PhoneNumbers As Map 
End Sub

Sub GetPhoneVolume As Int 
   Dim p As Phone
   Select Case p.GetRingerMode
      Case p.RINGER_NORMAL:  Return p.GetVolume( p.VOLUME_RING )
      Case p.RINGER_SILENT:  Return 0
      Case p.RINGER_VIBRATE: Return -1
   End Select
End Sub

Sub GetMonth(Month As Int, LongForm As Boolean) As String 
   Dim text() As String = Array As String("JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER")
   If LongForm Then 
      Return text(Month)
   Else
      Return Left(text(Month),3)
   End If
End Sub

Sub GetDuration(Seconds As Int) As String 
   Dim tempstr As StringBuilder ,temp As Long 
   tempstr.Initialize 
   Seconds = DurTest(Seconds, tempstr, 3600, "HRS")
   Seconds = DurTest(Seconds, tempstr, 60, "MIN")
   Seconds = DurTest(Seconds, tempstr, 1, "SEC")
   If tempstr.Length=0 Then Return "0 SEC"
   Return tempstr.ToString 
End Sub
Sub DurTest(TimeDate As Long, tempstr As StringBuilder, Ticks As Int, Text As String) As Int
   Dim temp As Int 
   If TimeDate>= Ticks Then
      temp = Floor(TimeDate/Ticks)
      Log(temp)
      TimeDate = TimeDate Mod Ticks
      If temp = 1 Then Text = Text.Replace("S","")
      tempstr.Append(IIF(tempstr.Length=0, "", ", ") & temp & " " & Text)
   End If
   Return TimeDate
End Sub

Sub HowLongAgo(TimeDate As Long) As String 
   Dim Diff As Long,Text As String 
   Diff = DateTime.Now - TimeDate
   If Diff < DateTime.TicksPerMinute Then
      Return "<1 MIN AGO"
   Else If Diff < DateTime.TicksPerHour Then
      Diff = Floor(Diff / DateTime.TicksPerMinute)
      Text = "MIN"
   Else If Diff < DateTime.TicksPerDay Then
      Diff =  Floor(Diff / DateTime.TicksPerHour)
      Text= "HRS"
   Else If Diff< DateTime.TicksPerDay * 7 Then
      Diff = Floor(Diff / DateTime.TicksPerDay)
      Text = "DAYS"
   Else If Diff< (DateTime.TicksPerDay * 30) Then
      Diff = Floor(Diff / (DateTime.TicksPerDay*7))
      Text = "WKS"
   Else If Diff < (DateTime.TicksPerDay * 365) Then
      Diff = Floor(Diff / (DateTime.TicksPerDay*30))
      Text= "MTHS"
   Else
      Diff = Floor(Diff / (DateTime.TicksPerDay*365)) 
      Text = "YRS"
   End If
   If Diff= 1 Then Text = Text.Replace("S", "")
   Return Diff & " " & Text & " AGO"
End Sub

'Form: 0=Full name, 1=Initials + Last name, 2= Last name
Sub GetUserName(Form As Int) As String 
   Dim pid As PhoneId, tempContact As Contact , text() As String, tempstr As StringBuilder ,temp As Int 
   If YourName.Length=0 Then 
      Try
         'Log("YOUR PHONE NUMBER: " & pid.GetLine1Number)
         'tempContact=EnumContacts(pid.GetLine1Number,True).Get(0) 
         'tempContact=GetContactByPhoneNumber(pid.GetLine1Number)
         'If tempContact <> Null Then 
         'Log("FULL: " & tempContact)
         'YourName=tempContact.DisplayName 
         
         tempContact=GetContactByPhoneNumber(pid.GetLine1Number)
         'Log("FAST: " & tempContact)
         YourName=tempContact.DisplayName 
      Catch
         Return pid.GetLine1Number
      End Try
   End If
   If Form=0 Then
      Return YourName
   Else
      text = Regex.Split(" ", YourName)
      If Form = 2 Then
         Return text(text.Length-1)
      Else
         tempstr.Initialize 
         For temp = 0 To text.Length-2
            tempstr.Append( Left(text(temp),1).ToUpperCase & ". ")
         Next
         tempstr.Append( Left(text(text.Length-1), 1).ToUpperCase & Right(text(text.Length-1), text(text.Length-1).Length -1).ToLowerCase )
         Return tempstr.ToString 
      End If
   End If
End Sub
Sub GetContactByPhoneNumber(PhoneNumber As String) As Contact 
   Dim ContactList As List , tempContact As Contact,tempContact2 As Contact, tempstr As String , NeedsInit As Boolean ,temp As Int, temp2 As Int,tempMap As Map ,CON As Contacts2
   If Not(PhoneNumbers.IsInitialized) Then
      NeedsInit =True
      PhoneNumbers.Initialize 
   Else If PhoneNumbers.Size=0 Then
      NeedsInit =True
   End If
   If NeedsInit Then
      YourName=""
      ContactList= EnumContacts("",True) 
      For temp = 0 To ContactList.Size-1
         tempContact = ContactList.Get(temp)
         If Not(tempContact.DisplayName.EqualsIgnoreCase("MiPhone")) Then
            tempMap=tempContact.GetPhones 
            For temp2 = 0 To tempMap.Size-1
               tempstr=FilterPhoneNumber(tempMap.GetKeyAt(temp2))
               If PhoneNumbers.ContainsKey(tempstr) Then
                  If Not( tempContact.PhoneNumber.EqualsIgnoreCase(tempContact.DisplayName)) Then
                     PhoneNumbers.Put(tempstr, tempContact.Id)
                     'Log("DUPE " & tempContact)
                  End If
               Else
                  PhoneNumbers.Put(tempstr, tempContact.Id)
               End If
            Next
         End If
      Next
   End If
   tempstr=FilterPhoneNumber(PhoneNumber)
   temp=PhoneNumbers.GetDefault(tempstr,-1)
   If temp>-1 Then tempContact2 = CON.GetById(temp,True,True)
   Return tempContact2
   
   'ContactList = EnumContacts(tempstr,True)
   'If ContactList.Size>0 Then tempContact = ContactList.Get(0)
   'Return tempContact
End Sub

Sub FilterPhoneNumber(Number As String) As String 
   If Left(Number,1) = "+" Then Number= Right(Number, Number.Length-2)
   Return RemoveAllExceptNumbers(Number)
End Sub

Sub KillCall'AddPermission("android.permission.CALL_PHONE")
    Dim r As Reflector
    r.Target = r.GetContext
    Dim TelephonyManager, TelephonyInterface As Object
    TelephonyManager = r.RunMethod2("getSystemService", "phone", "java.lang.String")
    r.Target = TelephonyManager
    TelephonyInterface = r.RunMethod("getITelephony")
    r.Target = TelephonyInterface
    r.RunMethod("endCall")
End Sub

Sub SendCall(PhoneNumber As String)
   Dim p As PhoneCalls
   StartActivity(p.Call(PhoneNumber))
End Sub

Sub SendTextMessage(PhoneNumber As String, Message As String)As Boolean 
   Dim SmsManager As PhoneSms ,r As Reflector, parts As Object
   Try
      If Message.Length <= 160 Then 
         SmsManager.Send(PhoneNumber, Message)
      Else
          r.Target = r.RunStaticMethod("android.telephony.SmsManager", "getDefault", Null, Null)
          parts = r.RunMethod2("divideMessage", Message, "java.lang.String")
         r.RunMethod4("sendMultipartTextMessage", Array As Object(PhoneNumber, Null, parts, Null, Null), Array As String("java.lang.String", "java.lang.String", "java.util.ArrayList", "java.util.ArrayList", "java.util.ArrayList"))
      End If
      Return True
   Catch
      Return False
   End Try
End Sub

Sub FindContactID(ID As Int, ContactList As List) As Int
   Dim temp As Int, tempContact As Contact
   For temp = 0 To ContactList.Size-1
      tempContact= ContactList.Get(temp)
      If tempContact.ID=ID Then Return temp
   Next
   Return -1
End Sub
Sub GetContactByID(ID As Int) As Contact 
   Dim CON As Contacts2
   Return CON.GetById(ID,True,True) 
End Sub

'Name = * = favorites, [text]* = name must start with [text], # = starts with a number, [number] = find by phone number, [number]+[any other symbol] = find by id number
Sub EnumContacts(Name As String, HasNames As Boolean) As List 
   Dim CON As Contacts2 ,tempContact As Contact, Names As List, Special As Int,DoRemove As Boolean  'returns a list of type Contact
   Dim temp As Int, temp2 As Int, tempContact As Contact , tempMap As Map,tempstr As String 
   If Name.Length =0 OR Name = "*" OR Name = "#" OR IsNumber(Name) Then
      Names = CON.GetAll(True,False)
      Select Case Name
         Case "*": Special = 1'get favorites
         Case "#": Special = 3'get names starting with number
         Case Else:If IsNumber(Name) Then  Special = 4'get by phone number   
      End Select
   Else If IsNumber(RemoveAllExceptNumbers(Name)) Then'get by id number
      Names.Initialize
      tempContact = CON.GetById(Name,True,True)
      If tempContact<> Null Then Names.Add(tempContact)
      Return Names
   Else If Name.Contains("@") AND Name.Contains(".") Then'get by email address
      Names = CON.FindByMail(Name,False,True,True)
   Else'get by name
      If Right(Name,1)= "*" Then'get names starting with text
         Special=2
         Name = Left(Name, Name.Length-1).ToUpperCase 
      End If
      Names = CON.FindByName(Name,False, True,True)
   End If
   If Names<>Null AND Names.IsInitialized Then 
      If Special>0 OR HasNames Then
         For temp = Names.Size-1 To 0 Step -1
            tempContact= Names.Get(temp)
            DoRemove=False
            If HasNames Then
               If tempContact.DisplayName.Contains("@") Then 
                  DoRemove =True
               Else If tempContact.DisplayName.EqualsIgnoreCase("DISQUS") Then
                  DoRemove =True
               Else If  tempContact.DisplayName.Contains(", (Google+)") Then
                  DoRemove =True
               Else If tempContact.DisplayName.Trim.Length=0 Then
                  DoRemove =True
               End If
            End If
            If Not(DoRemove) Then
               Select Case Special
                  Case 1'favorites only
                     If Not(tempContact.Starred) Then DoRemove=True
                  Case 2'starts with name text
                     If Not(tempContact.Name.ToUpperCase.StartsWith(Name)) Then DoRemove=True
                  Case 3'starts with a number
                     If isnumber(left(tempContact.Name,1)) Then DoRemove=True
                  Case 4'search by phone number
                     DoRemove=True
                     tempMap=tempContact.GetPhones
                     For temp2 = 0 To tempMap.Size-1
                        tempstr=RemoveAllExceptNumbers(tempMap.GetKeyAt(temp2))
                        If tempstr = Right(Name, tempstr.Length) Then
                           DoRemove=False
                           temp2=tempMap.Size
                        End If
                     Next
               End Select   
            End If
            
            If DoRemove Then Names.RemoveAt(temp) 
         Next
      End If
      
      'debug
'      For temp = 0 To Names.Size-1
'         tempContact= Names.Get(temp)
'         tempMap= tempContact.GetEmails 
'         
'         'If tempContact.PhoneNumber.Length>0 Then Log(tempContact.DisplayName & " " & tempContact.PhoneNumber )
'         tempMap=tempContact.GetPhones  
'         If tempMap.Size>0 Then
'            'Log(tempContact)
'            Log(tempContact.DisplayName & " " & tempMap)
'         
'            EnumCallLogs(20,tempMap)
'            EnumSMSmessages(tempContact.Id)
'         End If
'      Next
   End If
   If Names=Null Then 
      Names.Initialize 
   'Else
      'Names.SortType("DisplayName", True)
   End If
   Return Names
End Sub

'Zero = all
Sub EnumCallLogsByID(Quantity As Int, PersonID As Int) As List
   Dim Calls As List, CallLog As CallLog
   Try
      Calls = CallLog.GetById(PersonID)
   Catch
   End Try
   If Not(Calls.IsInitialized) Then Calls.Initialize 
   Return Calls
End Sub 

'Zero = all
Sub EnumCallLogs(Quantity As Int, Phones As Map) As List 
   Dim Calls As List, CallLog As CallLog,temp As Int, temp2 As Int,Found As Boolean ,tempstr As String 
   Calls = CallLog.GetAll(Quantity)
   If Phones.IsInitialized Then'filter by contact info
      For temp = Calls.Size - 1 To 0 Step -1
         Dim c As CallItem
         Found=False
         c = Calls.Get(temp)
         tempstr=RemoveAllExceptNumbers(c.Number)
         For temp2 = 0 To Phones.Size-1
            If RemoveAllExceptNumbers(Phones.GetKeyAt(temp2)) = tempstr Then 
               Found=True
               temp2=Phones.Size 
            End If
         Next
         If Not(Found) Then Calls.RemoveAt(temp)
      Next
   End If
   
   'debug
'   For temp = 0 To Calls.Size - 1
'       Dim c As CallItem, callType, name As String
'       c = Calls.Get(temp)
'       Select c.callType
'           Case c.TYPE_INCOMING:   callType = "Incoming"
'           Case c.TYPE_MISSED:      callType = "Missed"
'           Case c.TYPE_OUTGOING:   callType = "Outgoing"
'       End Select
'       name = c.CachedName
'       If name.Length = 0 Then name = "N/A"
'       Log("Number=" & c.Number & ", Name=" & name & ", Type=" & callType & ", Date=" & DateTime.Date(c.Date))
'   Next 
   If Not(Calls.IsInitialized) Then Calls.Initialize
   Return Calls
End Sub

'-1 = all unread
Sub EnumSMSmessages(PersonID As Int) As List 
   Dim SmsMessages1 As SmsMessages, List1 As List
   If PersonID=-1 Then
      List1 = SmsMessages1.GetUnreadMessages 
   Else
      List1 = SmsMessages1.GetByPersonId(PersonID)
      If List1.Size=0 Then
         Dim  tempContact As Contact ,CON As Contacts2, tempMap As Map, temp As Int, temp2 As Int ,theSms As Sms, Include As Boolean ,tempstr As String
         List1 = SmsMessages1.GetAll 
         tempMap.Initialize 
         'tempContact = CON.GetById(PersonID,False,False)
         'tempMap = tempContact.GetPhones
         For temp = List1.Size - 1 To 0 Step -1 
            theSms = List1.Get(temp)
            tempstr=FilterPhoneNumber(theSms.Address )
            If tempMap.ContainsKey(tempstr)  Then
               Include=tempMap.Get(tempstr)
            Else
               Include=True
               tempContact=GetContactByPhoneNumber(theSms.Address)
               If tempContact=Null Then
                  Include=False
               Else If Not(tempContact.Id  = PersonID) Then 
                  Include=False
               End If
               tempMap.Put(tempstr,Include)
            End If
            'tempstr=FilterPhoneNumber(theSms.Address)
            'For temp2 = 0 To tempMap.Size-1
            '   If tempstr = FilterPhoneNumber(tempMap.GetKeyAt(temp2)) Then
            '      Include=True
            '      temp2=tempMap.Size
            '   End If
            'Next

            If Not(Include) Then List1.RemoveAt(temp)
         Next
      End If
   End If
   List1.SortType("Id",True)
   
   'debug
'   Log(List1.Size & " messages found for person " & PersonID)
'   For i = 0 To List1.Size - 1
'       theSms = List1.Get(i)'Type: 1=to you, 2=from you
'       Log(theSms)
'   Next 
'   
   Return List1
End Sub

Sub GetContactByThreadID(ThreadID As Int) As Contact 
   Dim SmsMessages1 As SmsMessages, List1 As List,tempContact As Contact,theSms As Sms
   List1 = SmsMessages1.GetByThreadId(ThreadID)
   If List1.Size>0 Then
      theSms=  List1.Get(0)
      Return GetContactByPhoneNumber(theSms.Address)
   End If
   Return tempContact
End Sub
Sub EnumSMSmessagesByThread(ThreadID As Int) As List
   Dim SmsMessages1 As SmsMessages, List1 As List
   If ThreadID=-1 Then'enum threads
      Dim  temp As Int ,theSms As Sms, List2 As List ,tempMap As Map,temp2 As Int 
      List1.Initialize 
      tempMap.Initialize 
      Log("Getting SMS messages")
      List2 = SmsMessages1.GetAll 
      For temp = List2.Size - 1 To 0 Step -1 
         theSms = List2.Get(temp)
         If List1.IndexOf(theSms.ThreadId)=-1 Then List1.Add(theSms.ThreadId)
         If Not(theSms.Read) Then tempMap.Put(theSms.ThreadId, False)
      Next
      List1.Sort(True)
      Log("Sorting by unread")
      'put unread threads at the top
      For temp = List1.Size-1 To 1 Step -1
         temp2= List1.Get(temp)
         If Not(tempMap.GetDefault(temp2, True)) Then
            List1.RemoveAt(temp)
            List1.InsertAt(0, temp2)
            temp=temp+1
         End If
      Next
      UnreadThreads = tempMap.Size 
   Else
      List1 = SmsMessages1.GetByThreadId(ThreadID)
   End If
   Return List1
End Sub
Sub AddressOfThread(ThreadID As Int) As String 
   Dim SmsMessages1 As SmsMessages, List1 As List,theSms As Sms
   List1 = SmsMessages1.GetByThreadId(ThreadID)
   If List1.Size>0 Then
      theSms= List1.Get(0)
      Return FilterPhoneNumber(theSms.Address)
   End If
   Return ""
End Sub

Sub RemoveAllExceptNumbers(Text As String) As String
   Dim tempstr As StringBuilder ,temp As Int ,Chars As String
   tempstr.Initialize 
   For temp = 0 To Text.Length-1 
      Chars=Mid(Text,temp,1)
      If IsNumber(Chars) Then tempstr.Append(Chars)
   Next
   Return tempstr.ToString 
End Sub

Sub Left(Text As String, Length As Long)As String 
   If Length>Text.Length Then Length=Text.Length 
   Return Text.SubString2(0, Length)
End Sub
Sub Right(Text As String, Length As Long) As String
   If Length>Text.Length Then Length=Text.Length 
   Return Text.SubString(Text.Length-Length)
End Sub
 
Last edited:
Top