B4A Library Phone library update - v1.34

Discussion in 'Additional libraries, classes and official updates' started by Erel, Feb 13, 2011.

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

    Erel Administrator Staff Member Licensed User

    Edit: V1.34 is available.
    This version adds two new events: ConnectivityChanged and TextToSpeechFinish. This version also adds a new object named SmsInterceptor that handles new incoming Sms messages.

    A simple example that prints the events to the LogCat:
    Main activity
    Code:
    Sub Process_Globals
        
    Dim TTS As TTS
    End Sub
    Sub Globals

    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    StartService(S1)
        
    TTS.Initialize("tts")
    End Sub
    Sub TTS_Ready (Success As Boolean)
        
    If Success Then TTS.Speak("hello world"False)
    End Sub
    S1 service
    Code:
    'Service module
    Sub Process_Globals
        
    Dim PE As PhoneEvents
        
    Dim SI As SMSInterceptor
    End Sub
    Sub Service_Create
        PE.Initialize(
    "PE")
        SI.Initialize(
    "SI")
    End Sub

    Sub Service_Start

    End Sub
    Sub SI_MessageReceived (From As String, Body As String)
        
    Log("MessageReceived: From = " & From & ", Body = " & Body)
    End Sub
    Sub PE_TextToSpeechFinish (Intent As Intent)
        
    Log("TextToSpeechFinish")
    End Sub
    Sub PE_ConnectivityChanged (NetworkType As String, State As StringIntent As Intent)
        
    Log("ConnectivityChanged: " & NetworkType & ", state = " & State)
        
    Log(Intent.ExtrasToString)
    End Sub
    Sub PE_AirplaneModeChanged (State As Boolean, Intent As Intent)
        
    Log("AirplaneModeChanged: "& state)
        
    Log(Intent.ExtrasToString)
    End Sub
    Sub PE_BatteryChanged (Level As Int, Scale As Int, Plugged As Boolean, Intent As Intent)
        
    Log("BatteryChanged: Level = " & level & ", Scale = " & scale & ", Plugged = " & Plugged)
    End Sub
    Sub PE_CameraButtonPressed (Intent As Intent)
        
    Log("CameraButtonPressed")
        
    Log(Intent.ExtrasToString)
    End Sub
    Sub PE_PackageRemoved (Package As StringIntent As Intent)
        
    Log("PackageRemoved: " & Package)
        
    Log(Intent.ExtrasToString)
    End Sub
    Sub PE_PackageAdded (Package As StringIntent As Intent)
        
    Log("PackageAdded: " & Package)
        
    Log(intent.ExtrasToString)
    End Sub
    Sub PE_ScreenOff (Intent As Intent)
        
    Log("ScreenOff")
    End Sub
    Sub PE_ScreenOn (Intent As Intent)
        
    Log("ScreenOn")
    End Sub
    Sub PE_Shutdown (Intent As Intent)
        
    Log("Shutdown")
    End Sub
    Sub PE_UserPresent (Intent As Intent)
        
    Log("UserPresent")
    End Sub
    Sub PE_PhoneStateChanged (State As String, IncomingNumber As StringIntent As Intent)
        
    Log("PhoneStateChanged, State = " & State & ", IncomingNumber = " & IncomingNumber)
        
    Log(Intent.ExtrasToString)
    End Sub
    Sub Service_Destroy
        
    End Sub
    Installation instructions: Unzip the attached file and copy both files to the internal libraries folder. The default is: C:\Program Files\Anywhere Software\Basic4android\Libraries
     

    Attached Files:

    Daniel-White and ali.hassanabadi like this.
  2. corwin42

    corwin42 Expert Licensed User

    Wow this is a great feature.

    Is there a possibility to receive an event if Wifi gets connected?
    I want to write a service that begins its work only when there is a Wifi connection.
     
  3. kkolle

    kkolle Member Licensed User

    Example?!

    Hi Erel!

    Great work!

    A small example with the phoneevents in a service would be nice .... :sign0085:
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    First post was updated with v1.34.
     
  5. rkmoray

    rkmoray Member Licensed User

    MArk as read

    Can you now mark the SMS message as read?
     
  6. kkolle

    kkolle Member Licensed User

    :sign0188:

    Thanks!
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    No. These changes are not related to the SMS storing.
     
  8. ssg

    ssg Well-Known Member Licensed User

    Hi Erel,

    Will the sub SI_MessageReceived trigger even when the phone is in sleep mode?

    Cheers!
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    It will trigger as long as your service is running. Including when the device is sleeping.
     
  10. Cor

    Cor Active Member Licensed User

    I want to put recevied message in a label lblBericht which is located
    from layout main from mode main

    how to solve this?

    I want to keep the service in the same service module.

    Or can I move the Sub SI_MessageReceived (From As String, Body As String)
    to a different module.


    Code:
    Sub SI_MessageReceived (From As String, Body As String)
        
    Log("MessageReceived: From = " & From & ", Body = " & Body)
        lblBericht.text=From   <-- cannot access this from main
    End Sub
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    First you should understand that it is possible for this event to be raised while your activity is paused.
    The best solution is to store the text in a process global object.
    And also use CallSub(Main, "AfterMessageReceived") to call a sub in Main named AfterMessageReceived. In this sub you should get the value from the service process global object.
    You should also check this variable in Activity_Resume to make sure you didn't miss any event while being paused.
     
  12. ZJP

    ZJP Active Member Licensed User

    Hi,

    Is there a way to know the running applications? A sort of "IsRunning list", and a event when a application is launching?

    JP
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    You can use Shell to run the 'ps' command. It will give you a list of running programs.
     
  14. andreas

    andreas Member Licensed User

    SMS text length limitation

    Hi,

    When I'm trying to send sms messages with body text more than 160 characters, the program returns a "java.lang.NullPointerException".
    How can i solve this problem ?


    Code:
    Sub SendMessage(Phone as string, LongText as string)
     
    Dim Ph As PhoneSms 
     ph.Send(
    Phone, LongText)
    End Sub
     
  15. moster67

    moster67 Well-Known Member Licensed User

  16. andreas

    andreas Member Licensed User

    moster67, thank you for your response.
    I had seen this thread before, but it can't solve the problem. (maybe i'm doing something wrong)
    When i split the long message to multiple smaller messages (of 159 or 160 chars each) and sending them, they are recieved as seperated messages in phones that supports long text (HTC P3300 and HTC Desire)
     
  17. moster67

    moster67 Well-Known Member Licensed User

    Sorry Andreas but I am afraid I can't help you with that. I simply referred you to the other thread since your issue seemed similar.

     
  18. agraham

    agraham Expert Licensed User

    To be received as a single long message multiple messages use the beginning 48 bits of each message that makes up the long message as a header that contains the information the receiving phone needs to identify that a single message is part of a longer message. This header is part of the payload and so reduces the number of characters that the message can carry to 153 characters. The sending device needs to add the required header to each sub-message and although it might be theoretically possible to compose the first seven characters of each message to represent the required header it is not really practical to do so.
     
  19. TomK

    TomK Member Licensed User

    Contacts in Phone Library

    Hi guys,

    I just want to say Erel, you have a wonderful product here and sincerely you have my thanks for making it!!


    That said, I would like to inquire about the contacts as they exist in the library right now. I'm trying to resolve Phone contacts with GMail contacts and some of the rudimentary information contained in both (ie., name, address, city, state, zip, country, phone number, email) and I have run into 2 stumbling blocks and perhaps I'm simply missing something.

    Issue #1 - It seems only those contacts which actually reside as a gmail contact get acted upon (in this case I was simply sending all info on all contacts to the Log)

    Issue # 2 - It seems not all information that could be possible for any given contact is available; in my case I was specifically looking for the Postal address.


    Any guidance on this would be greatly appreciated, although I suspect it may be in future updates in which case would my recourse be to get the functionality I need from firing up Eclipse in the meantime?


    Thank you in advance!



    Tom Kwasnik
     
  20. Erel

    Erel Administrator Staff Member Licensed User

    Thank you for your feedback :)

    Which contacts are missing? Of a specific source?

    The Postal field is currently not exposed.
    I will add it to the features list.
    Here is the code for the Contacts. Adding a field shouldn't be difficult.


    Code:
    package anywheresoftware.b4a.phone;

    import java.util.HashMap;

    import android.content.ContentResolver;
    import android.content.ContentUris;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.provider.BaseColumns;
    import android.provider.Contacts;
    import anywheresoftware.b4a.BA;
    import anywheresoftware.b4a.IOnActivityResult;
    import anywheresoftware.b4a.BA.Events;
    import anywheresoftware.b4a.BA.Hide;
    import anywheresoftware.b4a.BA.Permissions;
    import anywheresoftware.b4a.BA.ShortName;
    import anywheresoftware.b4a.keywords.Common;
    import anywheresoftware.b4a.objects.collections.List;
    import anywheresoftware.b4a.objects.collections.Map;
    import anywheresoftware.b4a.objects.drawable.CanvasWrapper.BitmapWrapper;
    import anywheresoftware.b4a.objects.streams.File.InputStreamWrapper;

    /**
     * 
    Contacts object allows you to access the device stored contacts.
     *The following code finds all 
    contacts named John (actually it will find all contacts which their name contains the string "john"),
     *
    and print its fields to the LogCat. It will also fetch the contact photo if it exists.
     *Example:<code>
     *
    Dim Contacts1 As Contacts
     *
    Dim listOfContacts As List
     *listOfContacts = Contacts1.FindByName(
    "John"False)
     *
    For i = 0 To listOfContacts.Size - 1
     *    
    Dim Contact As Contact
     *    
    Contact = listOfContacts.Get(i)
     *    
    Log(Contact'will print the fields to the LogCat
     *    Dim photo As Bitmap
     *    photo = 
    Contact.GetPhoto
     *    
    If photo <> Null Then Activity.SetBackgroundImage(photo)
     *    
    Dim emails As Map
     *    emails = 
    Contact.GetEmails
     *    
    If emails.Size > 0 Then Log("Email addresses: " & emails)
     *    
    Dim phones As Map
     *    phones = 
    Contact.GetPhones
     *    
    If phones.Size > 0 Then Log("Phone numbers: " & phones)
     *
    Next</code>
     */
    @ShortName(
    "Contacts")
    @Permissions(values={
    "android.permission.READ_CONTACTS"})
    public class ContactsWrapper {
        private static final String[] people_projection = {Contacts.People.TIMES_CONTACTED,
            Contacts.Phones.NUMBER, Contacts.People.LAST_TIME_CONTACTED,
            Contacts.People.DISPLAY_NAME, Contacts.People.NAME, Contacts.People.NOTES, Contacts.People.STARRED, BaseColumns._ID};
        
        /**
         * Returns a List of Contact objects with all the contacts. This list can be very large.
         */
        public List GetAll() {
            return getAllContacts(null, null);
        }
        /**
         * Returns a List of Contact objects with all contacts matching the given name.
         *Name - The name to search for.
         *Exact - If True then only contacts with the exact name value (case sensitive) will return
         *, otherwise all contacts names that include the Name string will return (case insensitive).
         */
        public List FindByName(String Name, boolean Exact) {
            if (!Exact)
                return getAllContacts(Contacts.People.NAME + " LIKE ?", new String[] {"%" + Name + "%"});
            else
                return getAllContacts(Contacts.People.NAME + " = ?", new String[] {Name});
        }
        /**
         * Returns a List of Contact objects with all contacts matching the given email.
         *Email - The email to search for.
         *Exact - If True then only contacts with the exact email address (case sensitive) will return
         *, otherwise all contacts email addresses that include the Email string will return (case insensitive).
         */
        public List FindByMail(String Email, boolean Exact) {
            ContentResolver cr = BA.applicationContext.getContentResolver();
            String sel, args;
            if (!Exact) {
                sel = " LIKE ?";
                args = "%" + Email + "%";
            }
            else {
                sel = " = ?";
                args = Email;
            }
            Cursor crsr = cr.query(Contacts.ContactMethods.CONTENT_EMAIL_URI, new String[] {Contacts.ContactMethods.PERSON_ID,
                    Contacts.ContactMethods.DATA}, Contacts.ContactMethods.DATA + sel, new String[] {args}, null);
            StringBuilder sb = new StringBuilder();
            while (crsr.moveToNext()) {
                for (int i = 0;i < crsr.getColumnCount();i++) {
                    sb.append(crsr.getString(0)).append(",");
                }
            }
            int count = crsr.getCount();
            crsr.close();
            if (count == 0) {
                List l = new List();
                l.Initialize();
                return l;
            }
            sb.setLength(sb.length() - 1);
            String selection = BaseColumns._ID +  " IN (" + sb.toString() + ")";
            return getAllContacts(selection, null);
        }
        /**
         * Returns the Contact with the specified Id.
         * Returns Null if no matching contact found.
         */
        public Contact GetById(int Id) {
            List l = getAllContacts(BaseColumns._ID + " = ?", new String[] {String.valueOf(Id)});
            if (l.getSize() == 0)
                return null;
            else
                return (Contact) l.Get(0);
        }
        private List getAllContacts(String selection, String[] args) {

            ContentResolver cr = BA.applicationContext.getContentResolver();
            Cursor crsr = cr.query(Contacts.People.CONTENT_URI, people_projection, selection, args, null);
            List l = new List();
            l.Initialize();
            HashMap<String, Integer> m = new HashMap<String, Integer>();
            for (int col = 0;col < crsr.getColumnCount();col++) {
                m.put(crsr.getColumnName(col), col);
            }
            
            while (crsr.moveToNext()) {
                Contact contact = new Contact(
                        crsr.getString(m.get(Contacts.People.DISPLAY_NAME)),
                        crsr.getString(m.get(Contacts.Phones.NUMBER)),
                        crsr.getInt(m.get(Contacts.People.STARRED)) > 0,
                        crsr.getInt(m.get(BaseColumns._ID)),
                        crsr.getString(m.get(Contacts.People.NOTES)),
                        crsr.getInt(m.get(Contacts.People.TIMES_CONTACTED)),
                        crsr.getLong(m.get(Contacts.People.LAST_TIME_CONTACTED)),
                        crsr.getString(m.get(Contacts.People.NAME)));
                l.Add(contact);
            }
            crsr.close();
            return l;
        }

        /**
         * Represents a single contact.
         *The Contacts object should be used to get lists of Contact objects.
         *EMAIL_x constants are the possible email types.
         *PHONE_x constants are the possible phone types.
         */
        @ShortName("Contact")
        public static class Contact {
            public static final int EMAIL_CUSTOM = 0;
            public static final int EMAIL_HOME = 1;
            public static final int EMAIL_WORK = 2;
            public static final int EMAIL_OTHER = 3;
            
            public static final int PHONE_CUSTOM = 0;
            public static final int PHONE_HOME = 1;
            public static final int PHONE_MOBILE = 2;
            public static final int PHONE_WORK = 3;
            public static final int PHONE_FAX_WORK = 4;
            public static final int PHONE_FAX_HOME = 5;
            public static final int PHONE_PAGER = 6;
            public static final int PHONE_OTHER = 7;
            /**
             * The displayed name. Equals to the Name if the Name is not empty, otherwise equals to the contacts first email address.
             */
            public String DisplayName;
            /**
             * Primary phone number.
             */
            public String PhoneNumber = "";
            /**
             * Whether this contact is a "favorite" contact.
             */
            public boolean Starred;
            /**
             * Internal Id.
             */
            public int Id = -1;
            public String Notes;
            /**
             * Number of times that this contact was contacted.
             */
            public int TimesContacted;
            /**
             * Last time that this contact was contacted. Value is a ticks value.
             */
            public long LastTimeContacted;
            /**
             * Contact name.
             */
            public String Name;
            public Contact() {}
            Contact(String displayName, String phoneNumber, boolean starred,
                    int id,  String notes,
                    int timesContacted,
                    long lastTimeContacted, String name) {
                DisplayName = displayName == null ? "" : displayName;
                PhoneNumber = phoneNumber == null ? "" : phoneNumber; 
                Starred = starred;
                Id = id;
                Notes = notes == null ? "" : notes;
                TimesContacted = timesContacted;
                LastTimeContacted = lastTimeContacted;
                Name = name == null ? "" : name;
            }
            /**
             * Returns the contact photo or Null if there is no attached photo.
             *This call executes an additional query.
             */
            public BitmapWrapper GetPhoto() {
                if (Id == -1)
                    throw new RuntimeException("Contact object should be set by calling one of the Contacts methods.");
                Uri u = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.People.CONTENT_URI, Id), 
                        Contacts.Photos.CONTENT_DIRECTORY);
                Cursor crsr = BA.applicationContext.getContentResolver().query(u, new String[] {Contacts.Photos.DATA}, null, null, null);
                BitmapWrapper bw = null;
                if (crsr.moveToNext()) {
                    byte[] b = crsr.getBlob(0);
                    if (b != null) {
                        InputStreamWrapper isw = new InputStreamWrapper();
                        isw.InitializeFromBytesArray(b, 0, b.length);
                        bw = new BitmapWrapper();
                        bw.Initialize2(isw.getObject());
                    }
                }
                crsr.close();
                return bw;
            }
            /**
             * Returns a Map with the contacts email addresses as keys and the email types as values.
             *This call executes an additional query.
             */
            public Map GetEmails() {
                if (Id == -1)
                    throw new RuntimeException("Contact object should be set by calling one of the Contacts methods.");
                Uri u = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.People.CONTENT_URI, Id), 
                        Contacts.People.ContactMethods.CONTENT_DIRECTORY);
                Cursor crsr = BA.applicationContext.getContentResolver().query(u, new String[] {Contacts.ContactMethods.DATA,Contacts.ContactMethods.TYPE,
                        Contacts.ContactMethods.KIND}, 
                        Contacts.ContactMethods.KIND + " = " + Contacts.KIND_EMAIL, null, null);
                Map m = new Map(); m.Initialize();
                while (crsr.moveToNext()) {
                    m.Put(crsr.getString(0), crsr.getInt(1));
                }
                crsr.close();
                return m;
            }
            /**
             * Returns a Map with all the contacts phone numbers as keys and the phone types as values.
             *This call executes an additional query.
             */
            public Map GetPhones() {
                if (Id == -1)
                    throw new RuntimeException("Contact object should be set by calling one of the Contacts methods.");
                Uri u = Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.People.CONTENT_URI, Id), 
                        Contacts.People.Phones.CONTENT_DIRECTORY);
                Cursor crsr = BA.applicationContext.getContentResolver().query(u, new String[] {Contacts.PhonesColumns.NUMBER, Contacts.PhonesColumns.TYPE}, 
                        null, null, null);
                Map m = new Map(); m.Initialize();
                while (crsr.moveToNext()) {
                    m.Put(crsr.getString(0), crsr.getInt(1));
                }
                crsr.close();
                return m;
            }
            @Override
            @Hide
            public String toString() {
                return "DisplayName=" + DisplayName + ", PhoneNumber=" + PhoneNumber + 
                ", Starred=" + Starred + ", Id=" + Id + ", Notes=" + Notes + ", TimesContacted=" + 
                TimesContacted + ", LastTimeContacted=" + LastTimeContacted + ", Name=" + Name;
            }
        }
    }
     
Thread Status:
Not open for further replies.
Loading...