⑴ 安卓開發中,使用surfaceView和Mediaplay播發視頻為什麼會失敗,模擬器上播放不了求大神解救,錯在哪
模擬器不能使用播放不能代表什麼,也可以是模擬器的配置問題,不一定就是代碼的問題,你先找一個手機試一下,手機可以運行那就沒什麼問題,如果不行再去定位問題,如果這樣一味調試下去的話,只能是浪費時間
⑵ android soundpool能不能在除了activity之外的類中使用
在開發android軟體中,經常需要播放多媒體音頻文件,通常會採用MediaPlayer類來執行此類操作。但MediaPlayer類佔用的資源比較多,對於游戲等應用而言,會帶來性能上的降低。在Android中,專門提供了SoundPool類來執行此類音頻播放,SoundPool類佔用的CPU資源較少、反應較快。
SoundPool使用MediaPlaybackService將音頻流解碼為16位的PCM單聲道或者立體聲流。這有利於減小解碼造成的應用延遲。
SoundPool的常用方法包括:
load() //載入音頻文件
pause() //暫停
play() //播放
resume() //恢復
setLoop() //設置循環模式
setOnLoadCompleteListener() //設置監聽器
setVolume() //設置音量
setRate() //設置播放速率
SoundPool類和其他音頻播放類相比,可以自行設置音頻播放時的品質、音量、播放速率等。並且它可以管理多個音頻流,每個流均擁有自己獨立的ID,對單個音頻流的管理均是通過其ID來進行的。SoundPool類適用的場景包括應用程序中的聲效(按鍵提示音、消息等)、游戲中密集而短暫的聲音(如多個飛船同時爆炸)。
SoundPool類的使用方法如下:
代碼10-5 SoundPool播放音頻的一般過程
int srcQuality=100;
int waitMsec=1000;
float leftVolume=SILENT;
float rightVolume=LOUD;
int priority=1;
int loop=0;
float rate=1f;
SoundPool mSoundPool=new SoundPool(SOUNDPOOL_STREAMS, AudioManager.STREAM_MUSIC, srcQuality);
int sampleId1=mSoundPool.load(mContext, SOUND_A, PRIORITY);
int streamID=mSoundPool.play(sampleID, leftVolume, rightVolume, priority, loop, rate);
……
⑶ 怎樣監聽android的mediaplay播放網路音樂時,每一次的緩沖以及每一次緩沖結束
isplaying和!isplaying不行嗎?
⑷ android.media.AsyncPlayer這個類應該怎麼用
代碼結構:
Open Core 的代碼在Android 代碼的 External/Opencore 目錄中 。這個目錄是OpenCore
的根目錄,其中包含的子目錄如下所示 :
android :這裡面是一個上層的庫,它實現了一個為Android 使用的音視頻採集,播放的介面,和DRM 數字版權管理的介面實現。
baselibs :包含數據結構和線程安全等內容的底層庫
codecs_v2 :音視頻的編解碼器,基於 OpenMAX 實現
engines :核心部分 ,多媒體 引擎的實現
extern_libs_v2 :包含了 khronos 的 OpenMAX 的頭文件
fileformats :文件格式的解析( parser )工具
nodes :提供一些PVMF 的NODE ,主要是編解碼和文件解析方面的。
oscl :操作系統兼容庫
pvmi : 輸入輸出控制的抽象介面
protocols :主要是與網路相關的 RTSP 、 RTP 、 HTTP 等協議 的相關內容
pvcommon : pvcommon 庫文件的 Android.mk 文件,沒有源文件。
pvplayer : pvplayer 庫文件的 Android.mk 文件,沒有源文件。
pvauthor : pvauthor 庫文件的 Android.mk 文件,沒有源文件。
tools_v2 :編譯工具以及一些可注冊的模塊。
本文主要介紹Android MediaPlayer的架構,主要由OpenCore 里的PV Player來實現的。
1.概述
Android的MediaPlayer包含了Audio和Video的播放功能,Music和Video兩個應用程序都是調用MediaPlayer實現的。
代碼主要分布在以下的目錄中:
java程序的路徑:
packages/apps/Music/src/com/android/music/
JAVA類的路徑:
frameworks/base/media/java/android/media/MediaPlayer.java
JAVA本地調用部分(JNI):
frameworks/base/media/jni/android_media_MediaPlayer.cpp
編譯為 libmedia_jni.so
頭文件:
frameworks/base/include/media/
多媒體庫:
frameworks/base/media/libmedia/
編譯為 libmedia.so
多媒體服務:
frameworks/base/media/libmediaplayerservice/
編譯為 libmediaplayerservice.so
具體實現:
external/opencore/
編譯為 libopencoreplayer.so
libopencoreplayer.so是主要的實現部分,其他的庫基本上都是在其上建立的封裝和為建立進程間通訊的機制。
2.框架
運行的時候,大致可以分成Client和Server兩個部分,分別在兩個進程中運行,使用Binder機制實現IPC通訊。從框架結構上來看,IMediaPlayerService.h、IMediaPlayerClient.h和MediaPlayer.h三個類定義了MeidaPlayer的介面和架構,MediaPlayerService.cpp和mediaplayer.cpp兩個文件用於MeidaPlayer架構的實現,MeidaPlayer的具體功能在PVPlayer(庫libopencoreplayer.so)中的實現。
2.1 IMediaPlayerClient.h
描述一個MediaPlayer客戶端的介面
class IMediaPlayerClient: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerClient);
virtual void notify(int msg, int ext1, int ext2) = 0;
};
class BnMediaPlayerClient: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在定義中,IMediaPlayerClient類繼承IInterface,並定義了一個MediaPlayer客戶端的介面,BnMediaPlayerClient繼承了BnInterface,這是為基於Android的基礎類Binder機制實現在進程通訊而構建的。事實上,根據BnInterface類模版的定義,BnInterface類相當於雙繼承了BnInterface和ImediaPlayerClient,這是Android一種常用的定義方式。
2.2 mediaplayer.h
對外的介面類,它最主要是定義了一個MediaPlayer類:
class MediaPlayer : public BnMediaPlayerClient
{
public:
MediaPlayer();
~MediaPlayer();
void onFirstRef();
void disconnect();
status_t setDataSource(const char *url);
status_t setDataSource(int fd, int64_t offset, int64_t length);
status_t setVideoSurface(const sp& surface);
status_t setListener(const sp& listener);
status_t prepare();
status_t prepareAsync();
status_t start();
status_t stop();
status_t pause();
bool isPlaying();
status_t getVideoWidth(int *w);
status_t getVideoHeight(int *h);
status_t seekTo(int msec);
status_t getCurrentPosition(int *msec);
status_t getDuration(int *msec);
status_t reset();
status_t setAudioStreamType(int type);
status_t setLooping(int loop);
status_t setVolume(float leftVolume, float rightVolume);
void notify(int msg, int ext1, int ext2);
static sp decode(const char* url, uint32_t *pSampleRate, int*
pNumChannels);
static sp decode(int fd, int64_t offset, int64_t length, uint32_t
*pSampleRate, int* pNumChannels);
//……
}
從介面中可以看出MediaPlayer類剛好實現了一個MediaPlayer的基本操作,例如播放(start)、停止(stop)、暫停(pause)等。
另外的一個類DeathNotifier在MediaPlayer類中定義,它繼承了IBinder類中的DeathRecipient類:
class DeathNotifier: public IBinder:: DeathRecipient
{
public:
DeathNotifier() {}
virtual ~DeathNotifier();
virtual void binderDied(const wp& who);
};
事實上,MediaPlayer類正是間接地繼承了IBinder,而MediaPlayer:: DeathNotifier類繼承了IBinder::
DeathRecipient,這都是為了實現進程間通訊而構建的。
2.3 IMediaPlayer.h
主要的的內容是一個實現MediaPlayer功能的介面:
class IMediaPlayer: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayer);
virtual void disconnect() = 0;
virtual status_t setVideoSurface(const sp& surface) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual status_t isPlaying(bool* state) = 0;
virtual status_t getVideoSize(int* w, int* h) = 0;
virtual status_t seekTo(int msec) = 0;
virtual status_t getCurrentPosition(int* msec) = 0;
virtual status_t getDuration(int* msec) = 0;
virtual status_t reset() = 0;
virtual status_t setAudioStreamType(int type) = 0;
virtual status_t setLooping(int loop) = 0;
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
};
class BnMediaPlayer: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在IMediaPlayer類中,主要定義MediaPlayer的功能介面,這個類必須被繼承才能夠使用。值得注意的是,這些介面和MediaPlayer類的介面有些類似,但是它們並沒有直接的關系。事實上,在MediaPlayer類的各種實現中,一般都會通過調用IMediaPlayer類的實現類來完成。
2.4 頭文件IMediaPlayerService.h
描述一個MediaPlayer的服務,定義方式如下所示:
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
virtual sp create(pid_t pid, const
sp& client, const char* url) = 0;
virtual sp create(pid_t pid, const
sp& client, int fd, int64_t offset, int64_t length) =
0;
virtual sp decode(const char* url, uint32_t *pSampleRate, int*
pNumChannels) = 0;
virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t
*pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
由於有純虛函數,IMediaPlayerService
以及BnMediaPlayerService必須被繼承實現才能夠使用,在IMediaPlayerService定義的create和decode等介面,事實上是必須被繼承者實現的內容。注意,create的返回值的類型是sp,這個IMediaPlayer正是提供實現功能的介面。
3 實現
3.1 App
在packages/apps/Music/src/com/android/music/里的MediaPlaybackService.java文件中,包含了對MediaPlayer的調用。
在MediaPlaybackService.java中包含對包的引用:
import android.media.MediaPlayer;
在MediaPlaybackService類的內部,定義了MultiPlayer類:
private class MultiPlayer {
private MediaPlayer mMediaPlayer = new MediaPlayer();
}
MultiPlayer類中使用了MediaPlayer類,其中有一些對這個MediaPlayer的調用,調用的過程如下所示:
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
reset,setDataSource和setAudioStreamType等介面就是通過JAVA本地調用(JNI)來實現的。
3.2 Jni
在frameworks/base/media/jni/android_media_MediaPlayer.cpp中實現,其中android_media_MediaPlayer_reset函數的實現如下所示:
static void android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
{
sp mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
}
先獲取一個MediaPlayer指針,通過對它的調用來實現實際的功能。
register_android_media_MediaPlayer用於將gMethods注冊為的類"android/media/MediaPlayer",其實現如下所示。
static int register_android_media_MediaPlayer(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer");
// ......
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
"android/media/MediaPlayer"對應JAVA的類android.media.MediaPlayer。
3.3 libmedia.so
frameworks/base/media/libmedia/mediaplayer.cpp文件實現mediaplayer.h提供的介面,其中一個重要的片段如下所示:
const sp& MediaPlayer::getMediaPlayerService()
{
Mutex::Autolock _l(mServiceLock);
if (mMediaPlayerService.get() == 0) {
sp sm = defaultServiceManager();
sp binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0)
break;
LOGW("MediaPlayerService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (mDeathNotifier == NULL) {
mDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(mDeathNotifier);
mMediaPlayerService = interface_cast(binder);
}
LOGE_IF(mMediaPlayerService==0, "no MediaPlayerService!?");
return mMediaPlayerService;
}
其中最重要的一點是binder =
sm->getService(String16("media.player"));這個調用用來得到一個名稱為"media.player"的服務,這個調用返回值的類型為IBinder,根據實現將其轉換成類型IMediaPlayerService使用。
一個具體的函數setDataSource如下所示:
status_t MediaPlayer::setDataSource(const char *url)
{
LOGV("setDataSource(%s)", url);
status_t err = UNKNOWN_ERROR;
if (url != NULL) {
const sp& service(getMediaPlayerService());
if (service != 0) {
sp player(service->create(getpid(), this, url));
err = setDataSource(player);
}
}
return err;
}
⑸ android里音樂沒播放怎麼也調用setoncompletionlistener
1.對於控制研究媒體播放器,通過本地服務打,不如送媒體播放器參考其他類一樣CarefulMediaPlayer(MP,這一點);你在處理此類播放器的屬性。我認為它幫助你。 謝謝
2.我為這個問題掙扎,最後我得到了它的工作班以下。這個想法是一個線程與活套,剩下活著,並處理所有的MediaPlayer的邏輯。 我只退出尺蠖和清理線程,如果服務接收到的明確
{
privatestaticPowerManager.WakeLockwakeLock;
privatestaticfinalStringTAG="PlayService";
privatestaticStringLOCK_NAME=TAG;
publicstaticfinalStringEXTRA_FILE="file";
publicstaticfinalStringACTION_PLAY="play";
_STOP="stop";
publicstaticfinalintMSG_START=1;
publicstaticfinalintMSG_STOP=2;
publicPlayService(Stringname){
super(name);
}
publicPlayService(){
super("PlayService");
}
@Override
publicvoidonCreate(){
super.onCreate();
}
@Override
protectedvoidonHandleIntent(Intentintent){
Messagemsg=newMessage();
if(ACTION_PLAY.equalsIgnoreCase(intent.getAction())){
StringfileName=intent.getExtras().getString(EXTRA_FILE);
msg.what=MSG_START;
msg.obj=fileName;
}elseif(ACTION_STOP.equalsIgnoreCase(intent.getAction())){
msg.what=MSG_STOP;
}
try{
PlayMediaThread.getInstance(this).sendMessage(msg);
}catch(InterruptedExceptione){
Log.e(TAG,e.getMessage());
}
}
publicstaticPowerManager.WakeLockacquireLock(Contextcontext){
if(wakeLock==null||!wakeLock.isHeld()){
PowerManagerpowerManager=(PowerManager)context
.getSystemService(Context.POWER_SERVICE);
wakeLock=powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
LOCK_NAME);
wakeLock.setReferenceCounted(true);
wakeLock.acquire();
}
returnwakeLock;
}
publicstaticvoidreleaseLock(Contextcontext){
if(wakeLock!=null&&wakeLock.isHeld()){
wakeLock.release();
}
}
}
,
OnErrorListener,OnPreparedListener{
=newSemaphore(0);
privatestaticHandlerhandler;
privatestaticLoopermyLooper;
privatestaticContextcontext;
;
;
;
privatestaticfinalStringTAG="PlayMediaThread";
privatePlayMediaThread(Contextcontext)throwsInterruptedException{
super(TAG);
PlayMediaThread.context=context;
start();
//
//instance
semaphore.acquire();
}
(Contextcontext)
throwsInterruptedException{
if(instance==null){
instance=newPlayMediaThread(context);
}
PlayMediaThread.context=context;
returninstance;
}
publicvoidsendMessage(Messagemsg){
handler.sendMessage(msg);
}
publicvoidquitLooper(){
try{
if(myLooper!=null){
myLooper.quit();
Log.i(TAG,"Afterquit");
}
}catch(Exceptionex){
Log.e(TAG,ex.getMessage());
}
}
@Override
publicvoidrun(){
Looper.prepare();
myLooper=Looper.myLooper();
handler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==PlayService.MSG_START){
startPlayer((String)msg.obj);
}elseif(msg.what==PlayService.MSG_STOP){
//.e.user
//explicitlyclickedstop,Iquitthelooperand
//cleanthethread
stopPlayer(true);
}
}
};
semaphore.release();
Log.i(TAG,"BeforeLoop");
Looper.loop();
}
privatevoidstopPlayer(booleanclean){
if(player!=null){
if(player.isPlaying()){
player.stop();
}
player.release();
player=null;
}
if(clean){
PlayService.releaseLock(context);
quitLooper();
instance=null;
}
}
privatevoidstartPlayer(StringfileName){
if(player!=null&&player.isPlaying()&¤tFileName!=null
&¤tFileName.equalsIgnoreCase(fileName)){
return;
}
currentFileName=fileName;
stopPlayer(false);
player=newMediaPlayer();
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
player.setOnPreparedListener(this);
try{
player.setDataSource(context,Uri.parse(currentFileName));
player.prepare();
player.start();
PlayService.acquireLock(context);
}catch(Exceptione){
Log.e(TAG,e.getMessage());
}
}
@Override
publicbooleanonError(MediaPlayermp,intarg1,intarg2){
Log.e(TAG,"onError");
stopPlayer(true);
returnfalse;
}
@Override
publicvoidonCompletion(MediaPlayermp){
Log.d(TAG,"onCompletion");
//
stopPlayer(true);
}
@Override
publicvoidonPrepared(MediaPlayermp){
Log.d(TAG,"onPrepared");
}
}
⑹ android mediaplay 怎麼播放 rtsp /http 流媒體
但是網路電台的連接就是沒有擴展名的,在PC 上的media play 都可以播放的
⑺ android MediaPlayer setDataSource( String path )報錯
這是java的異常處理;這行代碼會產生異常,而在這里你沒有對異常處理,所以系統提示你「Unhandled exception」;解決方法如下:
第一種:使用try-catch捕獲該異常:
try{
ar.set~~~~~~~~~~~~~~;
}catch(Exception e){
e.printStackTrace();
}
第二種:在方法定義時 throws 該異常 public void play throws Exception(){。。。}