I have so far looked at many questions where this is the topic, not a single answer has worked for me so far. In my code I get the user's google account and their contact info. I can successfully look at their email and display name fine. When I grab their id number and use it how http://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html would have me use it, the InputStream comes up null. When I debug through the following method the program never loads the blob into data, it immediately skips down to finally.
public InputStream openPhoto(long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = context.getContentResolver().query(photoUri,
new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
if (cursor == null) {
return null;
}
try {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
if (data != null) {
return new ByteArrayInputStream(data);
}
}
} finally {
cursor.close();
}
return null;
}
Does this mean the selected contact does not have a profile image??? I no this to not be the case as it is accessing my personal gmail account and giving me the other data correctly. I get this id with the following code (along with email and display name). I get the email with googleAccount.name
AccountManager accountManager;
accountManager = AccountManager.get(context);
Account[] account = accountManager.getAccounts();
Account googleAccount = null;
for(int i = 0; i < account.length; i++) {
if(account[i].type.equals("com.google")) {
googleAccount = account[i];
}
}
Cursor c = context.getContentResolver().query(ContactsContract.Profile.CONTENT_URI, null, null, null, null);
int count = c.getCount();
c.moveToFirst();
String id = "";
String displayName = "";
String[] columnNames = c.getColumnNames();
int position = c.getPosition();
if (count == 1 && position == 0) {
for (int j = 0; j < columnNames.length; j++) {
String columnName = columnNames[j];
String columnValue = c.getString(c.getColumnIndex(columnName));
if(columnName.equals("_id"))
id = columnValue;
if(columnName.equals("display_name"))
displayName = columnValue;
// consume the values here
}
}
c.close();
Why is this inputstream coming up null? I got the code directly from google. Has anyone had this problem with this code before?
Related
In my Music-Player, a Playlist may contain two identical songs (the user adds the same song two times).
Let's say the song which is 2 times in the Playlist has the id 7664.
When removing this song from the Playlist, ContentResolver.delete(URI_OF_PLAYLIST, "audio_id=7664", null); removes both matches.
So how do I only delete one match?
Thanks in advance!
This is how I do it in my app New Playlist Manager:
step 1: create an array with audio Ids
step 2: whilst looping around this, use the .lastindex() function to determine if it exists elsewhere. (otherwise the value should be the same as position)
step 3: if found, remove from audio Ids array by setting it to null (you do not want to change its size) and remove from playlist
step 4: reorder the playorder
public void dedupe_playlist(Context context, long playlist_id) {
Cursor cursor = plist.getPlaylistTracks(context, playlist_id);
ArrayList<String> audio_ids = new ArrayList<>();
// build up the array with audio_id's
int i = 0;
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String audio_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID));
audio_ids.add(audio_id);
}
i = 0;
int duplicates = i;
boolean success = false;
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String audio_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID));
duplicates = audio_ids.lastIndexOf(audio_id);
if (duplicates > i) {
success = true;
cursor.moveToPosition(duplicates);
int _id = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members._ID));
removePlaylistTrack(context, playlist_id, _id);
audio_ids.set(duplicates, null);
cursor.moveToPosition(i - 1); // move back to test again
} else {
i++;
}
}
if (success) {
renumber_playorder(context, playlist_id);
}
try {
cursor.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void removePlaylistTrack(Context context, long selectedplaylist,
int _id) {
ContentResolver resolver = context.getContentResolver();
Uri newuri = MediaStore.Audio.Playlists.Members.getContentUri(
"external", selectedplaylist);
try {
resolver.delete(newuri, MediaStore.Audio.Playlists.Members._ID + " = " + _id, null);
} catch (Exception e) {
e.printStackTrace();
}
}
To reorder a playlist:
public void renumber_playorder(Context context, long playlist_id) {
Cursor cursor = getPlaylistTracks(context, playlist_id);
Uri newuri = MediaStore.Audio.Playlists.Members.getContentUri(
"external", playlist_id);
ContentResolver resolver = context.getContentResolver();
ContentValues values = new ContentValues();
int i = 0;
if (cursor != null && cursor.moveToFirst()) {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String _id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members._ID));
String[] selection = {_id};
values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, i);
resolver.update(newuri, values, MediaStore.Audio.Playlists.Members._ID + " =? ", selection);
i++;
}
cursor.close();
}
}
Im trying to save the users contacts in an ArrayList <Contacts> but somehow I got duplicates in it. I found out that I should use
ContractsContact.Contacts.CONTENT_URI
and not
ContractsContact.DATA.CONTENT_URI
But its not helping me. I still got dublicates in my ArrayList. Here is my code :
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(CONTENT_URI, null,null, null, null);
// Loop for every contact in the phone
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String contact_id = cursor.getString(cursor.getColumnIndex( _ID ));
String name = cursor.getString(cursor.getColumnIndex( DISPLAY_NAME ));
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex( HAS_PHONE_NUMBER )));
if (hasPhoneNumber > 0) {
// Query and loop for every phone number of the contact
Cursor phoneCursor = contentResolver.query(PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?", new String[]{contact_id}, null);
while (phoneCursor.moveToNext()) {
phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
if (phoneNumber.charAt(0) == '0' && phoneNumber.charAt(1) == '0')
{
String temp = "+";
for(int j=2;j<phoneNumber.length();++j)
temp += phoneNumber.charAt(j);
phoneNumber = temp;
}
if (!phoneNumber.contains("+"))
{
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber normalized_number = null;
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String current_iso_code = telephonyManager.getSimCountryIso();
current_iso_code = current_iso_code.toUpperCase();
try {
normalized_number = phoneUtil.parse(phoneNumber,current_iso_code);
}catch(Exception e){
e.printStackTrace();
}
String str_normalized_number = phoneUtil.format(normalized_number, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
str_normalized_number = str_normalized_number.replaceAll(" ","");
str_normalized_number = str_normalized_number.replaceAll("\\(","");
str_normalized_number = str_normalized_number.replaceAll("\\)","");
contacts.add(new Contact (name,str_normalized_number,current_iso_code,contact_id));
}
else {
phoneNumber = phoneNumber.replaceAll(" ","");
phoneNumber = phoneNumber.replaceAll("\\(","");
phoneNumber = phoneNumber.replaceAll("\\)","");
phoneNumber = phoneNumber.replaceAll("-","");
String iso_code = null;
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
Phonenumber.PhoneNumber numberProto = phoneUtil.parse(phoneNumber, "");
iso_code = phoneUtil.getRegionCodeForNumber(numberProto);
}catch(Exception e){}
contacts.add(new Contact (name,phoneNumber,iso_code,contact_id));
}
}
phoneCursor.close();
}
}
Is there a wrong part in my code which I'm not seeing ?
I think Hash set Concept in Java may help to solve this problem as it removes duplicate items.I hope it will address the problem
The following link may help in this regard.
Removing Duplicate Values from ArrayList
I'm trying to share a video(to social media) in an app I'm building. I'm using intents for which I need a Uri to parse. I'm trying to select items on a simple file manager (List activity) and then share them on long press. Thus I require the following code to get the Uri of the video for using it in the intents.
ContentResolver contentResolver = ctx.getContentResolver();
String videoUriStr = null;
long videoId = -1;
Uri videosUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns._ID };
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = contentResolver.query(videosUri, projection,
MediaStore.Video.VideoColumns.DATA + " =?",
new String[] { fileToShare }, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
cursor.close();
if (videoId != -1)
videoUriStr = videosUri.toString() + "/" + videoId;
{
return videoUriStr;
}
UPDATE
The first few items on the ListActivity File manager file will share properly. But the latest videos show the error.
Error: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
your cursor has 0 rows. So, the line cursor.getLong(columnIndex); throws CursorIndexOutOfBoundsException. please check for null and check whether any rows exist or not.
If there is no rows cursor.moveToFirst() will return false.
Cursor cursor = contentResolver.query(videosUri, projection,
MediaStore.Video.VideoColumns.DATA + " =?",
new String[] { fileToShare }, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
cursor.close();
if (videoId != -1)
{
videoUriStr = videosUri.toString() + "/" + videoId;
}
}
}
return videoUriStr;
The MediaStore.Video.VideoColumns.DATA field holds the path for the video file. So, if you are using uri (content://mnt/sdcard/Videos/test.mp4) to fetch the file change it to file path (/mnt/sdcard/Videos/test.mp4).
Use while loop to check is cursor have data or not :
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
cursor.close();
Replace with this code :
while (cursor.moveToNext()){
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
}
cursor.close();
Error: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
means your cursor has no data.
use check for cursor emptyness:
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
}
cursor.close();
This scenario does not depend on phone to phone. The problem is that your cursor has no data.
You can use cursor.moveToFirst() which returns false if the cursor is empty, or use cursor.getCount() to know the number of rows in the cursor.
e.g
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
}
cursor.close();
or
if (cursor.getCount() > 0) {
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
}
cursor.close();
first of all you need to check the size of the cursor.
if(cursor.size()>0)
{
// do here
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
videoId = cursor.getLong(columnIndex);
cursor.close();
if (videoId != -1)
videoUriStr = videosUri.toString() + "/" + videoId;
{
return videoUriStr;
}
}
I was able to get my problem solved but I still don't understand why I faced that problem with the old code. Thanks for all the help.
public static Uri getVideoContentUriFromFilePath(Context context, File fileToShare) {
String filePath = fileToShare.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.Media._ID },
MediaStore.Video.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
return Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
if (fileToShare.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
Am new to android(Java) and i want to perform a simple task
how can i Fetch all the contacts phone numbers, email, and fullname on the device and their details and put
them in a single array as such
I am from a PHP BACKGROUND SO THE ARRAY WOULD LOOK LIKE THIS IN PHP :
ContactsArray[0] = array(
'fullname' => 'John doe',
'Phone' => '0909809890' ,
'email' => 'johndoe#email.com'
)
Thats what the array should look like from a PHP perspective,
Am new to android and would like a class to fetch all this data
put them in a single array
return the data.
PSEUDO CODE
function GetContacts(){
contacts = fetchAllContactsDetails
return contacts;
}
This could be a start. Please note that I haven't tested this out and there could be errors but you'll get the idea.
Read this for more info on multi dimensional array. Link
String phpArray;
int x=3;
int y=array.length();
String[][] myStringArray = new String [y][x];
for(int i=0; i<array.length; i++){
for(int j=0; j<3; j++){
phpArray = contactsArray[i];
myStringARray[i][j] = phpArray[j];
}
}
First you need add the permission to read the contacts in your manifest file:
<uses-permission android:name="android.permission.READ_CONTACTS" >
</uses-permission>
And you can check this code:
public void fetchContacts() {
String phoneNumber = null;
String email = null;
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
Uri EmailCONTENT_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
String EmailCONTACT_ID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
String DATA = ContactsContract.CommonDataKinds.Email.DATA;
StringBuffer output = new StringBuffer();
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(CONTENT_URI, null,null, null, null);
// Loop for every contact in the phone
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String contact_id = cursor.getString(cursor.getColumnIndex( _ID ));
String name = cursor.getString(cursor.getColumnIndex( DISPLAY_NAME ));
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex( HAS_PHONE_NUMBER )));
if (hasPhoneNumber > 0) {
output.append("\n First Name:" + name);
// Query and loop for every phone number of the contact
Cursor phoneCursor = contentResolver.query(PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?", new String[] { contact_id }, null);
while (phoneCursor.moveToNext()) {
phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
output.append("\n Phone number:" + phoneNumber);
}
phoneCursor.close();
// Query and loop for every email of the contact
Cursor emailCursor = contentResolver.query(EmailCONTENT_URI, null, EmailCONTACT_ID+ " = ?", new String[] { contact_id }, null);
while (emailCursor.moveToNext()) {
email = emailCursor.getString(emailCursor.getColumnIndex(DATA));
output.append("\nEmail:" + email);
}
emailCursor.close();
}
output.append("\n");
}
outputText.setText(output);
}
}
}
I am trying fetch contact details such as Name, phone number, email and photo. attached to a contact in an arraylist.
But for a contact having both phone number and email address. I can see the same contact name twice at first with its email address & then with its phone number and is not shown as a single contact (which it should be).
Can anyone please help me out with this?
TIA :)
Ref.:
public ArrayList<User> getPhoneContact(String paramString, ArrayList<User> paramArrayList)
throws CustomException
{
//Cursor localCursor = null;
Cursor cursor = null;
ArrayList localArrayList = new ArrayList();
User user;
boolean flag;
String s1;
String s2;
String s6;
String s5;
String s3;
String s4;
int i;
int j;
int k;
int l;
int i1;
try
{
cursor = getNamesAndPictures(paramArrayList);
if(cursor != null && cursor.moveToFirst()){
user = null;
i = cursor.getColumnIndex("data1");
j = cursor.getColumnIndex("contact_id");
k = cursor.getColumnIndex("display_name");
l = cursor.getColumnIndex("data1");
i1 = cursor.getColumnIndex("mimetype");
s1 = null;
do{
s2 = cursor.getString(j);
if(s2 == null)
return localArrayList;
//if(s2.equals(s1))
//return localArrayList;
user = new User();
s1 = s2;
s3 = cursor.getString(k);
user.setName(s3);
user.setContactId(s2);
user.setContactType(paramString);
s4 = cursor.getString(i1);
if(s4 != null){
if(s4.equals("vnd.android.cursor.item/phone_v2")){
s6 = cursor.getString(i);
user.setPhone(s6);
}
else if(s4.equals("vnd.android.cursor.item/email_v2")){
s5 = cursor.getString(l);
user.setEmail(s5);
}
}
localArrayList.add(user);
}while(cursor.moveToNext());
}
}
catch (Exception localException)
{
//localException
}
finally
{
//closeCursor(localCursor);
closeCursor(cursor);
closeDatabase();
}
return localArrayList;
}
And:
private Cursor getNamesAndPictures(ArrayList<User> paramArrayList)
{
String str1 = prepareContactIdsString(paramArrayList);
ContentResolver localContentResolver = this.getAppContext().getContentResolver();
String[] arrayOfString = { "data1", "contact_id", "display_name", "_id", "data1", "mimetype" };
String str2 = "display_name != 'null' AND ( (mimetype = 'vnd.android.cursor.item/phone_v2' AND is_primary != -1 ) OR (mimetype = 'vnd.android.cursor.item/email_v2' AND is_primary != -1 ) ) AND contact_id NOT IN ( " + str1 + ")";
return localContentResolver.query(android.provider.ContactsContract.Data.CONTENT_URI, arrayOfString, str2, null, "display_name COLLATE LOCALIZED ASC");
}
this is because you query the Data table which holds data rows , each row foe some kind of information about the contact, for example one row for email and one row for phone number.
if you want to get only the contacts you should query ContactsContract.Contacts table but then you will have to query for each of them the email and phone.
http://developer.android.com/guide/topics/providers/contacts-provider.html