1

I'm developing a Chrome OS app and I want to play a song when a song dragged and dropped onto a view in my app. I created a listener and I'm able to get the dragged file with its path. But the problem is; I can't get the information about the dropped song.

Here's what I've tried so far;

class BackingTrackDragListener implements View.OnDragListener {
    private final static Uri ARTWORK_URI = Uri.parse("content://media/external/audio/albumart");
    BackingTrackViewModel viewModel;

    public BackingTrackDragListener(BackingTrackViewModel viewModel) {
        super();
        this.viewModel = viewModel;
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public boolean onDrag(View v, DragEvent event) {

        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                return true;

            case DragEvent.ACTION_DROP:
                if (event.getClipDescription().hasMimeType("application/x-arc-uri-list")) {
                    MainActivity mainActivity = MyApplication.getMainActivity();

                    if (mainActivity == null) {
                        break;
                    }

                    mainActivity.requestDragAndDropPermissions(event);
                    ClipData.Item item = event.getClipData().getItemAt(0);

                    ContentResolver contentResolver = mainActivity.getContentResolver();

                    try {
                        String audioPath = new File(new URI(item.getUri().toString()).getPath()).getCanonicalPath();

                        Cursor cursor = contentResolver.query(
                                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                                new String[]{
                                        MediaStore.Audio.Media.TITLE,
                                        MediaStore.Audio.Media.DURATION,
                                        MediaStore.Audio.Media.ALBUM_ID
                                },
                                MediaStore.Audio.Media.DATA + " = ?",
                                new String[]{audioPath},
                                "");

                        String[] str = cursor.getColumnNames(); // prints the column names

                        final String displayName = cursor.getString(0);
                        final long duration = cursor.getLong(1);
                        final long albumId = cursor.getLong(2);
                        final Uri imageUri = ContentUris.withAppendedId(ARTWORK_URI, albumId);
                        if (audioPath.endsWith("mp3") && duration > 15000) {
                            viewModel.setSelectedAudio(new BackingTrackAudio(displayName, imageUri, audioPath));
                        } else {
                            break;
                        }
                        cursor.close();
                    } catch (IOException | URISyntaxException e) {
                        e.printStackTrace();
                    }

                    break;
                }

            default:
                break;
        }

        return false;
    }
}

The actual problem here is I can't read the column data.

I think the problem is occurring when I create the cursor. When I wanted to get a column data from the cursor, my app throws the below error:

Error: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0

Error line: final String displayName = cursor.getString(0);

I also tried this using a while loop like cursor.moveToNext() or cursor.moveToFirst() but no luck.

What I want is to get the track name, album cover, and duration from the mp3 file's path. Is there another way to achieve this? I also tried this solution: Android: How to get audio detail from audio file but this one also didn't work :/ Any suggestion would help, thank you.

UPDATE

I also tried:

  Cursor cursor = contentResolver.query(
                            item.getUri(),
                            new String[]{
                                    MediaStore.Audio.Media.TITLE,
                                    MediaStore.Audio.Media.DURATION,
                                    MediaStore.Audio.Media.ALBUM_ID
                            },
                            MediaStore.Audio.Media.DATA + " = ?",
                            new String[]{audioPath},
                            "");

And the error was very similar to the previous one: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1

tpbafk
  • 501
  • 5
  • 26
  • 1
    `contentResolver.query( item.getUri(), ........` Dont mess around with the File class and paths. Just query the uri for the song file. – blackapps Feb 24 '21 at 11:39
  • Please show complete content scheme examples of item.getUri(). – blackapps Feb 24 '21 at 11:42
  • Better post complete new code in a new code block. – blackapps Feb 24 '21 at 11:43
  • I'm using this listener in my fragment `myView.setOnDragListener(new BackingTrackDragListener(this.viewModel));` like so. So, actually, this is the full code. And my getUri() result: https://share.getcloudapp.com/o0uEXDq6 if that's what you've asked. Thanks – tpbafk Feb 24 '21 at 11:53
  • And, my `str` values which the columns I tried to get: https://share.getcloudapp.com/X6u9Qz8J – tpbafk Feb 24 '21 at 11:58
  • You should use the uri of the song on your device of course. That uri would look like `content://external/audio/media/1234` or so. Ehh... sorry... I see now Chrome OS. Maybe things are different there... – blackapps Feb 24 '21 at 12:36
  • Yeah, could be. But I can print the column names but can't get the data. That's very strange. Anyway, if I find a solution I'll post it out here... – tpbafk Feb 24 '21 at 12:46
  • Still, I couldn't solve the problem but I think it's about the file's path. `ClipData.Item item = event.getClipData().getItemAt(0);` this lines gives me the path like `download/mysong.mp3` but I need `/storage/emulated/0/Download/mysong.mp3`. If can get that path with ClipedData, then I cant make it work @blackapps – tpbafk Feb 25 '21 at 08:17
  • I hardcoded the `emulated` path to make it work. Like `String audioPath = "/storage/emulated/0/" + item.getUri().getPath()` – tpbafk Feb 25 '21 at 08:19
  • `.getClipData().getItemAt(0); this lines gives me the path like` Dit you use getPath() on it? Dont do that. Use .toString() to see that you got a nice content scheme. – blackapps Feb 25 '21 at 09:15
  • `String audioPath = new File(new URI(item.getUri().toString()).getPath()).getCanonicalPath();` That is nonsense. You have a nice uri and using path of it will not help you as it is not a file system path that you could use for the File class. DOnt use the File class at all. Query the uri itself for DISPLAY_NAME and such.I told you that already in my first comment. Please start adapting your code. Also here. Post comp[lete code as that CursorIndexOutOfBoundsException: is thrown by code you did not post. – blackapps Feb 25 '21 at 09:18
  • Use `contentResolver.query( item.getUri(), null, null, nulll, null);` Using the DATA column makes no sense as the uri is for one file only. There is nothing to select with DATA. – blackapps Feb 25 '21 at 09:23

1 Answers1

1

Here is the code to get details about the song from the mp3 file.

String path = Environment.getExternalStorageDirectory().getPath() + "/Download/music1.mp3";
File file = new File(path);

String fileName = file.getName();

double bytes = file.length();
String fileSize = String.format("%.2f", bytes / 1024) + " kb";

Log.d("tag", fileName + " " + fileSize);

MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
Uri uri = Uri.fromFile(file);
mediaMetadataRetriever.setDataSource(MainActivity.this, URI);

String songName = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
String album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
String genre = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
String track = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS);

Log.d(TAG, "SongName: " + songName + " Artist: " + artist + " Album: " + album);
Log.d(TAG, "Genre: " + genre + " Track: " + track);
Marwa Eltayeb
  • 1,921
  • 1
  • 17
  • 29