Можно ли использовать контент://как источник для элемента <audio> в WebView
Я создал ContentProvider. Он экспортирует файлы в моем каталоге assets/. Я использую content://urls для доступа к экспортированному контенту в WebView.
Следующий HTML работает как ожидалось:
<img src="content://<provider-name>/test.jpg">
Я пытаюсь использовать контент-провайдер для mp3-аудио файлов:
<div id='player'></div>
<script>
url = "content://<provider-name>/test.mp3";
var audio = document.createElement('audio');
audio.src = url;
audio.controls = "controls";
document.getElementById("player").appendChild(audio);
</script>
Я получаю следующее сообщение об ошибке.
E/MediaPlayer(24120): Unable to to create media player
E/HTML5Audio(24120): couldn't load the resource: content://.../test.mp3 exc: java.io.IOException: setDataSource failed.: status=0x80000000
Я пробовал Android SDK 8 и 10 без успеха. Я не вижу доступа к моему ContentProvider в журнале. Похоже, что доступ к содержимому из аудио-тегов невозможен в WebView. Кажется странным, поскольку следующий код работает так, как ожидалось:
MediaPlayer player = MediaPlayer.create(this,
Uri.parse("content://<provider-name>/test.mp3")
);
player.start();
Как воспроизводить аудиофайлы из ContentProvider в WebView?
Ответы
Ответ 1
Короткий ответ - нет, вы не можете использовать content://
в качестве источника для аудио-элемента.
Ошибка, которую вы получаете, исходит из метода HTML5Audio setDataSource
, который, если вы посмотрите на исходный код, вызывает MediaPlayer setDataSource
с помощью звуковой url. И если вы посмотрите документацию для класса MediaPlayer
, он поддерживает только пути к файлам и URL-адреса http/rtsp.
Я считаю, что лучше всего сохранить аудиоконтент в пути к файлу и использовать URL-адрес file:
для доступа к нему.
Однако, если я правильно помню, вам также потребуется сделать мир файлов доступным для того, чтобы код MediaPlayer
имел к нему доступ. Для этого требуется использовать частный android.os.FileUtils
класс с таким кодом:
void makeFileReadable(String filename) {
try {
Class fileUtils = Class.forName("android.os.FileUtils");
Method setPermissions = fileUtils.getMethod("setPermissions", String.class,
int.class, int.class, int.class);
setPermissions.invoke(fileUtils, filename, 0775, -1, -1);
}
catch (Exception ex) {
}
}
775
является эквивалентом rwxrwxr-x
, который может быть более разрешительным, чем необходимо, поэтому вы можете попробовать экспериментировать с менее разрешительными значениями. Также обратите внимание, что вам, скорее всего, нужно будет установить разрешения для каталога, содержащего этот файл, и этого родителя каталога и т.д. - а не только самого файла.
Ответ 2
Вот что я нашел полезным:
Только для пояснения, пути к файлу
Есть ли путь, похожий на файл:///android_asset/, который указывает на каталог приложений?
content:// - для уже экспортированного носителя на sdcard/
file:///android_asset - для элементов в папке assets/
Получение активов:
Вытягивание активов с помощью AssetManager
:
Как получить URI из файла активов?
Внесите звук из WebView
из активов программно с помощью MediaPlayer
:
Звук в веб-обозревателе
Android WebView воспроизводит аудио с помощью javascript
Использование HTML5:
Html Audio в Android Webview
Вот несколько методов, которые вы не пробовали. В последнее время я работал с alot WebViews
и JavaScript
, так что, возможно, один из этих других методов сделает трюк.
Привет,
Ответ 3
Вариант №1: Файл манифеста.
Убедитесь, что у вас есть правильное разрешение в файле манифеста:
<uses-permission android:name="android.permission.INTERNET" />
Вариант № 2: Плохой или поврежденный аудиофайл.
Проверьте, можете ли вы воспроизвести файл с помощью Android Media Player.
Вариант № 3: Разрешения на чтение
Возможно, файл на самом деле не читается игроком. В этом случае использование FileDescriptor должно работать. Я где-то читал (извините, не могу вспомнить, где), о каких-то проблемах с тем же исключением сообщалось с помощью setDataSource(FileDescriptor fd)
. Попытайтесь использовать setDataSource(FileDescriptor fd, long offset, long length)
, поскольку это, кажется, решает проблему.
Ответ 4
Мне удалось получить эту работу после большого ужаса.
По какой-то причине вызов вашего провайдера контента из webView (который использует MediaPlayer) для mp3 файла не вызывает openAssetFile, а вызывает openFile. (не уверен, что провайдер обрабатывает эту маршрутизацию). Эта проблема, по-видимому, была исправлена в 4.2 +
Решение для более старых версий, которые работали для меня, заключалось в том, чтобы переопределить openFile у вашего поставщика контента, таким образом:
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode){
//your asset reading code that works for other file types goes here.
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode){
try {
AssetFileDescriptor afd = openAssetFile(uri, mode);
return afd.getParcelFileDescriptor();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}