<uses-permission android:name="android.permission.CAMERA">
<uses-feature android:name="android.hardware.camera">
<uses-feature android:name="android.hardware.camera.autofocus">
2. 再來在 layout 中加上 SurfaceView
<SurfaceView
android:id="@+id/surfaceView1"
android:layout_width="320px"
android:layout_height="240px">
</SurfaceView>
3. 程式碼
參考 Android SDK 網頁
http://developer.android.com/reference/android/hardware/Camera.html
下面是範例code
package newslab.video.server;
import android.app.Activity;
import android.hardware.Camera;
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 android.widget.TextView;
public class VideoServer extends Activity implements SurfaceHolder.Callback {
TextView testView;
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
private final String tag = "VideoServer";
Button start, stop;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
start = (Button)findViewById(R.id.btn_start);
start.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0) {
start_camera();
}
});
stop = (Button)findViewById(R.id.btn_stop);
stop.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0) {
stop_camera();
}
});
surfaceView = (SurfaceView)findViewById(R.id.surfaceView1);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private void start_camera()
{
try{
camera = Camera.open();
}catch(RuntimeException e){
Log.e(tag, "init_camera: " + e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
//modify parameter
param.setPreviewFrameRate(20);
param.setPreviewSize(176, 144);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.e(tag, "init_camera: " + e);
return;
}
}
private void stop_camera()
{
camera.stopPreview();
camera.release();
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
startPreview 之後 就可以看是要照像還是拍影片了
我在google搜尋android surfaceholder
回覆刪除你的網頁是第二個耶好酷哦~~!!
你好!想請問一下~
回覆刪除我有在手機上實作出來,可是好像沒辦法儲存
我是想要實作錄影
不知道startPreview之後是要如何改
謝謝喔~
如果想要把影片存到 SD 卡的話,要用到 MediaRecorder
回覆刪除先加上權限
接著在 camera.startPreview(); 之後 加上下面的code
camera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(camera);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile("/sdcard/record.3gp");
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mediaRecorder.setVideoSize(176, 144);
mediaRecorder.prepare();
mediaRecorder.start();
mediaRecorder 各項設定有一定的順序與必要性
可以參考 android sdk 的網站,有比較詳細的解說
這邊只寫出最少且可以執行的設定
===============================
在 camera.stopPreview() 之前 加上下面的 code
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
try {
camera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(tag, "stop_camera: " + e);
}
補充一下 要加上的權限是 WRITE_EXTERNAL_STORAGE
回覆刪除這樣才可以寫入SD卡中
你好!請問一下
回覆刪除我在camera.reconnect();這地方還是一直出錯
出現的訊息是
The method reconnect() is undefined for the type Camera
不知道該怎麼解決~
謝謝喔~
這應該是 Android 版本的問題
回覆刪除reconnect 要 android 2.2 之後才能用
試試 camera.lock();
你好!
回覆刪除難怪了,我用的是2.1版本
不過換了camera.lock();
變成IOException e有問題
然後這整段要刪掉
try {
camera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(tag, "stop_camera: " + e);
}
這樣會有影響嗎?
這樣改完後可以成功執行
存檔也成功
不過播出來的是雜訊?!
會是編碼的問題嗎?
謝謝囉~
那整段刪掉應該是沒問題
回覆刪除我改成 lock()之後執行,畫面也是正常的
你可以試試看看各項設定
你好!不好意思耶
回覆刪除在請問一下,如果我想要一開始就有預覽畫面
而不是按Start之後才有
這樣應該怎麼改?
謝謝你~
請問如何弄成一開始就有預覽畫面...我弄不出來.
刪除你好~
回覆刪除然後在你說改lock()的地方
try {
camera.lock();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(tag, "stop_camera: " + e);
}
IOException e 是不是應該是Exception e?
謝謝~
我是把整個 try 都去掉
回覆刪除只有 camera.lock();
謝謝你囉~
回覆刪除我後來有改出可以存檔也可以順利播放
一開始也有顯示預覽畫面
太感恩了~
Hello Tommy,
刪除參考了您和顧顧的討論過程,實作出來了"可錄製、可存檔"狀態
但是"開始就顯示預覽畫面"這一步沒有做出來,
請教您這一步也如何做到呢?
感謝!
請問一下,怎樣字定義相機,加入瞄準框??大概要怎麼做
回覆刪除不好意思 問一下
回覆刪除我想取得鏡頭畫面的pixel值,並將pixel值傳給JNI做影像的處理
我要如何取得鏡頭畫面的pixel值(surfaceview畫面)
取得相機的畫面可以用 Camera.PreviewCallback 這個interface
刪除相機每抓取一張畫面就會call一次callback function
我開啟相機的方式如下
刪除private Button.OnClickListener start_camera = new Button.OnClickListener()
{
public void onClick(View v)
{
try
{
camera = Camera.open();
camera.setPreviewDisplay(surface_buf_inter);
camera.startPreview();
Log.e("Camera_test", "Camera open success!!! : ");
}
catch(RuntimeException err)
{
Log.e("Camera_test", "Camera open fail!!! : " + err);
}
catch(IOException err)
{
Log.e("Camera_test", "Set preview fail!!! : " + err);
}
camera.startPreview();
}
};
並非使用SurfaceHolder.Callback 來開起相機
這樣的話我還是一樣可以用Camera.PreviewCallback 來抓取畫面嗎??
Camera.PreviewCallback 只有這種方式可以抓取嗎?
刪除Camera.PreviewCallback 是一個 interface
刪除你需要一個class 去implement 他
然後用 camera.setPreviewCallback()
這個function 來設定
可以參考
http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html
Camera.PreviewCallback
刪除每次會一直刷新畫面
這樣我要怎把之前的畫面存再暫存器...
因為我要利用JNI 將每張畫面給錄檔....
我是新手.....不知怎將每次刷新的畫面存在暫存器
單純錄影應該不需要用到 JNI 吧?
刪除可以直接用 mediaRecorder 就可以錄了
hi~請問一下如何把相機調整成和螢幕同側的相機???
回覆刪除可以參考一下這邊的回答
刪除http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform
十分感謝!!!!!
刪除不好意思在請問一下~請問如果要相機連拍如何實做??
回覆刪除不好意思 請問一下 ...
回覆刪除我有相機的程式了
可是 每次開起都為橫向 ...
想要請問一下 要怎麼將他改為直向呢 ... ?
可以參考一下網站,應該可以改過來
刪除http://www.fish24k.com/?p=655965
Hi 顧顧,
刪除根據您的範例,我加入setCameraDisplayOrientation的程式碼卻仍然橫向預覽,請教您要更改何處才對呢?
請問要怎麼寫才可以不讓這個程式覆蓋先前錄的影片?!
回覆刪除儲存的檔名是用 setOutputFile 來指定的,可以判斷檔案如果存在的話就換一個檔名
刪除private void start_camera()
刪除{
try{
camera = Camera.open();
camera.setDisplayOrientation(90);
}catch(RuntimeException e){
Log.e(tag, "init_camera: " + e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
//modify parameter
param.setPreviewFrameRate(20);
param.setPreviewSize(176, 144);
camera.setParameters(param);
String fileName = "video.3gp";
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
camera.unlock();
File SDCardpath = Environment.getExternalStorageDirectory();
File myDataPath = new File( SDCardpath.getAbsolutePath() + "/video" );
if( !myDataPath.exists() ) myDataPath.mkdirs();
File recodeFile = new File(SDCardpath.getAbsolutePath() + "/video/"+fileName);
mrecorder = new MediaRecorder();
mrecorder.setCamera(camera);
mrecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mrecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mrecorder.setOutputFile(mrecAudioFile
.getAbsolutePath());
mrecorder.setPreviewDisplay(surfaceHolder.getSurface());
mrecorder.setOutputFile(recodeFile.getAbsolutePath());
mrecorder.setVideoSize(176, 144);
mrecorder.prepare();
mrecorder.start();
}
catch (Exception e) {
Log.e(tag, "init_camera: " + e);
return;
}
}
private void stop_camera()
{
mrecorder.stop();
mrecorder.reset();
mrecorder.release();
try {
camera.reconnect();
}
catch (IOException e) {
// TODO Auto-generated catch block
Log.e(tag, "stop_camera: " + e);
}
camera.stopPreview();
camera.release();
}
我把setOutputFile成這樣又多加了幾行,但是這樣跑的時候變成停止鍵沒辦法按!!
但是我不知道是錯哪?
不好意思
刪除我加了這行String fileName = "video.3gp";
然後在後面又加了
File SDCardpath=Environment.getExternalStorageDirectory();
File myDataPath=new File SDCardpath.getAbsolutePath()+"/DCIM/Camera");
if( !myDataPath.exists() ) myDataPath.mkdirs();
File recodeFile = new File(SDCardpath.getAbsolutePath() + "/DCIM/Camera/"+fileName);
然後把setOutputFile後面改成(recodeFile.getAbsolutePath());
改成這樣可以跑,但是還是會覆蓋原檔!
因為對這個還不是很熟,所以一直看不出來要改哪些東西
fileName 就是要存的檔名,如果存在的話就要重設一個,不改的話都是存在 video.3gp 裡
刪除摁摁,謝謝 我知道怎麼改了
刪除可以錄了,但是好像沒聲音!!
刪除是要加mrecorder01.setAudioSource(MediaRecorder.AudioSource.MIC);這行嗎?
可是加了就沒辦法按停止了
請問一下會有版本的問題嗎?
回覆刪除我是使用Android 4.0.3版本
沒加入錄影那段code之前,程式可以正常start preview和stop preview
加入錄影的code之後,只有start preview能正常work,
但stop preview按下沒有反應。
謝謝
您好 請問我要在相機預覽狀態下讓它自己抓圖片(不靠)並存在手機裡該如何改?
回覆刪除取得相機的畫面可以用 Camera.PreviewCallback 這個interface
刪除相機每抓取一張畫面就會call一次callback function,這時再存入SD卡中即可
版大您好
回覆刪除請問為什麼直接把您po的code貼上去後,燒錄到手機裡裡執行時,按下start的button畫面還是黑色的呢?
你好:
刪除我自己的code都是有測試過可以執行的,不過經過多次 eclipse 和 Android 改版,說不定會有問題,可以用 LogCat 來看看程式是否有成功執行或是有發生 Exception
刪除要加反斜線
版大您好:
回覆刪除想問一下,可以不使用preview的方式,直接開啟camera,然後拍照嗎?
根據 SDK 寫的
刪除http://developer.android.com/reference/android/hardware/Camera.html
一定要執行 startPreview 才行開始照相
不過我想應該是可以用一個看不見的 surfaceview 來達到沒有預覽畫面可是可以拍照的功能,你可以試試看
板大你好 我是照您的code方法做的
回覆刪除但是只有畫面 start鈕 無法擷取照片和儲存??
你好~我想請問使用setPreviewCallback(this)要放在哪裡?
回覆刪除我將取得的圖片數據透過JNI做成灰階圖片再傳回用ImageView顯示
如果我設置一按鈕啟用PreviewCallback後,成功顯示一張,但之後整個程式就停止運作
如果放在surfaceCreated裡感覺沒反應
setPreviewCallback 是要放在 Camara open 之後,設定完後還要 implement 一個 Callback Function 讓相機把預覽到的畫面傳給他,才可以接收到畫面
刪除這些我有做啊 ~ 我把抓到的影像數據轉成灰階圖片後,可顯示一張,但是沒辦法一直重復顯示,有東西沒釋放掉的感覺,也不能做其他的操作
刪除大大您好,想請問一下
回覆刪除我有實作出來預覽畫面
現在我想做出拍照的功能
但是不太了解startPreview之後是要怎麼改
謝謝您~
大大您好,想請問一下
回覆刪除我使用inventor來做app開啟相機
但是inventor只能開啟相機
無法再使用相機ㄉ其他進階功能
請問~我可以
使用inventor製作版面
再來嵌入其他程式來使用相機ㄉ進階功能ㄇ?
如~只能拍灰階ㄉ照片~
請問你會實作 錄影暫停的功能嗎? 暫停後還可以繼續錄!
回覆刪除你好:這個部分android並沒有內建,如果需要的話最簡單的方法就是錄製兩個影片後再把他們接起來,一樣可以達到暫停的效果
刪除你好~我想問 設定錄影格式有甚麼限制嗎?
回覆刪除我用了官網的方法setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
在停止錄影時會報錯
所以改用自己設定格式不會報錯,但儲存完的影片用手機撥放器撥放,畫面是錯誤的
請問一下
回覆刪除他說 btn_start cannot be resolved or is not a field
還有 btn_stop 跟 surfaceView1 都是一樣情形
請問該如何解決
謝謝
作者已經移除這則留言。
回覆刪除感謝,非常實用,收穫良多
回覆刪除