get count of certain extension files from Android device - android

I am trying to count certain extension files (pdf, txt, docx, pptx, xlsx) which are stored in Android device using getcontentresolver query and reading file by file.
However, I'm getting different results from both ways. count results are the following:
By Content Resolver Query:
pdf 289
txt 133
docs 29
pptx 21
xlsx 9
By reading file by file
pdf 289
txt 134
docs 151
pptx 77
xlsx 27
Here is Code
By Content Resolver Query:
public static long getFilesCount() {
long myCounter = 0;
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?" + " OR " + MediaStore.Files.FileColumns.MIME_TYPE + "=?" + " OR " + MediaStore.Files.FileColumns.MIME_TYPE + "=?" + " OR " + MediaStore.Files.FileColumns.MIME_TYPE + "=?" + " OR " + MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String pdfMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
String txtMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("txt");
String docMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("docx");
String pptxMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pptx");
String xlsxMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("xlsx");
String[] selectionArgs = new String[]{pdfMimeType, txtMimeType, docMimeType, pptxMimeType, xlsxMimeType};
Cursor mCursor = App
.getInstance()
.getApplicationContext()
.getContentResolver()
.query(MediaStore.Files.getContentUri("external")
, null, selectionMimeType, selectionArgs, null);
if (mCursor != null && mCursor.moveToFirst()) {
int aCount = 0;
do {
int id = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Files.FileColumns._ID));
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Files.FileColumns.DATA));
String type = mCursor.getString(mCursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE));
if (path == null || type == null)
continue;
File file = new File(path);
if (file.exists()) {
if (!file.isDirectory()) {
myCounter++;
}
}
} while (mCursor.moveToNext());
}
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
return myCounter;
}
`
By reading file by file
`
public static long filesCount() {
long counter = _loadFiles(predefineExtension(), new File(getFilesPath())));
return counter;
}
public static String getFilesPath() {
return Environment.getExternalStorageDirectory().getPath();
}
public static ArrayList<String> predefineExtension() {
ArrayList<String> list = new ArrayList<>();
list.add("pdf");
list.add("txt");
list.add("docx");
list.add("pptx");
list.add("xlsx");
return list;
}
private static long _loadFiles(ArrayList<String> selectedExtension, File directory) {
long counter = 0;
File[] files = directory.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i] != null) {
if (files[i].isDirectory()) {
counter += _loadFiles(selectedExtension, files[i]);
} else {
File file = files[i];
if (file.exists()) {
for (int j = 0; j < selectedExtension.size(); j++) {
String ext = selectedExtension.get(j);
if (file.getPath().endsWith("." + ext)) {
counter++;
break;
} // file match
} // selected file extension loop
} // file exist
} // file is not directory
} // file is not null
} // loop
} // files array is not null
return counter;
}
So, my question is why these both approaches have different results? Any help is appreciated! Thank you!

my question is why these both approaches have different results?
They are unlikely to be identical.
Not every file on external storage necessarily gets indexed by the MediaStore. This is particularly true of files that were recently put on external storage and files in dot-prefixed directories (e.g., .stuff/).
MediaStore has access to content on removable storage that you may not have access to.
Note that your filesystem-based approach will not work on Android Q (by default) or Android R+ (for all apps). I am not certain about your MediaStore approach.

Related

Can't create file with deleted file name at android 10

I want to keep a log text file for each day in the download folder. I want to store day based text files in my own Log folder(MyApp Log folder) in the Download folder.
When I delete the My App Log folder, I can't create this folder in the same location with the same name. Likewise, when the text file I created is deleted, I can't create a file with the same text file name. resolver.insert(downloadUri, contentValues); always returns null.
Even though I get a null result when I query whether there is a file belonging to that path, I can't create the same file.
The function where I created the file:
public static void createFile(){
String contentType = "text/log";
Date cDate = new Date(System.currentTimeMillis());
String today = new SimpleDateFormat("yyyy_MM_dd").format(cDate);
long seconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, today + ".txt");//2021_10_13.txt
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, contentType);//text/log
contentValues.put(MediaStore.MediaColumns.DATE_ADDED, seconds);//System.currentTimeMillis
contentValues.put(MediaStore.MediaColumns.DATE_MODIFIED, seconds);//System.currentTimeMillis
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + "MyApp Log");//Download/MyApp Log
ContentResolver resolver = getContext().getContentResolver();
outputUri = resolver.insert(getDownloadUri(), contentValues);
if (outputUri == null)
throw new IOException("Failed to create new MediaStore record.");
try (final OutputStream stream = resolver.openOutputStream(outputUri)) {
if (stream == null)
return;
} finally {
ContentValues updateValues = new ContentValues();
updateValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
resolver.update(outputUri, updateValues, null, null);
}
}
public static #NonNull
Uri getDownloadUri() {
if (Build.VERSION.SDK_INT < 29) {
return getLegacyUri(Environment.DIRECTORY_DOWNLOADS);
} else {
return MediaStore.Downloads.EXTERNAL_CONTENT_URI;
}
}
The function I am querying if the file exists:
public static Uri getExternalContentUriFromFile(Uri externalUri, String filePath) {
if (externalUri == null)
return null;
try (Cursor cursor = getContentResolver().query(externalUri, new String[]{MediaStore.MediaColumns._ID},
MediaStore.MediaColumns.DATA + "=? ", new String[]{filePath}, null)) {
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
return Uri.withAppendedPath(externalUri, "" + id);
}
return null;
}
}
I found a solution myself:
int fileNo = 0;
Uri uri = saveToUri(fileName, contentType, seconds, relativePath);
if (uri == null) {
while (fileNo < 4 && uri == null) {
fileNo++;
fileName = AttachmentUtil.removeExtensionForName(fileName) + "(" + fileNo + ")" + extension;
uri = saveToUri(fileName, contentType, seconds, storageName + File.separator + myDirName, storageUri);
}
}
#Will V :
public static String removeExtensionForName(String fileName) {
int i = fileName.lastIndexOf('.');
if (i > 0) {
return fileName.substring(0, i);
}
return fileName;
}
And I got my code in above question into saveToUri function.

How to delete image file from Android Internal when path is stored in SQLite DB

I Know this is already answered question.But I'm unable to figure it out when using SQLite DB. My app captures some documents and will be stores in phone memory. I'm using SQLite DB in my app which stores the path of the above image. How can i delete the image from phone memory if i delete the image in SQLite DB.
String photoPath = cursor.getString(i_COL_PICTURE);
--My path is
`"content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F153/ORIGINAL/NONE/1743496576"
`
When you want delete some file in your storage, Just do this.
File file = new File(yourFilePathHere);
deleted = file.delete();
I am considering you have required permissions because you are able to write files in storage.
Edit
You are using MediaStore for getting images. So now when you want delete file you should delete file from MediaStore also. I have a method which will help you.
public static int deleteFileFromMediaStore(final ContentResolver contentResolver, final File file) {
String canonicalPath;
try {
canonicalPath = file.getCanonicalPath();
} catch (IOException e) {
canonicalPath = file.getAbsolutePath();
}
final Uri uri = MediaStore.Files.getContentUri("external");
final int result = contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
if (result == 0) {
final String absolutePath = file.getAbsolutePath();
if (!absolutePath.equals(canonicalPath)) {
int deletedRow = contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
return deletedRow;
}
} else return result;
return result;
}
Call it in your Activity like
deleteFileFromMediaStore(getContentResolver(), fileToDelete)
Note Check if you are getting absolute path by MediaStore. Here is my method to get all gallery images if you have problem with your code.
public static ArrayList<ModelBucket> getImageBuckets(Context context) {
ArrayList<ModelBucket> list = new ArrayList<>();
String absolutePathOfImage;
String absoluteFolder;
boolean same_folder = false;
int pos = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = context.getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
if (cursor == null) return null;
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
absoluteFolder = cursor.getString(column_index_folder_name);
Log.d("Column", absolutePathOfImage);
Log.d("Folder", absoluteFolder);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getFolderName().equals(absoluteFolder)) {
same_folder = true;
pos = i;
break;
} else {
same_folder = false;
}
}
if (same_folder) {
ArrayList<String> al_path = new ArrayList<>(list.get(pos).getAllFilesPath());
al_path.add(absolutePathOfImage);
list.get(pos).setAllFilesPath(al_path);
} else {
ArrayList<String> al_path = new ArrayList<>();
al_path.add(absolutePathOfImage);
ModelBucket modelBucket = new ModelBucket();
modelBucket.setFolderName(absoluteFolder);
modelBucket.setAllFilesPath(al_path);
list.add(modelBucket);
}
}
return list;
}
here ModelBucket.class is a model class.
public class ModelBucket {
String folderName;
ArrayList<String> allFilesPath;
ArrayList<ModelFile> files;
// make getter setter
}
before deleting the image get the path of the image and pass the path to below code
File fdelete = new File(path);
if (fdelete.exists()) {
if (fdelete.delete()) {
System.out.println("file Deleted :" + path);
} else {
System.out.println("file not Deleted :" + path);
}
}
after this remove the path from sqlite db
If you have your Uri pointing to the file you can do :
String pathToFile = myUri.getEncodedPath(); // this gives your the real path to the file, like /emulated/0/sdcard/myImageFile.jpg
File file = new File(pathToFile);
if(file.exists()){
file.delete();
}

How to query specific hidden folder for images in android

I need to query a specific hidden folder created by my application and need to fetch all the images saved in that hidden folder. I am able to query that very same folder if its not hidden but when I make the folder hidden, the cursor counts returns me 0 even though images are well kept inside the folder.
public static List<MediaData> getHiddenFolderData(Context context) {
Cursor imagecursor = null;
List<MediaData> gallerydata = new ArrayList<MediaData>();
try {
final String orderBy = Images.Media._ID + " DESC";
imagecursor = context.getContentResolver()
.query(Images.Media.EXTERNAL_CONTENT_URI,
projectionImage,
Images.Media.BUCKET_DISPLAY_NAME + "='"
+ ".HiddenFolder" + "'", null,
orderBy);
System.out.println("1026 check log 1");
if (imagecursor != null) {
System.out.println("1026 check log 2");
imagecursor.moveToFirst();
int count = imagecursor.getCount();
System.out.println("1026 check log 3 count"+" "+count);
for (int i = 0; i < count; i++) {
MediaData galData = new MediaData();
galData.setKey_id(i);
galData.setId(imagecursor.getString(0));
galData.setName(imagecursor.getString(1));
galData.setPath(imagecursor.getString(2));
galData.setDate(imagecursor.getString(3));
gallerydata.add(galData);
imagecursor.moveToNext();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (imagecursor != null) {
imagecursor.close();
}
}
return gallerydata;
}
Another approach
private void getHiddenFolderData() {
String path = Environment.getExternalStorageDirectory().toString() + "/Pictures/.HiddenFolder";
System.out.println("here is path" + " " + "Path: " + path);
File directory = new File(path);
File[] files = directory.listFiles();
System.out.println("here is size" + " " + files.length);
for (int i = 0; i < files.length; i++) {
System.out.println("here get file prop"+" "+files[i].getName()+" "+files[i].getPath());
}
}

How to create a thumbnail playlist for a music player in android?

I developed a simple media player app in android. It has a list view to load all songs in SD card, seek bar and play button. I need to create a album art gallery for my app (Like in google play music app). I used this code to get all songs from SD card,
public ArrayList<String> GetFiles(String DirectoryPath) {
ArrayList<String> MyFiles = new ArrayList<String>();
File f = new File(DirectoryPath);
f.mkdirs();
File[] files = f.listFiles();
if (files.length == 0) {
return null;
}else {
for (int i=0; i<files.length; i++)
MyFiles.add(files[i].getName());
}
return MyFiles;
}
How to improve this code to return song name and album-art?
How to create a thumbnail view for each song ?
_________
| |
| image |
| |
|_________|
| title |
|_________|
You need to use content resolver.
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// Perform a query on the content resolver. The URI we're passing specifies that we
// want to query for all audio media on external storage (e.g. SD card)
Cursor cur = contentResolver.query(uri, null,
MediaStore.Audio.Media.IS_MUSIC + " = 1", null, null);
if (cur == null) {
Log.e(TAG, "Failed to retrieve music: cursor is null :-(");
subscriber.onError(new Throwable("Failed to retrieve music: cursor is null :-("));
return;
}
if (!cur.moveToFirst()) {
subscriber.onError(new Throwable("No results. :( Add some tracks!"));
Log.e(TAG, "Failed to move cursor to first row (no query results).");
return;
}
int artistColumn = cur.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int titleColumn = cur.getColumnIndex(MediaStore.Audio.Media.TITLE);
int albumColumn = cur.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
int durationColumn = cur.getColumnIndex(MediaStore.Audio.Media.DURATION);
int idColumn = cur.getColumnIndex(MediaStore.Audio.Media._ID);
int dataColumn = cur.getColumnIndex(MediaStore.Audio.Media.DATA);
ArrayList<LocalTrack> tracks = new ArrayList<>();
do {
Log.i(TAG, "ID: " + cur.getString(idColumn) + " Title: " + cur.getString(titleColumn));
tracks.add(new LocalTrack(
cur.getLong(idColumn),
cur.getString(artistColumn),
cur.getString(titleColumn),
cur.getLong(albumColumn),
cur.getLong(durationColumn),
cur.getString(dataColumn)));
} while (cur.moveToNext());
Log.i(TAG, "Done querying media. MusicRetriever is ready.");
cur.close();
for (LocalTrack localTrack : tracks) {
localTrack.setArtPath(findAlbumArt(localTrack));
}
subscriber.onNext(tracks);
public String findAlbumArt(LocalTrack localTrack) {
Cursor cursor = contentResolver.query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID + "=?",
new String[]{String.valueOf(localTrack.getAlbum())},
null);
String path = null;
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
// do whatever you need to do
cursor.close();
}
}
return path;
}

Get path of song from SD card in android

In my android application I want to fetch song from SD card but I am not able to get the path of that particular file.I am using android api level 7 which doesn't support following method.
Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_MUSIC);
I have also tried following code :
path = Environment.getExternalStorageDirectory();
but I don't know how to specify path of music file.Please suggest some solution.Thanx.
Get path and song Name from SD Card. You can find the path of the song from MediaStore.
The Media provider contains meta data for all available media on both internal and external storage devices.
private String[] STAR = { "*" };
public void ListAllSongs()
{
Cursor cursor;
Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
if (isSdPresent()) {
cursor = getContentResolver().query(allsongsuri, STAR, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String songname = cursor
.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
int song_id = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media._ID));
String fullpath = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
String albumname = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM));
} while (cursor.moveToNext());
}
cursor.close();
}
}
}
public static boolean isSdPresent()
{
return android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
}
you can scan the entire sd card for any file format,here i used for mp3 and mp4.
you can use this for any format that u required.
/** To store the available media files */
private List<String> mediaList = new ArrayList<String>();
externalStoragePath = Environment.getExternalStorageDirectory()
.getAbsolutePath();
targetDir = new File(externalStoragePath);
Log.d(" externalStoragePath ::: ", targetDir.getAbsolutePath());
public File[] mediaFiles = targetDir.listFiles();
/**
* scanFiles
*
* #param scanFiles
*/
public void scanFiles(File[] scanFiles) {
if (scanFiles != null) {
for (File file : scanFiles) {
if(mediaList.size() > 4){
return;
}
if (file.isDirectory()) {
// Log.d(" scaned File ::isDirectory: ",
// file.getAbsolutePath());
scanFiles(file.listFiles());
} else {
addToMediaList(file);
}
}
} else {
Log.d(SCANNER,
" *************** No file is available ***************");
}
}
/**
*
* #param file
*/
private void addToMediaList(File file) {
if (file != null) {
String path = file.getAbsolutePath();
int index = path.lastIndexOf(".");
String extn = path.substring(index + 1, path.length());
if (extn.equalsIgnoreCase("mp4") || extn.equalsIgnoreCase("mp3")) {// ||
Log.d(" scanned File ::: ", file.getAbsolutePath()
+ " file.getPath( ) " + file.getPath());// extn.equalsIgnoreCase("mp3"))
// {
Log.d(SCANNER, " ***** above file is added to list ");
mediaList.add(path);
}
}
}

Categories

Resources