/* register service */ package gov.anzong.mediaplayer; import io.vov.vitamio.MediaPlayer; import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener; import io.vov.vitamio.MediaPlayer.OnCompletionListener; import io.vov.vitamio.MediaPlayer.OnErrorListener; import io.vov.vitamio.MediaPlayer.OnHWRenderFailedListener; import io.vov.vitamio.MediaPlayer.OnInfoListener; import io.vov.vitamio.MediaPlayer.OnPreparedListener; import io.vov.vitamio.MediaPlayer.OnSeekCompleteListener; import io.vov.vitamio.MediaPlayer.OnTimedTextListener; import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener; import gov.anzong.mediaplayer.VP; import gov.anzong.mediaplayer.VitamioInstaller; import gov.anzong.util.StringUtil; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import android.annotation.SuppressLint; import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.media.AudioManager; import android.media.AudioManager.OnAudioFocusChangeListener; import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.view.SurfaceHolder; public class PlayerService extends Service implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, OnErrorListener, OnInfoListener, OnSeekCompleteListener, OnTimedTextListener { private MediaPlayer mPlayer; private VPlayerListener mListener; private Uri mUri; private Uri mOldUri; private float mSeekTo = -1f; private boolean mFromNotification; private String[] mSubPaths; private AudioManager mAm; private boolean mInitialized; private final IBinder mBinder = new LocalBinder(); private int mCurrentState; private SurfaceHolder mSurfaceHolder; public static final int VPLYAER_NOTIFICATION_ID = 1; public static final int STATE_PREPARED = -1; public static final int STATE_PLAYING = 0; private TelephonyManager mTelephonyManager; public static final int STATE_NEED_RESUME = 1; public static final int STATE_STOPPED = 2; public static final int STATE_RINGING = 3; private int mLastAudioTrack = -1; private String mLastSubTrack; private int mLastSubTrackId = -1; private long mMediaId = -1l; public class LocalBinder extends Binder { public PlayerService getService() { return PlayerService.this; } } @Override public void onCreate() { super.onCreate(); mInitialized = false; mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); mAm = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int a = mAm.requestAudioFocus(focusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (VitamioInstaller.isNativeLibsInited(this)) { vplayerInit(intent.getBooleanExtra("isHWCodec", false)); } else { stopSelf(); } return super.onStartCommand(intent, flags, startId); } private void vplayerInit(boolean isHWCodec) { mPlayer = new MediaPlayer(PlayerService.this.getApplicationContext(), isHWCodec); mPlayer.setOnHWRenderFailedListener(new OnHWRenderFailedListener() { @Override public void onFailed() { if (mListener != null) mListener.onHWRenderFailed(); } }); mPlayer.setOnBufferingUpdateListener(PlayerService.this); mPlayer.setOnCompletionListener(PlayerService.this); mPlayer.setOnPreparedListener(PlayerService.this); mPlayer.setOnVideoSizeChangedListener(PlayerService.this); mPlayer.setOnErrorListener(PlayerService.this); mPlayer.setOnInfoListener(PlayerService.this); } public void releaseContext() { if (mPlayer != null) mPlayer.release(); mPlayer = null; } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onDestroy() { super.onDestroy(); release(true); releaseContext(); mAm.abandonAudioFocus(focusChangeListener); } public boolean isInitialized() { return mInitialized; } public boolean initialize(Uri filePath, String displayName, boolean saveUri, float startPos, VPlayerListener listener, int parentId, boolean isHWCodec) { if (mPlayer == null) vplayerInit(isHWCodec); mListener = listener; mOldUri = mUri; mUri = filePath; mSeekTo = startPos; mMediaId = -1; mLastAudioTrack = -1; mLastSubTrackId = -1; mLastSubTrack = ""; setMediaTrack(); mFromNotification = mInitialized && mUri != null && mUri.equals(mOldUri); mListener.onOpenStart(); if (!mFromNotification) openVideo(); else openSuccess(); return mInitialized; } private void setMediaTrack() { } private void openVideo() { if (mUri == null || mPlayer == null) return; mPlayer.reset(); mInitialized = false; mPrepared = false; mVideoSizeKnown = false; HashMap<String, String> headers = new HashMap<String, String>(); try { mPlayer.setScreenOnWhilePlaying(true); if (mUri != null) { if (mUri.toString().indexOf(".56.com/") < 0) { headers.put( "user-agent", "Mozilla/5.0 (iPad; CPU OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3"); } else { headers.put("user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0"); headers.put("seekable", "1"); } } mPlayer.setDataSource(PlayerService.this, mUri, headers); if (mLastAudioTrack != -1) mPlayer.selectTrack(mLastAudioTrack); if (mLastSubTrackId != -1) mPlayer.selectTrack(mLastSubTrackId); if (mSurfaceHolder != null && mSurfaceHolder.getSurface() != null && mSurfaceHolder.getSurface().isValid()) mPlayer.setDisplay(mSurfaceHolder); mPlayer.prepareAsync(); } catch (IllegalArgumentException e) { } catch (IllegalStateException e) { } catch (IOException e) { } } public Uri getUri() { return mUri; } public long getMediaId() { return mMediaId; } public int getLastAudioTrack() { return mLastAudioTrack; } public String getLastSubTrack() { return mLastSubTrack; } public int getLastSubTrackId() { return mLastSubTrackId; } public void setVPlayerListener(VPlayerListener listener) { mListener = listener; } public void setState(int state) { mCurrentState = state; } public boolean needResume() { return mInitialized && (mCurrentState == STATE_NEED_RESUME || mCurrentState == STATE_PREPARED); } public boolean ringingState() { return mInitialized && mCurrentState == STATE_RINGING; } public void release() { release(true); } private void release(boolean all) { if (mPlayer != null) { if (mListener != null) mListener.onCloseStart(); mPlayer.reset(); mInitialized = false; mPrepared = false; mVideoSizeKnown = false; if (mListener != null) mListener.onCloseComplete(); } if (all) { mListener = null; mUri = null; } } public void stop() { if (mInitialized) { mPlayer.pause(); } } public void start() { if (mInitialized) { mPlayer.start(); setState(STATE_PLAYING); } } public void setDisplay(SurfaceHolder surface) { mSurfaceHolder = surface; if (mPlayer != null) mPlayer.setDisplay(surface); } public void releaseSurface() { if (mInitialized) mPlayer.releaseDisplay(); } public boolean isPlaying() { return (mInitialized && mPlayer.isPlaying()); } public int getVideoWidth() { if (mInitialized) return mPlayer.getVideoWidth(); return 0; } public int getVideoHeight() { if (mInitialized) return mPlayer.getVideoHeight(); return 0; } public float getVideoAspectRatio() { if (mInitialized) return mPlayer.getVideoAspectRatio(); return 0f; } public long getDuration() { if (mInitialized) return mPlayer.getDuration(); return 0; } public long getCurrentPosition() { if (mInitialized) return mPlayer.getCurrentPosition(); return 0; } public Bitmap getCurrentFrame() { if (mInitialized) return mPlayer.getCurrentFrame(); return null; } public float getBufferProgress() { if (mInitialized) return mPlayer.getBufferProgress(); return 0f; } public void seekTo(float percent) { if (mInitialized) mPlayer.seekTo((int) (percent * getDuration())); } public String getMetaEncoding() { if (mInitialized) return mPlayer.getMetaEncoding(); return null; } public void setAudioTrack(int num) { if (mInitialized) mPlayer.selectTrack(num); } public int getAudioTrack() { if (mInitialized) return mPlayer.getAudioTrack(); return 0; } public HashMap<String, Integer> getAudioTrackMap() { return null; } public HashMap<String, Object> getSubTrackMap() { return null; } public int getSubTrack() { if (mInitialized) return mPlayer.getTimedTextTrack(); return 0; } public void setSubTrack(int id) { if (mInitialized) mPlayer.selectTrack(id); } public String getSubPath() { if (mInitialized) return mPlayer.getTimedTextPath(); return null; } public void setSubShown(boolean shown) { if (mInitialized) mPlayer.setTimedTextShown(shown); } protected boolean isBuffering() { return (mInitialized && mPlayer.isBuffering()); } protected void setBuffer(int bufSize) { if (mInitialized) mPlayer.setBufferSize(bufSize); } protected void setVolume(float left, float right) { if (mInitialized) { if (left <= 0f) left = 0f; else if (left >= 1f) left = 1f; if (right <= 0f) right = 0f; else if (right >= 1f) right = 1f; mPlayer.setVolume(left, right); } } protected void setVideoQuality(int quality) { if (mInitialized) mPlayer.setVideoQuality(quality); } protected void setDeinterlace(boolean deinterlace) { if (mInitialized) mPlayer.setDeinterlace(deinterlace); } public int getSubLocation() { if (mInitialized) return mPlayer.getTimedTextLocation(); return -1; } protected void setSubEncoding(String encoding) { if (mInitialized) { String enc = encoding.equals(VP.DEFAULT_SUB_ENCODING) ? null : encoding; mPlayer.setTimedTextEncoding(enc); } } public void setSubPath(String subPath) { if (mInitialized) mPlayer.addTimedTextSource(subPath); } public static interface VPlayerListener { public void onHWRenderFailed(); public void onVideoSizeChanged(int width, int height); public void onSubChanged(String text); public void onSubChanged(byte[] pixels, int width, int height); public void onOpenStart(); public void onOpenSuccess(); public void onOpenFailed(); public void onBufferStart(); public void onBufferComplete(); public void onDownloadRateChanged(int kbPerSec); public void onPlaybackComplete(); public void onCloseStart(); public void onCloseComplete(); } private boolean mVideoSizeKnown = false; private boolean mPrepared = false; @Override public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) { mVideoSizeKnown = true; if (mListener != null) mListener.onVideoSizeChanged(arg1, arg2); } @Override public void onPrepared(MediaPlayer arg0) { mPrepared = true; openSuccess(); } private void openSuccess() { mInitialized = true; if (!mFromNotification && mSeekTo > 0 && mSeekTo < 1) seekTo(mSeekTo); mSeekTo = -1; mListener.onOpenSuccess(); if (!mFromNotification) { setSubEncoding(VP.DEFAULT_SUB_ENCODING); if (mUri != null) mSubPaths = getSubFiles(mUri.getPath()); if (mSubPaths != null) setSubPath(getCanonical(new File(mSubPaths[0]))); setSubShown(VP.DEFAULT_SUB_SHOWN); } } public static String getCanonical(File f) { if (f == null) return null; try { return f.getCanonicalPath(); } catch (IOException e) { return f.getAbsolutePath(); } } @Override public void onCompletion(MediaPlayer arg0) { if (mListener != null) { mListener.onPlaybackComplete(); } else { release(true); } } @Override public void onBufferingUpdate(MediaPlayer arg0, int arg1) { } @Override public void onTimedText(String arg0) { if (mListener != null) mListener.onSubChanged(arg0); } @Override public void onTimedTextUpdate(byte[] arg0, int arg1, int arg2) { if (mListener != null) mListener.onSubChanged(arg0, arg1, arg2); } @Override public void onSeekComplete(MediaPlayer arg0) { } @Override public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) { switch (arg1) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: if (mListener != null) mListener.onBufferStart(); else mPlayer.pause(); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: if (mListener != null) mListener.onBufferComplete(); else mPlayer.start(); break; case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED: if (mListener != null) mListener.onDownloadRateChanged(arg2); break; } return true; } @Override public boolean onError(MediaPlayer arg0, int arg1, int arg2) { mListener.onOpenFailed(); return true; } private PhoneStateListener mPhoneListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: case TelephonyManager.CALL_STATE_RINGING: if (isPlaying()) { stop(); setState(STATE_RINGING); } break; default: break; } } }; private String[] getSubFiles(String videoPath) { ArrayList<String> files = new ArrayList<String>(); for (String ext : MediaPlayer.SUB_TYPES) { File s = new File(videoPath.substring(0, videoPath.lastIndexOf('.') > 0 ? videoPath.lastIndexOf('.') : videoPath.length()) + ext); if (s.exists() && s.isFile() && s.canRead()) files.add(s.getAbsolutePath()); } if (files.isEmpty()) return null; else return files.toArray(new String[files.size()]); } private OnAudioFocusChangeListener focusChangeListener = new OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { switch (focusChange) { case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK): // Lower the volume while ducking. setVolume(0.2f, 0.2f); break; case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT): stop(); break; case (AudioManager.AUDIOFOCUS_LOSS): stop(); break; case (AudioManager.AUDIOFOCUS_GAIN): // Return the volume to normal and resume if paused. setVolume(1f, 1f); start(); break; default: break; } } }; }