How to get Ringtone name in Android? - java

I'm allowing my user to pick a ringtone for notifications in my app. I want to store the URI of the sound along with the human readable title of the sound.
So far the URI code works great:
Uri uri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
But when I try to get the title, and set it as a button text, I don't get anything. Seems to have no title?
String title = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
button.setText(title);
But my button text is empty. If I do:
button.setText(uri.toString());
then I see the uri perfectly. Should I just try to get the title from the URI? Thanks

This should get it:
Ringtone ringtone = RingtoneManager.getRingtone(this, uri);
String title = ringtone.getTitle(this);
Refer to http://developer.android.com/reference/android/media/Ringtone.html for the documentation, but the short story: Ringtone.getTitle(Context ctx);

I personally had a serious performance problem when I tried the accepted answer, it took about 2 seconds to just load a list of 30 ringtones. I changed it a bit and it works about 10x faster:
uri = ringtoneMgr.getRingtoneUri(cursor.getPosition());
ContentResolver cr = getContext().getContentResolver();
String[] projection = {MediaStore.MediaColumns.TITLE};
String title;
Cursor cur = cr.query(uri, projection, null, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
title = cur.getString(0);
cur.close();

I had problems with 'MediaPlayer finalized without being released'. I use this:
Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
returnCursor.moveToFirst();
String title = returnCursor.getString(returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
returnCursor.close();
Refer to https://developer.android.com/training/secure-file-sharing/retrieve-info.html for the documentation.

Related

Android media provider does not get recently added images

I want to fetch all the images in android device. Therefore I used this code to fetch images-
private fun getAllShownImagesPath(activity: Activity): ArrayList<String>
{
val uri: Uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val listOfAllImages = ArrayList<String>()
var absolutePathOfImage : String
val projection = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
val orderBy = MediaStore.Images.Media.DATE_ADDED
val cursor = activity.contentResolver.query(uri, projection, null, null, orderBy)
val indexData = cursor!!.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
cursor.moveToLast()
while (cursor.moveToPrevious())
{
absolutePathOfImage = cursor.getString(indexData)
listOfAllImages.add(absolutePathOfImage)
}
cursor.close()
return listOfAllImages
}
But this does not returns recently added images like if you downloaded it few hours ago.
This is somehow fixed when you reboot the device or the image you want to access is like one day old.
Note- you can also provide solution in java.
Thanks
Forcefully send broadcast then media cursor will be updated. call this before access media cursor
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse("file://" + Environment.getExternalStorageDirectory())));

How to get MediaStore.Images.ImageColumns.TITLE of an image in my gallery in android?

I have an image here: /storage/emulated/0/Pictures/1487951012463.jpg
The title is a text obviously. This title is shown in the default gallery viewer in android 5.1.1. (select image-->details)
But from my app, I just cannot read it.
Can someone help me out?
The code I am using is:
public static void loadTitle(Context context) {
Uri contentUri = Uri.parse("/storage/emulated/0/Pictures/1487951012463.jpg");
String[] projection = new String[] {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.LATITUDE,
MediaStore.Images.ImageColumns.LONGITUDE,
MediaStore.Images.ImageColumns.DESCRIPTION,
MediaStore.Images.ImageColumns.SIZE,
};
Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
cursor.moveToFirst();
String title, name;
title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.TITLE));
name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME));
Log.e("Title", title);
Log.e("Display_Name", name);
}
The app crashes as the cursor contains nothing.
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.database.Cursor.moveToFirst()' on a null object reference
I call this from an Activity if this matters...
What am I doing wrong?
EDIT - EDIT - EDIT - EDIT - EDIT - EDIT - EDIT
I have tried to do the same with the ExifInterface as it was suggested. The result I am getting with this is 'null'.
ExifInterface exif = new ExifInterface("/storage/emulated/0/Pictures/1487955364408.jpg");
String x = exif.getAttribute("XPTitle");
Log.e("Title with Exif: ", "X = "+ x );
Please help.
First, /storage/emulated/0/Pictures/1487951012463.jpg is not a Uri. It is a path. A Uri has a scheme.
Second, even if you put the file scheme on that Uri (which would make the Uri valid), you cannot use that Uri with query() on ContentResolver. query() only works with a content Uri, and you do not have one of those.
Presumably, that title is in an EXIF header in the JPEG file, though I am not certain which EXIF tag is the correct one. If you can find that out, you can use the support library's ExifInterface to read in the value.

How to mark all text messages as read on Android?

I'm trying to mark all text messages as read when user opens my inbox. I've pieced together code from a few tutorials online and ended up with this:
Uri uri = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
while (cursor.moveToNext()) {
if ((cursor.getInt(cursor.getColumnIndex("read")) == 0)) {
String SmsMessageId = cursor.getString(cursor.getColumnIndex("_id"));
ContentValues values = new ContentValues();
values.put("read", true);
getContentResolver().update(Uri.parse("content://sms/inbox"), values, "read=0", null);
}
I just want to mark all text messages as read in the onResume() function on this activity. My code may be a pile of crap, like i said it's mashed together from a few places. Corrections to, or alternatives to, my code would be very appreciated. Compiling the code with the sdk for 5.1, testing on 4.4, my app is the default SMS app.
If you want to mark all messages as read, you can do that in one go.
ContentValues values = new ContentValues();
values.put(Telephony.Sms.READ, 1);
getContentResolver().update(Telephony.Sms.Inbox.CONTENT_URI,
values, Telephony.Sms.READ + "=0", null);

Best way to load a large amount of data in android without making the user wait

I'm working in an application that read phone contacts and use them in my application (Call history, Favorite contacts and All contacts).
My UI consist of tab host control and user can swap between them, as I want my data to be shared across all my activities and also to be saved in only one place.
So I have created a singleton class called data controller, and when I open the application I show loading screen until all data loaded.
The problem now that user is complaining because of waiting a lot of time about (1 minute) every time they open the application when he has a very large amount of contacts, so how can I optimize my code in a good way?
EDIT
This is the method that I'm using to get all contacts:
public static ArrayList<ContactInfo> getAllContactWithNumberAndNameAndPhoto(
Context context, boolean starred) {
ArrayList<ContactInfo> retList = new ArrayList<ContactInfo>();
ContentResolver cr = context.getContentResolver();
Cursor cur = null;
if (starred == true) {
cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
"starred=?", new String[] { "1" }, null);
} else {
cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,
null, null);
}
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
ContactInfo item = new ContactInfo();
String id = cur.getString(cur
.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur
.getString(cur
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Uri photo = PhoneUtils.getPhotoUriFromID(context, id);
String starredValue = cur.getString(cur
.getColumnIndex(ContactsContract.Contacts.STARRED));
boolean isFav = false;
if (starredValue.equals("1"))
isFav = true;
if (Integer
.parseInt(cur.getString(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));
item.addPhone(removeCharactersFromPhoneNumber(phoneNo));
}
pCur.close();
if (photo != null) {
item.setPhoto(photo.toString());
}
item.setName(name);
item.setFavorite(isFav);
item.setRecent(false);
retList.add(item);
}
}
cur.close();
}
return retList;
}
Please let me know if I can optimize this method.
Im surprised it takes that long to load the contacts from the device.
Have you profiled the app to see where the time is actually spent? Something seems wrong here.
If it truly takes that long to load from the system providers (due to the OS) you could cache the results (i.e. put in your own SQL db) so you can load quickly on each app visit (< 1 sec) and refresh from device in the background.
I guess that the bottleneck of your method is photo loading. Try to load everything except photos, and then show your activity, concurrently loading photos.
Also you can try to create your own app table that contains just the data you need. So you'll do less selects while loading contacts. But you would have to synchronize your table. You can do so concurrently.

How do I get and display the album_art for a media player

I've spent ages searching for this and I'm now at the point where I see no alternative but to ask for help.
I'm trying to display album art within a media player I'm using. I have almost everything else fully functional including the other metadata, playing albums (vs. individual tracks) etc.
My code at the moment is as follows:
public View getView(int position, View convertView, ViewGroup parent) {
System.gc();
View cellLayout = getLayoutInflater().inflate(R.layout.albumbrowsercell, null);
ImageView album_art = (ImageView) cellLayout.findViewById(R.id.albums_album_cover);
TextView album_title = (TextView) cellLayout.findViewById(R.id.albums_album_title);
TextView artist_title = (TextView) cellLayout.findViewById(R.id.albums_artist_title);
String albumName;
String artistName;
int albumID;
album_column_index = albumCursor.getColumnIndexOrThrow(MediaStore.Audio.Albums._ID);
albumCursor.moveToPosition(position);
albumID = albumCursor.getInt(album_column_index);
Uri sArtworkUri = Uri.parse(MediaStore.Audio.Albums.ALBUM_ART);
Uri uri = ContentUris.withAppendedId(sArtworkUri, albumID);
album_art.setImageURI(uri);
//code to do set text above etc.
return cellLayout;
Logcat is giving errors similar to this:
I/System.out(12781): resolveUri failed on bad bitmap uri: album_art/224
Hence the problem seems to be with the appendedID. I don't know how else to call it though (I even resorted to trying random numbers to see if I could hit on one).
It's possible that I'm making a fundamental mistake. Most of my time spend so far has been due to learning how to work with the content providers etc and I'm still not even 50% sure about them (never done Databases or Android before).
Also, is it just be me or is the Android documentation, at least regarding this topic, pretty rubbish?
ALBUM_ART is a column name, not a content URI. You need to query the album and get the column with the name ALBUM_ART. This will presumably give you a URI to the ImageStore (dunno, haven't tried it myself).
Btw, there is an open bug about the ABLUM_ART column, but I would suggest you try it first - grab the ALBUM_ART column and see what's in there.
Sample code (note that this is off the top of my head, so it could be wrong):
Cursor cursor = getContentResolver().query(
ContentUris.withAppendedId(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, albumId),
new String[] { MediaStore.Audio.AlbumColumns.ALBUM_ART },
null,
null,
null);
if (cursor.moveToFirst()) {
String albumArtUri = cursor.getString(0);
}
cursor.close();
Again, no guarantees this works, I've never used the media store, and I wrote this code without being able to test it.
this worked for me..
Cursor cursorAlbum = managedQuery(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},MediaStore.Audio.Albums._ID+ "=" + album_id, null, null);
if(cursorAlbum != null && cursorAlbum.moveToFirst()){
String uri = cursorAlbum.getString(cursorAlbum.getColumnIndex("album_art"));
cursorAlbum.close();
if(uri != null )
{
//Log.i("albumUri", uri);
wrapper.image.setImageURI(Uri.parse(uri));
}
}

Categories