Android MediaPlayer отлично работает в приложении Custom Audio Streaming до Android 2.1, но не в более высоких версиях

РЕДАКТИРОВАТЬ:

Android 2.2 MediaPlayer отлично работает с одним URL-адресом SHOUTcast, но не с другим

Мне нужно воспроизвести аудиофайлы с внешних URL-адресов (поток криков). В настоящее время аудиофайлы загружаются постепенно и воспроизводятся, как только мы получаем достаточно звука в локальном временном хранилище телефона. Я использую класс StreamingMediaPlayer .

Проверьте этот фрагмент кода:

private MediaPlayer createMediaPlayer(File mediaFile) throws IOException { MediaPlayer mPlayer = new MediaPlayer(); //example of mediaFile =/data/data/package/cache/playingMedia0.dat FileInputStream fis = new FileInputStream(mediaFile); mPlayer.setDataSource(fis.getFD()); mPlayer.prepare(); return mPlayer; } 

Текущее состояние:

1- Он отлично работает с Android 1.6 до 2.1, но не в более высоких версиях, таких как Android 2.2.

2- «mPlayer.setDataSource (fis.getFD ())» – это строка, которая выдает ошибку.

3- Ошибка «Невозможно создать медиаплеер»

Другое решение попыталось:

Я попробовал под альтернативным решением, но пока ничего не получилось.

Android 2.2 MediaPlayer отлично работает с одним URL-адресом SHOUTcast, но не с другим

Что я ищу?

Моя цель – иметь мир кода, который может работать на Android 2.1 и выше.

Этот вопрос также обсуждается здесь:

Непоследовательность 2.2. Поведение медиаплеера

2-й код Android для потокового разрыва потока криков в 2.2

3- Этот вопрос также обсуждается во множестве вопросов на этом сайте, но я нашел ответ не где.

4- markmail.org

Трассировка LogCat:

 Unable to to create media player Error copying buffered conent. java.lang.NullPointerException com.ms.iradio.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.java:251) com.ms.iradio.StreamingMediaPlayer.access$2(StreamingMediaPlayer.java:221) com.ms.iradio.StreamingMediaPlayer$2.run(StreamingMediaPlayer.java:204) android.os.Handler.handleCallback(Handler.java:587) android.os.Handler.dispatchMessage(Handler.java:92) android.os.Looper.loop(Looper.java:123) android.app.ActivityThread.main(ActivityThread.java:3683) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:507) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) dalvik.system.NativeStart.main(Native Method) 

Класс StreamingMediaPlayer использует метод двойной буферизации, чтобы обойти ограничения в версиях Android до 1.2. Все выпуски операционной системы Android включают MediaPlayer, который поддерживает потоковые медиа (1). Я бы рекомендовал это сделать, а не использовать этот метод двойной буферизации, чтобы обойти проблему.

Android OS 2.2 заменил старый код медиаплеера проигрывателем FrightCast, который, вероятно, по-другому действует в этом случае.

Номера строк в вашей трассировке стека не сопоставляются с файлом, к которому вы ссылаетесь, поэтому я предполагаю, что вы используете другую версию. Я собираюсь предположить, что это сообщение NullPointerException сообщается MediaPlayer но ни FileInputStream ни возвращенный FileDescriptor могут быть null .

(1) До версии 2.2 медиаплеер не распознал потоки ShoutCast с заголовком версии «ICY / 1.1» в ответе. Создав прокси-сервер, который заменяет его на «HTTP / 1.1», вы можете это решить. См. Класс StreamProxy для примера.

Проблема в том, что потоковая передача контента типа «аудио / aacp» напрямую не поддерживается. Некоторые библиотеки декодирования могут использоваться для воспроизведения «aacp», см. Решение ниже:

Freeware Advanced Audio (AAC) декодер для Android

Как использовать эту библиотеку?

Рассмотрите правовые вопросы при его использовании .

[T] он проект http://code.google.com/p/aacplayer-android/ лицензируется под лицензией GPL, поэтому вы можете создавать коммерческие приложения поверх него, но вам нужно заполнить GPL – в основном это означает публикацию Ваш код также. Если вы используете второй проект http://code.google.com/p/aacdecoder-android/ , то вам не нужно публиковать свой код (библиотека лицензируется под LGPL).

Я использую этот код и запускаю 2,2 в верхнюю версию для потоковой загрузки.

 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import android.content.Context; import android.media.MediaPlayer; import android.os.Environment; import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.TextView; public class StreamingMediaPlayer { private static final int INTIAL_KB_BUFFER = 96*10;//assume 96kbps*10secs/8bits per byte private TextView textStreamed; private ImageButton playButton; private ProgressBar progressBar; ProgressBar pb; int audiofiletime=0; private long mediaLengthInSeconds; private int totalKbRead = 0; int totalsize=0; int numread; int totalBytesRead = 0; private final Handler handler = new Handler(); private MediaPlayer mediaPlayer; private File downloadingMediaFile; private boolean isInterrupted; private Context context; private int counter = 0; public StreamingMediaPlayer(Context context,TextView textStreamed, ImageButton playButton, Button streamButton,ProgressBar progressBar,ProgressBar pb) { this.context = context; this.textStreamed = textStreamed; this.playButton = playButton; this.progressBar = progressBar; this.pb=pb; } /** * Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available. */ public void startStreaming(final String mediaUrl) throws IOException { //this.mediaLengthInSeconds = 100; Runnable r = new Runnable() { public void run() { try { downloadAudioIncrement(mediaUrl); } catch (IOException e) { Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e); return; } } }; new Thread(r).start(); } /** * Download the url stream to a temporary location and then call the setDataSource * for that local file */ @SuppressWarnings({ "resource", "unused" }) public void downloadAudioIncrement(String mediaUrl) throws IOException { URLConnection cn = new URL(mediaUrl).openConnection(); cn.connect(); InputStream stream = cn.getInputStream(); if (stream == null) { Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl); } ///////////////////save sdcard/////////////// File direct = new File(Environment.getExternalStorageDirectory()+"/punya"); if(!direct.exists()) { if(direct.mkdir()); //directory is created; } String[] files=mediaUrl.split("/"); String fileName=files[files.length-1]; fileName = fileName.replace(".m4a", ".rdo"); //create a new file, to save the downloaded file File file = new File(direct,fileName); @SuppressWarnings("resource") FileOutputStream fileOutput = new FileOutputStream(file); ///////////////////end///////////////// totalsize=cn.getContentLength(); //mediaLengthInKb = 10000; downloadingMediaFile = new File(context.getCacheDir(),fileName); if (downloadingMediaFile.exists()) { downloadingMediaFile.delete(); } FileOutputStream out = new FileOutputStream(downloadingMediaFile); byte buf[] = new byte[16384]; int incrementalBytesRead = 0; do { numread = stream.read(buf); if (numread <= 0) break; out.write(buf, 0, numread); fileOutput.write(buf, 0, numread); totalBytesRead += numread; incrementalBytesRead += numread; totalKbRead = totalBytesRead/1000; // pb.setMax(100); // pb.setProgress(totalKbRead); testMediaBuffer(); fireDataLoadUpdate(); } while (validateNotInterrupted()); stream.close(); if (validateNotInterrupted()) { fireDataFullyLoaded(); } } private boolean validateNotInterrupted() { if (isInterrupted) { if (mediaPlayer != null) { mediaPlayer.pause(); //mediaPlayer.release(); } return false; } else { return true; } } /** * Test whether we need to transfer buffered data to the MediaPlayer. * Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler. */ private void testMediaBuffer() { Runnable updater = new Runnable() { public void run() { if (mediaPlayer == null) { // Only create the MediaPlayer once we have the minimum buffered data if ( totalKbRead >= INTIAL_KB_BUFFER) { try { startMediaPlayer(); } catch (Exception e) { Log.e(getClass().getName(), "Error copying buffered conent.", e); } } } else if ( mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000 ){ // NOTE: The media player has stopped at the end so transfer any existing buffered data // We test for < 1second of data because the media player can stop when there is still // a few milliseconds of data left to play transferBufferToMediaPlayer(); } } }; handler.post(updater); } private void startMediaPlayer() { try { //File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a"); //moveFile(downloadingMediaFile,bufferedFile); // Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath()); // Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+""); mediaPlayer = createMediaPlayer(downloadingMediaFile); //mediaPlayer.start(); startPlayProgressUpdater(); //playButton.setEnabled(true); playButton.setVisibility(View.VISIBLE); } catch (IOException e) { Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e); return; } } private MediaPlayer createMediaPlayer(File mediaFile) throws IOException { MediaPlayer mPlayer = new MediaPlayer(); mPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp, int what, int extra) { Log.e(getClass().getName(), "Error in MediaPlayer: (" + what +") with extra (" +extra +")" ); return false; } }); FileInputStream fis = new FileInputStream(mediaFile); mPlayer.setDataSource(fis.getFD()); mPlayer.prepare(); return mPlayer; } /** * Transfer buffered data to the MediaPlayer. * NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so * this method should always be called using a Handler. */ private void transferBufferToMediaPlayer() { try { boolean wasPlaying = mediaPlayer.isPlaying(); int curPosition = mediaPlayer.getCurrentPosition(); File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".m4a"); File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a"); bufferedFile.deleteOnExit(); moveFile(downloadingMediaFile,bufferedFile); //mediaPlayer.pause(); mediaPlayer.release(); mediaPlayer = createMediaPlayer(bufferedFile); mediaPlayer.seekTo(curPosition); boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000; if (wasPlaying || atEndOfFile){ mediaPlayer.start(); } oldBufferedFile.delete(); }catch (Exception e) { Log.e(getClass().getName(), "Error updating to newly loaded content.", e); } } private void fireDataLoadUpdate() { Runnable updater = new Runnable() { public void run() { //float loadProgress = ((float)totalBytesRead/(float)mediaLengthInKb); //float per = ((float)numread/mediaLengthInKb) * 100; float per = ((float)totalBytesRead/totalsize) * 100; textStreamed.setText((totalKbRead + " Kb (" + (int)per + "%)")); progressBar.setSecondaryProgress((int)(per)); pb.setSecondaryProgress((int)(per)); } }; handler.post(updater); } private void fireDataFullyLoaded() { Runnable updater = new Runnable() { public void run() { transferBufferToMediaPlayer(); downloadingMediaFile.delete(); textStreamed.setText(("Download completed" )); } }; handler.post(updater); } public MediaPlayer getMediaPlayer() { return mediaPlayer; } public void startPlayProgressUpdater() { audiofiletime =mediaPlayer.getDuration(); float progress = (((float)mediaPlayer.getCurrentPosition()/ audiofiletime) * 100); progressBar.setProgress((int)(progress)); //pb.setProgress((int)(progress*100)); if (mediaPlayer.isPlaying()) { Runnable notification = new Runnable() { public void run() { startPlayProgressUpdater(); } }; handler.postDelayed(notification,1000); } } public void interrupt() { playButton.setEnabled(false); isInterrupted = true; validateNotInterrupted(); } /** * Move the file in oldLocation to newLocation. */ public void moveFile(File oldLocation, File newLocation) throws IOException { if ( oldLocation.exists( )) { BufferedInputStream reader = new BufferedInputStream( new FileInputStream(oldLocation) ); BufferedOutputStream writer = new BufferedOutputStream( new FileOutputStream(newLocation, false)); try { byte[] buff = new byte[5461]; int numChars; while ( (numChars = reader.read( buff, 0, buff.length ) ) != -1) { writer.write( buff, 0, numChars ); } } catch( IOException ex ) { throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath()); } finally { try { if ( reader != null ){ writer.close(); reader.close(); } } catch( IOException ex ){ Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); } } } else { throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); } } }