package org.mortbay.ijetty.movieservice; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.bug.Speak; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.mortbay.ijetty.AppConstants; import org.mortbay.ijetty.IJetty; import org.mortbay.ijetty.R; import org.mortbay.ijetty.movieservice.MediaPlaybackService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.media.AudioManager; import android.media.MediaPlayer; 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.SystemClock; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; public class MyFloatView implements OnCompletionListener, OnErrorListener, OnInfoListener, OnPreparedListener, OnSeekCompleteListener, OnVideoSizeChangedListener, SurfaceHolder.Callback, android.view.View.OnClickListener { private static List<File> mMediaFiles = null; private static int mCurIndex = 0; private float mTouchStartX; private float mTouchStartY; public static float x = 0; public static float y = 0; public static float width = 800; public static float height = 600; public static boolean mAutoPlayList = false; public static boolean mPlayViewPrepareStatus = false; public static boolean mPlayViewStatus = false; public static String playListJsonString = ""; static ViewGroup mlayoutView; static Context context; Display currentDisplay; static SurfaceView surfaceView; SurfaceHolder surfaceHolder; Button mButton; static MediaPlayer mediaPlayer;// 使用的是MediaPlayer来播放视频 int videoWidth = 0; // 视频的宽度,初始化,后边会对其进行赋值 int videoHeight = 0; // 同上 boolean readyToPlayer = false; public final static String LOGCAT = "=>MyFloatView"; public static final String ACTION_DESTROY_MOVIE = "org.mortbay.ijetty.send.movie.Destroy"; public MyFloatView(ViewGroup layoutView) { // TODO Auto-generated constructor stub mlayoutView = layoutView; context = mlayoutView.getContext(); mlayoutView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View paramView, MotionEvent paramMotionEvent) { // TODO Auto-generated method stub onTouchEvent(paramMotionEvent); return false; } }); initWindow(); } public View getLayoutView() { return mlayoutView; } public void onResume() { } public void initWindow() { // 获取WindowManager wm = (WindowManager) context.getApplicationContext().getSystemService("window"); // 设置LayoutParams(全局变量)相关参数 // wmParams = ((MyApplication)getApplication()).getMywmParams(); wmParams = new WindowManager.LayoutParams(); /** * 以下都是WindowManager.LayoutParams的相关属性 具体用途可参考SDK文档 */ wmParams.type = /*LayoutParams.TYPE_SYSTEM_ALERT | */LayoutParams.TYPE_SYSTEM_OVERLAY; // 设置window type // 设置图片格式,效果为背景透明 wmParams.format = PixelFormat.TRANSPARENT; // 设置Window flag // wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL // | LayoutParams.FLAG_NOT_FOCUSABLE // | LayoutParams.FLAG_LAYOUT_NO_LIMITS; /* * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; */ wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角 // 以屏幕左上角为原点,设置x、y初始值 currentDisplay = wm.getDefaultDisplay(); // WIDTH = currentDisplay.getWidth(); // HEIGHT = currentDisplay.getHeight(); //以下参数调整视频窗口的位置 wmParams.x = (int)x; wmParams.y = (int)y; wmParams.width = (int)width; wmParams.height = (int)height; } static int VIEW_WIDTH = 200, VIEW_HEIGHT = 200; public void bindViewListener() { initialUI(); } private void initialUI() { // 关于SurfaceView和Surfaceolder可以查看文档 //loc = PlayLocation.restoreLocation();//暂不考虑播放位置 surfaceView = (SurfaceView) mlayoutView.findViewById(R.id.myView); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mediaPlayer = new MediaPlayer(); mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnErrorListener(this); mediaPlayer.setOnPreparedListener(this); mediaPlayer.setOnSeekCompleteListener(this); mediaPlayer.setOnVideoSizeChangedListener(this); //listSupportedMediaFiles(); if(!mMediaFiles.isEmpty()){ curFile = mMediaFiles.get(mCurIndex); } else{ Log.w("smallstar", "============================================="); Log.w("smallstar", "mMediaFiles is null!"); } // if (loc == null) { // curFile = mMediaFiles.get(mCurIndex); // } else { // curFile = new File(loc.getFilename()); // mCurIndex = mMediaFiles.indexOf(curFile); // } // 本地地址和网络地址都可以 try { Log.w("smallstar", "============================================="); Log.v(LOGCAT, curFile.getAbsolutePath()); mediaPlayer.setDataSource(curFile.getAbsolutePath()); } catch (IllegalArgumentException e) { // TODO: handle exception Log.v(LOGCAT, e.getMessage()); onExit(); } catch (IllegalStateException e) { Log.v(LOGCAT, e.getMessage()); onExit(); } catch (IOException e) { Log.v(LOGCAT, e.getMessage()); onExit(); } IntentFilter filter = new IntentFilter(ACTION_DESTROY_MOVIE); context.registerReceiver(sReceiver, filter); } private PlayLocation loc = null; private static File curFile = null; public static void startPlay() { mPlayViewStatus = true; if (mediaPlayer.isPlaying()) return; mediaPlayer.start(); } public boolean prepare() { //Log.e(LOGCAT, "prepare() video prepare 1"); // if (mMediaFiles != null && mMediaFiles.size() < 1) { // //MainActivity.mImageView.setVisibility(View.VISIBLE); // return false; // } else { // //MainActivity.mImageView.setVisibility(View.GONE); // } //Log.e(LOGCAT, "prepare() video prepare 2"); //loc = PlayLocation.restoreLocation(); if(mMediaFiles == null || mMediaFiles.size() < 1) { Log.e(LOGCAT, "prepare() video prepare error!-----mMediaFiles is null or mMediaFiles.size is zero."); return false; } curFile = mMediaFiles.get(mCurIndex); // if (loc == null) { // curFile = mMediaFiles.get(mCurIndex); // } else { // curFile = new File(loc.getFilename()); // mCurIndex = mMediaFiles.indexOf(curFile); // } //Log.e(LOGCAT, "prepare() video prepare 3"); if (mediaPlayer != null) { mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null; } try { //Speak.setOn(); mediaPlayer = new MediaPlayer(); mediaPlayer.reset(); mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnErrorListener(this); mediaPlayer.setOnPreparedListener(this); mediaPlayer.setOnSeekCompleteListener(this); mediaPlayer.setOnVideoSizeChangedListener(this); mediaPlayer.setOnInfoListener(new OnInfoListener() { @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { //Log.e("gayr", "onInfo what: "+what+" extra: "+extra); return false; } }); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);// .STREAM_MUSIC); mediaPlayer.setDisplay(surfaceHolder); mediaPlayer.setScreenOnWhilePlaying(true); try { Log.v(LOGCAT, curFile.getAbsolutePath()); mediaPlayer.setDataSource(curFile.getAbsolutePath()); } catch (IllegalArgumentException e) { // TODO: handle exception Log.v(LOGCAT, e.getMessage()); onExit(); } catch (IllegalStateException e) { Log.v(LOGCAT, e.getMessage()); onExit(); } catch (IOException e) { Log.v(LOGCAT, e.getMessage()); onExit(); } mediaPlayer.prepareAsync(); // mMediaPlayer.seekTo(pos); return true; } catch (Exception e) { e.printStackTrace(); // if (curFile != null && curFile.exists()) // curFile.delete(); SystemClock.sleep(500); //MainActivity.mImageView.setVisibility(View.GONE); prepareNext(); } return false; } public void play() { if (mediaPlayer.isPlaying()) return; mediaPlayer.start(); // new Timer().schedule(new TimerTask() { // @Override // public void run() { // if (mediaPlayer != null && mediaPlayer.isPlaying()) { // int length = mediaPlayer.getDuration(); // //Log.e("smallstar", "play length: " + length); // mMediaPlayer.seekTo(length); // } // } // }, 2 * 1000); // if (loc != null) { // mediaPlayer.seekTo(loc.getPos()); // } } static BroadcastReceiver sReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub onExit(); } }; public static void onExit() { try { //wm.removeView(mlayoutView); Intent mIntent = new Intent("removeUI"); mIntent.setClass(context, MediaPlaybackService.class); context.startService(mIntent); context.unregisterReceiver(sReceiver); mediaPlayer.pause(); mediaPlayer.stop(); mediaPlayer.release(); //Log.v(LOGCAT, "onExit() 2"); } catch (Exception e) { // TODO: handle exception } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v(LOGCAT, "surfaceChanged Called"); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.v(LOGCAT, "surfaceCreated calles"); mediaPlayer.setDisplay(holder);// 若无次句,将只有声音而无图像 try { mediaPlayer.prepare(); } catch (IllegalStateException e) { onExit(); } catch (IOException e) { onExit(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.v(LOGCAT, "surfaceDestroyed Called"); } @Override public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) { Log.v(LOGCAT, "onVideoSizeChanged Called"); } @Override public void onSeekComplete(MediaPlayer mp) { Log.v(LOGCAT, "onSeekComplete Called"); } public static void listAllMediaFiles(){ //File[] files; mMediaFiles = new ArrayList<File>(); mCurIndex = 0; if(playListJsonString.isEmpty()) { Log.e(LOGCAT, "playListJsonString is null!"); } else { JSONArray jsonar=null; try { jsonar = new JSONArray(playListJsonString); for(int i=0; i<jsonar.length(); i++) { JSONObject oj = jsonar.getJSONObject(i); Log.v("smallstar", oj.getString("file")); String filenpath = oj.getString("file"); String end = filenpath.toLowerCase(); if (end.endsWith(".mp4") || end.endsWith(".rmvb") || end.endsWith(".3gp") || end.endsWith(".avi") || end.endsWith(".rm") || end.endsWith(".mov") || end.endsWith(".flv") || end.endsWith(".mkv")) { File file = new File(IJetty.__JETTY_DIR+"/"+IJetty.__WEBAPP_DIR + "/console/demo/" + filenpath); if(file.exists()){mMediaFiles.add(file);} } } } catch (JSONException e) { e.printStackTrace(); } } if(mMediaFiles.isEmpty()){ //播放垫底节目 File file = new File(IJetty.__JETTY_DIR+"/"+IJetty.__WEBAPP_DIR + "/console/demo/" + "upload/default.mp4"); mMediaFiles.add(file); } Log.e("gary", "listSupportedMediaFiles: " + mMediaFiles); } private static void listSupportedMediaFiles() { File mediaFile = new File(AppConstants.getMediaSdFolder()); mCurIndex = 0; mMediaFiles = null; if (!mediaFile.exists()) mediaFile.mkdirs(); File[] files = mediaFile.listFiles(new FileFilter() { @Override public boolean accept(File f) { if (f == null) return false; if (!f.exists()) return false; if (f.isDirectory()) return true; String end = f.getName().toLowerCase(); if (end.endsWith(".mp4") || end.endsWith(".rmvb") || end.endsWith(".3gp") || end.endsWith(".avi") || end.endsWith(".rm") || end.endsWith(".mov") || end.endsWith(".flv") || end.endsWith(".mkv")) { return true; } return false; } }); if (files == null) return; mMediaFiles = Arrays.asList(files); Log.e("gary", "listSupportedMediaFiles: " + mMediaFiles); } @Override public void onPrepared(MediaPlayer mp) { //MediaPlayer加载准备完毕才能开始播放 Log.v(LOGCAT, "onPrepared Called"); videoWidth = (int)this.width; //mp.getVideoWidth(); videoHeight = (int)this.height;//mp.getVideoHeight(); Log.v(LOGCAT, String.valueOf(videoWidth)); Log.v(LOGCAT, String.valueOf(videoHeight)); /** 这一步为videod的高宽赋值,将其值控制在可控的范围之内, * 在VideoView的源码中也有相关的代码 * */ // if (videoWidth > currentDisplay.getWidth() // || videoHeight > currentDisplay.getHeight()) // { // float heightRatio = (float) videoHeight // / (float) currentDisplay.getHeight(); // float widthRatio = (float) videoWidth // / (float) currentDisplay.getWidth(); // if (heightRatio > 1 || widthRatio > 1) // { // if (heightRatio > widthRatio) // { // videoHeight = (int) Math.ceil((float) videoHeight // / (float) heightRatio); // videoWidth = (int) Math.ceil((float) videoWidth // / (float) heightRatio); // } else // { // videoHeight = (int) Math.ceil((float) videoHeight // / (float) widthRatio); // videoWidth = (int) Math.ceil((float) videoWidth // / (float) widthRatio); // } // } // } //videoWidth = 800; //videoHeight = 600; // 设置悬浮窗口长宽数据 wmParams.width = VIEW_WIDTH = videoWidth; wmParams.height = VIEW_HEIGHT = videoHeight; surfaceView.setLayoutParams(new FrameLayout.LayoutParams(videoWidth, videoHeight)); if(mAutoPlayList) { try { play(); } catch (Exception e) { Log.e(LOGCAT, "========>"); e.printStackTrace(); if (curFile != null && curFile.exists()) curFile.delete(); prepareNext(); } } } @Override public boolean onInfo(MediaPlayer arg0, int whatInfo, int extra) { if (whatInfo == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) { Log.v(LOGCAT, "Media Info, Media Info Bad Interleaving " + extra); } else if (whatInfo == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) { Log.v(LOGCAT, "Media Info, Media Info Not Seekable " + extra); } else if (whatInfo == MediaPlayer.MEDIA_INFO_UNKNOWN) { Log.v(LOGCAT, "Media Info, Media Info Unknown " + extra); } else if (whatInfo == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) { Log.v(LOGCAT, "MediaInfo, Media Info Video Track Lagging " + extra); } else if (whatInfo == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) { Log.v(LOGCAT, "MediaInfo, Media Info Metadata Update " + extra); } return false; } @Override public boolean onError(MediaPlayer arg0, int arg1, int arg2) { Log.v(LOGCAT, "onError Called"); if (arg1 == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { Log.v(LOGCAT, "Media Error, Server Died " + arg2); } else if (arg1 == MediaPlayer.MEDIA_ERROR_UNKNOWN) { Log.v(LOGCAT, "Media Error, Error Unknown " + arg2); } onExit();//出错后关闭视频播放窗口。 return false; } @Override public void onCompletion(MediaPlayer arg0) { Log.v(LOGCAT, "onCompletion Called"); Log.e("smallstar", " onComplete: "+ mediaPlayer.getCurrentPosition()); if (mediaPlayer != null) { mediaPlayer.setScreenOnWhilePlaying(false); mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null; } prepareNext(); //onExit(); //播放完后是否关闭视频播放窗口。 } private void prepareNext(){ if (mCurIndex < 0) { //listSupportedMediaFiles(); listAllMediaFiles(); } else { mCurIndex++; if (mCurIndex >= mMediaFiles.size()) { //listSupportedMediaFiles(); listAllMediaFiles(); } } prepare(); } public void showLayoutView() { wm.addView(mlayoutView, wmParams); } public void playViewPrepareFinish() { mPlayViewPrepareStatus = true; } public static int WIDTH = 1024, HEIGHT = 552; public static final int left = -VIEW_WIDTH / 2, top = 0, right = WIDTH - VIEW_WIDTH / 2, bottom = HEIGHT - VIEW_HEIGHT / 2; private static WindowManager wm = null; private static WindowManager.LayoutParams wmParams = null; private float mLastTouchY = 0; int rangeOut_H = -1, rangeOut_V = -1; public boolean onTouchEvent(MotionEvent event) { // 获取相对屏幕的坐标,即以屏幕左上角为原点 x = event.getRawX(); y = event.getRawY(); // 25是系统状态栏的高度 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.getX(); mTouchStartY = event.getY(); break; case MotionEvent.ACTION_MOVE: if (mLastTouchY > 110) { mTouchStartX = event.getX(); mTouchStartY = event.getY(); mLastTouchY = 0; } int positionX = (int) (x - mTouchStartX); int positionY = (int) (y - mTouchStartY); if (positionX < left || positionX > right) {// check borad just // reset rangeOut_H = positionX < left ? left : right; } if (positionY < top || positionY > bottom) {// check borad just // reset rangeOut_V = positionY < top ? top : bottom; } updateViewPosition(); break; case MotionEvent.ACTION_UP: if (rangeOut_H != -1) { x = rangeOut_H + mTouchStartX; } if (rangeOut_V != -1) { y = rangeOut_V + mTouchStartY; } updateViewPosition(); mTouchStartX = mTouchStartY = 0; rangeOut_H = rangeOut_V = -1; break; default: mTouchStartX = mTouchStartY = 0; rangeOut_H = rangeOut_V = -1; break; } return true; } // public void updateViewPosition() // { // // 更新浮动窗口位置参数 // wmParams.x = (int) (x - mTouchStartX); // wmParams.y = (int) (y - mTouchStartY); // wm.updateViewLayout(mlayoutView, wmParams); // } public static void updateViewSize() { if(width<0)width=0; if(height<0)height=0; surfaceView.setLayoutParams(new FrameLayout.LayoutParams((int)width, (int)height)); } //放大 public static void zoomIn(){ wmParams.width = wmParams.width + 20; wmParams.height = wmParams.height + 20; //wm.updateViewLayout(mlayoutView, wmParams); surfaceView.setLayoutParams(new FrameLayout.LayoutParams(wmParams.width, wmParams.height)); } //缩小 public static void zoomOut(){ wmParams.width = wmParams.width - 20; wmParams.height = wmParams.height - 20; wm.updateViewLayout(mlayoutView, wmParams); } public static void updateViewPosition() { // 更新浮动窗口位置参数 if(x<0) x=0; if(y<0) y=0; wmParams.x = (int)y; wmParams.y = (int)x; wm.updateViewLayout(mlayoutView, wmParams); } public static void leftMoveView() { Log.v("smallstar", "================moveleft==================="); wmParams.x = (int) (wmParams.x - 5); //wmParams.y = (int) (y - mTouchStartY); wm.updateViewLayout(mlayoutView, wmParams); } public static void rightMoveView() { Log.v("smallstar", "================right==================="); wmParams.x = (int) (wmParams.x + 5); //wmParams.y = (int) (y - mTouchStartY); wm.updateViewLayout(mlayoutView, wmParams); } @Override public void onClick(View v) { // TODO Auto-generated method stub } }