摘要: 客户端进程需要实现,其中notify方法需要service跨进程调用,通知客户端播放消息 IMediaPlayerClient.aidlpackagecom.example.demo;importcom.example.demo.ParcelableParcel;interfaceIMediaPlayerClient{ voidnotify(intmsg,intext1,intext2
客户端进程需要实现,其中notify方法需要service 跨进程调用,通知客户端播放消息
IMediaPlayerClient.aidl
package com.example.demo;
import com.example.demo.ParcelableParcel;
interface IMediaPlayerClient {
void notify(int msg, int ext1, int ext2, in ParcelableParcel obj);
}
public class MediaPlayerClientBn extends IMediaPlayerClient.Stub implements
IMediaDeathNotifier {
// 其中重要的方法
public void init() {
this.mLock = new ReentrantLock();
this.mNotifyLock = new ReentrantLock();
this.mSignal = this.mLock.newCondition();
mPlayer = null;
mListener = null;
mCookie = null;
mStreamType = 3 /* TODO AUDIO_STREAM_MUSIC */;
mAudioAttributesParcel = null;
mCurrentPosition = -1;
mSeekPosition = -1;
mCurrentState = MEDIA_PLAYER_IDLE;
mPrepareSync = false;
mPrepareStatus = MediaErrorsNum.NO_ERROR;
mLoop = false;
mLeftVolume = mRightVolume = 1.0f;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
mAudioSessionId = 0;
/*
* TODO mAudioSessionId = AudioSystem::newAudioUniqueId();
* AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
*/
mSendLevel = 0;
mRetransmitEndpointValid = false;
}
int attachNewPlayer(IMediaPlayer player) {
Log.i(LOG_TAG, "attachNewPlayer");
int err = MediaErrorsNum.UNKNOWN_ERROR;
IMediaPlayer p;
{ // scope for the lock
mLock.lock();
if (( 0 == (mCurrentState & MEDIA_PLAYER_IDLE)) || (mCurrentState == MEDIA_PLAYER_STATE_ERROR)) {
Log.e(LOG_TAG, "attachNewPlayer called in state = "
+ mCurrentState);
return MediaErrorsNum.INVALID_OPERATION;
}
clear_l();
p = mPlayer;
mPlayer = player;
Log.i(LOG_TAG, "mPlayer is "+mPlayer.toString());
if (player != null) {
mCurrentState = MEDIA_PLAYER_INITIALIZED;
err = MediaErrorsNum.NO_ERROR;
} else {
Log.e(LOG_TAG, "Unable to create media player");
}
mLock.unlock();
}
if (p != null) {
try {
p.disconnect();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return err;
}
//获得getRemoteMediaPlayerServiceInstance,创建IMediaPlayer,并且使得
IMediaPlayer 和IMediaPlayerClient 实例一一对应,互相引用。 并且用MediaDeathNotifier
通知service 的生命周期。
public int setDataSource(final IMediaHTTPService httpService, String url,
final HashMap
mAudioSessionId ++;
int err = MediaErrorsNum.BAD_VALUE;
Log.i(LOG_TAG, "setDataSource(" + url + ")");
try {
if (url != null) {
IMyMediaPlayerService service;
/* service = MediaDeathNotifier.getMediaPlayerService();*/
service = MediaPlayer_Surface_iadl_MultThread_TestBase.getRemoteMediaPlayerServiceInstance();
if (service != null) {
IMediaPlayer player = (service
.create(this, mAudioSessionId));
if ((MediaErrorsNum.NO_ERROR != doSetRetransmitEndpoint(player))
|| (MediaErrorsNum.NO_ERROR != player
.setDataSource(httpService, url, null/* TODO */))) {
player = null;
}
err = attachNewPlayer(player);
}
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return err;
}
//prepare
public int prepare() {
Log.i(LOG_TAG, "prepare()");
mLock.lock();
mLockThreadId = (int) Thread.currentThread().getId();
if (mPrepareSync) {
mLockThreadId = 0;
return MediaErrorsNum.EALREADY;
}
mPrepareSync = true;
int ret = MediaErrorsNum.NO_ERROR;
try {
ret = prepareAsync_l();
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (ret != MediaErrorsNum.NO_ERROR) {
mLockThreadId = 0;
return ret;
}
if (mPrepareSync) {
try {
mSignal.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // wait for prepare done
mPrepareSync = false;
}
Log.i(LOG_TAG, "prepare complete - status= " + mPrepareStatus);
mLockThreadId = 0;
mLock.unlock();
return mPrepareStatus;
}
private int prepareAsync_l() throws RemoteException {
if ((mPlayer != null)&& (mCurrentState & (MediaPlayerClientBn.MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED)) != 0) {
Log.i(LOG_TAG,"mCurrentState is MEDIA_PLAYER_INITIALIZED or MEDIA_PLAYER_STOPPED");
if (mAudioAttributesParcel != null) {
mPlayer.setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES,
ParcelableParcel.CREATOR
.createFromParcel(mAudioAttributesParcel));
} else {
mPlayer.setAudioStreamType(mStreamType);
}
mCurrentState = MEDIA_PLAYER_PREPARING;
return mPlayer.prepareAsync();
}
Log.i(LOG_TAG, "prepareAsync called in state = " + mCurrentState);
return MediaErrorsNum.INVALID_OPERATION;
}
// start play
public int start() {
Log.i(LOG_TAG, "start()");
int ret = MediaErrorsNum.NO_ERROR;
mLock.lock();
mLockThreadId = Thread.currentThread().getId();
if ((mCurrentState & MEDIA_PLAYER_STARTED) == 1) {
ret = MediaErrorsNum.NO_ERROR;
} else if ((mPlayer != null)&& ((mCurrentState & (MEDIA_PLAYER_PREPARED| MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED)) != 0)) {
try {
mPlayer.setLooping(mLoop);
mPlayer.setVolume(mLeftVolume, mRightVolume);
mPlayer.setAuxEffectSendLevel(mSendLevel);
mCurrentState = MEDIA_PLAYER_STARTED;
ret = mPlayer.start();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (ret != MediaErrorsNum.NO_ERROR) {
mCurrentState = MEDIA_PLAYER_STATE_ERROR;
} else {
if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
Log.i(LOG_TAG,
"playback completed immediately following start()");
}
}
} else {
Log.e(LOG_TAG, "start called in state " + mCurrentState);
ret = MediaErrorsNum.INVALID_OPERATION;
}
mLockThreadId = 0;
mLock.unlock();
return ret;
}
// 消息传递
@Override
public void notify(int msg, int ext1, int ext2, ParcelableParcel obj)
throws RemoteException {
// TODO Auto-generated method stub
Log.i(LOG_TAG,"message received msg=%d, ext1=%d, ext2=%d"+msg+":"+ext1+":"+ ext2);
boolean send = true;
boolean locked = false;
// TODO: In the future, we might be on the same thread if the app is
// running in the same process as the media server. In that case,
// this will deadlock.
//
// The threadId hack below works around this for the care of prepare,
// seekTo and start within the same process.
// FIXME: Remember, this is a hack, it's not even a hack that is applied
// consistently for all use-cases, this needs to be revisited.
if (mLockThreadId != Thread.currentThread().getId()) {
mLock.lock();
locked = true;
}
// Allows calls from JNI in idle state to notify errors
if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == null) {
Log.i(LOG_TAG,"notify(%d, %d, %d) callback on disconnected mediaplayer :"+msg+":"+ext1+":"+ext2);
if (locked) mLock.unlock(); // release the lock when done.
return;
}
switch (msg) {
case MEDIA_NOP: // interface test message
break;
case MEDIA_PREPARED:
Log.i(LOG_TAG,"prepared");
mCurrentState = MEDIA_PLAYER_PREPARED;
if (mPrepareSync) {
Log.i(LOG_TAG,"signal application thread");
mPrepareSync = false;
mPrepareStatus = MediaErrorsNum.NO_ERROR;
mSignal.signal();
}
break;
case MEDIA_PLAYBACK_COMPLETE:
Log.i(LOG_TAG,"playback complete");
if (mCurrentState == MEDIA_PLAYER_IDLE) {
Log.e(LOG_TAG,"playback complete in idle state");
}
if (!mLoop) {
mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
}
break;
case MEDIA_ERROR:
// Always log errors.
// ext1: Media framework error code.
// ext2: Implementation dependant error code.
Log.e(LOG_TAG,"error (%d, %d)"+":"+ext1+":"+ ext2);
mCurrentState = MEDIA_PLAYER_STATE_ERROR;
if (mPrepareSync)
{
Log.i(LOG_TAG,"signal application thread");
mPrepareSync = false;
mPrepareStatus = ext1;
mSignal.signal();
send = false;
}
break;
case MEDIA_INFO:
// ext1: Media framework error code.
// ext2: Implementation dependant error code.
if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Log.w(LOG_TAG,"info/warning (%d, %d)"+":"+ext1+":"+ ext2);
}
break;
case MEDIA_SEEK_COMPLETE:
Log.i(LOG_TAG,"Received seek complete");
if (mSeekPosition != mCurrentPosition) {
Log.i(LOG_TAG,"Executing queued seekTo(%d) "+mSeekPosition);
mSeekPosition = -1;
seekTo_l(mCurrentPosition);
}
else {
Log.i(LOG_TAG,"All seeks complete - return to regularly scheduled program");
mCurrentPosition = mSeekPosition = -1;
}
break;
case MEDIA_BUFFERING_UPDATE:
Log.i(LOG_TAG,"buffering %d"+ ext1);
break;
case MEDIA_SET_VIDEO_SIZE:
Log.i(LOG_TAG,"New video size %d x %d"+":"+ext1+":"+ ext2);
mVideoWidth = ext1;
mVideoHeight = ext2;
break;
case MEDIA_TIMED_TEXT:
Log.i(LOG_TAG,"Received timed text message");
break;
case MEDIA_SUBTITLE_DATA:
Log.i(LOG_TAG,"Received subtitle data message");
break;
case MEDIA_META_DATA:
Log.i(LOG_TAG,"Received timed metadata message");
break;
default:
Log.i(LOG_TAG,"unrecognized message: (%d, %d, %d) :"+ msg+":"+ext1+":"+ ext2);
break;
}
MediaPlayerListener listener = mListener;
if (locked) mLock.unlock();
// this prevents re-entrant calls into client code
if ((listener != null) && send) {
mNotifyLock.lock();
Log.i(LOG_TAG,"callback application");
listener.notify(msg, ext1, ext2, null == obj?null:obj.getParcel());
mNotifyLock.unlock();
}
}
}
IMyMediaPlayerService.aidl
package com.example.demo;
import com.example.demo.IMediaPlayer;
import com.example.demo.IMediaPlayerClient;
import com.example.demo.IOMX;
import com.example.demo.ICrypto;
import com.example.demo.IDrm;
import com.example.demo.IHDCP;
import com.example.demo.IMediaCodecList;
import android.view.Surface;
interface IMyMediaPlayerService {
IMediaPlayer create(in IMediaPlayerClient client, int audioSessionId);
IOMX getOMX();
ICrypto makeCrypto();
IDrm makeDrm();
IHDCP makeHDCP( boolean createEncryptionModule);
IMediaCodecList getCodecList();
}
public class MyMediaPlayerService extends Service {
private static final String LOG_TAG = MyMediaPlayerService.class.getName()
+ "";
public static void instantiate() {
Log.i(LOG_TAG, "instantiate call");
}
// For battery usage tracking purpose
class BatteryUsageInfo {
// how many streams are being played by one UID
int refCount;
// a temp variable to store the duration(ms) of audio codecs
// when we start a audio codec, we minus the system time from
// audioLastTime
// when we pause it, we add the system time back to the audioLastTime
// so after the pause, audioLastTime = pause time - start time
// if multiple audio streams are played (or recorded), then
// audioLastTime
// = the total playing time of all the streams
int audioLastTime;
// when all the audio streams are being paused, we assign audioLastTime
// to
// this variable, so this value could be provided to the battery app
// in the next pullBatteryData call
int audioTotalTime;
int videoLastTime;
int videoTotalTime;
};
HashMap
private static final int SPEAKER = 0;
private static final int OTHER_AUDIO_DEVICE = 1;
private static final int SPEAKER_AND_OTHER = 2;
private static final int NUM_AUDIO_DEVICES = 3;
// ////////////////////////////////////////////////////////////////////////////////////////////
ReentrantLock mLock = new ReentrantLock();
Vector
int mNextConnId = 0;
AtomicInteger tmp = new AtomicInteger(mNextConnId);
IOMX mOMX;
ICrypto mCrypto;
@SuppressLint("NewApi")
private final IMyMediaPlayerService.Stub mBinder = new IMyMediaPlayerService.Stub() {
// 创建与IMediaPlayerClient相对的IMediaPlayer,互粉并加入一个软引用向量管理对应关系。
@Override
public IMediaPlayer create(IMediaPlayerClient client, int audioSessionId)
throws RemoteException {
// TODO Auto-generated method stub
long pid = Binder.getCallingPid();
int connId = tmp.getAndIncrement();
MediaPlayerBn c = new MediaPlayerBn(MyMediaPlayerService.this, pid,
connId, client, audioSessionId, Binder.getCallingUid());
Log.i(LOG_TAG, "Create new client("+connId+") from pid "+pid+", uid "+getCallingUid()+", ");
SoftReference
{
mLock.lock();
mClients.add(w);
mLock.unlock();
}
return c;
}
}
}
IMediaPlayer.aidl:
package com.example.demo;
import android.view.Surface;
import com.example.demo.IMediaHTTPService;
import com.example.demo.AudioPlaybackRate;
import com.example.demo.AVSyncSettings;
import com.example.demo.ParcelableParcel;
import android.os.Messenger;
interface IMediaPlayer {
//void playLoadedVideo_iadl(in Surface surface);
void disconnect();
int setDataSource(in IMediaHTTPService httpService, String url, String header /*HashMap
//int setDataSource(int fd, long offset, long length);
//int setDataSource(in IStreamSource source);
//int setDataSource(in IDataSource source);
int setVideoSurfaceTexture(in Surface surface);
int prepareAsync();
int start();
int stop();
int pause();
int isPlaying(boolean state);
int setPlaybackSettings(in AudioPlaybackRate rate);
int getPlaybackSettings(in AudioPlaybackRate rate /* nonnull */);
int setSyncSettings(in AVSyncSettings sync, float videoFpsHint);
int getSyncSettings(in AVSyncSettings sync /* nonnull */, float videoFps /* nonnull */);
int seekTo(int msec) ;
int getCurrentPosition(int msec);
int getDuration(int msec);
int reset();
/*typedef enum {
AUDIO_STREAM_DEFAULT = -1,
AUDIO_STREAM_MIN = 0,
AUDIO_STREAM_VOICE_CALL = 0,
AUDIO_STREAM_SYSTEM = 1,
AUDIO_STREAM_RING = 2,
AUDIO_STREAM_MUSIC = 3,
AUDIO_STREAM_ALARM = 4,
AUDIO_STREAM_NOTIFICATION = 5,
AUDIO_STREAM_BLUETOOTH_SCO = 6,
AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
AUDIO_STREAM_BOOT = 10,
AUDIO_STREAM_VIBSPK = 11,
AUDIO_STREAM_ACCESSIBILITY = 12,
AUDIO_STREAM_REROUTING = 13,
AUDIO_STREAM_PATCH = 14,
AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_VIBSPK + 1,
AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;*/
int setAudioStreamType(/*audio_stream_type_t type*/int type);
int setLooping(boolean loop) ;
int setVolume(float leftVolume, float rightVolume) ;
int setAuxEffectSendLevel(float level);
int attachAuxEffect(int effectId) ;
int setParameter(int key,in ParcelableParcel request);
int getParameter(int key,in ParcelableParcel reply);
int setRetransmitEndpoint0(String endpoint /*const struct sockaddr_in* endpoint*/);
int getRetransmitEndpoint1(String endpoint /*struct sockaddr_in* endpoint*/);
int setNextPlayer(in IMediaPlayer next);
int setMetadataFilter(in ParcelableParcel filter);
int getMetadata(boolean update_only, boolean apply_filter,in ParcelableParcel metadata);
}
package com.example.demo;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.concurrent.locks.ReentrantLock;
import android.annotation.SuppressLint;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Binder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
@SuppressLint("NewApi")
public class MediaPlayerBn extends IMediaPlayer.Stub {
private static final String LOG_TAG = MediaPlayerBn.class.getName();
private static final int NO_INIT = 0;
private static final int AUDIO_ATTRIBUTES_TAGS_MAX_SIZE = 64/* TODO */;
class audio_attributes_t {
/*
* TODO audio_content_type_t content_type; audio_usage_t usage;
* audio_source_t source; audio_flags_mask_t flags; char
* tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; UTF8
*/
};
ReentrantLock mLock;
/* MediaPlayerBase mPlayer; */
MediaPlayer mPlayer;
MyMediaPlayerService mService;
IMediaPlayerClient mClient;
AudioOutput mAudioOutput;
int mPid;
int mStatus;
boolean mLoop;
int mConnId;
int mAudioSessionId;
audio_attributes_t mAudioAttributes;
long mUID;
Surface mConnectedWindow;
Binder mConnectedWindowBinder;
String mRetransmitEndpoint;
boolean mRetransmitEndpointValid;
MediaPlayerBn mNextClient;
// Metadata filters.
/* media::Metadata::Filter */Object mMetadataAllow; // protected by mLock
/* media::Metadata::Filter */Object mMetadataDrop; // protected by mLock
// Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
// notification we try to update mMetadataUpdated which is a
// set: no duplicate.
// getMetadata clears this set.
/* media::Metadata::Filter */Object mMetadataUpdated; // protected by mLock
/*
* TODO #if CALLBACK_ANTAGONIZER Antagonizer* mAntagonizer; #endif
*/
Object mAntagonizer;
OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 100, what, extra, null);
return false;
}
};
OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 200, what, extra, null);
return false;
}
};
OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 3, 3, percent, null);
}
};
OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 2, 2, 0, null);
}
};
OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.i(LOG_TAG,"mPreparedListener.onPrepared() ");
MediaPlayerBn.this.notify(MediaPlayerBn.this, 1, 1, 0, null);
}
};
OnSeekCompleteListener mSeekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mp) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 4, 4, 0, null);
}
};
OnVideoSizeChangedListener mVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
// TODO Auto-generated method stub
MediaPlayerBn.this.notify(MediaPlayerBn.this, 5, 5, 0, null);
}
};
public MediaPlayerBn(MyMediaPlayerService service, long pid, int connId,
IMediaPlayerClient client, int audioSessionId, long uid) {
Log.i(LOG_TAG, "Client(%d) constructor" + connId);
mPid = (int) pid;
mConnId = connId;
mService = service;
mClient = client;
mLoop = false;
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
mUID = uid;
mRetransmitEndpointValid = false;
mAudioAttributes = null;
mLock = new ReentrantLock();
Log.i(LOG_TAG, "create Antagonizer is null");
mAntagonizer = null;
mPlayer = new MediaPlayer();
mPlayer.setOnErrorListener(mErrorListener);
mPlayer.setOnInfoListener(mInfoListener);
mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mPlayer.setOnCompletionListener(mCompletionListener);
mPlayer.setOnPreparedListener(mPreparedListener);
mPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
mPlayer.setOnVideoSizeChangedListener(mVideoSizeChangedListener);
}
public void desdroy() {
Log.i(LOG_TAG, "Client(%d) destructor pid = %d" + mConnId + ":" + mPid);
mAudioOutput = null;
SoftReference
this);
try {
disconnect();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// destory 的时候删除引用
mService.removeClient(client);
if (mAudioAttributes != null) {
/* TODO free(mAudioAttributes); */
mAudioAttributes = null;
}
}
@Override
public void disconnect() throws RemoteException {
// TODO Auto-generated method stub
Log.i(LOG_TAG, "disconnect(%d) from pid %d" + mConnId + ":" + mPid);
// grab local reference and clear main reference to prevent future
// access to object
MediaPlayer p;
{
mLock.lock();
p = mPlayer;
mLock.unlock();
}
mPlayer = null;
// clear the notification to prevent callbacks to dead client
// and reset the player. We assume the player will serialize
// access to itself if necessary.
if (p != null) {
/* TODO p.setNotifyCallback(0, 0); */
p.reset();
}
/* TODOdisconnectNativeWindow(); */
/* TODO IPCThreadState::self()->flushCommands(); */
}
@Override
public int setDataSource(IMediaHTTPService httpService, String url,
String header) throws RemoteException {
// TODO Auto-generated method stub
Log.i(LOG_TAG, "setDataSource(%s) " + url);
try {
mPlayer.setDataSource(url);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
}
客户端多实例调用
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.demo;
import java.io.IOException;
import java.util.logging.Logger;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@SuppressLint("NewApi")
public class MediaPlayer_Surface_iadl_MultThread_TestBase extends Activity {
private static final String LOG_TAG = MediaPlayer_Surface_iadl_MultThread_TestBase.class
.getName() + "liyl add";
protected static final int SLEEP_TIME = 1000;
protected static final int LONG_SLEEP_TIME = 6000;
protected static final int STREAM_RETRIES = 1;
protected static boolean sUseScaleToFitMode = false;
/*
* protected Monitor mOnVideoSizeChangedCalled = new Monitor(); protected
* Monitor mOnVideoRenderingStartCalled = new Monitor(); protected Monitor
* mOnBufferingUpdateCalled = new Monitor(); protected Monitor
* mOnPrepareCalled = new Monitor(); protected Monitor mOnSeekCompleteCalled
* = new Monitor(); protected Monitor mOnCompletionCalled = new Monitor();
* protected Monitor mOnInfoCalled = new Monitor(); protected Monitor
* mOnErrorCalled = new Monitor();
*/
protected SurfaceHolder mSurfaceHolder1 = null;
protected SurfaceHolder mSurfaceHolder2 = null;
private SurfaceHolder mHolder1;
private SurfaceHolder mHolder2;
protected MediaPlayer_Surface_iadl_MultThread_TestBase mActivity;
private boolean mIsRemoteBound = false;
private static IMyMediaPlayerService mRemoteService = null;
private MediaPlayerClientWrapper mPlayerWrapper1;
private MediaPlayerClientWrapper mPlayerWrapper2;
public static IMyMediaPlayerService getRemoteMediaPlayerServiceInstance() {
if(mRemoteService == null) {
Log.e(LOG_TAG,"not should be here!!!");
return mRemoteService;
}
return mRemoteService;
}
protected class MediaPlayerClientWrapper implements MediaPlayerListener {
public MediaPlayerClientWrapper() {
super();
this.mPlayerClient = new MediaPlayerClientBn();
}
private MediaPlayerClientBn mPlayerClient;
public MediaPlayerClientBn getmPlayerClient() {
return mPlayerClient;
}
@Override
public void notify(int msg, int ext1, int ext2, Parcel obj) {
// TODO Auto-generated method stub
Log.e(LOG_TAG,"msg = "+msg+" ext1 = "+ext1+" ext2 = "+ext2+" obj = "+obj);
if(msg == 1/*MEDIA_PREPARED*/) {
mPlayerClient.start();
}
}
public void desdroy() {
this.mPlayerClient = null;
}
}
private ServiceConnection mRemoteConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mRemoteService = IMyMediaPlayerService.Stub.asInterface(service);
Log.i(LOG_TAG,"mRemoteService == null is "+(mRemoteService == null));
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mRemoteService = null;
}
};
public MediaPlayer_Surface_iadl_MultThread_TestBase() {
super();
}
protected void setUp() {
mSurfaceHolder1 = getSurfaceHolder1();
mSurfaceHolder2 = getSurfaceHolder2();
if (!mIsRemoteBound) {
Intent mIntent = new Intent();
mIntent.setAction("com.example.demo.IMyMediaPlayerService");//你定义的service的action
mIntent.setPackage(getPackageName());//这里你需要设置你应用的包名
//startService(mIntent);
bindService(mIntent,
mRemoteConnection, Context.BIND_AUTO_CREATE);
mIsRemoteBound = !mIsRemoteBound;
}
mPlayerWrapper1 = new MediaPlayerClientWrapper();
mPlayerWrapper2 = new MediaPlayerClientWrapper();
mPlayerWrapper1.getmPlayerClient().setListener(mPlayerWrapper1);
mPlayerWrapper2.getmPlayerClient().setListener(mPlayerWrapper2);
}
public SurfaceHolder getSurfaceHolder1() {
return mHolder1;
}
public SurfaceHolder getSurfaceHolder2() {
return mHolder2;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mediaplayermultsurface);
mActivity = this;
SurfaceView surfaceV1 = (SurfaceView) findViewById(R.id.surface1);
mHolder1 = surfaceV1.getHolder();
SurfaceView surfaceV2 = (SurfaceView) findViewById(R.id.surface2);
mHolder2 = surfaceV2.getHolder();
setUp();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
tearDown();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(mRemoteService == null) {
Log.w(LOG_TAG,"mRemoteService is null");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
mSurfaceHolder1 = arg0;
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
try {
mPlayerWrapper1.getmPlayerClient().setDataSource(null,"http://10.154.250.32:8081/share/mediatest/normal/hls/1080p/desc.m3u8", null);
mPlayerWrapper1.getmPlayerClient().setVideoSurfaceTexture(mActivity.getSurfaceHolder1()
.getSurface());
mPlayerWrapper1.getmPlayerClient().prepare();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
mSurfaceHolder1 = null;
}
});
mSurfaceHolder2.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
mSurfaceHolder2 = arg0;
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
try {
mPlayerWrapper2.getmPlayerClient().setDataSource(null,"http://10.154.250.32:8081/share/mediatest/normal/hls/1080p/desc.m3u8", null);
mPlayerWrapper2.getmPlayerClient().setVideoSurfaceTexture(mActivity.getSurfaceHolder2()
.getSurface());
mPlayerWrapper2.getmPlayerClient().prepare();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
mSurfaceHolder2 = null;
}
});
Log.w(LOG_TAG,"Sleep 5 s");
/* try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
private void clear() {
mPlayerWrapper1.desdroy();
mPlayerWrapper2.desdroy();
}
protected void tearDown() {
clear();
if (!mIsRemoteBound) {
unbindService(mRemoteConnection);
mIsRemoteBound = !mIsRemoteBound;
}
}
// //////////////////////////////////////////////////////////////////////
}