22
33import android .app .Activity ;
44import android .content .Intent ;
5+ import android .content .pm .PackageManager ;
56import android .database .Cursor ;
67import android .graphics .Bitmap ;
78import android .media .ThumbnailUtils ;
1920import android .widget .TextView ;
2021
2122import java .util .ArrayList ;
23+ import java .util .Collections ;
24+ import java .util .Comparator ;
2225import java .util .List ;
2326import java .util .Locale ;
27+ import java .util .Random ;
2428
2529import lb .library .PinnedHeaderListView ;
2630import lb .library .SearchablePinnedHeaderListViewAdapter ;
@@ -46,6 +50,21 @@ protected void onCreate(Bundle savedInstanceState)
4650 mInflater =LayoutInflater .from (MainActivity .this );
4751 setContentView (R .layout .activity_main );
4852 final ArrayList <Contact > contacts =getContacts ();
53+ // mCollator = java.text.Collator.getInstance();
54+ // mCollator.setStrength(java.text.Collator.PRIMARY);
55+ Collections .sort (contacts ,new Comparator <Contact >()
56+ {
57+ @ Override
58+ public int compare (Contact lhs ,Contact rhs )
59+ {
60+ char lhsFirstLetter =TextUtils .isEmpty (lhs .displayName )?' ' :lhs .displayName .charAt (0 );
61+ char rhsFirstLetter =TextUtils .isEmpty (rhs .displayName )?' ' :rhs .displayName .charAt (0 );
62+ int firstLetterComparison =Character .toUpperCase (lhsFirstLetter )-Character .toUpperCase (rhsFirstLetter );
63+ if (firstLetterComparison ==0 )
64+ return lhs .displayName .compareTo (rhs .displayName );
65+ return firstLetterComparison ;
66+ }
67+ });
4968 mListView =(PinnedHeaderListView )findViewById (android .R .id .list );
5069 mAdapter =new ContactsAdapter (contacts );
5170
@@ -73,25 +92,61 @@ public static int getResIdFromAttribute(final Activity activity,final int attr)
7392
7493 private ArrayList <Contact > getContacts ()
7594 {
76- Uri uri =ContactsQuery .CONTENT_URI ;
95+ if (checkContactsReadPermission ())
96+ {
97+ Uri uri =ContactsQuery .CONTENT_URI ;
98+ final Cursor cursor =managedQuery (uri ,ContactsQuery .PROJECTION ,ContactsQuery .SELECTION ,null ,ContactsQuery .SORT_ORDER );
99+ if (cursor ==null )
100+ return null ;
101+ ArrayList <Contact > result =new ArrayList <>();
102+ while (cursor .moveToNext ())
103+ {
104+ Contact contact =new Contact ();
105+ contact .contactUri =ContactsContract .Contacts .getLookupUri (
106+ cursor .getLong (ContactsQuery .ID ),
107+ cursor .getString (ContactsQuery .LOOKUP_KEY ));
108+ contact .displayName =cursor .getString (ContactsQuery .DISPLAY_NAME );
109+ contact .photoId =cursor .getString (ContactsQuery .PHOTO_THUMBNAIL_DATA );
110+ result .add (contact );
111+ }
77112
78- final Cursor cursor =managedQuery (uri ,ContactsQuery .PROJECTION ,ContactsQuery .SELECTION ,null ,ContactsQuery .SORT_ORDER );
79- if (cursor ==null )
80- return null ;
113+ return result ;
114+ }
81115 ArrayList <Contact > result =new ArrayList <>();
82- while (cursor .moveToNext ())
116+ Random r =new Random ();
117+ StringBuilder sb =new StringBuilder ();
118+ for (int i =0 ;i <1000 ;++i )
83119 {
84120 Contact contact =new Contact ();
85- contact .contactUri =ContactsContract .Contacts .getLookupUri (
86- cursor .getLong (ContactsQuery .ID ),
87- cursor .getString (ContactsQuery .LOOKUP_KEY ));
88- contact .displayName =cursor .getString (ContactsQuery .DISPLAY_NAME );
89- contact .photoId =cursor .getString (ContactsQuery .PHOTO_THUMBNAIL_DATA );
121+ sb .delete (0 ,sb .length ());
122+ int strLength =r .nextInt (10 )+1 ;
123+ for (int j =0 ;j <strLength ;++j )
124+ switch (r .nextInt (3 ))
125+ {
126+ case 0 :
127+ sb .append ((char )('a' +r .nextInt ('z' -'a' )));
128+ break ;
129+ case 1 :
130+ sb .append ((char )('A' +r .nextInt ('Z' -'A' )));
131+ break ;
132+ case 2 :
133+ sb .append ((char )('0' +r .nextInt ('9' -'0' )));
134+ break ;
135+ }
136+
137+ contact .displayName =sb .toString ();
90138 result .add (contact );
91139 }
92140 return result ;
93141 }
94142
143+ private boolean checkContactsReadPermission ()
144+ {
145+ String permission ="android.permission.READ_CONTACTS" ;
146+ int res =checkCallingOrSelfPermission (permission );
147+ return (res ==PackageManager .PERMISSION_GRANTED );
148+ }
149+
95150 @ Override
96151 protected void onDestroy ()
97152 {
@@ -150,6 +205,12 @@ private class ContactsAdapter extends SearchablePinnedHeaderListViewAdapter<Cont
150205 private final int [] PHOTO_TEXT_BACKGROUND_COLORS ;
151206 private final AsyncTaskThreadPool mAsyncTaskThreadPool =new AsyncTaskThreadPool (1 ,2 ,10 );
152207
208+ @ Override
209+ public CharSequence getSectionTitle (int sectionIndex )
210+ {
211+ return ((StringArrayAlphabetIndexer .AlphaBetSection )getSections ()[sectionIndex ]).getName ();
212+ }
213+
153214 public ContactsAdapter (final ArrayList <Contact > contacts )
154215 {
155216 setData (contacts );
@@ -162,7 +223,7 @@ public void setData(final ArrayList<Contact> contacts)
162223 {
163224 this .mContacts =contacts ;
164225 final String [] generatedContactNames =generateContactNames (contacts );
165- setSectionIndexer (new StringArrayAlphabetIndexer (generatedContactNames ));
226+ setSectionIndexer (new StringArrayAlphabetIndexer (generatedContactNames , true ));
166227 }
167228
168229 private String [] generateContactNames (final List <Contact > contacts )
0 commit comments