Selecting multiple contacts in Android - android

Is there a way similar to ACTION_PICK to select multiple contacts from the address book and then return to previous activity?

Not a full answer, but maybe helpful anyway:
// Let user select (multiple) from a list of contacts with email addresses
Intent i = new Intent(Intent.ACTION_GET_CONTENT, Email.CONTENT_URI);
startActivityForResult(Intent.createChooser(i, ""), MY_RESULT_1);
In onActivityResult, you'll apparently just get a Uri (in data.getData()) that represents the entire set of contacts. Great.
On HTC Desire/Froyo, data.getExtras() contain three ArrayLists, one of which seems to hold the Id's of the records the user selected.
Set<String> keys = data.getExtras().keySet();
ArrayList<Integer> ids = null;
for (String s : keys) {
Object o = data.getExtras().get(s);
if (o instanceof ArrayList) {
ArrayList a = (ArrayList) o;
if (a.size() > 0 && a.get(0) instanceof Integer) {
ids = a;
}
}
}
You can use these to filter the result from querying the data.getData() Uri.
Not pretty, and possibly HTC specific. You mileage may vary.
If someone can point out a smarter way, I'm a happy listener :)

Related

How to query users collection using array of IDs from group collection

I have a collection where I store user groups. Each group has a group name, group limit and an array of users ID's.
I wonder how the best way to retrieve one group details and then users details, like name, photo, etc.
Right now, I am doing two queries to the database. First retrieving the group data(name, etc), second getting a list of users who has in the user details the information of the group ID:
"syncDesp = a4sQ27xb1wuD2rhONU2K"
I'm afraid of calling the database to many times.
// Get Group details
Preferencias prefs = new Preferencias(view.getContext());
listenGroups = pFirestore.collection("syncDesps").document(prefs.getSyncDesp()).addSnapshotListener((documentSnapshot, e) -> {
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e).getMessage());
}
if(documentSnapshot != null){
String nomeGrupo = Objects.requireNonNull(documentSnapshot.get("nomeGrupo")).toString();
textNomeGrupo.setText(nomeGrupo);
ArrayList membrosGrupo = (ArrayList) Objects.requireNonNull(documentSnapshot.get("syncDesp"));
}
});
// Get User Details
FirebaseFirestore grupoFire = FirebaseFirestore.getInstance();
grupoFire.collection("usuarios")
.whereEqualTo("syncDesp", prefs.getSyncDesp())
.addSnapshotListener((queryDocumentSnapshots, e1) -> {
listaUsuarios.clear();
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e1).getMessage());
}
for(DocumentSnapshot usuarioSnapshot : Objects.requireNonNull(queryDocumentSnapshots).getDocuments()){
String idU = (usuarioSnapshot.get("id") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("id")).toString();
String nomeUsuario = (usuarioSnapshot.get("nome") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("nome")).toString();
String fotoUsuario = (usuarioSnapshot.get("imgUsuario") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("imgUsuario")).toString();
UsuarioMeuGrupo usuarioMeuGrupo = new UsuarioMeuGrupo();//
usuarioMeuGrupo.setIdUsuario(idU);
usuarioMeuGrupo.setNome(nomeUsuario);
usuarioMeuGrupo.setFoto(fotoUsuario);
listaUsuarios.add(usuarioMeuGrupo);
}
adaptera.setOnItemClickRemoverListener(uMeuGrupo -> {
Log.i("dados uMeuGrupo Clic", uMeuGrupo.getNome());
});
adaptera.notifyDataSetChanged();
});
I wonder if I should query the group collection separately from the users collection or if there is a way of making only one function to retrieve data from both collections.
It's not possible to make a single query in Cloud Firestore span multiple collections. There is no join-like operation like you have in SQL. The only exception to this is collection group queries, which doesn't apply to your situation.
What you're doing right now is probably the best you can do with the database structure you have. If you want fewer queries, you'll have to do something to restructure your data to support that.

Android: Quickest way to filter lists as user types a query

Good day all, I have a list of Objects (Let's call them ContactObject for simplicity). This object contains 2 Strings, Name and Email.
This list of objects will number somewhere around 2000 in size. The goal here is to filter that list as the user types letters and display it on the screen (IE in a recyclerview) if they match. Ideally, It would filter where the objects with a not-null name would be above an object with a null name.
As of right now, the steps I am taking are:
1) Create 2 lists to start and get the String the user is typing to compare to
List<ContactObject> nameContactList = new ArrayList<>();
List<ContactObject> emailContactList = new ArrayList<>();
String compareTo; //Passed in as an argument
2) Loop though the master list of ContactObjects via an enhanced for loop
3) Get the name and email Strings
String name = contactObject.getName();
String email = contactObject.getEmail();
4) If the name matches, add it to the list. Intentionally skip this loop if the name is not null and it gets added to the list to prevent doubling.
if(name != null){
if(name.toLowerCase().contains(compareTo)){
nameContactList.add(contactObject);
continue;
}
}
if(email != null){
if(email.toLowerCase().contains(compareTo)){
emailContactList.add(contactObject);
}
}
5) Outside of the for loop now as the object lists are build, use a comparator to sort the ones with names (I do not care about sorting the ones with emails at the moment)
Collections.sort(nameContactList, new Comparator<ContactObject>() {
public int compare(ContactObject v1, ContactObject v2) {
String fName1, fName2;
try {
fName1 = v1.getName();
fName2 = v2.getName();
return fName1.compareTo(fName2);
} catch (Exception e) {
return -1;
}
}
});
6) Loop through the built lists (one sorted) and then add them to the master list that will be used to set into the adapter for the recyclerview:
for(ContactObject contactObject: nameContactList){
masterList.add(contactObject);
}
for(ContactObject contactObject: emailContactList){
masterList.add(contactObject);
}
7) And then we are all done.
Herein lies the problem, this code works just fine, but it is quite slow. When I am filtering through the list of 2000 in size, it can take 1-3 seconds each time the user types a letter.
My goal here is to emulate apps that allow you to search the contact list of the phone, but seem to always to it quicker than I am able to replicate.
Does anyone have any recommendations as to how I can speed this process up at all?
Is there some hidden Android secret I don't know of that only allows you to query a small section of the contacts in quicker succession?

Android get contact names by phone number efficiently for displaying in ListView

I'm creating an Sms app which contains a ListView in the Main Activity that displays all the conversations from the sms inbox. Each ListView row displays one conversation along with the phone number, message body and time of the message. Now instead of the phone number I want to display the contact name if it exists.
So far, for getting the contact name by phone number I found this code
private String getDisplayNameByNumber(String number) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor contactLookup = context.getContentResolver().query(uri, new String[] {ContactsContract.PhoneLookup._ID,
ContactsContract.PhoneLookup.DISPLAY_NAME }, null, null, null);
int indexName = contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
try {
if (contactLookup != null && contactLookup.moveToNext()) {
number = contactLookup.getString(indexName);
}
} finally {
if (contactLookup != null) {
contactLookup.close();
}
}
return number;
}
But this seems inefficient as it has to make a query for each contact name individually and lags the app. So instead I tried to get all the contact names from the phone and store it in an HashMap with the phone number as the key and the contact name as the value, so that I can get the contact name any time I want from the HashMap. But there seems to be another problem, the phone numbers are stored in many different formats, for eg:
+91 4324244434
04324244434
0224324244434
So how do I search for a phone number from the HashMap since it can be stored in many different formats?
Before you add the contact to the HashMap, use regular expression to grab the phone number. This way, no matter what format the phone number is in, the regular expression will be able to grab the appropriate number needed.
Once you grab the number, add it to the HashMap accordingly.
Hope that answers your question.

Getting User Certificates with KeyStore.saw(String prefix)

There is described on this page how android is able to select all user certificates and show them in a spinner...
http://source-android.frandroid.com/packages/apps/Settings/src/com/android/settings/vpn2/VpnDialog.java
They use the Method:
private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) {
Context context = getContext();
String first = (firstId == 0) ? "" : context.getString(firstId);
String[] certificates = mKeyStore.saw(prefix);
if (certificates == null || certificates.length == 0) {
certificates = new String[] {first};
} else {
String[] array = new String[certificates.length + 1];
array[0] = first;
System.arraycopy(certificates, 0, array, 1, certificates.length);
certificates = array;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
context, android.R.layout.simple_spinner_item, certificates);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
for (int i = 1; i < certificates.length; ++i) {
if (certificates[i].equals(selected)) {
spinner.setSelection(i);
break;
}
}
}
with this call:
loadCertificates(mIpsecUserCert, Credentials.USER_CERTIFICATE,
0, mProfile.ipsecUserCert);
now they use Credetials.USER_CERTIFICATE for the Method mKeyStore.saw(String prefix)
thats exactly what im looking for, but i cannot invoke the method saw and its also not mentioned in the android api...
so is there somehow a way of getting the same result for me?
the keystore library is not able of making a difference of user or system certs, and if i want to put all certs in a dropdown list it will cost me a lot of loading time. The other way of typing the subject name of the cert and looping through all certs till its the right one is not really practicable for a non-IT guy, so its crappy to handle for a normal user...
there are almost no references on this topic in the net, thats why im asking google android pro's on this post only.
thankyou
This is a private API, it cannot be used by third party applications. Why do you want to select a user certificate? You generally want the user's private key, and the KeyChain API supports letting the user select one of those.

Get contacts in Android

I want to get the contact numbers in Android but as far as I found a tutorial, it puts out the number in ascending order, not in the order they appear in the contacts...
How can I modify the code to obtain the numbers in the exact order from my contact list??
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, null,null, null);
ArrayList <String> nr_formatat = new ArrayList <String> ();
if (cursor != null) {
while (cursor.moveToNext() == true)
nr_formatat.add(cursor.getString( cursor.getColumnIndex(Phone.NUMBER)));
}
You're going about it the wrong way. You need to query the number against the CONTACT_ID or else you won't have any correspondence between the two. Take a look at this tutorial.
It depends on how your contacts are ordered in your contact list. Hit the menu button and tap on 'Display Options'. Other than that, you don't have enough information in your question to adequately answer it.
From what I can see, you're going about it the wrong way. I would look over this example application. It fetches the contacts differently than you and will allow you to sort it however you want.
http://developer.android.com/resources/samples/BusinessCard/src/com/example/android/businesscard/index.html
Following should work if:
(Anna, 0342) has ID 1, (Lulu, 0311) has ID 2, (John, 0088) has ID 3
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, null,null, new String[]{Phone.ID});
ArrayList <String> nr_formatat = new ArrayList <String> ();
if (cursor != null) {
while (cursor.moveToNext() == true)
nr_formatat.add(cursor.getString( cursor.getColumnIndex(Phone.NUMBER)));
}
The last variable of ContentResolver().query() takes the sortorder. So here you put something like the ID, if your contactlist also sorts on ID.
ConecntResolver().Query() info here.

Categories

Resources