Android - Pick multiple contacts - java

I'm aware that there is some old answer on here regarding on how to do this but was hoping for a more updated version.
I want to let the user pick multiple contacts from their phone and add it to an array.
I'm using ContactContract with PICK_CONTENT.
So far I have got the following:
public void onActivityResult(int reqCode, int resultCode, Intent data){
super.onActivityResult(reqCode,resultCode,data);
switch (reqCode){
case(PICK_CONTACT):
if(resultCode == Activity.RESULT_OK){
Uri contactData = data.getData();
Cursor phone = getContentResolver().query(contactData,null,null,null,null);
PlayerDetails player = new PlayerDetails(); //TODO turn this into a loop to add each player the user picks and then display it
if(phone.moveToFirst()) {
player.name = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
player.number =phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
playerListGame.addPlayer(player);
But this clicking a button to launch this activity and then :
public void showPlayerGameList(){
playerTextView = findViewById(R.id.aPlayerBox);
for(PlayerDetails i : playerListGame.myPlayers){
playerTextView.append(i.name + "\n" + i.number); //TODO sort this out so it doesnt repeat the same names
}
}
Then I loop through the array I add it to, to display the info I need.
I don't know how to get the application to allow the user to select multiple users
Thanks

I know it is late but i hope someone else or even you can implement in this way.
Launching CONTACTS intent with PICK_CONTACT will not be able to pick multiple contacts. Even if you manage to select multiple contacts on some device, It would not work on most of the other devices and versions of android systems. As i have tried in the same way before..
Then created a listview with multiple choce and given a list of contacts to adapter of the listview. Now how to get contacts list..
ContactsList = new ArrayList<String>();
ContactsNumbersList = new ArrayList<String>();
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
// Contacts Database queries
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, ContactsContract.CommonDataKinds.Phone.SORT_KEY_PRIMARY +" ASC");
while (cursor.moveToNext())
{
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
phoneNumber = phoneNumber.replace("-","");
phoneNumber = phoneNumber.replace(" ","");
phoneNumber = phoneNumber.replace("(","");
phoneNumber = phoneNumber.replace(")","");
if (normalizedNumbersAlreadyFound.add(phoneNumber))
{
ContactsList.add(name);
ContactsNumbersList.add(phoneNumber);
}
}
cursor.close();

Related

How can I update the phone numbers of contacts in Android Studios

I am new to developing apps with android studio, and I decided to make an app to edit the phone numbers of my phone contacts as my first test app.
I use a class to get information about all the contacts that I have on my cell phone, then I have created a listview where I show the contact's name, ID, avatar and registered phone numbers.
The information has been gotten from the ContactsContract.Contacts table. This all works fine, so far.
But now I have to edit the phone numbers of all the contacts, but I don't know exactly how to do it. I've been going through the Android devs documentation but I can't get anything that can help me. I don't want to use Intent in this case.
I have this kotlin class that I use to get the information of all contacts is this:
#file:Suppress("unused")
package com.example.uimx
import android.Manifest
import android.content.ContentUris
import android.content.Context
import android.net.Uri
import android.provider.ContactsContract
import androidx.annotation.RequiresPermission
#RequiresPermission(Manifest.permission.READ_CONTACTS)
fun Context.isContactExists(
phoneNumber: String
): Boolean {
val lookupUri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNumber)
)
val projection = arrayOf(
ContactsContract.PhoneLookup._ID,
ContactsContract.PhoneLookup.NUMBER,
ContactsContract.PhoneLookup.DISPLAY_NAME
)
contentResolver.query(lookupUri, projection, null, null, null).use {
return (it?.moveToFirst() == true)
}
}
#RequiresPermission(Manifest.permission.READ_CONTACTS)
#JvmOverloads
fun Context.retrieveAllContacts(
searchPattern: String = "",
retrieveAvatar: Boolean = true,
limit: Int = -1,
offset: Int = -1
): List<ContactData> {
val result: MutableList<ContactData> = mutableListOf()
contentResolver.query(
ContactsContract.Contacts.CONTENT_URI,
CONTACT_PROJECTION,
if (searchPattern.isNotBlank()) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE '%?%'" else null,
if (searchPattern.isNotBlank()) arrayOf(searchPattern) else null,
if (limit > 0 && offset > -1) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} ASC LIMIT $limit OFFSET $offset"
else ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC"
)?.use {
if (it.moveToFirst()) {
do {
val contactId = it.getLong(it.getColumnIndex(CONTACT_PROJECTION[0]))
val name = it.getString(it.getColumnIndex(CONTACT_PROJECTION[2])) ?: ""
val hasPhoneNumber = it.getString(it.getColumnIndex(CONTACT_PROJECTION[3])).toInt()
val phoneNumber: List<String> = if (hasPhoneNumber > 0) {
retrievePhoneNumber(contactId)
} else mutableListOf()
val avatar = if (retrieveAvatar) retrieveAvatar(contactId) else null
result.add(ContactData(contactId, name, phoneNumber, avatar))
} while (it.moveToNext())
}
}
return result
}
private fun Context.retrievePhoneNumber(contactId: Long): List<String> {
val result: MutableList<String> = mutableListOf()
contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
"${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} =?",
arrayOf(contactId.toString()),
null
)?.use {
if (it.moveToFirst()) {
do {
result.add(it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)))
} while (it.moveToNext())
}
}
return result
}
private fun Context.retrieveAvatar(contactId: Long): Uri? {
return contentResolver.query(
ContactsContract.Data.CONTENT_URI,
null,
"${ContactsContract.Data.CONTACT_ID} =? AND ${ContactsContract.Data.MIMETYPE} = '${ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}'",
arrayOf(contactId.toString()),
null
)?.use {
if (it.moveToFirst()) {
val contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
contactId
)
Uri.withAppendedPath(
contactUri,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY
)
} else null
}
}
private val CONTACT_PROJECTION = arrayOf(
ContactsContract.Contacts._ID,
ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
ContactsContract.Contacts.HAS_PHONE_NUMBER
)
data class ContactData(
val contactId: Long,
val name: String,
val phoneNumber: List<String>,
val avatar: Uri?
)
I have a button prepared that receives the click event and calls a function that would have the script to replace all the phone numbers of all the contacts, for new phone numbers that I will define for each contact.
I have this next code that I got on the internet but I can't get it to work in my app.
private int updateContactPhoneByID(long rawContactId)
{
int ret = 0;
ContentResolver contentResolver = getContentResolver();
// Update data table phone number use contact raw contact id.
if(rawContactId > -1) {
// Update mobile phone number.
updatePhoneNumber(contentResolver, rawContactId, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, "66666666666666");
// Update work mobile phone number.
updatePhoneNumber(contentResolver, rawContactId, ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE, "8888888888888888");
// Update home phone number.
updatePhoneNumber(contentResolver, rawContactId, ContactsContract.CommonDataKinds.Phone.TYPE_HOME, "99999999999999999");
ret = 1;
}else
{
ret = 0;
}
return ret;
}
/* Update phone number with raw contact id and phone type.*/
private void updatePhoneNumber(ContentResolver contentResolver, long rawContactId, int phoneType, String newPhoneNumber)
{
// Create content values object.
ContentValues contentValues = new ContentValues();
// Put new phone number value.
contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, newPhoneNumber);
// Create query condition, query with the raw contact id.
StringBuffer whereClauseBuf = new StringBuffer();
// Specify the update contact id.
whereClauseBuf.append(ContactsContract.Data.RAW_CONTACT_ID);
whereClauseBuf.append("=");
whereClauseBuf.append(rawContactId);
// Specify the row data mimetype to phone mimetype( vnd.android.cursor.item/phone_v2 )
whereClauseBuf.append(" and ");
whereClauseBuf.append(ContactsContract.Data.MIMETYPE);
whereClauseBuf.append(" = '");
String mimetype = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;
whereClauseBuf.append(mimetype);
whereClauseBuf.append("'");
// Specify phone type.
whereClauseBuf.append(" and ");
whereClauseBuf.append(ContactsContract.CommonDataKinds.Phone.TYPE);
whereClauseBuf.append(" = ");
whereClauseBuf.append(phoneType);
// Update phone info through Data uri.Otherwise it may throw java.lang.UnsupportedOperationException.
Uri dataUri = ContactsContract.Data.CONTENT_URI;
// Get update data count.
int updateCount = contentResolver.update(dataUri, contentValues, whereClauseBuf.toString(), null);
}
How to make the above script work to update the correct contact table with the information I have.
I think you have a confusion about contactId and rawContactId.
When you read all the contacts from the device, you're getting the contactId of that contact, but the updateContactPhoneByID method you're trying to use is expecting a rawContactId which is different.
In a nutshell, every Contact in the ContactsContract.Contacts table is comprised out of multiple RawContacts each is usually synced by some different app or account (e.g. one RawContact from your personal Google account, another RawContact from your work Google account, another one from Whatsapp, and one from Yahoo), the details from ALL these RawContacts are join to make up a single contact profile.
I'm not sure how you want the edit to work, if a contact has multiple phone numbers, do you want to replace ALL those phones with a single new phone number, or do you allow the user to type multiple phones in your edit screen?
Anyway, here's a small kotlin function that takes a contactId and an existing phone number X and replaces that single number with a new one.
I hope you can adapt it to your needs.
private fun updatePhone(contactId:Long, existingNumber:String, newNumber:String) {
val contentValues = ContentValues()
contentValues.put(Phone.NUMBER, newNumber)
val where = Data.CONTACT_ID + "=?" + " AND " + Data.MIMETYPE + "=?" + " AND " + Phone.NUMBER + "=?"
val whereArgs = arrayOf<String>((contactId).toString(), Phone.CONTENT_ITEM_TYPE, existingNumber)
contentResolver.update(Data.CONTENT_URI, contentValues, where, whereArgs)
}
Note that the existingNumber param must match the string in the ContactsContract DB exactly.

Passing phone number or CONTACT_ID from android contact details to activity (whatsapp like)

What I'm trying to achieve is to add shortcut to my app in android book contact details, similar to what whatsapp is doing.
I've been following this tutotial: http://blogs.quovantis.com/syncing-contacts-with-an-android-application-2/ and it works well but the author doesn't show how to pass data from contact details to ViewingActivity: https://github.com/ajkh35/ContactsDemo/blob/master/app/src/main/java/com/example/ajay/contacts_4/ViewingActivity.java
There was some comments below the article but no specific answer from the author, can't find anything useful in
Uri data = getIntent().getData(); //content://com.android.contacts/data/1169
List<String> params = data.getPathSegments();
String first = params.get(0);
String second = params.get(1);
there is some number passed in second param but it's not CONTACT_ID or RAW_CONTACT_ID. Any help?
Ok, so it seems the Uri you're getting from the Contacts app is a Data uri.
Data rows contain info about a specific data-item (like a phone number or an email) of a specific RawContact, so a single Data row "belongs" to a single RawContact which "belongs" to a single Contact.
Luckily, the ContactsContract API allows for implicit joins when querying the Data table, so you can do something like this:
Uri dataUri = getIntent().getData(); //content://com.android.contacts/data/1169
String[] projection = new String[]{
Data.CONTACT_ID,
Data.RAW_CONTACT_ID,
Data.DISPLAY_NAME,
Data.MIMETYPE,
Data.DATA1};
Cursor cur = getContentResolver().query(dataUri, projection, null, null, null);
cur.moveToFirst(); // there should always be exactly one result, since we have a specific data uri here
Log.i("Contact Info", "Got info: id=" + cur.getLong(0) + ", raw-id=" + cur.getLong(1) + ", " + cur.getString(2) + ", " + cur.getString(3) + ", " + cur.getString(4));
cur.close();
I know this is a very late response but checkout the following code.
class MessageActivity : AppCompatActivity() {
private val TAG: String = javaClass.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_message)
if(intent != null && intent.data != null) {
Log.e(TAG, intent.data.toString())
var contactName = ""
val cursor = contentResolver.query(intent.data!!,
arrayOf(ContactsContract.Data.DATA1,ContactsContract.Data.DATA2,ContactsContract.Data.DATA3),
null,null,null)
if(cursor != null && cursor.moveToFirst()) {
do{
Log.e(TAG, cursor.getString(cursor
.getColumnIndexOrThrow(ContactsContract.Data.DATA1)))
contactName = cursor.getString(cursor
.getColumnIndexOrThrow(ContactsContract.Data.DATA2))
Log.e(TAG, contactName)
Log.e(TAG, cursor.getString(cursor
.getColumnIndexOrThrow(ContactsContract.Data.DATA3)))
}while (cursor.moveToNext())
cursor.close()
}
messaging_text.text = getString(R.string.messaging) + " $contactName"
}
}}
So when you register a contact you set some Data1, Data2 and Data3 values. Data3 is what gets displayed in the contacts. You can set Data1 and Data2 some value you like and then retrieve it like in the code I mentioned above.
You can also checkout my blog here. Look for the "Sync Service" section, towards the end you will find the MessageActivity.
Thanks & regards

How do I pass integer variable in sqlite query which I receive from first Activity?

I am new to programming for Android devices. I have two activities, in the first activity I send an integer value from the first activity to the second activity.
How can I add this variable in sqlite query which I receive from my first activity?
I want to add booknumber where in query written b=1 I want replace 1 with booknumber
private void setData() {
Intent mIntent = getIntent();
int booknumber= mIntent.getIntExtra("booknumber", 0);
stringArrayList = new ArrayList<>();
mDBHelper = new DatabaseHelper(this);
mDb = mDBHelper.getReadableDatabase();
Cursor cursor = mDb.rawQuery("select DISTINCT c from t_asv where b=1", new String[]{});
if(cursor!=null && cursor.getCount() > 0)
{
if (cursor.moveToFirst())
{
do {
stringArrayList.add(cursor.getString(0));
} while (cursor.moveToNext());
}
}
Just Concatenate the int booknumber to your query like below:
int booknumber= mIntent.getIntExtra("booknumber", 0);
...
Cursor cursor = mDb.rawQuery("select DISTINCT c from t_asv where b=" + booknumber, new String[]{});
Update:
Its better to use the PreparedStatement / how to use as mentioned by #patrick-hollweck
Writing code like this leaves your app wide open to a sql injection vulnerability and is generally considered a very bad practice

How to get the phone contacts in a hashmap and store it locally and use it anywhere in the project?

I am trying to get the phone contacts and store it in a Hashmap. I want to save that locally and use it anywhere in the project.
Following is my code to get phone contacts:
public HashMap getPhoneContacts() {
ArrayList contactList=null;
ContentResolver cr = getContext().getContentResolver(); //Activity/Application android.content.Context
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null
, null, null, null);
if(cursor.moveToFirst())
{
contactList = new ArrayList<String>();
do
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String contactName=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
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 contactNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//String contactId = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String noramliseNum;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
noramliseNum = PhoneNumberUtils.normalizeNumber(contactNumber);
}else{
noramliseNum=contactNumber.replaceAll("\\s","");
}
phoneContacts.put(noramliseNum,contactName);
break;
}
pCur.close();
}
} while (cursor.moveToNext()) ;
}
return phoneContacts;
}
Its already taking lot of time to fetch all the contacts. So I dont want to call this function again and again from other classes. Instead I need to call the function only once,and then store it in a Hashmap locally and use it whenever we want,so that it wont take time to fetch the details again.
Please help.
You could put it into SharedPreferences if you don't want to re-download every time you start the app. Then, once the data is retreived, you could have a Singleton class to hold your Hashmap.
If you have many contacts, you should consider using a database.
Take a look at https://developer.android.com/guide/topics/data/data-storage.html
This would be more efficient than keeping everything in memory.

android- convert arraylist to one string in custom format

i have data in sqlit database so i use it to store categoreis and items
and i get it in arraylist like this:
public ArrayList showDataItems(String id_cate){
ArrayList<Items> arrayListItems = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cr = db.rawQuery("select * from items where id_cate = "+id_cate,null);
cr.moveToFirst();
while (cr.isAfterLast() == false){
String item_id = cr.getString(0);
String ItemName = cr.getString(1);
String Item_quantity = cr.getString(2);
String icon = cr.getString(3);
int isDone = Integer.parseInt(cr.getString(5));
arrayListItems.add(new Items(item_id,ItemName,Item_quantity,R.drawable.shopicon,icon,isDone));
cr.moveToNext();
}
return arrayListItems;
}
so i need to get this data and convert it to string and share it to other application like whatsapp in custom format for example :
1- first one *
2- second one *
3-....
so i use this code for send data
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,"hello world");
intent.setType("text/plain");
startActivity(Intent.createChooser(intent,"send items i need all
data here"));
so we can use string builder or some thing to get data in one string
please help me!
As you said, there is a StringBuilder class who can help formatting strings.
Here are the java docs
From StringBuilder, see the append(..) method. For your example:
int size = list.size();
for(int i = 0; i< size-1;i++){
stringBuilder.append(i+1).append("- ").append(list.get(i)).append('\n');
}
stringBuilder.append(size).append("- ").append(list.get(size-1));
The last call to append is different from the firstone by not appending the end line

Categories