OPlayer一款用来提高你的iPhone/iPod的媒体播放能力的应用程序,支持mp3/wma/wmv/avi/rm/rmvb/mp4/3gp/mkv/mpg格式.视频文件存放于/privatear/mobile/Documents/download目录.
项目除了jni文件,共有17个目标文件!项目如图:
效果如图:
由于模拟器上缺少必要设备,所以不可以在模拟器上播放!
分析如下:
FileBusiness类:文件操作!
class SQLiteHelper extends SQLiteOpenHelper:操作数据库。
TableColumns类:播放视频的必须信息表类。
PFile类:记录视频文件信息类。
FragmentBase类:UI类,Fragment 表现 Activity 中用UI的一个行为或者一部分. 可以组合多个fragment放在一个单独的activity中来创建一个多界面区域的UI,并可以在多个activity里重用某一个fragment.把fragment 想象成一个activity的模块化区域, 有它自己的生命周期, 接收属于它的输入事件, 并且可以在activity运行期间添加和删除.
class FragmentFile extends FragmentBase implements OnItemClickListener:遍历所有文件然后读取以及定位。
class FragmentOnline extends FragmentBase implements OnItemClickListener:在线视频界面!
class MainFragmentActivity extends FragmentActivity implements OnClickListener : 主界面!
class PlayerActivity extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback : 视频播放类!
class VideoPlayerActivity extends Activity implements OnCompletionListener :视频视图操作界面!
abstract class ArrayAdapter<T> extends BaseAdapter :抽象数据队列适配器!
abstract class FilterArrayAdapter<T> extends ArrayAdapter<T> :过滤字符适配器 !
VideoThumbnailUtils类:视频视图设置信息!
其它的就不介绍了!~
程序进入时会先遍历目标,检索文件信息,如下:
/** 扫描SD卡 */ private class ScanVideoTask extends AsyncTask<Void, File, ArrayList<PFile>> { private ProgressDialog pd; private ArrayList<File> files = new ArrayList<File>(); @Override protected void onPreExecute() { super.onPreExecute(); pd = new ProgressDialog(getActivity()); pd.setMessage("正在扫描视频文件..."); pd.show(); } @Override protected ArrayList<PFile> doInBackground(Void... params) { // ~~~ 遍历文件夹 eachAllMedias(Environment.getExternalStorageDirectory()); // ~~~ 入库 SQLiteHelper sqlite = new SQLiteHelper(getActivity()); SQLiteDatabase db = sqlite.getWritableDatabase(); try { db.beginTransaction(); SQLiteStatement stat = db.compileStatement("INSERT INTO files(" + FilesColumns.COL_TITLE + "," + FilesColumns.COL_TITLE_PINYIN + "," + FilesColumns.COL_PATH + "," + FilesColumns.COL_LAST_ACCESS_TIME + "," + FilesColumns.COL_FILE_SIZE + ") VALUES(?,?,?,?,?)"); for (File f : files) { String name = f.getName(); int index = 1; stat.bindString(index++, name);// title stat.bindString(index++, PinyinUtils.chineneToSpell(name.charAt(0) + ""));// title_pinyin stat.bindString(index++, f.getPath());// path stat.bindLong(index++, System.currentTimeMillis());// last_access_time stat.bindLong(index++, f.length()); stat.execute(); } db.setTransactionSuccessful(); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); db.close(); } // ~~~ 查询数据 return FileBusiness.getAllSortFiles(getActivity()); } @Override protected void onProgressUpdate(final File... values) { pd.setMessage(values[0].getName()); } /** 遍历所有文件夹,查找出视频文件 */ public void eachAllMedias(File f) { if (f != null && f.exists() && f.isDirectory()) { File[] files = f.listFiles(); if (files != null) { for (File file : f.listFiles()) { publishProgress(file); if (file.isDirectory()) { eachAllMedias(file); } else if (file.exists() && file.canRead() && FileUtils.isVideo(file)) { this.files.add(file); } } } } } @Override protected void onPostExecute(ArrayList<PFile> result) { super.onPostExecute(result); mAdapter = new FileAdapter(getActivity(), result); mListView.setAdapter(mAdapter); pd.dismiss(); } }
//播放界面 public class PlayerActivity extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback { private static final String TAG = "MediaPlayerDemo"; private int mVideoWidth; private int mVideoHeight; private MediaPlayer mMediaPlayer; private SurfaceView mPreview; private SurfaceHolder holder; private String path = Environment.getExternalStorageDirectory() + "/Moon.mp4"; private boolean mIsVideoSizeKnown = false; private boolean mIsVideoReadyToBePlayed = false; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.mediaplayer); mPreview = (SurfaceView) findViewById(R.id.surface); holder = mPreview.getHolder(); holder.addCallback(this); } private void playVideo() { doCleanUp(); try { mMediaPlayer = new MediaPlayer(this); mMediaPlayer.setDataSource(path); mMediaPlayer.setDisplay(holder); mMediaPlayer.prepareAsync(); mMediaPlayer.setScreenOnWhilePlaying(true); mMediaPlayer.setOnBufferingUpdateListener(this); mMediaPlayer.setOnCompletionListener(this); mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnVideoSizeChangedListener(this); } catch (Exception e) { Log.e(TAG, "error: " + e.getMessage(), e); } } public void onBufferingUpdate(MediaPlayer arg0, int percent) { Log.d(TAG, "onBufferingUpdate percent:" + percent); } public void onCompletion(MediaPlayer arg0) { Log.d(TAG, "onCompletion called"); mMediaPlayer.release(); } public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { Log.v(TAG, "onVideoSizeChanged called"); if (width == 0 || height == 0) { Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")"); return; } mIsVideoSizeKnown = true; mVideoWidth = width; mVideoHeight = height; if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { startVideoPlayback(); } } public void onPrepared(MediaPlayer mediaplayer) { Log.d(TAG, "onPrepared called"); mIsVideoReadyToBePlayed = true; if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { startVideoPlayback(); } } public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { Log.d(TAG, "surfaceChanged called" + i + " " + j + " " + k); } public void surfaceDestroyed(SurfaceHolder surfaceholder) { Log.d(TAG, "surfaceDestroyed called"); } public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "surfaceCreated called"); playVideo(); } @Override protected void onPause() { super.onPause(); releaseMediaPlayer(); doCleanUp(); } @Override protected void onDestroy() { super.onDestroy(); releaseMediaPlayer(); doCleanUp(); } private void releaseMediaPlayer() { if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } } private void doCleanUp() { mVideoWidth = 0; mVideoHeight = 0; mIsVideoReadyToBePlayed = false; mIsVideoSizeKnown = false; } private void startVideoPlayback() { Log.v(TAG, "startVideoPlayback"); holder.setFixedSize(mVideoWidth, mVideoHeight); mMediaPlayer.start(); } }
//视频视图操作界面 public class VideoPlayerActivity extends Activity implements OnCompletionListener { private String path; private VideoView mVideoView; private View mVolumeBrightnessLayout; private ImageView mOperationBg; private ImageView mOperationPercent; private AudioManager mAudioManager; /** 最大声音 */ private int mMaxVolume; /** 当前声音 */ private int mVolume = -1; /** 当前亮度 */ private float mBrightness = -1f; /** 当前缩放模式 */ private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM; private GestureDetector mGestureDetector; private MediaController mMediaController; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); Intent intent = getIntent(); path = intent.getStringExtra("path"); if (TextUtils.isEmpty(path)) path = Environment.getExternalStorageDirectory() + "/video/你太猖狂.flv"; else if (intent.getData() != null) path = intent.getData().toString(); Log.e("VideoPlayerActivity", path); setContentView(R.layout.videoview); mVideoView = (VideoView) findViewById(R.id.surface_view); mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness); mOperationBg = (ImageView) findViewById(R.id.operation_bg); mOperationPercent = (ImageView) findViewById(R.id.operation_percent); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mMaxVolume = mAudioManager .getStreamMaxVolume(AudioManager.STREAM_MUSIC); if (path.startsWith("http:")) mVideoView.setVideoURI(Uri.parse(path)); else mVideoView.setVideoPath(path); // mVideoView.setOnCompletionListener(this); mMediaController = new MediaController(this); mVideoView.setMediaController(mMediaController); mVideoView.requestFocus(); // mVideoView. // MediaPlayer mGestureDetector = new GestureDetector(this, new MyGestureListener()); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } @Override protected void onPause() { super.onPause(); mVideoView.pause(); } @Override protected void onResume() { super.onResume(); mVideoView.resume(); } @Override protected void onDestroy() { super.onDestroy(); mVideoView.stopPlayback(); } @Override public boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) return true; // 处理手势结束 switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: endGesture(); break; } return super.onTouchEvent(event); } /** 手势结束 */ private void endGesture() { mVolume = -1; mBrightness = -1f; // 隐藏 mDismissHandler.removeMessages(0); mDismissHandler.sendEmptyMessageDelayed(0, 500); } private class MyGestureListener extends SimpleOnGestureListener { /** 双击 */ @Override public boolean onDoubleTap(MotionEvent e) { if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM) mLayout = VideoView.VIDEO_LAYOUT_ORIGIN; else mLayout++; if (mVideoView != null) mVideoView.setVideoLayout(mLayout, 0); return true; } /** 滑动 */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { float mOldX = e1.getX(), mOldY = e1.getY(); int y = (int) e2.getRawY(); Display disp = getWindowManager().getDefaultDisplay(); int windowWidth = disp.getWidth(); int windowHeight = disp.getHeight(); if (mOldX > windowWidth * 4.0 / 5)// 右边滑动 onVolumeSlide((mOldY - y) / windowHeight); else if (mOldX < windowWidth / 5.0)// 左边滑动 onBrightnessSlide((mOldY - y) / windowHeight); return super.onScroll(e1, e2, distanceX, distanceY); } } /** 定时隐藏 */ private Handler mDismissHandler = new Handler() { @Override public void handleMessage(Message msg) { mVolumeBrightnessLayout.setVisibility(View.GONE); } }; /** * 滑动改变声音大小 * * @param percent */ private void onVolumeSlide(float percent) { if (mVolume == -1) { mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (mVolume < 0) mVolume = 0; // 显示 mOperationBg.setImageResource(R.drawable.video_volumn_bg); mVolumeBrightnessLayout.setVisibility(View.VISIBLE); } int index = (int) (percent * mMaxVolume) + mVolume; if (index > mMaxVolume) index = mMaxVolume; else if (index < 0) index = 0; // 变更声音 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0); // 变更进度条 ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume; mOperationPercent.setLayoutParams(lp); } /** * 滑动改变亮度 * * @param percent */ private void onBrightnessSlide(float percent) { if (mBrightness < 0) { mBrightness = getWindow().getAttributes().screenBrightness; if (mBrightness <= 0.00f) mBrightness = 0.50f; if (mBrightness < 0.01f) mBrightness = 0.01f; // 显示 mOperationBg.setImageResource(R.drawable.video_brightness_bg); mVolumeBrightnessLayout.setVisibility(View.VISIBLE); } WindowManager.LayoutParams lpa = getWindow().getAttributes(); lpa.screenBrightness = mBrightness + percent; if (lpa.screenBrightness > 1.0f) lpa.screenBrightness = 1.0f; else if (lpa.screenBrightness < 0.01f) lpa.screenBrightness = 0.01f; getWindow().setAttributes(lpa); ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness); mOperationPercent.setLayoutParams(lp); } @Override public void onConfigurationChanged(Configuration newConfig) { if (mVideoView != null) mVideoView.setVideoLayout(mLayout, 0); super.onConfigurationChanged(newConfig); } // private void release() { // if (isInitialized()) { // if (Build.VERSION.SDK_INT > 13) { // android.os.Process.killProcess(android.os.Process.myPid()); // } else { // stopPlayer(); // vPlayer.release(); // vPlayer.releaseContext(); // } // } // } @Override public void onCompletion(MediaPlayer player) { finish(); } }