最近要做視頻直播類的app,之前基本沒有接觸過多媒體開發,在網上找了一些博客和代碼看了下,慢慢入手。
先從最基本的使用開始,功能包括
* 使用surfaceView在非主線程繪制界面
* 使用surfaceView和medioVideo播放本地和網絡視頻
先上效果圖
繪制界面
播放視頻
代碼
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tech.myapplication">
?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.INTERNET"/>
?
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
?
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
?
</manifest>
?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.tech.myapplication.MainActivity">
?
<SurfaceView
android:id="@+id/surface"
android:layout_width="match_parent"
android:layout_height="300dp" />
<Button
android:id="@+id/play"
android:text="play"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
?
</LinearLayout>
package com.tech.myapplication;
?
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
?
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
?
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
?
private SurfaceView surfaceView;
private Button play;
private MediaPlayer mediaPlay;
private SurfaceHolder holder;
private int possion = 0;
?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 自定義surfaceView繪圖,就調用下面
*/
// setContentView(new MySurfaceView(this));
/**
* 用surfaceView播放視頻
*/
setContentView(R.layout.activity_main);
initPlayView();
}
?
private void initPlayView() {
this.surfaceView = (SurfaceView) findViewById(R.id.surface);
this.play = (Button) findViewById(R.id.play);
this.holder = surfaceView.getHolder();
this.mediaPlay = new MediaPlayer();
//設置播放時打開屏幕
this.holder.setKeepScreenOn(true);
this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
this.holder.addCallback(new MyCallback());
play.setOnClickListener(this);
?
}
?
public void play() throws IllegalArgumentException, SecurityException,
IllegalStateException, IOException {
mediaPlay.reset();
mediaPlay.setAudioStreamType(AudioManager.STREAM_MUSIC);
//本地路徑視頻
String path = null;
if (android.os.Environment.getExternalStorageState().
equals(Environment.MEDIA_MOUNTED)){
path = Environment.getExternalStorageDirectory().toString()+"/testfile.mp4";
}
mediaPlay.setDataSource("http://play13.68mtv.com/play13/60329.mp4");
// 把視頻輸出到SurfaceView上
mediaPlay.setDisplay(holder);
//不要用prepareAsync,用了也報錯,ERROR(-38,0)
mediaPlay.prepare();
mediaPlay.start();
}
?
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.play:
try {
play();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
?
private class MyCallback implements SurfaceHolder.Callback{
?
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
play();
mediaPlay.seekTo(possion);
} catch (IOException e) {
e.printStackTrace();
}
}
?
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
?
}
?
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
?
}
}
?
@Override
protected void onPause() {
if (mediaPlay.isPlaying()) {
// 保存當前播放的位置
possion = mediaPlay.getCurrentPosition();
mediaPlay.stop();
}
super.onPause();
}
?
@Override
protected void onDestroy() {
if (mediaPlay.isPlaying())
mediaPlay.stop();
mediaPlay.release();
super.onDestroy();
}
/***************************************************************/
?
?
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
?
private SurfaceHolder holder;
private Context context;
private MyThread myThread;
?
public MySurfaceView(Context context) {
super(context);
this.context = context;
this.holder = this.getHolder();
this.holder.addCallback(this);
this.myThread = new MyThread(holder);
}
?
?
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
myThread.isRun = true;
myThread.start();
}
?
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
?
}
?
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
myThread.isRun = false;
}
}
?
class MyThread extends Thread {
?
public boolean isRun;
private SurfaceHolder holder;
?
public MyThread(SurfaceHolder holder) {
this.holder = holder;
isRun = true;
}
?
@Override
public void run() {
super.run();
int count = 0;
while (isRun) {
Canvas c = null;
try {
synchronized (holder) {
c = holder.lockCanvas();//鎖定畫布,一般在鎖定后就可以通過其返回的畫布對象Canvas,在其上面畫圖等操作了。
c.drawColor(Color.GREEN);
Paint p = new Paint();
p.setColor(Color.WHITE);
Rect r = new Rect(100, 50, 300, 250);
c.drawRect(r, p);
p.setTextSize(40);
c.drawText("這是第" + (count++) + "秒", 100, 310, p);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (c != null) {
holder.unlockCanvasAndPost(c);//結束鎖定畫圖,并提交改變。
?
}
}
}
}
}
}
?
?