I am working on media player application i am getting song image using MediaMetadataRetriever and i am getting image and and i set using Glide but image takes about 7-9 sec to load that is very very slow. i also try using BitmapFactory but that also same time.
so there is any faster way that can i get song image.
Thanks in advance
Here is my code that i getting image using MediaMetadataRetriever.
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(songpath);
byte[] art = retriever.getEmbeddedPicture();
if (art != null) {
Glide.with(c).load(art)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(holder.songimage);
//holder.songimage.setImageBitmap(BitmapFactory.decodeByteArray(art, 0, art.length));
} else {
Glide.with(c).load(R.drawable.splash)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(holder.songimage);
//holder.songimage.setImageResource(R.drawable.splash);
}
This method returns ArrayList<CommonModel> .
public static ArrayList<CommonModel> getAllMusicPathList(Context context,String selectAll) {
ArrayList<CommonModel> musicPathArrList = new ArrayList<>();
Uri songUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursorAudio = context.getContentResolver().query(songUri, null, null, null, null);
if (cursorAudio != null && cursorAudio.moveToFirst()) {
Cursor cursorAlbum;
if (cursorAudio != null && cursorAudio.moveToFirst()) {
do {
Long albumId = Long.valueOf(cursorAudio.getString(cursorAudio.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)));
cursorAlbum = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID + "=" + albumId, null, null);
if(cursorAlbum != null && cursorAlbum.moveToFirst()){
String albumCoverPath = cursorAlbum.getString(cursorAlbum.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
String data = cursorAudio.getString(cursorAudio.getColumnIndex(MediaStore.Audio.Media.DATA));
if("selectAll".equals(selectAll))
{
musicPathArrList.add(new CommonModel(data,albumCoverPath, true));
}
else
{
musicPathArrList.add(new CommonModel(data,albumCoverPath, false));
}
}
} while (cursorAudio.moveToNext());
}
}
return musicPathArrList;
}
I hope this helps you.
Related
So, I have android application using Sqlite Database. I has a cardview to showing the data. In the table, I have field like, name(text), cost(int) and an image(BLOB). I want to update the data. So, when I change and update the name or the cost, the image not updated and return blank or null. But when I change and update the image, it successfully updated.
First, this is my select query to showing the name, cost and image in update class
public ModelProduk getnama(int selection){
SQLiteDatabase db = this.getReadableDatabase();
String whereclause = KEY_ID_PRODUK + "=?";
String[] whereargs = new String[]{String.valueOf(selection)};
Cursor cursor = db.query(
TABLE_PRODUK,
null,
whereclause,
whereargs,
null,
null,
null
);
ModelProduk modelProduk = new ModelProduk();
if (cursor.moveToFirst()) {
modelProduk.set_id(Integer.parseInt(cursor.getString(0)));
modelProduk.set_nama(cursor.getString(1));
modelProduk.set_harga(Integer.parseInt(cursor.getString(2)));
modelProduk.set_gambar(cursor.getBlob(3));
}
cursor.close();
db.close();
return modelProduk;
}
Here's my database to update
public void update(ModelProduk modelProduk) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAMA_PRODUK, modelProduk.get_nama());
values.put(KEY_HARGA_PRODUK, modelProduk.get_harga());
values.put(KEY_GAMBAR_PRODUK, modelProduk.get_gambar());
String where = "id=?";
String[] whereArgs = new String[] {String.valueOf(modelProduk.get_id())};
// update baris
db.update(TABLE_PRODUK, values, where, whereArgs);
db.close();
}
my java class for update
private void init(){
pilih = getIntent().getIntExtra("id_produk", 0);
db = new Database(this);
modelProduk = db.getnama(pilih);
gambar_produku = (ImageView) findViewById(R.id.pilihgambaru);
tambahgambaru = (Button) findViewById(R.id.btaddu);
simpandatau = (Button) findViewById(R.id.btsimpanu);
deskripsiu = (EditText) findViewById(R.id.etdesku);
harga_produku = (EditText) findViewById(R.id.ethargau);
kembaliu = (Button) findViewById(R.id.btkembaliu);
deskripsiu.setText(modelProduk.get_nama());
harga_produku.setText(String.valueOf(modelProduk.get_harga()));
if (modelProduk.get_gambar() != null) {
gambar_produku.setImageBitmap(bitmap(modelProduk.get_gambar()));
}
}
public void showFileChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Pilih Gambar"), 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
filePath = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
gambar_produku.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public byte[] getImageByte(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte imageInByte[]=null;
if(bitmap!=null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
imageInByte=stream.toByteArray();
}
return imageInByte;
}
public Bitmap bitmap (byte[] byteImage){
byte[] outImage = byteImage;
Bitmap image ;
if (outImage != null){
ByteArrayInputStream imageStream = new ByteArrayInputStream(outImage);
image = BitmapFactory.decodeStream(imageStream);
}else {
image= null;
}
return image;
}
my onclick to save the update
simpandatau.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
modelProduk.set_nama(deskripsiu.getText().toString());
modelProduk.set_harga(Integer.parseInt(harga_produku.getText().toString()));
modelProduk.set_gambar(getImageByte(bitmap));
db.update(modelProduk);
Toast.makeText(getApplicationContext(), "Data Berhasil Diubah!", Toast.LENGTH_SHORT).show();
}
});
Please Help! I have read many solutions but it's not same to my problems.
Thank you!
You could try the following. This will attempt to get the row that is to be updated before updating. However, rather than return blank or null or update successful it returns an integer which can be -1, 0 or 1 which indicates three possible outcomes.
If the row doesn't exist then it will return -1 (NOTUPDATED).
Otherwise it will then compare the stored image against the image passed.
If the images are different then it will add the new image to values and set the value to be returned to 1 (IMAGEUPDATED).
Otherwise the new image is not added to the values and the value to be returned will remain as 0 (IMAGENOTUPDATED). By not adding the image to values the gambar column will not be included in the SET clause of the SQL generated by the update method.
:-
public int update(ModelProduk modelProduk) {
final int NOTUPDATED = -1;
final int IMAGENOTUPDATED = 0;
final int IMAGEUPDATED = 1;
String where = "id=?";
String[] whereArgs = new String[] {String.valueOf(modelProduk.get_id())};
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
// get the current row from the database (return -1 if it doesn't exist)
Cursor before_update = db.query(TABLE_PRODUK,null,where,whereArgs,null,null,null);
if (!before_update.moveToFirst) {
before_update.close();
return NOTUPDATED;
}
// Default value to return
rv = IMAGENOTUPDATED;
// Compare the store image against the new image, if not the same
// then include the image in the update
if (!Arrays.equals(before_update.getBlob(3),modelProduk.get_gambar)) {
values.put(KEY_GAMBAR_PRODUK, modelProduk.get_gambar());
rv = IMAGEUPDATED;
}
before_update.close();
values.put(KEY_NAMA_PRODUK, modelProduk.get_nama());
values.put(KEY_HARGA_PRODUK, modelProduk.get_harga());
// Update baris checking to see if an update occurred, if not
// then set return value to -1 (could be a different status code)
if (db.update(TABLE_PRODUK, values, where, whereArgs) = 0) {
rv = NOTUPDATED;
}
db.close();
before_update.close();
return rv;
}
Note the above is in-principle code, it has not been tested and therefore may contain errors.
You may wish to define NOTUPDATED, IMAGENOTUPDATED and IMAGEUPDATED elsewhere with greater scope.
First of all, I can get all the song and its details. All I am trying is to get the song details from the URL as I can get the only URL from file navigation this is what I am trying
public ArrayList<Songfileinfo> getPlayList(Context context, String uri) {
{
String sortOrder = null;
try {
String[] proj = {MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ALBUM_ID
};
String selection = null;
String[] selectionArgs = {uri};
Cursor audioCursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj, selection, selectionArgs, sortOrder);
if (audioCursor != null) {
if (audioCursor.moveToFirst()) {
do {
int audioTitle = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE);
int audioartist = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST);
int audioduration = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION);
int audiodata = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
int audioalbum = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM);
int audioalbumid = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID);
int song_id = audioCursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
Songfileinfo info = new Songfileinfo();
info.setFile_uri(audioCursor.getString(audiodata));
info.setTitle(audioCursor.getString(audioTitle));
info.setDuration((audioCursor.getString(audioduration)));
info.setArtist(audioCursor.getString(audioartist));
info.setAlbum(audioCursor.getString(audioalbum));
info.setId(audioCursor.getLong(song_id));
info.setAlbum_art((ContentUris.withAppendedId(albumArtUri, audioCursor.getLong(audioalbumid))).toString());
songList.add(info);
} while (audioCursor.moveToNext());
}
}
assert audioCursor != null;
audioCursor.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return songList;
}
This is the method I am trying to use it is not working I am getting the array-list size as 0 I also tried to compare the string file location from the list of all the locations but still the array size is 0. I don't want to use media meta data retrieve as I will not get the album art URL. Any hint about how to get the details of this particular location?
I tried this way also but same result by comparing the file URI string
if (audioCursor.getString(audiodata).equals(uri)){
}
I tried to use the media metadata retriever class but it will just will not give the image url and it will be in bitmap and as my whole app is using the image url it will be difficult for me.
I just give this to get all the data from the url
if (new File(audioCursor.getString(audiodata)).getName().equals(url.getName())) {
Songfileinfo info = new Songfileinfo();
info.setFile_uri(audioCursor.getString(audiodata));
info.setTitle(audioCursor.getString(audioTitle));
info.setDuration((audioCursor.getString(audioduration)));
info.setArtist(audioCursor.getString(audioartist));
info.setAlbum(audioCursor.getString(audioalbum));
info.setId(audioCursor.getLong(song_id));
info.setAlbum_art((ContentUris.withAppendedId(albumArtUri, audioCursor.getLong(audioalbumid))).toString());
songList.add(info);
}
I am aware that media artwork is stored under albums and to get them you need to have the album id to access it. I have been able to get the images for tracks and albums using the album id.
However for artists table doesn't have the album id field. Other apps such as Play Music and Poweramp are somehow able to get the track artwork and add them to the respective artists.
How do i achieve this?
The way I do it is to get all albums for an artist and then use the rnd function to return an albumid:
String artist_id = c.getString(c.getColumnIndex(MediaStore.Audio.Artists._ID));
Cursor crs = album.getArtistsAlbumcursor(mContext, artist_id);
if(crs!=null && crs.moveToFirst()) {
Random rn = new Random();
int rnd = rn.nextInt( crs.getCount());
crs.moveToPosition(rnd);
album_id = crs.getLong(crs.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
crs.close();
}
where getArtistsAlbumcursor is:
public Cursor getArtistsAlbumcursor(Context context, String artistId) {
ContentResolver cr = context.getContentResolver();
final String _id = MediaStore.Audio.Media._ID;
final String album_id = MediaStore.Audio.Media.ALBUM_ID;
final String artistid = MediaStore.Audio.Media.ARTIST_ID;
final String[] columns = { _id, album_id, artistid };
String where = artistid +" =?";
String[] aId = {artistId};
return cr.query(uri, columns, where, aId, null);
}
Once you have an albumid you can get your albumart using your original method.
Or
if you want to get the albumart from the mp3 track itself, you will need to implement a libary such as jaudiotagger or org.blinkenlights.jid3.v2.
Life gets a little more complicated but below how to get albumart from the mp3 tag using the JID3 library:
try {
bmp = getmp3AlbumArt(sourceFile);
} catch (Exception e) {
e.printStackTrace();
}
where getmp3Albumart is:
public Bitmap getmp3AlbumArt(File SourceFile) throws Exception {
Bitmap bmp = null;
arrayByte = null;
APICID3V2Frame frames[];
MediaFile MediaFile = new MP3File(SourceFile);
try {
Object obj = null;
obj = MediaFile.getID3V2Tag();
if (obj != null) {
tagImage = (org.blinkenlights.jid3.v2.ID3V2_3_0Tag) obj;
if ((tagImage != null) && (arrayByte == null) && (tagImage.getAPICFrames() != null) && (tagImage.getAPICFrames().length > 0)) {
frames = tagImage.getAPICFrames();
for (int i = 0; i < tagImage.getAPICFrames().length; i++) {
if (frames[i] != null) {
arrayByte = frames[i].getPictureData();
break;
}
}
}
}
} catch (ID3Exception | OutOfMemoryError e) {
e.printStackTrace();
}
if (arrayByte != null) {
try {
bmp = BitmapFactory.decodeByteArray(arrayByte, 0, arrayByte.length);
} catch (Exception|OutOfMemoryError e) {
e.printStackTrace();
}
}
return bmp;
}
I am a newbie in developing android apps.
I'm developing a music player and would like to get song name, artist, album name, album art from the metadata of audio files.
I have used MediaMetadataRetriever but it is slow when there are 800+ songs and returns null for some files while other music players can retrieve those information.
Then I use MediaStore.Audio.Media.EXTERNAL_CONTENT_URI to get song name, artist, album name and MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI to get the album art.
Is there any uri to get (song name, artist, album name, album art) at the same time?
As I need to create a song object in my program.
Below is my code, but it is very slow as it asks for album art for each song.
public ArrayList<Songs> getPlayList(Context c) {
String[] TRACK_PROJ = {
MediaStore.Audio.AudioColumns.ARTIST,
MediaStore.MediaColumns.TITLE,
MediaStore.Audio.AudioColumns.ALBUM,
MediaStore.Audio.AudioColumns.YEAR,
MediaStore.MediaColumns.DATA
};
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = c.getContentResolver().query(uri, TRACK_PROJ, null, null, null);
int count;
if (cursor != null) {
count = cursor.getCount();
if (count > 0) {
cursor.moveToFirst();
do {
Songs song;
String artist = cursor.getString(cursor.getColumnIndex(TRACK_PROJ[0]));
String title = cursor.getString(cursor.getColumnIndex(TRACK_PROJ[1]));
String album = cursor.getString(cursor.getColumnIndex(TRACK_PROJ[2]));
String year = cursor.getString(cursor.getColumnIndex(TRACK_PROJ[3]));
String path = cursor.getString(cursor.getColumnIndex(TRACK_PROJ[4]));
if (path.toLowerCase().contains(MEDIA_PATH.toLowerCase())) {
song = new Songs(artist, title, album, year, path);
songsList.add(song);
}
} while (cursor.moveToNext());
}
cursor.close();
}
for (Songs aSongsList : songsList) {
String[] ALBUM_PROJ = {MediaStore.Audio.Albums.ALBUM_ART};
String selection = MediaStore.Audio.Albums.ALBUM + "=?";
String[] values = new String[]{aSongsList.getAlbum()};
Cursor cur = c.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, ALBUM_PROJ, selection, values, null);
int cnt;
if (cur != null) {
cnt = cur.getCount();
if (cnt > 0) {
cur.moveToFirst();
do {
String art = cur.getString(cur.getColumnIndex(ALBUM_PROJ[0]));
if (art != null)
aSongsList.setAlbumArt(art);
} while (cur.moveToNext());
cur.close();
}
}
}
return songsList;
}
EDIT: (Code of using MediaMetadataRetriever)
private Songs getMetadata (File file){
String artist, title, album, path;
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(file.getPath());
try {
artist = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
album = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
path = file.getPath();
title = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
} catch (Exception e) {
artist = "Unknown";
title = "Unknown";
album = "Unknown";
path = "Unknown";
}
Thanks a lot!!!
Do you know this - http://developer.android.com/reference/android/media/MediaMetadataRetriever.html
MediaMetadataRetriever metaRetriver;
metaRetriver = new MediaMetadataRetriever();
metaRetriver.setDataSource("/sdcard/audio.mp3");
try {
byte [] art = metaRetriver.getEmbeddedPicture();
Bitmap songImage = BitmapFactory
.decodeByteArray(art, 0, art.length);
metaRetriver.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM));
String artist = metaRetriver
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
String genre = metaRetriver
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE));
} catch (Exception e) {
// TO-DO Exception
}
You would be interested for other available options in above API.
It turns out MediaMetadataRetriever only processes all the data in an MP3 file that is UTF-16
Some of (a lot really) of my MP3s were old and when made for some reason were ISO-8859-1
Using MP3Tag. I made sure the option ID3v2.3 UTF-16 was selected.
Verify Saving as UTF-16
And then selected all the MP3 Files that I had that were ISO-8859-1 and save (or resave) them
If you are not sure if you are having this problem. You can create a Column tag in MP3 to show the encoding
Create MP3 Tag Column
See Files with wrong Encoding
After resaving all my MP3's that had ISO-8859-1 as UTF-16 Now MediaMetadataRetriever NEVER returns Nulls and always returns the proper data.
BobVal
I am using native Android camera and save file to my application data folder (/mnt/sdcard/Android/data/com.company.app/files/Pictures/). At the same time anther copy of photo is saved to DCIM folder.
This is my code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String formattedImageName = getDateString() + ".jpg";
File image_file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), formattedImageName);
Uri imageUri = Uri.fromFile(image_file);
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(intent, REQUEST_FROM_CAMERA);
How can I prevent saving additional copy of image to DCIM folder?
Many Thanks
You can use the following :
First we get the last saved image by checking which was the last modified image. Then check if last modified time is in the last few seconds. You may also have to check the exact location of where camera stores the image.
private boolean deleteLastFromDCIM() {
boolean success = false;
try {
File[] images = new File(Environment.getExternalStorageDirectory()
+ File.separator + "DCIM/Camera").listFiles();
File latestSavedImage = images[0];
for (int i = 1; i < images.length; ++i) {
if (images[i].lastModified() > latestSavedImage.lastModified()) {
latestSavedImage = images[i];
}
}
// OR JUST Use success = latestSavedImage.delete();
success = new File(Environment.getExternalStorageDirectory()
+ File.separator + "DCIM/Camera/"
+ latestSavedImage.getAbsoluteFile()).delete();
return success;
} catch (Exception e) {
e.printStackTrace();
return success;
}
}
Unfortunately, some smart phones save images in another folder such as DCIM/100MEDIA. So can't rely to these solution. I prefer use this way:
String[] projection = new String[] {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE};
final Cursor cursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,projection, null, null,
MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if(cursor != null){
cursor.moveToFirst();
// you will find the last taken picture here and can delete that
}
I tried to find out if a second copy exists and delete the copy. I used the above code to find the last taken picture.
Notice: Don't use cursor.close(); after using managedQuery, Leave the cursor for the Android system to manage and don't call that. You can see managedQuery()
Notice2: The managedQuery method is deprecated and it should be avoided, implement CursorLoaders instead.
check this code..
private void FillPhotoList() {
// initialize the list!
GalleryList.clear();
String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
for(int i=0;i<projection.length;i++)
Log.i("InfoLog","projection "+projection[0].toString());
// intialize the Uri and the Cursor, and the current expected size.
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Log.i("InfoLog","FillPhoto Uri u "+u.toString());
// Query the Uri to get the data path. Only if the Uri is valid.
if (u != null)
{
c = managedQuery(u, projection, null, null, null);
}
// If we found the cursor and found a record in it (we also have the id).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Loop each and add to the list.
GalleryList.add(c.getString(0)); // adding all the images sotred in the mobile phone(Internal and SD card)
}
while (c.moveToNext());
}
Log.i(INFOLOG,"gallery size "+ GalleryList.size());
}
and this is where the method is doing all magic
/** Method will check all the photo is the gallery and delete last captured and move it to the required folder.
*/
public void movingCapturedImageFromDCIMtoMerchandising()
{
// This is ##### ridiculous. Some versions of Android save
// to the MediaStore as well. Not sure why! We don't know what
// name Android will give either, so we get to search for this
// manually and remove it.
String[] projection = { MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
BaseColumns._ID,};
// intialize the Uri and the Cursor, and the current expected size.
for(int i=0;i<projection.length;i++)
Log.i("InfoLog","on activityresult projection "+projection[i]);
//+" "+projection[1]+" "+projection[2]+" "+projection[3] this will be needed if u remove the for loop
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Log.i("InfoLog","on activityresult Uri u "+u.toString());
if (CurrentFile != null)
{
// Query the Uri to get the data path. Only if the Uri is valid,
// and we had a valid size to be searching for.
if ((u != null) && (CurrentFile.length() > 0))
{
//****u is the place from data will come and projection is the specified data what we want
c = managedQuery(u, projection, null, null, null);
}
// If we found the cursor and found a record in it (we also have the size).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Check each area in the gallery we built before.
boolean bFound = false;
for (String sGallery : GalleryList)
{
if (sGallery.equalsIgnoreCase(c.getString(1)))
{
bFound = true;
Log.i("InfoLog","c.getString(1) "+c.getString(1));
break;
}
}
// To here we looped the full gallery.
if (!bFound) //the file which is newly created and it has to be deleted from the gallery
{
// This is the NEW image. If the size is bigger, copy it.
// Then delete it!
File f = new File(c.getString(2));
// Ensure it's there, check size, and delete!
if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
{
// Finally we can stop the copy.
try
{
CurrentFile.createNewFile();
FileChannel source = null;
FileChannel destination = null;
try
{
source = new FileInputStream(f).getChannel();
destination = new FileOutputStream(CurrentFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally
{
if (source != null)
{
source.close();
}
if (destination != null)
{
destination.close();
}
}
}
catch (IOException e)
{
// Could not copy the file over.
ToastMaker.makeToast(this, "Error Occured", 0);
}
}
//****deleting the file which is in the gallery
Log.i(INFOLOG,"imagePreORNext1 "+imagePreORNext);
Handler handler = new Handler();
//handler.postDelayed(runnable,300);
Log.i(INFOLOG,"imagePreORNext2 "+imagePreORNext);
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + c.getString(3), null);
break;
}
}
while (c.moveToNext());
}
}
}
A nice solution by Parth. But it's good for Samsungs that keep images in DCIM/Camera. Some phones - Sony Ericssons, HTCs keep them in folders like DCIM/100MEDIA, DCIM/100ANDRO so I have slightly modified the code:
private boolean deleteLastFromDCIM() {
boolean success = false;
try {
//Samsungs:
File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM/Camera");
if(!folder.exists()){ //other phones:
File[] subfolders = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM").listFiles();
for(File subfolder : subfolders){
if(subfolder.getAbsolutePath().contains("100")){
folder = subfolder;
break;
}
}
if(!folder.exists())
return false;
}
File[] images = folder.listFiles();
File latestSavedImage = images[0];
for (int i = 1; i < images.length; ++i) {
if (images[i].lastModified() > latestSavedImage.lastModified()) {
latestSavedImage = images[i];
}
}
success = latestSavedImage.delete();
return success;
} catch (Exception e) {
e.printStackTrace();
return success;
}
}
I am encountering a similar problem with the Moto Z Force (7.1.1). I have the MediaStore.EXTRA_OUTPUT defined on the intent, but a duplicate file is still created in the camera directory.
I need to test on other devices, but here's an approach I took regarding this issue. Rather than trying to find the specific camera directory, I'm using the MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME location.
Here's my code snippet:
private void removeCameraDuplicate() {
String[] proj = {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns._ID };
String selection = MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME + " = ? ";
String[] selectionArgs = new String[] { "Camera" };
Cursor cursor = mActivity.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj, selection, selectionArgs, MediaStore.Images.ImageColumns.DATE_TAKEN + " desc");
if (cursor != null) {
int idxPath = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (cursor.getCount() > 0 && idxPath > -1 && cursor.moveToFirst()) {
File original = new File(mMediaPath);
File cameraDupe = new File(cursor.getString(idxPath));
if (original.exists() && cameraDupe.exists()) {
LogUtils.LOGE("***> camera", "original " + original.length());
LogUtils.LOGE("***> camera", "original " + original.lastModified());
LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.length());
LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.lastModified());
if (original.length() == cameraDupe.length() && original.lastModified() == cameraDupe.lastModified()) {
if (cameraDupe.delete()) {
LogUtils.LOGE("***> camera", "duplicate deleted");
}
}
}
}
cursor.close();
}
}