本文主要講述了在Android項目中模仿微信的拍攝和上傳短視頻功能,點擊開始拍攝,設置最長拍攝時間,現在把實現思路和代碼整理出來分享給Android程序員兄弟們,希望給他們的開發工作帶來幫助。
1.視頻錄製自定義控件:
1 |
<span style= "font-size: medium;" > /** |
2 |
* 視頻播放控件 |
3 |
*/ |
4 |
public class
MovieRecorderView extends
LinearLayout implements
OnErrorListener { |
5 |
6 |
private
SurfaceView mSurfaceView; |
7 |
private
SurfaceHolder mSurfaceHolder; |
8 |
private
ProgressBar mProgressBar; |
9 |
10 |
private
MediaRecorder mMediaRecorder; |
11 |
private
Camera mCamera; |
12 |
private
Timer mTimer; // 計時器 |
13 |
private
OnRecordFinishListener mOnRecordFinishListener; // 錄製完成回調接口 |
14 |
15 |
private
int mWidth; // 視頻分辨率寬度 |
16 |
private
int mHeight; // 視頻分辨率高度 |
17 |
private
boolean isOpenCamera; // 是否一開始就打開攝像頭 |
18 |
private
int mRecordMaxTime; // 一次拍攝最長時間 |
19 |
private
int mTimeCount; // 時間計數 |
20 |
private
File mVecordFile = null ; // 文件 |
21 |
22 |
public
MovieRecorderView(Context context) { |
23 |
this (context,
null ); |
24 |
} |
25 |
26 |
public
MovieRecorderView(Context context, AttributeSet attrs) { |
27 |
this (context, attrs,
0 ); |
28 |
} |
29 |
30 |
@SuppressLint ( "NewApi" ) |
31 |
public
MovieRecorderView(Context context, AttributeSet attrs,
int defStyle) { |
32 |
super (context, attrs, defStyle); |
33 |
34 |
TypedArray a = context.obtainStyledAttributes(attrs, |
35 |
R.styleable.MovieRecorderView, defStyle,
0 ); |
36 |
mWidth = a.getInteger(R.styleable.MovieRecorderView_width,
320 ); // 默認320 |
37 |
mHeight = a.getInteger(R.styleable.MovieRecorderView_height,
240 ); // 默認240 |
38 |
39 |
isOpenCamera = a.getBoolean( |
40 |
R.styleable.MovieRecorderView_is_open_camera,
true ); // 默認打開 |
41 |
mRecordMaxTime = a.getInteger( |
42 |
R.styleable.MovieRecorderView_record_max_time,
10 ); // 默認爲10 |
43 |
44 |
LayoutInflater.from(context) |
45 |
.inflate(R.layout.movie_recorder_view,
this ); |
46 |
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview); |
47 |
mProgressBar = (ProgressBar) findViewById(R.id.progressBar); |
48 |
mProgressBar.setMax(mRecordMaxTime); // 設置進度條最大量 |
49 |
50 |
mSurfaceHolder = mSurfaceView.getHolder(); |
51 |
mSurfaceHolder.addCallback( new
CustomCallBack()); |
52 |
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); |
53 |
54 |
a.recycle(); |
55 |
} |
56 |
57 |
/** |
58 |
*
|
59 |
*/ |
60 |
private
class CustomCallBack implements
Callback { |
61 |
62 |
@Override |
63 |
public
void surfaceCreated(SurfaceHolder holder) { |
64 |
if
(!isOpenCamera) |
65 |
return ; |
66 |
try
{ |
67 |
initCamera(); |
68 |
}
catch (IOException e) { |
69 |
e.printStackTrace(); |
70 |
} |
71 |
} |
72 |
73 |
@Override |
74 |
public
void surfaceChanged(SurfaceHolder holder,
int format, int
width, |
75 |
int
height) { |
76 |
77 |
} |
78 |
79 |
@Override |
80 |
public
void surfaceDestroyed(SurfaceHolder holder) { |
81 |
if
(!isOpenCamera) |
82 |
return ; |
83 |
freeCameraResource(); |
84 |
} |
85 |
86 |
} |
87 |
88 |
/** |
89 |
* 初始化攝像頭 |
90 |
*/ |
91 |
private
void initCamera() throws
IOException { |
92 |
if
(mCamera != null ) { |
93 |
freeCameraResource(); |
94 |
} |
95 |
try
{ |
96 |
mCamera = Camera.open(); |
97 |
}
catch (Exception e) { |
98 |
e.printStackTrace(); |
99 |
freeCameraResource(); |
100 |
} |
101 |
if
(mCamera == null ) |
102 |
return ; |
103 |
104 |
setCameraParams(); |
105 |
mCamera.setDisplayOrientation( 90 ); |
106 |
mCamera.setPreviewDisplay(mSurfaceHolder); |
107 |
mCamera.startPreview(); |
108 |
mCamera.unlock(); |
109 |
} |
110 |
111 |
/** |
112 |
* 設置攝像頭爲豎屏 |
113 |
*/ |
114 |
private
void setCameraParams() { |
115 |
if
(mCamera != null ) { |
116 |
Parameters params = mCamera.getParameters(); |
117 |
params.set( "orientation" ,
"portrait" ); |
118 |
mCamera.setParameters(params); |
119 |
} |
120 |
} |
121 |
122 |
/** |
123 |
* 釋放攝像頭資源 |
124 |
*/ |
125 |
private
void freeCameraResource() { |
126 |
if
(mCamera != null ) { |
127 |
mCamera.setPreviewCallback( null ); |
128 |
mCamera.stopPreview(); |
129 |
mCamera.lock(); |
130 |
mCamera.release(); |
131 |
mCamera =
null ; |
132 |
} |
133 |
} |
134 |
135 |
private
void createRecordDir() { |
136 |
//錄製的視頻保存文件夾 |
137 |
File sampleDir =
new File(Environment.getExternalStorageDirectory() |
138 |
+ File.separator +
"ysb/video/" ); //錄製視頻的保存地址 |
139 |
if
(!sampleDir.exists()) { |
140 |
sampleDir.mkdirs(); |
141 |
} |
142 |
File vecordDir = sampleDir; |
143 |
// 創建文件 |
144 |
try
{ |
145 |
mVecordFile = File.createTempFile( "recording" ,
".mp4" , vecordDir); // mp4格式的錄製的視頻文件 |
146 |
}
catch (IOException e) { |
147 |
e.printStackTrace(); |
148 |
} |
149 |
} |
150 |
151 |
/** |
152 |
* 初始化 |
153 |
* @throws IOException |
154 |
*/ |
155 |
@SuppressLint ( "NewApi" ) |
156 |
private
void initRecord() throws
IOException { |
157 |
mMediaRecorder =
new MediaRecorder(); |
158 |
mMediaRecorder.reset(); |
159 |
if
(mCamera != null ) |
160 |
mMediaRecorder.setCamera(mCamera); |
161 |
mMediaRecorder.setOnErrorListener( this ); |
162 |
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); |
163 |
mMediaRecorder.setVideoSource(VideoSource.CAMERA); // 視頻源 |
164 |
mMediaRecorder.setAudioSource(AudioSource.MIC); // 音頻源 |
165 |
mMediaRecorder.setOutputFormat(OutputFormat.MPEG_4); // 視頻輸出格式 |
166 |
mMediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB); // 音頻格式 |
167 |
mMediaRecorder.setVideoSize(mWidth, mHeight); // 設置分辨率: |
168 |
// mMediaRecorder.setVideoFrameRate(16);// 這個我把它去掉了,感覺沒什麼用 |
169 |
mMediaRecorder.setVideoEncodingBitRate( 1
* 1024
* 1024 * 100 ); // 設置幀頻率,然後就清晰了 |
170 |
mMediaRecorder.setOrientationHint( 90 ); // 輸出旋轉90度,保持豎屏錄製 |
171 |
mMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP); // 視頻錄製格式 |
172 |
// mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000); |
173 |
mMediaRecorder.setOutputFile(mVecordFile.getAbsolutePath()); |
174 |
mMediaRecorder.prepare(); |
175 |
try
{ |
176 |
mMediaRecorder.start(); |
177 |
}
catch (IllegalStateException e) { |
178 |
e.printStackTrace(); |
179 |
}
catch (RuntimeException e) { |
180 |
e.printStackTrace(); |
181 |
}
catch (Exception e) { |
182 |
e.printStackTrace(); |
183 |
} |
184 |
} |
185 |
186 |
/** |
187 |
* 開始錄製視頻 |
188 |
* @param fileName |
189 |
* 視頻儲存位置 |
190 |
* @param onRecordFinishListener |
191 |
* 達到指定時間之後回調接口 |
192 |
*/ |
193 |
public
void record( final
OnRecordFinishListener onRecordFinishListener) { |
194 |
this .mOnRecordFinishListener = onRecordFinishListener; |
195 |
createRecordDir(); |
196 |
try
{ |
197 |
if
(!isOpenCamera) // 如果未打開攝像頭,則打開 |
198 |
initCamera(); |
199 |
initRecord(); |
200 |
mTimeCount =
0 ; // 時間計數器重新賦值 |
201 |
mTimer =
new Timer(); |
202 |
mTimer.schedule( new
TimerTask() { |
203 |
204 |
@Override |
205 |
public
void run() { |
206 |
mTimeCount++; |
207 |
mProgressBar.setProgress(mTimeCount); // 設置進度條 |
208 |
if
(mTimeCount == mRecordMaxTime) { // 達到指定時間,停止拍攝 |
209 |
stop(); |
210 |
if
(mOnRecordFinishListener != null ) |
211 |
mOnRecordFinishListener.onRecordFinish(); |
212 |
} |
213 |
} |
214 |
},
0 , 1000 ); |
215 |
}
catch (IOException e) { |
216 |
e.printStackTrace(); |
217 |
} |
218 |
} |
219 |
220 |
/** |
221 |
* 停止拍攝 |
222 |
*/ |
223 |
public
void stop() { |
224 |
stopRecord(); |
225 |
releaseRecord(); |
226 |
freeCameraResource(); |
227 |
} |
228 |
229 |
/** |
230 |
* 停止錄製 |
231 |
*/ |
232 |
public
void stopRecord() { |
233 |
mProgressBar.setProgress( 0 ); |
234 |
if
(mTimer != null ) |
235 |
mTimer.cancel(); |
236 |
if
(mMediaRecorder != null ) { |
237 |
// 設置後不會崩 |
238 |
mMediaRecorder.setOnErrorListener( null ); |
239 |
mMediaRecorder.setPreviewDisplay( null ); |
240 |
try
{ |
241 |
mMediaRecorder.stop(); |
242 |
}
catch (IllegalStateException e) { |
243 |
e.printStackTrace(); |
244 |
}
catch (RuntimeException e) { |
245 |
e.printStackTrace(); |
246 |
}
catch (Exception e) { |
247 |
e.printStackTrace(); |
248 |
} |
249 |
} |
250 |
} |
251 |
252 |
/** |
253 |
* 釋放資源 |
254 |
*/ |
255 |
private
void releaseRecord() { |
256 |
if
(mMediaRecorder != null ) { |
257 |
mMediaRecorder.setOnErrorListener( null ); |
258 |
try
{ |
259 |
mMediaRecorder.release(); |
260 |
}
catch (IllegalStateException e) { |
261 |
e.printStackTrace(); |
262 |
}
catch (Exception e) { |
263 |
e.printStackTrace(); |
264 |
} |
265 |
} |
266 |
mMediaRecorder =
null ; |
267 |
} |
268 |
269 |
public
int getTimeCount() { |
270 |
return
mTimeCount; |
271 |
} |
272 |
273 |
//返回錄製的視頻文件 |
274 |
public
File getmVecordFile() { |
275 |
return
mVecordFile; |
276 |
} |
277 |
278 |
/** |
279 |
* 錄製完成回調接口 |
280 |
*/ |
281 |
public
interface OnRecordFinishListener { |
282 |
public
void onRecordFinish(); |
283 |
} |
284 |
285 |
@Override |
286 |
public
void onError(MediaRecorder mr,
int what, int
extra) { |
287 |
try
{ |
288 |
if
(mr != null ) |
289 |
mr.reset(); |
290 |
}
catch (IllegalStateException e) { |
291 |
e.printStackTrace(); |
292 |
}
catch (Exception e) { |
293 |
e.printStackTrace(); |
294 |
} |
295 |
} |
296 |
}</span> |
2.視頻錄製界面文件movie_recorder_view.xml:
1 |
<span style= "font-size: medium;" ><?xml version= "1.0"
encoding= "utf-8" ?> |
2 |
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" |
3 |
xmlns:tools= "http://schemas.android.com/tools" |
4 |
android:layout_width= "match_parent" |
5 |
android:layout_height= "match_parent" |
6 |
android:background= "@android:color/background_dark" |
7 |
android:orientation= "vertical" > |
8 |
9 |
<SurfaceView
|
10 |
android:id= "@+id/surfaceview" |
11 |
android:layout_width= "fill_parent" |
12 |
android:layout_height= "0dp" |
13 |
android:layout_weight= "1" |
14 |
/> |
15 |
16 |
<ProgressBar |
17 |
android:id= "@+id/progressBar" |
18 |
style= "?android:attr/progressBarStyleHorizontal" |
19 |
android:layout_width= "match_parent" |
20 |
android:layout_height= "2dp" |
21 |
/> |
22 |
23 |
</LinearLayout></span> |
做好這些準備工作,下面我們就可以開始設計我們的視頻錄製功能了。PS:以上代碼取至網上,在此向大牛致敬。
3.拍攝主界面,拍攝界面有兩部分組成,上面是視頻拍攝控件顯示,下面是用戶點擊拍攝按鈕,配置文件:
1 |
<span style= "font-size: medium;" ><?xml version= "1.0"
encoding= "utf-8" ?> |
2 |
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" |
3 |
xmlns:tools= "http://schemas.android.com/tools" |
4 |
android:layout_width= "match_parent" |
5 |
android:layout_height= "match_parent" |
6 |
android:background= "@android:color/white" |
7 |
android:orientation= "vertical" > |
8 |
9 |
<com.example.wechatvideorecorddemo.MovieRecorderView |
10 |
android:id= "@+id/movieRecorderView" |
11 |
android:layout_width= "match_parent" |
12 |
android:layout_height= "0dp" |
13 |
android:layout_weight= "1" |
14 |
android:layout_margin= "3dp"
/> |
15 |
16 |
<Button |
17 |
android:id= "@+id/shoot_button" |
18 |
android:layout_width= "wrap_content" |
19 |
android:layout_height= "wrap_content" |
20 |
android:layout_gravity= "center" |
21 |
android:background= "@drawable/bg_movie_add_shoot" |
22 |
android:text= "按住拍" |
23 |
android:textColor= "#20b6ff" /> |
24 |
25 |
</LinearLayout></span> |
4.有了主界面的視圖,下面我們就開始書寫我們的Activity文件MainActivity.java:
1 |
<span style= "font-size: medium;" > public
class MainActivity extends
Activity { |
2 |
3 |
private
MovieRecorderView mRecorderView; //視頻錄製控件 |
4 |
private
Button mShootBtn; //視頻開始錄製按鈕 |
5 |
private
boolean isFinish = true ; |
6 |
private
boolean success = false ; //防止錄製完成後出現多次跳轉事件 |
7 |
8 |
@Override |
9 |
protected
void onCreate(Bundle savedInstanceState) { |
10 |
super .onCreate(savedInstanceState); |
11 |
setContentView(R.layout.activity_main); |
12 |
mRecorderView = (MovieRecorderView) findViewById(R.id.movieRecorderView); |
13 |
mShootBtn = (Button) findViewById(R.id.shoot_button); |
14 |
15 |
//用戶長按事件監聽 |
16 |
mShootBtn.setOnTouchListener( new
OnTouchListener() { |
17 |
18 |
@Override |
19 |
public
boolean onTouch(View v, MotionEvent event) { |
20 |
if
(event.getAction() == MotionEvent.ACTION_DOWN) { //用戶按下拍攝按鈕 |
21 |
mShootBtn.setBackgroundResource(R.drawable.bg_movie_add_shoot_select); |
22 |
mRecorderView.record( new
OnRecordFinishListener() { |
23 |
24 |
@Override |
25 |
public
void onRecordFinish() { |
26 |
if (!success&&mRecorderView.getTimeCount()< 10 ){ //判斷用戶按下時間是否大於10秒 |
27 |
success =
true ; |
28 |
handler.sendEmptyMessage( 1 ); |
29 |
} |
30 |
} |
31 |
}); |
32 |
}
else if
(event.getAction() == MotionEvent.ACTION_UP) { //用戶擡起拍攝按鈕 |
33 |
mShootBtn.setBackgroundResource(R.drawable.bg_movie_add_shoot); |
34 |
if
(mRecorderView.getTimeCount() > 3 ){ //判斷用戶按下時間是否大於3秒 |
35 |
if (!success){ |
36 |
success =
true ; |
37 |
handler.sendEmptyMessage( 1 ); |
38 |
} |
39 |
}
else { |
40 |
success =
false ; |
41 |
if
(mRecorderView.getmVecordFile() != null ) |
42 |
mRecorderView.getmVecordFile().delete(); //刪除錄製的過短視頻 |
43 |
mRecorderView.stop(); //停止錄製 |
44 |
Toast.makeText(MainActivity. this ,
"視頻錄製時間太短" , Toast.LENGTH_SHORT).show(); |
45 |
} |
46 |
} |
47 |
return
true ; |
48 |
} |
49 |
}); |
50 |
} |
51 |
52 |
@Override |
53 |
public
void onResume() { |
54 |
super .onResume(); |
55 |
isFinish =
true ; |
56 |
if
(mRecorderView.getmVecordFile() != null ) |
57 |
mRecorderView.getmVecordFile().delete(); //視頻使用後刪除 |
58 |
} |
59 |
60 |
@Override |
61 |
public
void onSaveInstanceState(Bundle outState) { |
62 |
super .onSaveInstanceState(outState); |
63 |
isFinish =
false ; |
64 |
success =
false ; |
65 |
mRecorderView.stop(); //停止錄製 |
66 |
} |
67 |
68 |
@Override |
69 |
public
void onPause() { |
70 |
super .onPause(); |
71 |
} |
72 |
73 |
@Override |
74 |
public
void onDestroy() { |
75 |
super .onDestroy(); |
76 |
} |
77 |
78 |
private
Handler handler = new
Handler() { |
79 |
@Override |
80 |
public
void handleMessage(Message msg) { |
81 |
if (success){ |
82 |
finishActivity(); |
83 |
} |
84 |
} |
85 |
}; |
86 |
87 |
//視頻錄製結束後,跳轉的函數 |
88 |
private
void finishActivity() { |
89 |
if
(isFinish) { |
90 |
mRecorderView.stop(); |
91 |
Intent intent =
new Intent( this , SuccessActivity. class ); |
92 |
Bundle bundle =
new Bundle(); |
93 |
bundle.putString( "text" , mRecorderView.getmVecordFile().toString()); |
94 |
intent.putExtras(bundle); |
95 |
startActivity(intent); |
96 |
} |
97 |
success =
false ; |
98 |
} |
99 |
100 |
/** |
101 |
* 錄製完成回調 |
102 |
*/ |
103 |
public
interface OnShootCompletionListener { |
104 |
public
void OnShootSuccess(String path,
int second); |
105 |
public
void OnShootFailure(); |
106 |
} |
107 |
}</span> |
到這裏我們仿微信的短視頻拍攝就已經大功告成,那麼下面我們檢驗一下,我們錄製的效果如何,下面我以Android提供的視頻播放控件(VideoView)爲大家介紹一下如何播放錄製的短視頻。
5.播放視頻的配置文件activity_success.xml:
1 |
<span style= "font-size: medium;" ><?xml version= "1.0"
encoding= "utf-8" ?> |
2 |
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" |
3 |
xmlns:tools= "http://schemas.android.com/tools" |
4 |
android:layout_width= "match_parent" |
5 |
android:layout_height= "match_parent" |
6 |
android:background= "@android:color/white" |
7 |
android:orientation= "vertical" > |
8 |
9 |
<TextView
|
10 |
android:id= "@+id/text" |
11 |
android:layout_width= "wrap_content" |
12 |
android:layout_height= "wrap_content" |
13 |
android:layout_gravity= "center" |
14 |
android:text= "@string/app_name"
/> |
15 |
<LinearLayout
|
16 |
android:layout_width= "match_parent" |
17 |
android:layout_height= "wrap_content" |
18 |
android:orientation= "horizontal" |
19 |
> |
20 |
<Button
|
21 |
android:id= "@+id/button1" |
22 |
android:layout_width= "match_parent" |
23 |
android:layout_height= "wrap_content" |
24 |
android:layout_weight= "1" |
25 |
android:gravity= "center" |
26 |
android:padding= "5dp" |
27 |
android:text= "播放" |
28 |
/> |
29 |
<Button
|
30 |
android:id= "@+id/button2" |
31 |
android:layout_width= "match_parent" |
32 |
android:layout_height= "wrap_content" |
33 |
android:layout_weight= "1" |
34 |
android:gravity= "center" |
35 |
android:padding= "5dp" |
36 |
android:text= "暫停" |
37 |
/> |
38 |
<Button
|
39 |
android:id= "@+id/button3" |
40 |
android:layout_width= "match_parent" |
41 |
android:layout_height= "wrap_content" |
42 |
android:layout_weight= "1" |
43 |
android:gravity= "center" |
44 |
android:padding= "5dp" |
45 |
android:text= "重播" |
46 |
/> |
47 |
<Button
|
48 |
android:id= "@+id/button4" |
49 |
android:layout_width= "match_parent" |
50 |
android:layout_height= "wrap_content" |
51 |
android:layout_weight= "1" |
52 |
android:gravity= "center" |
53 |
android:padding= "5dp" |
54 |
android:text= "視頻長度" |
55 |
/> |
56 |
</LinearLayout> |
57 |
<VideoView |
58 |
android:id= "@+id/videoView1" |
59 |
android:layout_width= "wrap_content" |
60 |
android:layout_height= "500dp"
/> |
61 |
62 |
</LinearLayout></span> |
6.視頻播放的控制代碼SuccessActivity.java:
1 |
<span style= "font-size: medium;" > public
class SuccessActivity extends
Activity implements
OnClickListener{ |
2 |
3 |
private
TextView text; //視頻保存的路徑 |
4 |
private
Button button1; //播放開關 |
5 |
private
Button button2; //暫停開關 |
6 |
private
Button button3; //重新播放開關 |
7 |
private
Button button4; //視頻大小開關 |
8 |
private
VideoView videoView1; //視頻播放控件 |
9 |
private
String file; //視頻路徑 |
10 |
11 |
@Override |
12 |
protected
void onCreate(Bundle savedInstanceState) { |
13 |
super .onCreate(savedInstanceState); |
14 |
setContentView(R.layout.activity_success); |
15 |
Bundle bundle = getIntent().getExtras(); |
16 |
file = bundle.getString( "text" ); //獲得拍攝的短視頻保存地址 |
17 |
init(); |
18 |
setValue(); |
19 |
} |
20 |
21 |
//初始化 |
22 |
private
void init() { |
23 |
text = (TextView) findViewById(R.id.text); |
24 |
button1 = (Button) findViewById(R.id.button1); |
25 |
button2 = (Button) findViewById(R.id.button2); |
26 |
button3 = (Button) findViewById(R.id.button3); |
27 |
button4 = (Button) findViewById(R.id.button4); |
28 |
videoView1 = (VideoView) findViewById(R.id.videoView1); |
29 |
} |
30 |
31 |
//設置 |
32 |
private
void setValue() { |
33 |
text.setText(file); |
34 |
button1.setOnClickListener( this ); |
35 |
button2.setOnClickListener( this ); |
36 |
button3.setOnClickListener( this ); |
37 |
button4.setOnClickListener( this ); |
38 |
videoView1.setVideoPath(file); |
39 |
} |
40 |
41 |
@Override |
42 |
public
void onClick(View v) { |
43 |
switch
(v.getId()) { |
44 |
case
R.id.button1: |
45 |
videoView1.start(); |
46 |
break ; |
47 |
48 |
case
R.id.button2: |
49 |
videoView1.pause();
|
50 |
break ; |
51 |
52 |
case
R.id.button3: |
53 |
videoView1.resume(); |
54 |
videoView1.start(); |
55 |
break ; |
56 |
57 |
case
R.id.button4: |
58 |
Toast.makeText( this ,
"視頻長度:" +(videoView1.getDuration()/ 1024 )+ "M" , Toast.LENGTH_SHORT).show(); |
59 |
break ; |
60 |
61 |
default : |
62 |
break ; |
63 |
} |
64 |
} |
65 |
66 |
}</span> |
功能界面截圖:
好了,到這裏關於拍攝短視頻的知識就和大家分享完畢,具體的實現很簡單,相信大家看到這裏已經已經學會了。
本文到此結束,需要的朋友可以參考下。