MediaMetadataRetriever.setDataSource(Native Method) causes RuntimeException: status = 0xFFFFFFEA

旧巷老猫 提交于 2019-12-24 18:27:04

问题


I'm building a media player using ReactNative. In order to accomplish such app I had to export a module I built for retrieving music metadata like album, artist, etc as well as file path.

The code above was working perfectly using jdk1.8.0_112, but since I updated to jdk1.8.0_144 It stopped working.

In this example, I'm not checking for not null, not empty, length > 0, etc, But I really do in the original one.

try {
    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
    mmr.setDataSource("Path to the file"); // /storage/337C-1C15/Music/Edguy/Speedhoven.mp3
} catch (RuntimeException ex) {
    // java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA
}

I'm facing two problems. On one hand, I'm not a great Android dev so getting some clues is such hard task. On the other hand, the error does provide a good description.

Just in case some of you had a better way to accomplish what I tried, I left here the whole code:

@ReactMethod
public void getAll(Callback errorCallback, Callback successCallback){

    ContentResolver musicResolver = this.getCurrentActivity().getContentResolver();
    Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);

    if (musicCursor != null && musicCursor.moveToFirst()) {

        WritableArray jsonArray = new WritableNativeArray();
        MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        WritableMap items = new WritableNativeMap();

        int titleColumn = musicCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
        int idColumn = musicCursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
        int artistColumn = musicCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.ARTIST);

        try {
            do {
                items = new WritableNativeMap();
                byte[] art;

                long thisId = musicCursor.getLong(idColumn);
                String thisPath = musicCursor.getString(musicCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
                String thisTitle = musicCursor.getString(titleColumn);
                String thisArtist = musicCursor.getString(artistColumn);
                String duration = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.DURATION));


                if(thisPath != null && thisPath != "" && thisPath.endsWith(".mp3")) {

                    mmr.setDataSource(thisPath);

                    String album = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
                    String artist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                    String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
                    String genre = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
                    String encoded = "";
                    String encodedImage = "";
                    art = mmr.getEmbeddedPicture();

                    if (album == null) {
                        album = thisArtist;
                    }

                    if (artist == null) {
                        artist = thisArtist;
                    }

                    if (title == null) {
                        title = thisTitle;
                    }

                    if (art != null) {
                        Bitmap songImage = BitmapFactory.decodeByteArray(art, 0, art.length);
                        if(songImage != null){
                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                            songImage.compress(Bitmap.CompressFormat.JPEG, 60, byteArrayOutputStream);
                            byte[] byteArray = byteArrayOutputStream.toByteArray();
                            encodedImage = Base64.encodeToString(byteArray, Base64.DEFAULT);
                            String pathtoImg = "";
                            byte[] imageByte = Base64.decode(encodedImage, Base64.DEFAULT);
                            try {
                                pathtoImg = Environment.getExternalStorageDirectory() + "/" + thisId + ".jpg";
                                File filePath = new File(pathtoImg);
                                FileOutputStream fos = new FileOutputStream(filePath, true);
                                encoded = pathtoImg;
                                fos.write(imageByte);
                                fos.flush();
                                fos.close();
                            } catch (FileNotFoundException fnfe) {
                                errorCallback.invoke(fnfe.getMessage());
                            } catch (IOException ioe) {
                                errorCallback.invoke(ioe.getMessage());
                            }
                        }
                    }

                    String str = String.valueOf(thisId);
                    items.putString("id", str);
                    items.putString("album", album);
                    items.putString("artist", artist);
                    items.putString("title", title);
                    items.putString("genre", genre);

                    if (encoded == "") {
                        items.putString("cover", "");
                    } else {
                        items.putString("cover", "file://" + encoded);
                    }

                    items.putString("duration", duration);
                    items.putString("path", thisPath);
                    jsonArray.pushMap(items);
                }
            } while (musicCursor.moveToNext());

            successCallback.invoke(jsonArray);
            mmr.release();
        } catch (RuntimeException e) {
            errorCallback.invoke(e.toString());
            mmr.release();
        } catch (Exception e) {
            errorCallback.invoke(e.getMessage());
            mmr.release();
        }
    }
}

Of course, I've already taken a look at:

  • This post
  • This post
  • This post

回答1:


After debugging and researching a lot I found the problem.

It seems that mmr.setDataSource("path") returns a RuntimeException when something is wrong with the file. This is particularly important since even when the file exists its metadata cannot be retrieved.

The solution was to use the MediaMetadataRetriever into a try/catch like this:

while(cursor.moveNext()){
  try {
    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
    mmr.setDataSource("Path to the file"); // /storage/337C 1C15/Music/Edguy/Speedhoven.mp3
  } catch (RuntimeException ex) {
    // something went wrong with the file, ignore it and continue
  }
}


来源:https://stackoverflow.com/questions/46029813/mediametadataretriever-setdatasourcenative-method-causes-runtimeexception-sta

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!