package com.example.service;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.FloatMath;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.VideoView;
import com.example.videoviewwindow.R;
public class VideoService extends Service {
private static final int MODE_NONE = 0;
private static final int MODE_ONE_TOUCH = 1;
private static final int MODE_DOUBLE_TOUCH = 2;
private int mTouchMode = MODE_NONE;
/**
* 터치시 탭 모션 인지
*/
private boolean isSingleTap;
private float START_X;
private float START_Y;
private float distance;
private int PREV_X;
private int PREV_Y;
/**
* 해상도 값
*/
private int mWidth;
private int mHeight;
/**
* 비디오 뷰 크기
*/
private int videoWidth;
private int videoHeight;
private WindowManager mWindowManager;
private WindowManager.LayoutParams windowParams;
private Button btnClose;
private RelativeLayout mOverlay;
private RelativeLayout layoutVideo;
private VideoView videoViewPlayer;
private RemoteCallbackList<IMessageServiceCallback> callbackList =
new RemoteCallbackList<IMessageServiceCallback> ();
@Override
public IBinder onBind(Intent intent) {
return serviceStub;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/**
* 서비스 런처에서 킬해도 죽지 않도록 설정
*/
startForeground(startId, new Notification());
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
finishVideo();
stopForeground(true);
}
/**
* 비디오 종료
*/
private void finishVideo(){
mWindowManager.removeView(mOverlay);
}
/**
* 윈도우 매니저 init하는 메소드
*/
private void initWindowManager() {
windowParams = new WindowManager.LayoutParams(
mWidth/2,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE, // 항상 최 상위. 터치 이벤트 받을 수
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, // 포커스를 가지지 않음
PixelFormat.TRANSLUCENT);
windowParams.gravity = Gravity.LEFT | Gravity.TOP;
mWindowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
}
/**
* 레이아웃초기화
*/
private void initLayout() {
// 윈도우 Layout init 하는 부분
LayoutInflater mInflater = LayoutInflater.from(this);
mOverlay = (RelativeLayout) mInflater.inflate(R.layout.activity_video_window, null);
layoutVideo = (RelativeLayout) mOverlay.findViewById(R.id.layoutVideo);
btnClose = (Button) mOverlay.findViewById(R.id.btnClose);
videoViewPlayer = (VideoView) mOverlay.findViewById(R.id.videoViewPlayer);
mWindowManager.addView(mOverlay, windowParams);
btnClose.setOnClickListener(mOnClickListener);
videoViewPlayer.setOnTouchListener(mOnTouchListener);
videoViewPlayer.setOnPreparedListener(mNativePreparedListener);
}
/**
* 데이터 초기화
*/
private void initData(){
videoDataInit();
}
/**
* 비디오뷰 데이터 초기화
*/
private void videoDataInit() {
String tempVideoURL = "http://www.boisestatefootball.com/sites/default/files/videos/original/01%20-%20coach%20pete%20bio_4.mp4";
Uri uri = Uri.parse(tempVideoURL);
videoViewPlayer.setVideoURI(uri);
}
@SuppressLint("FloatMath")
private float doubleTouchDistance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
distance = (float) (FloatMath.sqrt(x * x + y * y));
//화면 밖으로 나가지 못하도록 Block
if(distance >= mWidth){
distance = mWidth ;
return distance;
}
return distance;
}
/**
* 액티비티에서 넘어온 데이터 수신
*/
public IMessageService.Stub serviceStub = new IMessageService.Stub() {
@Override
public void sendMessage(String message,int width , int height) throws RemoteException {
mWidth = width;
mHeight = height;
initWindowManager();
initLayout();
initData();
}
@Override
public void registerCallback(IMessageServiceCallback callback)throws RemoteException {
callbackList.register(callback);
}
@Override
public void unregisterCallback(IMessageServiceCallback callback)throws RemoteException {
callbackList.unregister(callback);
}
};
/**
* 비디오 로드가 완료 되면 불리는 리스너
*/
private OnPreparedListener mNativePreparedListener = new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
layoutVideo.setVisibility(View.VISIBLE);
videoViewPlayer.start();
videoWidth = videoViewPlayer.getWidth();
videoHeight = videoViewPlayer.getHeight();
int cnt = callbackList.beginBroadcast();
for (int i = 0 ; i < cnt ; i++ ){
try {
callbackList.getBroadcastItem(i).finishAppCallback();
} catch (RemoteException e) {
e.printStackTrace();
}
}
callbackList.finishBroadcast();
}
};
/**
* 클릭 리스너
*/
private Button.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
// 비디오뷰 종료 버튼
case R.id.btnClose:
int cnt = callbackList.beginBroadcast();
for (int i = 0 ; i < cnt ; i++ ){
try {
callbackList.getBroadcastItem(i).finishCallback();
} catch (RemoteException e) {
e.printStackTrace();
}
}
callbackList.finishBroadcast();
break;
}
}
};
/**
* 터치 리스너
*/
private OnTouchListener mOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
isSingleTap = true;
mTouchMode = MODE_ONE_TOUCH;
btnClose.setVisibility(View.INVISIBLE);
START_X = event.getRawX();
START_Y = event.getRawY();
PREV_X = windowParams.x;
PREV_Y = windowParams.y;
break;
case MotionEvent.ACTION_MOVE: // 이동 시
if(mTouchMode == MODE_ONE_TOUCH){
int x = (int) (event.getRawX() - START_X);
int y = (int) (event.getRawY() - START_Y);
windowParams.x = PREV_X + x;
windowParams.y = PREV_Y + y;
mWindowManager.updateViewLayout(mOverlay, windowParams);
}
if(mTouchMode == MODE_DOUBLE_TOUCH){
isSingleTap = false;
float distance = doubleTouchDistance(event);
windowParams.width = (int) distance;
mWindowManager.updateViewLayout(mOverlay, windowParams);
}
break;
case MotionEvent.ACTION_UP:
btnClose.setVisibility(View.VISIBLE);
//싱글탭
if( (PREV_X - 0.1 < windowParams.x && windowParams.x < PREV_X +0.1 ) && isSingleTap){
int cnt = callbackList.beginBroadcast();
for (int i = 0 ; i < cnt ; i++ ){
try {
callbackList.getBroadcastItem(i).startAppCallback();
} catch (RemoteException e) {
e.printStackTrace();
}
}
callbackList.finishBroadcast();
}
mWindowManager.updateViewLayout(mOverlay, windowParams);
btnClose.setVisibility(View.VISIBLE);
break;
case MotionEvent.ACTION_POINTER_DOWN: // 두 손가락 터치 시
mTouchMode = MODE_DOUBLE_TOUCH;
isSingleTap = false;
break;
case MotionEvent.ACTION_POINTER_UP: // 두 손가락을 떼었을 시
isSingleTap = false;
mTouchMode = MODE_NONE;
break;
}
return true;
}
};
}