How to solve 'Cannot retrieve length of file, path (OS Error: No such file or directory, errno = 2) ' in flutter - java

I am building a simple music player app in which I want to fetch all songs available on the users device. I am doing this with my custom method in java
private static List<Map<String, String>> getAllSongs(Context context) {
List<Map<String, String>> songs = new ArrayList<>();
// Set up query to get all audio files
String[] projection = new String[] {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM_ID
};
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
// Execute query
Cursor cursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
sortOrder
);
// Extract metadata from query result
if (cursor != null && cursor.moveToFirst()) {
int idColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int titleColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int artistColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int albumColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int durationColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION);
int pathColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
int albumIdColumnIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
do {
Map<String, String> song = new HashMap<>();
song.put("id", cursor.getString(idColumnIndex));
song.put("title", cursor.getString(titleColumnIndex));
song.put("artist", cursor.getString(artistColumnIndex));
song.put("album", cursor.getString(albumColumnIndex));
song.put("duration", cursor.getString(durationColumnIndex));
song.put("path", cursor.getString(pathColumnIndex));
long albumId = cursor.getLong(albumIdColumnIndex);
Uri albumArtUri = Uri.withAppendedPath(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, Long.toString(albumId));
song.put("albumArt", albumArtUri.toString());
songs.add(song);
} while (cursor.moveToNext());
cursor.close();
}
return songs;
}
This is then handled in flutter by ->
class Song {
String id;
String title;
String artist;
String album;
String path;
String albumArt;
Song(
{required this.id,
required this.title,
required this.artist,
required this.album,
required this.path,
required this.albumArt});
}
class MusicService {
static const MethodChannel _channel = const MethodChannel('com.mybea.ah');
static Future<List<Song>> getAllSongs() async {
List<Song> songs = [];
try {
final List<dynamic> result = await _channel.invokeMethod('getAllSongs');
if (result.isNotEmpty) {
for (int i = 0; i < result.length; i++) {
songs.add(Song(
id: result[i]['id'],
title: result[i]['title'],
artist: result[i]['artist'],
album: result[i]['album'],
path: result[i]['path'],
albumArt: result[i]['albumArt'],
));
}
}
} on PlatformException catch (e) {
print("Failed to get all songs: '${e.message}'.");
}
return songs;
}
}
When I fetch the songs from the method all is fetched properly but when I try to display the artwork I get the following error->
════════ Exception caught by image resource service
════════════════════════════ Cannot retrieve length of file, path =
'content://media/external/audio/albums/89' (OS Error: No such file or
directory, errno = 2)
This is the code where I try to use the method ->
Future<void> _loadSongs() async {
if (await Permission.storage.request().isGranted) {
List<Song> songs = await MusicService.getAllSongs();
setState(() {
_songs = songs;
} else {
return;
}
}
_songs.length == 0
? Center(
child: Text("No Songs Found"),
)
: ListView.builder(
itemCount: _songs.length,
itemBuilder: (context, index) {
Song song = _songs[index];
return ListTile(
onTap: () {
debugPrint(song.path);
},
leading: CircleAvatar(
backgroundImage: FileImage(File(song.albumArt)),
),
title: Text(song.title),
subtitle: Text(song.artist),
trailing: Icon(Icons.play_arrow),
);
},
),
I tried displaying the image by Image.file() and Image.network() but nothing seemed to work and gave the same error.
Please Help

Related

How to implement a contentobserver specifically for contacts

I am looking a way to handle this case when I would expect some service gets a notificaction when the contact database changed... but I dont find an example how to implement this class(for example a handler in this case would be some Action?) and how do I find the Uri for the contacts' db ?
public class ContactContentObserver : ContentObserver
{
public Android.Content.Context _Context { get; set; }
public Android.Net.Uri GetCurrentContactData(Android.Net.Uri uri) =>
Android.Net.Uri.WithAppendedPath(uri, "data");
public ContactContentObserver(Handler handler) : base(handler)
{
}
public ContactContentObserver(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public override void OnChange(bool selfChange, Android.Net.Uri uri)
{
if(uri.Path.Contains(ContactsContract.AuthorityUri.Path))
{
// Android.Database
// Android.App.Application.Context.
string[] queryColumns =
{
IPhoneLookupColumns.ContactId,
IPhoneLookupColumns.DataId,
IPhoneLookupColumns.Number,
CommonDataKinds.StructuredName.DisplayName,
CommonDataKinds.StructuredName.InterfaceConsts.ContactLastUpdatedTimestamp
};
Dictionary<string, string> values = new Dictionary<string, string>();
Android.Net.Uri newUri = GetCurrentContactData(uri);
ICursor? cursor =_Context.ContentResolver.Query(newUri,queryColumns,null,null,null);
int cols = cursor.GetColumnNames().Length;
Dictionary<string, ContactQueryResult> contactQueryResult = new Dictionary<string, ContactQueryResult>();
for (int row=0;row<cursor.Count;row++)
{
for(int col=0;col<cols;col++)
{
string val = cursor.GetString(col);
values.Add(cursor.GetColumnName(col), val);
}
int.TryParse(values[IPhoneLookupColumns.ContactId], out int contactId);
int.TryParse(values[IPhoneLookupColumns.DataId], out int dataId);
DateTime dateModified = DateTime.MinValue;
bool parsed =DateTime.TryParse(values[CommonDataKinds.StructuredName.InterfaceConsts.ContactLastUpdatedTimestamp], out dateModified);
if (values[IPhoneLookupColumns.Number] is not null or "")
{
string phone = values[IPhoneLookupColumns.Number];
var val = new ContactQueryResult
{
ContactId = contactId,
ContactLastUpdatedTimestamp = parsed ? dateModified : null,
DataId = dataId,
DisplayName = values[CommonDataKinds.StructuredName.DisplayName],
PhoneNumber = phone
};
contactQueryResult.Add(phone, val);
}
values.Clear();
}
}
base.OnChange(selfChange, uri);
}
}```

How to fetch all pdf file from all directories in my Android app

I want to know how to fetch all PDF files from internal storage. Files can be in any directory, like some in DCIM folders or some in Downloads folder, and so on and so forth.
Note: I am using Android Studio (language: Java).
i have search almost all the ans but it was not working in Android 11. so i have a short solution for picking up all file for example image, video, pdf, doc, audio etc. there was a github library which was recently created
Click [here] https://github.com/HBiSoft/PickiT
and if you want to do all this without dependency
Code Below
do it in orderwise
var mimeTypes = arrayOf(
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .doc & .docx
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation", // .ppt & .pptx
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xls & .xlsx
"application/pdf"
)
findViewById<Button>(R.id.btnclick).setOnClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
// mimeTypes = mimeTypes
}
startActivityForResult(intent, 100)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.e(">>>>>>", "check")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getFile(this,intentToDocumentFiles(data)[0])
}
}
private fun intentToDocumentFiles(intent: Intent?): List<DocumentFile> {
val uris = intent?.clipData?.run {
val list = mutableListOf<Uri>()
for (i in 0 until itemCount) {
list.add(getItemAt(i).uri)
}
list.takeIf { it.isNotEmpty() }
} ?: listOf(intent?.data ?: return emptyList())
return uris.mapNotNull { uri ->
if (uri.isDownloadsDocument && Build.VERSION.SDK_INT < 28 && uri.path?.startsWith("/document/raw:") == true) {
val fullPath = uri.path.orEmpty().substringAfterLast("/document/raw:")
DocumentFile.fromFile(File(fullPath))
} else {
fromSingleUri(uri)
}
}.filter { it.isFile }
}
#RequiresApi(Build.VERSION_CODES.R)
fun getFile(context: Context, document: DocumentFile): File? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return null
}
try {
val volumeList: List<StorageVolume> = context
.getSystemService(StorageManager::class.java)
.getStorageVolumes()
if (volumeList == null || volumeList.isEmpty()) {
return null
}
// There must be a better way to get the document segment
val documentId = DocumentsContract.getDocumentId(document.uri)
val documentSegment = documentId.substring(documentId.lastIndexOf(':') + 1)
for (volume in volumeList) {
val volumePath: String
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
val class_StorageVolume = Class.forName("android.os.storage.StorageVolume")
val method_getPath: Method = class_StorageVolume.getDeclaredMethod("getPath")
volumePath=method_getPath.invoke(volume).toString()
} else {
// API 30
volumePath=volume.directory!!.path
}
val storageFile = File(volumePath + File.separator + documentSegment)
// Should improve with other checks, because there is the
// remote possibility that a copy could exist in a different
// volume (SD-card) under a matching path structure and even
// same file name, (maybe a user's backup in the SD-card).
// Checking for the volume Uuid could be an option but
// as per the documentation the Uuid can be empty.
val isTarget = (storageFile.exists()
&& storageFile.lastModified() == document.lastModified()
&& storageFile.length() == document.length())
if (isTarget) {
Log.e(">>>>>>>",storageFile.absolutePath)
return storageFile
}
}
} catch (e: Exception) {
e.printStackTrace()
}
Log.e(">>>>>>>","null")
return null
}
You can use MediaStore to fetch all PDF Files ,this is an example how to get all your PDF files :
protected ArrayList<String> getPdfList() {
ArrayList<String> pdfList = new ArrayList<>();
Uri collection;
final String[] projection = new String[]{
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.MIME_TYPE,
};
final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC";
final String selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ?";
final String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
final String[] selectionArgs = new String[]{mimeType};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
}else{
collection = MediaStore.Files.getContentUri("external");
}
try (Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
assert cursor != null;
if (cursor.moveToFirst()) {
int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
int columnName = cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME);
do {
pdfList.add((cursor.getString(columnData)));
Log.d(TAG, "getPdf: " + cursor.getString(columnData));
//you can get your pdf files
} while (cursor.moveToNext());
}
}
return pdfList;
}
This is improvised answer of #Shay Kin.
As we know in latest android versions we have many restrictions to access files in external storage.
MediaStore api and Storage Access Framework apis provides access to shared files. This is explained clearly in this video.
Coming to the answer, in Shay Kin's answer we can able to fetch all pdf files which are there in the shared files but ignores downloads.
Permissions required
READ_EXTERNAL_STORAGE
if api is Q plus you also need MANAGE_EXTERNAL_STORAGE
please find the below code to fetch all pdf files.
protected List<String> getPdfList() {
List<String> pdfList = new ArrayList<>();
final String[] projection = new String[]{
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.MIME_TYPE,
};
final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC";
final String selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ?";
final String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
final String[] selectionArgs = new String[]{mimeType};
Uri collection = MediaStore.Files.getContentUri("external");
pdfList.addAll(getPdfList(collection, projection, selection, selectionArgs, sortOrder));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Downloads.getContentUri("external");
pdfList.addAll(getPdfList(collection,projection, selection, selectionArgs, sortOrder));
}
return pdfList;
}
private List<String> getPdfList(Uri collection, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
List<String> pdfList = new ArrayList<>();
try (Cursor cursor = getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
assert cursor != null;
if (cursor.moveToFirst()) {
int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
do {
pdfList.add((cursor.getString(columnData)));
Log.d(TAG, "getPdf: " + cursor.getString(columnData));
//you can get your pdf files
} while (cursor.moveToNext());
}
}
return pdfList;
}
Hope this works.

`MediaStore.MediaColumns.DATA` is deprecated, what column should I use as an alternative

I want to load all the pictures from the media provider to my app by using MediaStore API, but this column MediaStore.MediaColumns.DATA is deprecated. So, what can I use as an alternative?
I want to update the following code to get rid of the deprecated MediaStore.MediaColumns.DATA column:
fun ContentResolver.loadImagesPaths(): List<String> {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val images = mutableListOf<String>()
val projection = arrayOf(MediaStore.MediaColumns.DATA)
query(uri, projection, null, null, null)?.use { cursor ->
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
while (cursor.moveToNext()) {
images += cursor.getString(dataColumn)
}
}
return images
}
Edit:
Updated code:
fun ContentResolver.loadImagesUris(): List<Uri> {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val images = mutableListOf<Uri>()
val projection = arrayOf(MediaStore.Images.Media._ID)
query(uri, projection, null, null, null)?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext()) {
images += ContentUris.withAppendedId(uri, cursor.getLong(idColumn))
}
}
return images
}
Check out this link for further details on how to access media files from shared storage: https://developer.android.com/training/data-storage/shared/media
I was able to replace MediaStore.MediaColumns.Data with its own file ID (incredibly, files have IDs) and correctly constructing its URI, like this:
fun getAllShownImagesPath(activity: Activity): MutableList<Uri> {
val uriExternal: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor?
val columnIndexID: Int
val listOfAllImages: MutableList<Uri> = mutableListOf()
val projection = arrayOf(MediaStore.Images.Media._ID)
var imageId: Long
cursor = activity.contentResolver.query(uriExternal, projection, null, null, null)
if (cursor != null) {
columnIndexID = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext()) {
imageId = cursor.getLong(columnIndexID)
val uriImage = Uri.withAppendedPath(uriExternal, "" + imageId)
listOfAllImages.add(uriImage)
}
cursor.close()
}
return listOfAllImages
}
and then with Uri you build it in your Views!
I managed to come up with the following solution, its kind of an addition to the previous answer
but there I still couldn't load images with the obtained Uri.
Documentation suggested to use openFileDescriptor() which I did and then decoded images' bitmaps from it:
override fun loadImagesFromStorage(): List<AdapterImage> {
val uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor?
val columnIndexId: Int
val listOfAllImages = mutableListOf<AdapterImage>()
val projection = arrayOf(MediaStore.Images.Media._ID)
cursor = context.contentResolver
.query( uri, projection, null, null, null)
if ( cursor != null ){
columnIndexId = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext()){
val contentUri = ContentUris.withAppendedId(uri, cursor.getLong(columnIndexId))
//here I open FileDescriptor and then decode it into Bitmap
var image: Bitmap
context.contentResolver.openFileDescriptor(contentUri, "r").use { pfd ->
if( pfd != null ){
image = BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor)
listOfAllImages.add(AdapterImage(image))
}
}
}
cursor.close()
}
return listOfAllImages
}
P.S. My method will return a list of AdapterImage objects that I use later in app but you can put anything you need there at this point
I finally solved the problem by creating this class
class FileHelper {
val mediaType = "multipart/form-data".toMediaTypeOrNull()
fun getPartBodyFromUri(context: Context, uri: Uri): MultipartBody.Part {
val realPath = getPathFromURI(context, uri)
val fileImage = createFile(realPath)
val requestBody = createRequestBody(fileImage)
return createPart(fileImage, requestBody)
}
private fun createFile(realPath: String): File {
return File(realPath)
}
private fun createRequestBody(file: File): RequestBody {
return file.asRequestBody(mediaType)
}
private fun createPart(file: File, requestBody: RequestBody): MultipartBody.Part {
return MultipartBody.Part.createFormData("imageFile", file.name, requestBody)
}
private fun getPathFromURI(context: Context, uri: Uri): String {
var realPath = String()
uri.path?.let { path ->
val databaseUri: Uri
val selection: String?
val selectionArgs: Array<String>?
if (path.contains("/document/image:")) { // files selected from "Documents"
databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
selection = "_id=?"
selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
} else { // files selected from all other sources, especially on Samsung devices
databaseUri = uri
selection = null
selectionArgs = null
}
try {
val column = "_data"
val projection = arrayOf(column)
val cursor = context.contentResolver.query(
databaseUri,
projection,
selection,
selectionArgs,
null
)
cursor?.let {
if (it.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow(column)
realPath = cursor.getString(columnIndex)
}
cursor.close()
}
} catch (e: Exception) {
println(e)
}
}
return realPath
}
}
Media.DATA it's deprecate and "MediaStore.Images.Media._ID" to get the correct column, not working so I create column I need
val column = "_data"
val projection = arrayOf(column)
then I use getColumnIndexOrThrow() method to get correct index
val columnIndex = cursor.getColumnIndexOrThrow(column)
realPath = cursor.getString(columnIndex)
In Java
FileInputStream input = null;
FileOutputStream output = null;
try {
String filePath = new File(getCacheDir(), "tmp").getAbsolutePath();
android.os.ParcelFileDescriptor pfd = getContentResolver ().openFileDescriptor(
sharedFileUri, "r");
if (pfd != null) {
FileDescriptor fd = pfd . getFileDescriptor ();
input = new FileInputStream (fd);
output = new FileOutputStream (filePath);
int read;
byte[] bytes = new byte[4096];
while ((read = input.read(bytes)) != -1) {
output.write(bytes, 0, read);
}
File sharedFile = new File(filePath);
String finalPath = sharedFile.getPath();
}
}catch(Exception ex) {
} finally {
try {
input.close();
output.close();
} catch (Exception ignored) {
}
}
Loading images from internal store.Reading all folders which has images and videos using MediaStore class.
And returning result as ArrayList.
private fun getAllShownImagesPath(activity: Activity): ArrayList<Albums> {
val uri: Uri
val cursor: Cursor
var cursorBucket: Cursor
val column_index_data: Int
val column_index_folder_name: Int
val listOfAllImages = ArrayList<String>()
var absolutePathOfImage: String? = null
var albumsList = ArrayList<Albums>()
var album: Albums? = null
val BUCKET_GROUP_BY = "1) GROUP BY 1,(2"
val BUCKET_ORDER_BY = "MAX(datetaken) DESC"
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.ImageColumns.BUCKET_ID,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATA)
cursor = activity.contentResolver.query(uri, projection, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY)
if (cursor != 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)
Log.d("title_apps", "bucket name:" + cursor.getString(column_index_data))
val selectionArgs = arrayOf("%" + cursor.getString(column_index_folder_name) + "%")
val selection = MediaStore.Images.Media.DATA + " like ? "
val projectionOnlyBucket = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
cursorBucket = activity.contentResolver.query(uri, projectionOnlyBucket, selection, selectionArgs, null)
Log.d("title_apps", "bucket size:" + cursorBucket.count)
if (absolutePathOfImage != "" && absolutePathOfImage != null) {
listOfAllImages.add(absolutePathOfImage)
albumsList.add(Albums(cursor.getString(column_index_folder_name), absolutePathOfImage, cursorBucket.count, false))
}
}
}
return getListOfVideoFolders(albumsList)
}
// This function is resposible to read all videos from all folders.
private fun getListOfVideoFolders(albumsList: ArrayList<Albums>): ArrayList<Albums> {
var cursor: Cursor
var cursorBucket: Cursor
var uri: Uri
val BUCKET_GROUP_BY = "1) GROUP BY 1,(2"
val BUCKET_ORDER_BY = "MAX(datetaken) DESC"
val column_index_album_name: Int
val column_index_album_video: Int
uri = android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection1 = arrayOf(MediaStore.Video.VideoColumns.BUCKET_ID,
MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME,
MediaStore.Video.VideoColumns.DATE_TAKEN,
MediaStore.Video.VideoColumns.DATA)
cursor = this.contentResolver.query(uri, projection1, BUCKET_GROUP_BY, null, BUCKET_ORDER_BY)
if (cursor != null) {
column_index_album_name = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
column_index_album_video = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
while (cursor.moveToNext()) {
Log.d("title_apps", "bucket video:" + cursor.getString(column_index_album_name))
Log.d("title_apps", "bucket video:" + cursor.getString(column_index_album_video))
val selectionArgs = arrayOf("%" + cursor.getString(column_index_album_name) + "%")
val selection = MediaStore.Video.Media.DATA + " like ? "
val projectionOnlyBucket = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
cursorBucket = this.contentResolver.query(uri, projectionOnlyBucket, selection, selectionArgs, null)
Log.d("title_apps", "bucket size:" + cursorBucket.count)
albumsList.add(Albums(cursor.getString(column_index_album_name), cursor.getString(column_index_album_video), cursorBucket.count, true))
}
}
return albumsList
}
you can use "IMediaColumns" instead of "MediaColumns".

How to get paths of folders that has image or video

I want to create an android gallery app .
How to scan and get paths of folders that includes photos or videos .
I used this code and worked . but when i compare it with Quickpic Gallery in play store , i see the count of folders in my app is less than Quickpic folders
Do you see any problem in this code ?
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = ba.context.getContentResolver().query(uri, null, null,
null, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME);
if (cursor != null) {
cursor.moveToFirst();
int data = cursor
.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
int displayName = cursor
.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME);
imageFolders = new HashMap<>();
do {
String imageAddress = cursor.getString(data);
String imageName = cursor.getString(displayName);
String folderAddress = imageAddress.substring(0,
imageAddress.lastIndexOf(imageName) - 1);
if (!imageFolders.containsKey(folderAddress)) {
imageFolders.put(folderAddress, imageAddress);
}
} while (cursor.moveToNext());
for (String str : imageFolders.keySet()) {
ba.raiseEventFromDifferentThread(
null,
null,
0,
"result",
true,
new Object[] { String.format("%s", str),
String.format("%s", imageFolders.get(str)) });
}
}
this way you can find all video and image parents.
ArrayList<String> allFolder;
HashMap<String, ArrayList<String>> listImageByFolder;
ArrayList<String> allVideoFolder;
HashMap<String, ArrayList<String>> listVideoByFolder;
find all images folder path
private void getImageFolderList() {
String[] projection = new String[] { MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATE_TAKEN };
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
Cursor cur = getContentResolver().query(images, projection, // Which
// columns
// to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
orderBy + " DESC" // Ordering
);
ArrayList<String> imagePath;
if (cur.moveToFirst()) {
String bucket, date;
int bucketColumn = cur.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int dateColumn = cur.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
do {
bucket = cur.getString(bucketColumn);
date = cur.getString(dateColumn);
if (!allFolder.contains(bucket)) {
allFolder.add(bucket);
}
imagePath = listImageByFolder.get(bucket);
if (imagePath == null) {
imagePath = new ArrayList<String>();
}
imagePath.add(cur.getString(cur
.getColumnIndex(MediaStore.Images.Media.DATA)));
listImageByFolder.put(bucket, imagePath);
} while (cur.moveToNext());
}
}
find all videos folder path
private void getVideoFolderList() {
String[] projection = new String[] { MediaStore.Video.Media.DATA,
MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATE_TAKEN };
Uri images = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
final String orderBy = MediaStore.Video.Media.DATE_TAKEN;
Cursor cur = getContentResolver().query(images, projection, // Which
// columns
// to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
orderBy + " DESC" // Ordering
);
ArrayList<String> imagePath;
if (cur.moveToFirst()) {
String bucket, date;
int bucketColumn = cur.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
int dateColumn = cur.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN);
do {
bucket = cur.getString(bucketColumn);
date = cur.getString(dateColumn);
if (!allVideoFolder.contains(bucket)) {
allVideoFolder.add(bucket);
}
imagePath = listVideoByFolder.get(bucket);
if (imagePath == null) {
imagePath = new ArrayList<String>();
}
imagePath.add(cur.getString(cur
.getColumnIndex(MediaStore.Images.Media.DATA)));
listVideoByFolder.put(bucket, imagePath);
} while (cur.moveToNext());
}
}
i can see you are trying to get the folder names of all folders containing video files the answer given by #prakash ubhadiya is good an works but for the problem that if the are many of such folders with same name the function will keep only one and ignore the rest, below i have modified his fuction to return not only the folder names but also the folder absolute path in case you will want to use this to get all the video files in that specific folder, i have created a class called floderFacer the holds the folder name and the folder adsolute path, done this way no folders with same names will be ignored below is the class
public class folderFacer {
private String path;
private String folderName;
public folderFacer(){
}
public folderFacer(String path, String folderName) {
this.path = path;
this.folderName = folderName;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
}
now below is the modified fuction that will return the folder names and paths in a folderFacer object all in an ArrayList<folderFacer>
private ArrayList<folderFacer> getVideoPaths(){
ArrayList<folderFacer> videoFolders = new ArrayList<>();
ArrayList<String> videoPaths = new ArrayList<>();
Uri allVideosuri = android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns.DATA ,MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,MediaStore.Video.Media.BUCKET_ID};
Cursor cursor = getContentResolver().query(allVideosuri, projection, null, null, null);
try {
cursor.moveToFirst();
do{
folderFacer folds = new folderFacer();
String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
String folder = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME));
String datapath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
String folderpaths = datapath.replace(name,"");
if (!videoPaths.contains(folderpaths)) {
videoPaths.add(folderpaths);
folds.setPath(folderpaths);
folds.setFolderName(folder);
videoFolders.add(folds);
}
}while(cursor.moveToNext());
cursor.close();
} catch (Exception e) {
e.printStackTrace();
}
for(int i = 0;i < videoFolders.size();i++){
Log.d("video folders",videoFolders.get(i).getFolderName()+" and path = "+videoFolders.get(i).getPath());
}
return videoFolders;
}
hope this helps

get mp3 files from path

I'm trying to get mp3 files from a folder path of my system to list it in my listView, but unfortunately there's always the same error. (java.lang.NullPointerException: Attempt to get length of null array)
class Mp3Filter implements FilenameFilter{
public boolean accept(File dir, String name){
return (name.endsWith(".mp3"));
}
}
private static final String SD_PATH = new String(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).toString());
public void searchForSongs() {
ListView listView;
listView = (ListView) findViewById(R.id.listView);
File f = new File(SD_PATH);
try {
if (f.listFiles(new Mp3Filter()).length > 0){
for (File file : f.listFiles(new Mp3Filter())){
list.add(file.getName());
}
}
}
catch(Exception e) {
textView2.setText(""+e);
return;
}
final ArrayAdapter songList = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(songList);
}
Here is your solution use the following code to Read the MP3 file from the Specific Folder..
First of all Create 1 Model class as Given Below, to GET and SET Files in list.
AudioModel.class
public class AudioModel {
String aPath;
String aName;
String aAlbum;
String aArtist;
public String getaPath() {
return aPath;
}
public void setaPath(String aPath) {
this.aPath = aPath;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
public String getaAlbum() {
return aAlbum;
}
public void setaAlbum(String aAlbum) {
this.aAlbum = aAlbum;
}
public String getaArtist() {
return aArtist;
}
public void setaArtist(String aArtist) {
this.aArtist = aArtist;
}
}
Now We have our Model Class Now use the below code to Read the all MP3 files from your Folder.
This will return list of all MP3 Files with Music NAME, PATH, ARTIST, ALBUM and if you wants more detail please refer Media.Store.Audio doc..
https://developer.android.com/reference/android/provider/MediaStore.Audio.html
public List<AudioModel> getAllAudioFromDevice(final Context context) {
final List<AudioModel> tempAudioList = new ArrayList<>();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Audio.AudioColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM, MediaStore.Audio.ArtistColumns.ARTIST,};
Cursor c = context.getContentResolver().query(uri, projection, MediaStore.Audio.Media.DATA + " like ? ", new String[]{"%yourFolderName%"}, null);
if (c != null) {
while (c.moveToNext()) {
AudioModel audioModel = new AudioModel();
String path = c.getString(0);
String album = c.getString(1);
String artist = c.getString(2);
String name = path.substring(path.lastIndexOf("/") + 1);
audioModel.setaName(name);
audioModel.setaAlbum(album);
audioModel.setaArtist(artist);
audioModel.setaPath(path);
Log.e("Name :" + name, " Album :" + album);
Log.e("Path :" + path, " Artist :" + artist);
tempAudioList.add(audioModel);
}
c.close();
}
return tempAudioList;
}
To Read Files of Specific Folder, use below Query and write your folder name in Query..
Cursor c = context.getContentResolver().query(uri,
projection,
MediaStore.Audio.Media.DATA + " like ? ",
new String[]{"%yourFolderName%"}, // yourFolderName
null);
If you wants All Files of device use below Query..
Cursor c = context.getContentResolver().query(uri,
projection,
null,
null,
null);
Don't forget to add Storage Permission .. enjoy.

Categories

Resources