1. 程式人生 > >結合懸浮窗實現後臺播放視訊

結合懸浮窗實現後臺播放視訊

package com.frank.playervideo;

import java.io.IOException;
import java.util.LinkedList;


import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.LinearLayout;


/**
 * 視訊播放服務
 * 
 * @author Frank
 * @version 1.0 Create by 2015.10.29
 */
public class PlayerVideoService extends Service {
private final static String TAG = "PlayerVideoService";
private final IBinder mBinder = new LocalBinder();
private final static int UPDATE_WINDOWN_SHOW = 4;
private final static int UPDATE_WINDOWN_HIDEN = 5;
/* MediaPlayer物件 */
private MediaPlayer mMediaPlayer = null;
private int currentTime = 0;// 歌曲播放進度
private static int currentListItme = 0;// 當前播放第幾首歌
private LinkedList<Vedio> videos = new LinkedList<Vedio>();// 要播放的歌曲集合
private PowerManager pm;
private WakeLock wakeLock;
private Context context;
public static boolean isRuning = false;
public static boolean isPause = true;
private MyTimerThread myTimerThread;
private WindowManager mWindowManager;
private WindowManager.LayoutParams wmParams;
private LinearLayout windowLayout;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private boolean isShowSurface = false;
private Object object = new Object();
private Handler handler = new Handler();
private Handler mHandler = new Handler() {


@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_WINDOWN_SHOW:
wmParams.x = 50;
wmParams.y = 400;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowManager.updateViewLayout(windowLayout, wmParams);
break;
case UPDATE_WINDOWN_HIDEN:
wmParams.x = -1000;
wmParams.y = -1000;
wmParams.width = 0;
wmParams.height = 0;
mWindowManager.updateViewLayout(windowLayout, wmParams);
break;


default:
break;
}
}


};


{
videos.add(new Vedio(
"http://183.131.48.148/music.qqvideo.tc.qq.com/j0018ibiux9.mp4?type=mp4&fmt=mp4&vkey=074D2324D5072635F65AB7CE14AAE95CD6D29DC7F4F908B17ABE330648EC18111273FEA65D321D2256F76F1AB171252F7E9734843A4BE64E840CDCE79DDFEAB10824193A01A03574D5BEAE314E0D58690AD08553DFB44773&locid=0709dd73-4e55-4307-bfd0-b0445ac09145&size=13453943&ocid=337450412"));
}


@Override
public void onCreate() {
super.onCreate();
isRuning = true;
isPause = true;
context = this;
if (mMediaPlayer == null) {
mMediaPlayer = Util.getMediaPlayer(context);
}
if (myTimerThread == null) {
myTimerThread = new MyTimerThread();
myTimerThread.start();
}


initWakelock();


initWindowManager();
}


/**
* 初始化視窗控制
*/
private void initWindowManager() {
// 獲取的是LocalWindowManager物件
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);


// 獲取LayoutParams物件
wmParams = new WindowManager.LayoutParams();


wmParams.type = LayoutParams.TYPE_PHONE;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_LAYOUT_NO_LIMITS;
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.x = 0;
wmParams.y = 0;
wmParams.width = 0;
wmParams.height = 0;
// wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
// wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;


LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);


windowLayout = (LinearLayout) inflater.inflate(
R.layout.player_audio_service_surfaceview_layout, null);
windowLayout.setOnTouchListener(new OnTouchListener() {


@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
wmParams.x = (int) event.getRawX() - windowLayout.getWidth()
/ 2;
// 25為狀態列高度
wmParams.y = (int) event.getRawY() - windowLayout.getHeight()
/ 2 - 40;
mWindowManager.updateViewLayout(windowLayout, wmParams);
return false;
}
});
surfaceView = (SurfaceView) windowLayout
.findViewById(R.id.player_audio_service_surface);
surfaceHolder = surfaceView.getHolder();// SurfaceHolder是SurfaceView的控制介面
surfaceHolder.addCallback(new Callback() {


@Override
public void surfaceDestroyed(SurfaceHolder holder) {


}


@Override
public void surfaceCreated(SurfaceHolder holder) {
mMediaPlayer.setDisplay(surfaceHolder);
synchronized (object) {
isShowSurface = true;
object.notifyAll();
}
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {


}
});// 因為這個類實現了SurfaceHolder.Callback介面,所以回撥引數直接this
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// Surface型別
mWindowManager.addView(windowLayout, wmParams);
}


/**
* 初始化高亮控制
*/
private void initWakelock() {
if (pm == null) {
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
}


if (wakeLock == null) {


wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this
.getClass().getName());
wakeLock.acquire();
}
}


/**
* 得到當前播放進度
*/
public int getCurrent() {
if (mMediaPlayer.isPlaying()) {
return mMediaPlayer.getCurrentPosition();
} else {
return currentTime;
}
}


/**
* 獲得當前MediaPlayer

* @return
*/
public MediaPlayer getMediaPlayer() {
if (mMediaPlayer != null) {
return mMediaPlayer;
}
return null;
}


/**
* 跳到輸入的進度
*/
public void movePlay(int progress) {
if (mMediaPlayer != null) {
mMediaPlayer.seekTo(progress);
currentTime = progress;
}
}


/**
* @return 得到正在播放視訊的Music物件
*/
public Vedio getCurrentMusic() {
return videos.get(currentListItme);
}


/**
* 設定當前位置

* @param position
*/
public void setCurrentItem(int position) {
currentListItme = position;
}


/**
* 獲得當前位置

* @param position
*/
public static int getCurrentItem() {
return currentListItme;
}


/**
* 播放當前視訊

* @param video_type
*/
private void playMusic(final String path) {
new Thread(new Runnable() {


@Override
public void run() {
try {
/* 重置MediaPlayer */
currentTime = 0;
if (mMediaPlayer == null) {
mMediaPlayer = Util.getMediaPlayer(context);
}
mMediaPlayer.reset();
mMediaPlayer.setWakeMode(PlayerVideoService.this, 1);
/* 設定要播放的檔案的路徑 */
mMediaPlayer.setDataSource(path);


// mMediaPlayer
// .setDataSource("http://test1.baidu.bos.starunion.ping-qu.com/aini.m3u8");
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);


Message msg = Message.obtain();
msg.what = UPDATE_WINDOWN_SHOW;
mHandler.sendMessage(msg);
synchronized (object) {
if (!isShowSurface) {
object.wait();
}
}


mMediaPlayer.setScreenOnWhilePlaying(true);
/* 準備播放 */
mMediaPlayer.prepare();
/* 開始播放 */
mMediaPlayer.start();
isPause = false;


mMediaPlayer
.setOnPreparedListener(new OnPreparedListener() {


@Override
public void onPrepared(MediaPlayer mp) {
Logger.i(TAG, "OnPreparedListener");
}
});
// 音樂播放完畢
mMediaPlayer
.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
// 播放完成一首之後進行下一首
Logger.i(TAG, "播放完成");
currentTime = 0;
}
});
mMediaPlayer
.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {


@Override
public void onBufferingUpdate(MediaPlayer mp,
int percent) {
Logger.i(TAG, "OnBufferingUpdateListener");
}
});
mMediaPlayer.setOnInfoListener(new OnInfoListener() {


@Override
public boolean onInfo(MediaPlayer mp, int what,
int extra) {
Logger.i(TAG, "OnInfoListener");
return false;
}
});
// 播放音樂時發生錯誤的事件處理
mMediaPlayer
.setOnErrorListener(new MediaPlayer.OnErrorListener() {


public boolean onError(MediaPlayer mp,
int what, int extra) {
Logger.i(TAG, "播放出現錯誤");
currentTime = 0;
return false;
}
});
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}


/**
* 停止播放並結束服務
*/
public void stopMusic() {
if (mMediaPlayer != null) {
Log.i("test", "mMediaPlayer!=null");
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
stopSelf();
}
}


/**
* 歌曲是否真在播放
*/
public boolean isPlay() {
if (mMediaPlayer != null) {
return mMediaPlayer.isPlaying();
}
return false;
}


@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}


/**
* 自定義繫結Service類,通過這裡的getService得到Service,之後就可呼叫Service這裡的方法了
*/
public class LocalBinder extends Binder {
public PlayerVideoService getService() {
Log.d("playerService", "getService");
return PlayerVideoService.this;
}
}


@Override
public void onDestroy() {
Logger.i(TAG, "銷燬服務");
isRuning = false;
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
wakeLock = null;
}
if (myTimerThread != null) {
try {
myTimerThread.stop();
} catch (Exception e) {
e.printStackTrace();
} finally {


}
}
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
isRuning = true;
// 獲得activity傳過來的引數
if (intent != null) {
String type = intent.getAction();
switch (type) {
case "play":
playMusic(videos.get(0).url);
break;
case "close":
stopMusic();
mWindowManager.removeView(windowLayout);
break;
case "removeWindow":
wmParams.x = -1000;
wmParams.y = -1000;
wmParams.width = 0;
wmParams.height = 0;
mWindowManager.updateViewLayout(windowLayout, wmParams);
break;
case "adddWindow":
wmParams.x = 50;
wmParams.y = 400;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowManager.updateViewLayout(windowLayout, wmParams);
break;


default:
break;
}
}
return START_STICKY;
};


/**
* 時間執行緒

* @author Frank
*/
private class MyTimerThread extends Thread {
@Override
public void run() {
while (true) {
handler.post(new Runnable() {
@Override
public void run() {
// Logger.i(TAG, "回撥進度");
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
currentTime += 1000;
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Logger.e(TAG, e.getLocalizedMessage());
}


}
}
}
}