/* 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;
}
}
};
}