Java Question GetAllContacts too slow

Discussion in 'Libraries developers questions' started by Filippo, Oct 27, 2011.

  1. Filippo

    Filippo Expert Licensed User

    Hi,

    my code is too slow. The Procedure "GetAllContacts" used to store about 5 sec to 150 contacts in one list.

    Is it possible to optimize the code to something?

    Code:
    package fg.Contacts;

    import android.provider.ContactsContract;
    import android.provider.ContactsContract.RawContacts;
    import android.content.ContentProviderOperation;
    import android.content.ContentResolver;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.util.Log;
    import anywheresoftware.b4a.BA;
    import anywheresoftware.b4a.objects.collections.List;
    import java.util.ArrayList;

    @BA.ActivityObject
    @BA.ShortName(
    "fgContacts")
    @BA.Author(
    "Filippo Gozza")
    @BA.Version(
    1.0F)
    public class FgContacts
    {
      
    public static final String TAG = "fg.Contacts";
      
    private BA m_ba;

      
    public void Initialize(BA ba)
      {
        this.m_ba = ba;
      
    }

      public String GetPhoneNumberByID(String id)
      {
         List allPhone = new List();
         allPhone.Initialize();
          
         allPhone=GetAllPhoneNumberByID(id);
         if (allPhone.getSize() > 0 ){
            return allPhone.Get(0).toString();        
         }
         else{
            return "";
         }
      }

      public List GetAllPhoneNumberByID(String id)
      {
         List lstPhonMobil = new List();
         List lstPhonOter = new List();
         List allPhone = new List();
         lstPhonMobil.Initialize();
         lstPhonOter.Initialize();
         allPhone.Initialize();
      
         Uri Phones = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
         String[] projection = new String[] { "data1", "data2" };

         String selection = "contact_id = '" + id + "'";
         Cursor Phonecur = this.m_ba.activity.managedQuery(Phones, projection, selection, null, null);

         while (Phonecur.moveToNext()) {
            if (Integer.valueOf(Phonecur.getInt(1))== 2){
               lstPhonMobil.Add(Phonecur.getString(0));              
            }
            else{
               lstPhonOter.Add(Phonecur.getString(0));
            }
         }
         Phonecur.close();
         allPhone.AddAll(lstPhonMobil); //als erst alle Mobile telefonnummer
         allPhone.AddAll(lstPhonOter);  //und dann alle anderen
         return allPhone;
      }
      
      public Bitmap GetContactPhotoByID(String id)
      {
        Uri photo = ContactsContract.Data.CONTENT_URI;
        String[] projection = { "data15" };

        String selection = "contact_id = '" + id + "'";

        Cursor cur = this.m_ba.activity.managedQuery(photo, projection, selection, null, null);

        cur.moveToFirst();
        while (!cur.isAfterLast()) {
          for (int i = 0; i < cur.getColumnCount(); i++)
          {
            byte[] photodata = cur.getBlob(i);
            if (photodata != null) {
              Log.i("fg.Contacts", "Empfange Photo: " + photodata.length);
              Bitmap bmp = BitmapFactory.decodeByteArray(photodata, 0, photodata.length);
              cur.close();
              return bmp;
            }
          }
          cur.moveToNext();
        }
        cur.close();
        return null;
      }

      public Boolean DeleteAllContacts()
      {
        ContentResolver cr = this.m_ba.context.getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, 
          null, null, null, null);
        while (cur.moveToNext()) {
          try {
            String lookupKey = cur.getString(cur.getColumnIndex("lookup"));
            Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
            cr.delete(uri, null, null);
          }
          catch (Exception e)
          {
            return Boolean.valueOf(false);
          }
        }
        return Boolean.valueOf(true);
      }
      
      public Boolean DeleteContactById(String id)
      {
         ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
         ops.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
             .withSelection(RawContacts._ID + " = ?", new String[]{id})
             .build());
          ContentResolver cr = this.m_ba.context.getContentResolver();
            try {
                cr.applyBatch(ContactsContract.AUTHORITY, ops);
            }
            catch (Exception e)
             {
               return Boolean.valueOf(false);
             }
           return Boolean.valueOf(true);
      }
      
      private String[] getFirstLastNameById(String id)
        {
          String[] retValue = new String[2];  
          retValue[0] = "";  
          retValue[1] = "";
     
            // NAME: FIRST AND LAST
           String nameWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
           String[] nameWhereParams = new String[]{id, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};
           Cursor nameCur = this.m_ba.context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, nameWhere, nameWhereParams, null);
           //boolean valid = false;
           while (nameCur.moveToNext()) {
              String firstName = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
              String lastName = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
           
              if (firstName!=null && lastName!=null && (firstName.length()>0 || lastName.length()>0)) {
                 retValue[0]=firstName;
                 retValue[1]=lastName;
                 break;
              }
           }
           nameCur.close();     
           return retValue;
        }
       
       public List GetAllContacts()
       {
          List allContacts = new List();
          allContacts.Initialize();
                
          ContentResolver cr = this.m_ba.context.getContentResolver();
          Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
             
          if (cur.getCount() > 0) {
             while (cur.moveToNext()) {
                
                  String[] retValue = new String[5];  
                retValue[0] = "";  
                retValue[1] = "";
                retValue[2] = ""; 
                retValue[3] = ""; 
                retValue[4] = ""; 
                
                  String[] retValue1 = new String[2];  
                retValue1[0] = ""; 
                retValue1[1] = "";

                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
             
                retValue1=getFirstLastNameById(id);
                
                String phone=GetPhoneNumberByID(id);
                //Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{id}, null);
                //while (pCur.moveToNext()) {
                //   phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                //   break;
                //}
                //pCur.close();   
       
                retValue[0]=id;
                retValue[1]=name;
                retValue[2]=phone;
                retValue[3]=retValue1[0];
                retValue[4]=retValue1[1];
                
                allContacts.Add(retValue);
             }
          }
          return allContacts;
       }   
    }
    Thanks in advance
    Filippo
     
  2. Filippo

    Filippo Expert Licensed User

    Can anyone help me or is my source code so well that no longer can be optimized? :confused:
     
  3. mlc

    mlc Active Member Licensed User

    Hello Filippo

    It would be interesting to add a function that only returns name and ID, this will accelerate the process.

    Later, you could access the contact through the ID, but display all contacts would be faster.

    Something like :

    Code:
    public List GetAllContactsSimple(Boolean sort)
        {
            
    List allContacts = new List();
            allContacts.Initialize();
                    
            
    ContentResolver cr = this.m_ba.context.getContentResolver();
            
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,nullnullnullnull);
               
            
    if (cur.getCount() > 0) {
                
    while (cur.moveToNext()) {
                    
                      
    String[] retValue = new String[2];  
                    retValue[
    0] = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 
                    retValue[
    1] = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));

                    allContacts.Add(retValue);
                
    }
            }
            //sort the list
            return allContacts;
        }
    I need it. :)

    Thanks
     
  4. warwound

    warwound Expert Licensed User

    If a method blocks the UI Thread then you can use an instance of the Runnable Class to execute the same code as your method.
    The code in the Runnable will execute in it's own Thread and not block the UI.
    Once the code in the Runnable has completed you'd raise a B4A Event:

    Code:
    @Events(values = { "MyEventName(AllContacts As List)" })
    public class ExampleClass {
       public void GetAllContacts(final BA pBA, final String EventName){
          Runnable runnable1 =new Runnable(){
             @Override
             public void run() {
                //   put the body of your GetAllContacts method here
                
                //   once the method has completed raise an event and return the result to B4A
                pBA.raiseEvent(ExampleClass.this, EventName.toLowerCase(BA.cul)+"_myeventname", new Object[]{allContacts});
             }};
          BA.submitRunnable(runnable1, null, 0);
       }
    }
    Martin.
     
  5. Erel

    Erel Administrator Staff Member Licensed User

  6. warwound

    warwound Expert Licensed User

    Oooops my mistake - well spotted!

    Martin.
     
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