Ответ 1
Альтернативное решение №1: Использование Resource.getIdentifier()
Почему бы не использовать getResources(). getIdentifier(), чтобы получить идентификатор ресурса и использовать статический MediaPlayer.create(), как обычно?
public int getIdentifier (String name, String defType, String defPackage)
getIdentifier() берет ваше имя ресурса (test0), тип ресурса (raw), имя вашего пакета и возвращает фактический идентификатор ресурса.
MediaPlayer mp;
//String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp=MediaPlayer.create(getApplicationContext(), getResources().getIdentifier("test0","raw",getPackageName()));
mp.start();
Я тестировал этот код, и он работает.
Обновление # 1:
Альтернативное решение №2: Использование Uri.parse()
Я тоже тестировал этот код, и он тоже работает. Передайте свой путь ресурса как URI для setDataSource(). Я просто сделал это изменение для вашего кода, чтобы заставить его работать.
String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp = new MediaPlayer();
try { mp.setDataSource(this,Uri.parse(filename)); } catch (Exception e) {}
try { mp.prepare(); } catch (Exception e) {}
mp.start();
Обновление # 2: ответ НЕТ
О вызове setDataSource (String)
После просмотра комментария, похоже, что вы точно хотите, чтобы setDataSource (строка) использовался для вашей цели. Я не понимаю, почему. Но, я полагаю, по какой-то причине вы пытаетесь избежать использования "контекста". Если это не так, то эти два решения должны работать отлично для вас или если вы пытаетесь избежать контекста, я боюсь, что это невозможно с помощью функции с сигнатурой setDataSource (String). Причина такова, как показано ниже:
Функция MediaPlayer setDataSource() имеет следующие параметры, из которых вас интересует только setDataSource (String),
setDataSource (String) внутренне вызывает setDataSource (String path, String [] keys, String [] values). Если вы можете проверить источник ,
public void setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}
и если вы проверите ключи setDataSource (String path, String [], String []), вы увидите следующее условие, фильтрующее путь на основе его схемы, особенно если это "файловая" схема, называет setDataSource ( FileDescriptor), или если схема не является "файлом", она вызывает собственную функцию мультимедиа JNI.
{
final Uri uri = Uri.parse(path);
final String scheme = uri.getScheme();
if ("file".equals(scheme)) {
path = uri.getPath();
} else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
final File file = new File(path);
if (file.exists()) {
FileInputStream is = new FileInputStream(file);
FileDescriptor fd = is.getFD();
setDataSource(fd);
is.close();
} else {
throw new IOException("setDataSource failed.");
}
}
В приведенном выше коде ваша URI-схема файла ресурсов не будет равна null (android.resource://), а setDataSource (String) попытается использовать собственную функцию JNI nativeSetDataSource(), считая, что ваш путь - это http/https/rtsp, и, очевидно, что вызов завершится неудачно, не бросая никаких исключений. Вот почему ваш вызов setDataSource (String) экранируется без исключения и получает вызов prepare() со следующим исключением.
Prepare failed.: status=0x1
Таким образом, переопределение setDataSource (String) не может обрабатывать ваш файл ресурсов. Для этого вам нужно выбрать другое переопределение.
С другой стороны, проверьте setDataSource (контекст контекста, Uri uri, заголовки карт), который используется setDataSource (контекст контекста, Uri uri), он использует AssetFileDescriptor, ContentResolver из вашего контекста и openAssetFileDescriptor, чтобы открыть URI, который получает успех поскольку openAssetFileDescriptor() может открыть ваш файл ресурсов, и, наконец, результирующий fd используется для вызова переопределения setDataSource (FileDescriptor).
AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
fd = resolver.openAssetFileDescriptor(uri, "r");
// :
// :
// :
if (fd.getDeclaredLength() < 0) {
setDataSource(fd.getFileDescriptor());
} else {
setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
}
В заключение вы не можете использовать переопределение setDataSource (String), как использовать свой файл mp3 файла ресурса. Вместо этого, если вы хотите использовать строку для воспроизведения файла ресурсов, вы можете использовать статическую функцию MediaPlayer.create() с помощью getIdentifier(), как указано выше, или setDataSource (контекст, uri), как указано в обновлении №1.
Подробнее см. полный исходный код: Android MediaPlayer
Обновление # 3:
openFrameworks setDataSource (String):
Как я уже упоминал в комментариях ниже, openFrameworks использует asis для Android and Media Media Player. Если вы можете обратиться к строке №: 4,
import android.media.MediaPlayer;
и номер строки: 26, 27, 28 и 218
player = new MediaPlayer(); //26
player.setDataSource(fileName); //27
player.prepare(); //28
private MediaPlayer player; //218
Итак, если вы попытаетесь передать ardroid.resource//+ this.getPackageName() + "raw/test0" в setDataSource(), используя openFrameworks, вы все равно получите то же исключение, что и я объясняется в обновлении №2. Сказав это, я просто попробовал удачу в Google, чтобы удвоить то, что я говорю, и нашел эту ссылку openFrameworks, где один из основных разработчиков openFrameworks arturo говорит,
не знают точно, как работает MediaPlayer, но все в res/raw или bin/data копируются в /sdcard/cc.openframeworks.packagename
На основе этого комментария вы можете попробовать использовать скопированный путь в setDataSource(). Использование файла ресурсов в файле setDataSource (String) MediaPlayer невозможно, поскольку он не может принимать путь к файлу ресурсов. Обратите внимание, что я сказал, что "путь к файлу ресурсов" начинается со схемы android.resource//который на самом деле является местоположением банки (в пределах вашего apk), а не физическим местоположением. Локальный файл будет работать с setDataSource (String), который начинается со схемы file://.
Чтобы вы четко понимали, что вы пытаетесь сделать с файлом ресурсов, попробуйте выполнить этот ниже код и увидеть результат в logcat,
try{
Log.d("RESURI", this.getClass().getClassLoader().getResource("res/raw/test0").toURI().toString());
}
catch(Exception e) {
}
Вы получите результат как,
jar:file:/data/app/<packagename>/<apkname>.apk!/res/raw/test0
чтобы показать вам, что файл ресурсов, который вы пытаетесь получить, на самом деле не является файлом по физическому пути, а расположением jar (внутри apk), к которому вы не можете получить доступ, используя метод setDataSource (String). (Попробуйте использовать 7zip, чтобы извлечь файл apk, и вы увидите в нем res/raw/test0).
Надеюсь, что это поможет.
PS: Я знаю его длинный ответ, но я надеюсь, что это объяснит это подробно. Оставляя альтернативные решения в верхней части, если это может помочь другим.