How to remove duplicated contacts from ArrayList - java

i have a huge problem with duplicated contacts.
After sorting array with:
Collections.sort(mAllContacts);
I'm reading contacts with :
ContentResolver cr = mContext.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0) {
while (cur != null && cur.moveToNext()) {
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts = new AllContacts(name, phoneNo);
mAllContacts.add(contacts);
}
pCur.close();
}
}
}
if (cur != null) {
cur.close();
}
With this way, all contact are retrieved to a list (Local storage, Sim, Gmail etc).
I have no problem to remove duplicated contact by name like this:
for (int i = 0; i < mAllContacts.size() - 1; i++) {
if (mAllContacts.get(i).getmContactName().equals(mAllContacts.get(i + 1).getmContactName())) {
Log.d("duplicatedArray", "setAdapter: " + mAllContacts.get(i).getmContactName());
mAllContacts.remove(i+1);
}
}
but it's not a good practice because some times different contacts may have same name,
so i can remove duplicated contact with same method but use:
mAllContacts.get(i + 1).getmPhoneNumber()
And here is the problems comes:
For some reason , the phone number have different format while reading from gmail, local storage , sim.
For ex.
Gmail phone number : +972-54-333-55-88
Local storage phone number : +972-543335588
Sim : +972543335588
How can i solve my problem to remove duplicated values.
And yes , i need to read contact from all places where they appear (gmail, local storage , sim)

Apply regex to change the same phone numbers to a common format e.g.
class Main {
public static void main(String args[]) {
String p1 = "+972-54-333-55-88";
String p2 = "+972-543335588";
String p3 = "+972543335588";
String p4 = "+97(2543)335588";
String p5 = "+97 2543 335588";
String regex = "[^0-9+]";
System.out.println(p1.replaceAll(regex, ""));
System.out.println(p2.replaceAll(regex, ""));
System.out.println(p3.replaceAll(regex, ""));
System.out.println(p4.replaceAll(regex, ""));
System.out.println(p5.replaceAll(regex, ""));
}
}
Output:
+972543335588
+972543335588
+972543335588
+972543335588
+972543335588

Normalize
I think you should normalize these phone numbers before you store them.
So for example all of these:
Gmail phone number : +972-54-333-55-88
Local storage phone number : +972-543335588
Sim : +97254335588
Could just be stored as 97254335588 You can parse these numbers by removing all space, hyphens, and plus signs.
HashSet
It would also be easier to store these in a HashSet so you don't even need to worry about removing duplicates.

Related

I want to display the total number of messages in my device

Is there a way of determining the number of total messages in our device.
I've tried the following for finding the number of calls:
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
count= c.getCount();
Log.i("TAG",Integer.toString(count));
But I'm not able to view any number when i tried this similar to messages in my logcat.
Try this code to get all Messages
public List<String> getSMS(){
List<String> sms = new ArrayList<String>();
Uri uriSMSURI = Uri.parse("content://sms/inbox");
Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
while (cur != null && cur.moveToNext()) {
String address = cur.getString(cur.getColumnIndex("address"));
String body = cur.getString(cur.getColumnIndexOrThrow("body"));
sms.add("Number: " + address + " .Message: " + body);
}
if (cur != null) {
cur.close();
}
return sms;
}
Just Call the method and you will receive an ArrayList of all messages
Get List of Messages in Inbox Like Below:
First Add Permission in Manifest.xml to read sms:
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
public ArrayList<String> fetchInbox()
{
ArrayList<String> sms = new ArrayList();
//Read Draft message only by "content://sms/draft"
//Read Sent message only by "content://sms/sent"
Uri uriSms = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uriSms, new String[]{"_id", "address", "date", "body"},null,null,null);
cursor.moveToFirst();
while (cursor.moveToNext())
{
String address = cursor.getString(1);
String body = cursor.getString(3);
sms.add(body);
}
return sms;
}
And You can get SMS count by sms.size();

Multiply contacts' name On update (ContentProviderOperation)

A very strange porblem. I'm tring to update contacts name by this rule:
- if a contact's name start with "bit" + space ("bit ") so -> update the contact's name to name.substring(4, name.length()), and that means that the contact name will update without the "bit ".
when I use name.substring from number that lower them 4 (I think until the space in contact's name) its working perfectly. When I use from the 4 character onwards the contact's name multiply. For exmaple, when i use name = name.substring(4, name.length()) while name equal to "bit Lili" its update to:
Lili Lili.
private void updateContact(String name) {
ContentResolver cr = getContentResolver();
String where = ContactsContract.Data.DISPLAY_NAME + " = ?";
String[] params = new String[] {name};
Cursor phoneCur = managedQuery(ContactsContract.Data.CONTENT_URI,null,where,params,null);
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
if ((null == phoneCur)) {//createContact(name, phone);
Toast.makeText(this, "no contact with this name", Toast.LENGTH_SHORT).show();
return;} else {ops.add(ContentProviderOperation.newUpdate(android.provider.ContactsContract.Data.CONTENT_URI)
.withSelection(where, params)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name.substring(4,name.length()))
.build());
}
phoneCur.close();
try {cr.applyBatch(ContactsContract.AUTHORITY, ops);}
catch (RemoteException e) {e.printStackTrace();}
catch (OperationApplicationException e) {e.printStackTrace();}}
Thanks!
Not a certain answer but it suppose to work the issue you have is with the
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME //This specific part has a problem with the new update function
,name.substring(4,name.length()))
So my fix proposal is to change it to family name and given name change these as you need based on your question you want to remove the given name so it's a fix for that
public static boolean updateContactName(#NonNull Context context, #NonNull String name) {
if (name.length() < 4) return true;
String givenNameKey = ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME;
String familyNameKey = ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME;
String changedName = name.substring(4, name.length());
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
String where = ContactsContract.Data.DISPLAY_NAME + " = ?";
String[] params = new String[]{name};
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(where, params)
.withValue(givenNameKey, changedName)
.withValue(familyNameKey, "")
.build());
try {
context.getContentResolver()
.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}

Removing country code from phone number

I am stuck with a problem in which some contacts contain a country code while others don't.
I have code for fetching contact numbers which are being saved in list. The list looks like this:
[9999999999, 91-8888888888, 91-0000000000, 1111111111]
Now, I want to remove country code from those numbers which have it. I can't figure out a way to check this.
Here is my code for fetching contacts:
ContentResolver cr = getApplicationContext().getContentResolver(); //Activity/Application android.content.Context
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
if(cursor.moveToFirst())
{
do
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
if(Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{ id }, null);
while (pCur.moveToNext())
{
String contactName = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY));
String contactNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
allContacts.add(contactName);
contactNumber = contactNumber.replaceAll("\\s+","");
allnumbers.add(contactNumber);
break;
}
pCur.close();
}
} while (cursor.moveToNext()) ;
}
}
Here, allnumbers contains the number (where some have country code with them and others don't). How can I remove the country code from those who have it?
Any help or keywords to search will be appreciated, thanks.
If you want to remove the first occurance of a string containing '91-', you could simply use the replaceFirst() method. So your code will end up like this:
contactNumber.replaceAll("\\s+","").replaceFirst("91-","");
If you want to check if a string starts with '91-', you could use this:
if (contactNumber.startsWith("91-")) {
}
In your sample with array of numbers you have dash(-) between countrycode. So you can just use indexOf to determine if number has country code. You can do the same thing using regexp([\d]+-[\d]+)
Also you can count degits. Usually numbers without country codes have only 10 digits. It depends on your situation
Just try
contactNumber = contactNumber.replace("+91", "");
Hope this helps...

How to access android contacts into an array

I'm just begining on Android and Java in general and Im trying to write an app that allows you to select your some of your contacts, grabbing their Name and main number and putting them into seperate list arrays. I'm not sure how to go about doing that so I've only added it in manually where you must type each persons name and number.
List<String> phnnumbers = new ArrayList<String>();
List<String> names = new ArrayList<String>();
TextView quantityTextView = (TextView) findViewById(R.id.numbersview);
// Defines the box where we will grab the numbers
EditText addnumberfieldbox = (EditText) findViewById(R.id.addnumberfield);
EditText nameboxtext = (EditText) findViewById(R.id.namebox);
// Grabs the box's contents and puts it into useable data
Editable numberfieldEditable = addnumberfieldbox.getText();
Editable nameboxEditable = nameboxtext.getText();
// Finally uses the data from the box, and puts it in
String numberfieldString = numberfieldEditable.toString();
String nameboxString = nameboxEditable.toString();
names.add(nameboxString);
phnnumbers.add(numberfieldString);
That's the method I'm using to get the text and put it into arrays.
To access the contact list of your phone you need to follow these steps :
Step 1 : Add permission to access contacts in your manifest.xml file
<uses-permission android:name="android.permission.READ_CONTACTS"/>
Step 2 : Use the following code to fetch name and phone number and then store them to ArrayList.
ArrayList<JSONObject> contacts = new ArrayList<>();
public void addContacts(){
//to store name-number pair
JSONObject obj = new JSONObject();
try {
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
obj.put(name, phoneNumber);
contacts.add(obj);
Log.e("Contact list with name & numbers", " "+contacts);
}
phones.close();
}
catch (Exception e){
e.printStackTrace();
}
}
You can use the ArrayList contacts in your application code.
1 - Put the permissions on your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
<application
android:theme="#style/AppTheme" > ...
2 - import ContactsContract
import android.provider.ContactsContract;
3 - Populate a cursor with phone contacts:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
4 - Populate ArrayLists
List<String> phnnumbers = new ArrayList<String>();
List<String> names = new ArrayList<String>();
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
names.add(name);
phnnumbers.add(phoneNumber);
}
}

Getting ArrayList with SQLOpenHelper not working

I have a problem with my SQLiteOpenHelper class.
I have a database with printer manufacturers and details of any kind of printer.
I try to get all manufacturer from my database with this code and returning them in a arraylist.
// Read database for All printer manufacturers and return a list
public ArrayList<String> getPrManufacturer(){
ArrayList<String> manufacturerList = new ArrayList<String>();
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(CoDeskContract.Printer.TABLE_NAME,
printerManuProjection, null, null, null, null, null,null);
// If cursor is not null and manufacturer List
// does not contains Manufacturer in the list then add it!
if ((cursor != null) && (cursor.getCount()>0)){
cursor.moveToFirst();
do {
String cursorManufacturer = cursor.getString(0);
//Checking for manufacturer in the list
for(String manufacturerInList:manufacturerList){
if (!manufacturerInList.equals(cursorManufacturer))
manufacturerList.add(cursorManufacturer);
}
}while(cursor.moveToNext());
}
// Return list of manufacturers from database
return manufacturerList;
}
I want every manufacturer to be once in a list.
Somehow i cant to get it to work.
Im still a newbie.
Thanks for any Help.
You can also use the distinct keyword in SQLite (http://www.sqlite.org/lang_select.html). Use SQLiteDatabase.rawQuery(String query, String[] args) for that.
db.rawQuery("SELECT DISTINCT name FROM " + CoDeskContract.Printer.TABLE_NAME,null);
There are two issues:
In the beginning, when your list manufacturerInList is empty then it will not go inside for(String manufacturerInList:manufacturerList){ loop and hence it will never add any entry in the list.
Once you fix your problem 1, still it will not work as if (!manufacturerInList.equals(cursorManufacturer)) checks against each entry in the list and adds the non matching entry in the list possibly multiple times.
To fix the issue, you have two options.
Option1: Use contains as:
if (!manufacturerList.contains(cursorManufacturer)) {
manufacturerList.add(cursorManufacturer);
}
Option2: Use a matchFound boolean flag as:
String cursorManufacturer = cursor.getString(0);
boolean matchFound = false;
//Checking for manufacturer in the list
for(String manufacturerInList:manufacturerList){
if (manufacturerInList.equals(cursorManufacturer)){
matchFound = true;
break;
}
}
if(!matchFound){ // <- doesn't exit in the list
manufacturerList.add(cursorManufacturer);
}
Use ArrayList.contains(Object elem) to check if item is exist in ArrayList or not Change your code as:
// does not contains Manufacturer in the list then add it!
if ((cursor != null) && (cursor.getCount()>0)){
cursor.moveToFirst();
do {
String cursorManufacturer = cursor.getString(0);
//Checking for manufacturer in the list
if (!manufacturerList.contains(cursorManufacturer)) {
manufacturerList.add(cursorManufacturer);
} else {
System.out.println("cursorManufacturernot found");
}
}while(cursor.moveToNext());
}

Categories

Resources