Android自定義視訊播放器(網路/本地)
阿新 • • 發佈:2018-12-21
最近因公司專案要求需要寫一個播放器,自帶的又不太好用,也不太好看。自能自定義啦。查看了很多資料,都沒有完善的,還好得以為前輩的指點得以完成,感謝Yang。本篇裡面我有可能有些地方寫得不好(都附上了註釋)。希望各路大神指點,虛心受教。
先來個圖(原始碼在後面附上)
視訊列表裡面的資料是本地的,如果你需要使用網路的只需要在此獲取伺服器的資料展示就行了。播放頁面在後面。
package com.eteng.moblieplayer.video; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.MediaStore; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.TextView; import com.eteng.moblieplayer.BaseActivity; import com.eteng.moblieplayer.R; import com.eteng.moblieplayer.adapter.VideoAdapter; import com.eteng.moblieplayer.beans.VideoBenas; import com.eteng.moblieplayer.utils.StringTimeUtil; import org.xutils.view.annotation.ViewInject; import java.util.ArrayList; import java.util.Formatter; import java.util.List; /** * Created by zqf on 2016/7/6. */ public class VideoActivity extends BaseActivity implements AdapterView.OnItemClickListener { private ListView video_listview; private TextView noresources_tv; private VideoBenas beans; private List<VideoBenas> data = new ArrayList<VideoBenas>(); private VideoAdapter adapter; private StringTimeUtil util; public Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: if (data != null && data.size() != 0) { noresources_tv.setVisibility(View.GONE); adapter = new VideoAdapter(data, VideoActivity.this, util); video_listview.setAdapter(adapter); } else { noresources_tv.setVisibility(View.VISIBLE); } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); settabtitle("視訊列表"); setrightvisible(View.GONE); video_listview = (ListView) findViewById(R.id.video_listviw); noresources_tv = (TextView) findViewById(R.id.noresources_tv); util = new StringTimeUtil(); getAllVideo(); video_listview.setOnItemClickListener(this); } private void getAllVideo() { new Thread(new Runnable() { @Override public void run() { ContentResolver resolver = getContentResolver(); Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; //查詢的條件 String[] projection = {MediaStore.Video.Media.TITLE, //標題 MediaStore.Video.Media.DESCRIPTION, //描述 MediaStore.Video.Media.SIZE, //大小 MediaStore.Video.Media.DURATION, //時長 MediaStore.Video.Media.DATA}; //絕對路徑 Cursor cursor = resolver.query(uri, projection, null, null, null); while (cursor.moveToNext()) { //判斷視訊大小>3MB的才新增進來。 if (cursor.getLong(2) > 3 * 1024 * 1024) { beans = new VideoBenas(); beans.setTitle(cursor.getString(0)); beans.setDescribe(cursor.getString(1)); beans.setSize(cursor.getLong(2)); beans.setLongtime(cursor.getString(3)); beans.setPath(cursor.getString(4)); data.add(beans); } } handler.sendEmptyMessage(0); } }).start(); } @Override public void leftonclick() { finish(); } @Override public void rightonclick() { } //載入子佈局內容 @Override public View setcontent() { return View.inflate(VideoActivity.this, R.layout.activity_video, null); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { VideoBenas item = data.get(position); Intent intent = new Intent(VideoActivity.this, VideoPlayerActivity.class); intent.setData(Uri.parse(item.getPath())); intent.putExtra("videotitle",item.getTitle()); startActivity(intent); } }
好了,接下來就是播放器頁面了。
最後結尾來個圖吧!package com.eteng.moblieplayer.video; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; import com.eteng.moblieplayer.BaseActivity; import com.eteng.moblieplayer.R; import com.eteng.moblieplayer.utils.StringTimeUtil; import com.eteng.moblieplayer.view.VideoView; /** * Created by zqf on 2016/7/6. * 播放頁面 */ public class VideoPlayerActivity extends BaseActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnInfoListener { private VideoView videoView; //--播放的地址uri private Uri uri; private ImageView play_imag, fullview_imag, back_imag, battery_imag; private SeekBar mseekBar; private TextView videoTitle, SystemTime; private TextView videocurrent_time, videototal_time; private StringTimeUtil utils; private MyBrodCastReceiver receiver; //設定電量 private int leave; //手勢識別器 private GestureDetector detector; //頂部佈局 private RelativeLayout top_layout; //底部佈局 private LinearLayout bottom_layout; /** * 判斷是否播放 */ private boolean isPlayer = false; /*** * 判斷Activity是否被銷燬 * --true-->銷燬 * --false -->沒有銷燬 */ private boolean isDestory = false; // private static final int PROGRESS = 1; //隱藏頂部和底部的變數 private static final int HIDE_TOPBOTTOMLAYOUT = 2; /** * 網路載入等待佈局 */ private LinearLayout ll_loading; /*** * 出現卡的緩衝載入 */ private ProgressBar pg_buff; private Handler mhandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case PROGRESS: //設定進度 int currenttime = videoView.getCurrentPosition(); videocurrent_time.setText(utils.stringfortime(currenttime)); //更新seekbar mseekBar.setProgress(currenttime); //更新電量 //電量顯示和系統時間可自行設定多久時間更新一次 setBattery(); //設定系統時間 setsystemTime(); /*** * 得到視訊快取度 * --快取比例值-0~100 */ int Percentage = videoView.getBufferPercentage(); int total = Percentage * mseekBar.getMax(); int secondaryprogress = total / 100; mseekBar.setSecondaryProgress(secondaryprogress); if (!isDestory) { mhandler.removeMessages(PROGRESS); //訊息的死迴圈--用於更新播放進度 mhandler.sendEmptyMessageDelayed(PROGRESS, 1000); } break; case HIDE_TOPBOTTOMLAYOUT: hidelayout(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); settabvisible(View.GONE); initView(); initData(); setonclick(); //得到播放地址 uri = getIntent().getData(); videoView.setVideoURI(uri); //設定路徑 videoView.setOnPreparedListener(this); //準備好的監聽事件 } private void setsystemTime() { SystemTime.setText(utils.getSystemTime()); } private void setBattery() { if (leave <= 5) { battery_imag.setImageResource(R.mipmap.icv_power_00); } else if (leave <= 20) { battery_imag.setImageResource(R.mipmap.icv_power_01); } else if (leave <= 40) { battery_imag.setImageResource(R.mipmap.icv_power_02); } else if (leave <= 60) { battery_imag.setImageResource(R.mipmap.icv_power_03); } else if (leave <= 80) { battery_imag.setImageResource(R.mipmap.icv_power_04); } else if (leave <= 100) { battery_imag.setImageResource(R.mipmap.icv_power_05); } } /*** * true--顯示--false--隱藏 */ private boolean isShowLayout = false; private void initData() { videoTitle.setText(getIntent().getStringExtra("videotitle")); isDestory = false; utils = new StringTimeUtil(); //註冊電量監聽的廣播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); receiver = new MyBrodCastReceiver(); registerReceiver(receiver, intentFilter); //例項化 detector = new GestureDetector(VideoPlayerActivity.this, new GestureDetector.OnGestureListener() { //單擊 @Override public boolean onDown(MotionEvent e) { Log.e("TAG", "onDown"); if (isShowLayout) { removeHideTopBottomLayoutMessage(); hidelayout(); } else { sendDelayedHideTopBottomLayout(); showLayout(); } return true; } //長按執行的順序---1.onDown-->2.onShowPress-->onLongPress @Override public void onShowPress(MotionEvent e) { Log.e("TAG", "onShowPress"); } //單擊後執行onDown接著執行的方法 @Override public boolean onSingleTapUp(MotionEvent e) { Log.e("TAG", "onSingleTapUp"); return false; } //滑動 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.e("TAG", "onScroll"); return false; } //長按 @Override public void onLongPress(MotionEvent e) { Log.e("TAG", "onLongPress"); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } }); } /*** * 傳送延遲隱藏 */ private void sendDelayedHideTopBottomLayout() { mhandler.sendEmptyMessageDelayed(HIDE_TOPBOTTOMLAYOUT, 5000); } /*** * 移除延遲隱藏的Handler訊息 */ private void removeHideTopBottomLayoutMessage() { mhandler.removeMessages(HIDE_TOPBOTTOMLAYOUT); } /*** * 顯示的方法 */ private void showLayout() { isShowLayout = true; top_layout.setVisibility(View.VISIBLE); bottom_layout.setVisibility(View.VISIBLE); } /*** * 隱藏的方法 */ private void hidelayout() { isShowLayout = false; top_layout.setVisibility(View.GONE); bottom_layout.setVisibility(View.GONE); } /*** * 使用手勢介面卡 * * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); detector.onTouchEvent(event); return true; //返回true視交由人為處理 } /*** * 卡或者拖動卡時候出現的回撥 * * @param mp * @param what * @param extra * @return */ @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { switch (what) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: //開始出現卡或者拖動卡 pg_buff.setVisibility(View.VISIBLE); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: //結束卡或者拖動卡情況 pg_buff.setVisibility(View.GONE); break; } return true; } private class MyBrodCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //返回一個電量的範圍值 leave = intent.getIntExtra("level", 0); } } @Override protected void onDestroy() { super.onDestroy(); isDestory = true; unregisterReceiver(receiver); receiver = null; videoView.stopPlayback(); } public void initView() { pg_buff = (ProgressBar) findViewById(R.id.pg_buff); videoView = (VideoView) findViewById(R.id.videoview); ll_loading = (LinearLayout) findViewById(R.id.ll_loading); top_layout = (RelativeLayout) findViewById(R.id.topLayout); bottom_layout = (LinearLayout) findViewById(R.id.bottomLayout); SystemTime = (TextView) findViewById(R.id.videosystemTime); battery_imag = (ImageView) findViewById(R.id.videoPower); back_imag = (ImageView) findViewById(R.id.videoBack); play_imag = (ImageView) findViewById(R.id.videoPlay); fullview_imag = (ImageView) findViewById(R.id.videoFullScreen); mseekBar = (SeekBar) findViewById(R.id.videoPlayProgress); videoTitle = (TextView) findViewById(R.id.videoTitle); videocurrent_time = (TextView) findViewById(R.id.videoCurrentProgress); videototal_time = (TextView) findViewById(R.id.videototalTime); } public void setonclick() { back_imag.setOnClickListener(onclicklistener); play_imag.setOnClickListener(onclicklistener); fullview_imag.setOnClickListener(onclicklistener); videoView.setOnInfoListener(this); mseekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { /*** * * @param seekBar-->自身的seekba * @param progress-->seekbar的位置,視訊的長度和seekbar的位置一一對應 * @param fromUser-->如果是人為的拖動值為--true,如seekbar自身在改變的值--false */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { videoView.seekTo(progress); } } /** * 手指開始拖動時進行回撥 * @param seekBar */ @Override public void onStartTrackingTouch(SeekBar seekBar) { removeHideTopBottomLayoutMessage(); } /** * 手指離開回調 * @param seekBar */ @Override public void onStopTrackingTouch(SeekBar seekBar) { sendDelayedHideTopBottomLayout(); } }); /*** * 視訊加載出錯時進行回掉 * --true-->人為處理出錯的結果 */ videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Toast.makeText(VideoPlayerActivity.this, "視訊出錯了", Toast.LENGTH_LONG).show(); finish(); return true; } }); } View.OnClickListener onclicklistener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.videoPlay: if (isPlayer) { videoView.pause(); play_imag.setImageResource(R.mipmap.icv_play); } else { videoView.start(); play_imag.setImageResource(R.mipmap.icv_pause); } isPlayer = !isPlayer; break; case R.id.videoBack: finish(); videoView.stopPlayback(); break; } } }; @Override public void leftonclick() { } @Override public void rightonclick() { } //設定子佈局 @Override public View setcontent() { return View.inflate(VideoPlayerActivity.this, R.layout.activity_videoplayer, null); } /*** * 監聽是否準備好了 * * @param mp */ @Override public void onPrepared(MediaPlayer mp) { videoView.start(); play_imag.setImageResource(R.mipmap.icv_pause); isPlayer = true; //獲取總時長 int duration = videoView.getDuration(); videototal_time.setText("/" + utils.stringfortime(duration)); //設定seekbar的最大值 mseekBar.setMax(duration); setsystemTime(); mhandler.sendEmptyMessageDelayed(PROGRESS, 1000); sendDelayedHideTopBottomLayout(); ll_loading.setVisibility(View.GONE); } }
上次忘記發源碼地址啦,給補上,抱歉。