Android MediaPlayer在自定义audiostream媒体应用程序中工作正常,但不支持更高版本
编辑:
Android 2.2 MediaPlayer可以正常工作,只有一个SHOUTcast URL,但不能用另一个SHOUTcast URL
我需要从外部URL(shoutcaststream)播放audio文件。 目前,audio文件是逐步下载的,只要我们在手机本地临时存储中获得足够的audio,就会播放。 我正在使用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-错误是“无法创build媒体播放器”
其他解决scheme尝试
我尝试了下面的替代解决scheme,但没有任何工作到目
Android 2.2 MediaPlayer可以正常工作,只有一个SHOUTcast URL,但不能用另一个SHOUTcast URL
我在找什么?
我的目标是有一个Android 2.1及更高版本的代码的和平。
这个问题也在这里讨论:
1- 不一致的2.2媒体播放器行为
2.2 Androidstream媒体shoutcaststream的断点在2.2
3-这个问题也在这个网站上的很多问题讨论,但我find了答案没有在哪里。
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 OS的所有产品版本都包含支持stream媒体的MediaPlayer(1)。 我会build议这样做,而不是使用这种双缓冲技术来解决这个问题。
Android操作系统2.2取代旧的媒体播放器代码与FrightCast播放器可能在这种情况下行事不同。
您的堆栈跟踪中的行号不会映射到您链接的文件,所以我假定您使用的是不同的版本。 我将猜测, MediaPlayer
正在报告NullPointerException
,但是FileInputStream
和返回的FileDescriptor
都不能为null
。
(1)在版本2.2之前,媒体播放器在响应中将不识别具有“ICY / 1.1”版本标头的ShoutCaststream。 通过创build一个替代“HTTP / 1.1”的代理,你可以解决这个问题。 有关示例,请参阅StreamProxy类 。
问题是内容types“audio/ aacp”stream不直接支持。 有些解码库可以用来播放“aacp”,请看下面的解决scheme:
免费高级audio(AAC)解码器为Android
如何使用这个库?
考虑使用它的法律问题 。
他的项目http://code.google.com/p/aacplayer-android/使用GPL授权,因此您可以在其上创build商业应用,但您需要填写GPL,主要是发布你的代码也是如此。; 如果您使用第二个项目http://code.google.com/p/aacdecoder-android/ ,那么您不需要发布您的代码(该库在LGPL下许可)。
我正在使用这个代码,并运行2.2到上stream版本下载。
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() ); } } }
- java.lang.RuntimeException:无法在未调用Looper.prepare()的线程中创build处理程序;
- 在iOS中显示一条消息,其function与Android中的Toastfunction相同
- BuildConfig未正确创build(Gradle Android)
- Dagger2依赖 – Gradle
- 删除linearlayout内的所有项目
- 在AppCompat-v7中的操作栏/工具栏中显示图标21
- Android Studio需要用于Android-L mac的JDK 7
- 找不到Library.apk!
- SpinnerAdapter中的getView和getDropDownView之间的区别