Thanks for read this question.
I'm new to Android development.
In my project,I'm trying to access video file in shared storage.
To accomplished the purpose,I wrote the below code.
In the code, ContentResolver's query method is unresolved.I don't understand why.
val query = ContentResolver.query( <-Unresolved
collection,
projection,
selection,
selectionArgs,
sortOrder
)
query?.use{
cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)
val durationColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)
while(cursor.movieToNext()){
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val duration = cursor.getInt(durationColumn)
val size = cursor.getInt(sizeColumn)
val contentUri: Uri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
id)
videoList += Video(contentUri, name, duration, size)
}
So coule someone please explaine to me the reason.Thank you.
Related
I am having difficulty in importing music files in android. Problem is: I want to get all the music on the phone, but it doesn't work, only some of them are coming.
Hello, I am having difficulty in importing music files in android. Problem is: I want to get all the music on the phone, but it doesn't work, only some of them are coming.Why not coming ?
val arrayList: ArrayList<AudioModel> = ArrayList<AudioModel>()
val projection = arrayOf(
Audio.Media._ID,
Audio.Media.DISPLAY_NAME,
Audio.Media.DURATION,
Audio.Media.SIZE
)
val selection = Audio.Media.DISPLAY_NAME +
" >= ?"
val selectionArgs = arrayOf(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES).toString())
val sortOrder = Audio.Media.DISPLAY_NAME + " ASC"
val cursor: Cursor? = activity?.contentResolver?.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
selectionArgs,
sortOrder
)
val idColumn = cursor!!.getColumnIndexOrThrow(Audio.Media._ID)
val nameColumn = cursor!!.getColumnIndexOrThrow(Audio.Media.DISPLAY_NAME)
val durationColumn = cursor!!.getColumnIndexOrThrow(Audio.Media.DURATION)
val sizeColumn = cursor!!.getColumnIndexOrThrow(Audio.Media.SIZE)
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val duration = cursor.getInt(durationColumn)
val size = cursor.getInt(sizeColumn)
val contentUri = ContentUris.withAppendedId(
Audio.Media.EXTERNAL_CONTENT_URI, id
)
// Stores column values and the contentUri in a local object
// that represents the media file.
arrayList.add(AudioModel(contentUri.toString(),name,duration))
}
I'd like to know photos width and height before loading a bitmap. I'm using latest approach of ContentResolver to query locally stored photos.
contentResolver.query(
collection,
projection,
selection,
selectionArgs,
sortOrder
)!!.use { cursor ->
while (cursor.moveToNext()) {
// Use an ID column from the projection to get
// a URI representing the media item itself.
val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID)
val widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH)
val id: Long = cursor.getLong(idColumn)
val width: Int = cursor.getInt(widthColumn) //CRASH
}
Cursor is crashing on the selected line width:
IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
How am I supposed to do that then?
Try This
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.HEIGHT
)
val images: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
contentResolver.query(
images,
projection,
null,
null,
null
)!!.use { cursor ->
if (cursor.count > 0) {
val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID)
val widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH)
val heightColumn = cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT)
while (cursor.moveToNext()) {
val id: Long = cursor.getLong(idColumn)
val width: Int = cursor.getInt(widthColumn)
val height: Int = cursor.getInt(heightColumn)
Log.e("tag", " width :: $width - height :: $height");
}
}
}
I've seen a lot of people ask questions related to this, but they were all written in Java and they all use the method getContentResolver().loadThumbnail(imageUri, thumbSize, null);, but how to use loadThumbnail() in Kotlin?
Here is my attempt:
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val displayName = cursor.getString(displayNameColumn)
val album = cursor.getString(albumColumn)
val albumId = cursor.getLong(albumIdColumn)
val duration = cursor.getString(durationColumn)
val contentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id
)
val albumUri = ContentUris.withAppendedId(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, albumId
)
val albumCover = ContentResolver().loadThumbnail(
albumUri,
Size(100, 100),
null
)
val song = Song(id, displayName, album, albumId, duration, contentUri, albumUri,
albumCover.asImageBitmap())
songs += song
Log.v(TAG, "Added song:${song.displayName}")
}
Then Android studio prompted me with an error about ContentResolver():
Cannot create an instance of an abstract class
So how do I use loadThumbnail() appropriately?
Thank you!
The following code is used to save files from the app to downloads:
Uri collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, filename);
values.put(MediaStore.Downloads.MIME_TYPE, mimeType);
values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
ContentResolver contentResolver = context.getApplicationContext().getContentResolver();
Uri uri = contentResolver.insert(collection, values);
OutputStream outputStream = context.getApplicationContext().getContentResolver().openOutputStream(uri, "w");
Everything is saved, however, if you delete the file from downloads manually, and then try to download it again from the application, an error appears:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE[2067])
Is there a way to fix this or will I have to use unique names for each download?
This error happens because the machanism of OS: if we delete manually a file (media), its database will not be deleted immediately. Until we restart device.
Have a approach for this problem (still not be optimized - hope receiving sharing from people), such as:
Step 1: Get info of file via its name
Step 2: Ask OS to update its database via MediaScannerConnection.scanFile
Step 3: Use current code that has above problem
Codes for steps (collected on internet)
Step 1:
fun findByFileName(fileName: String): MutableList<FileInfo> {
val files = mutableListOf<FileInfo>()
val collection =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DATA
)
val selection = "${MediaStore.Video.Media.DISPLAY_NAME} LIKE ?"
val selectionArgs = arrayOf(
fileName
)
// Display videos in alphabetical order based on their display name.
val sortOrder = "${MediaStore.Video.Media.DISPLAY_NAME} ASC"
val query = context.contentResolver.query(
collection,
projection,
selection,
selectionArgs,
sortOrder
)
query?.use { cursor ->
// Cache column indices.
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)
val durationColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
while (cursor.moveToNext()) {
// Get values of columns for a given video.
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val duration = cursor.getInt(durationColumn)
val size = cursor.getInt(sizeColumn)
val data = cursor.getStringOrNull(dataColumn)
val contentUri: Uri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
id
)
// Stores column values and the contentUri in a local object
// that represents the media file.
files += FileInfo(contentUri, name, duration, size, data)
}
}
return files
}
data class FileInfo(
val uri: Uri,
val name: String,
val duration: Int,
val size: Int,
val data: String? = null
)
Step 2 + Step 3:
val exitedData = findByFileName(fileName = name)
if (exitedData != null) {
MediaScannerConnection.scanFile(context, arrayOf(exitedData.first().data.toString()), null, object: MediaScannerConnection.OnScanCompletedListener {
override fun onScanCompleted(path: String?, uri: Uri?) {
// Step 3
// Use current code have this problem
...
}
}
} else {
// Save file normally
// Use current code have this problem
...
}
I'm trying to get all the images on the device, for now my code is:
val imageProjection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DATE_TAKEN,
)
val cursor = context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageProjection,
null,
null,
"${MediaStore.Images.Media.DATE_MODIFIED} DESC"
)
cursor?.use {
val idColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
val nameColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
val sizeColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)
val dateColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN)
while (it.moveToNext()) {
val id = it.getLong(idColumn)
val name = it.getString(nameColumn)
val size = it.getString(sizeColumn)
val date = it.getString(dateColumn)
Log.d("IMAGE", "$id $name $size $date")
}
}
The query does give me a Cursor, but the Cursor appears to be empty as the code never enter the while.
I've checked that i have the READ_EXTERNAL_STORAGE permission, and i do have it, but it still doesn't work, i also tried using MediaStore.Images.Media.INTERNAL_CONTENT_URI as the query uri, but that didn't change anything, the result is always an empty cursor.
Can someone give me an hint on what i'm doing wrong?