一般情況下,可以使用MediaRecorder來錄製視頻,視頻數據也可在SurfaceView上顯示,但是那要寫數據到存儲設備上。而且我們項目是視頻聊天,就不能使用Media了。
網上找了找資料,自己給改了下:
public class CameravedioActivity extends Activity{
private static final String TAG = "CameravedioActivity";
private Camera camera;
private boolean preview = false ;
private SeekBar mSeekBar;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
*設置窗口屬性:一定要在 setContentView(R.layout.main) 之前
*/
// 窗口標題,其實可以在manifes文件裏面註冊
// requestWindowFeature(Window.FEATURE_NO_TITLE);
// 全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(200, 200);
surfaceView.getHolder().addCallback(new SurfaceViewCallback());
/**
* seekbar 用來實現變焦邏輯
*/
mSeekBar = (SeekBar)findViewById(R.id.seekbar);
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
Log.d(TAG, "progress:"+progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
Log.d(TAG, "onStartTrackingTouch");
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
Log.d(TAG, "onStartTrackingTouch");
}
});
}
private final class SurfaceViewCallback implements Callback {
/**
* surfaceView 被創建成功後調用此方法
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG,"surfaceCreated");
/*
* 在SurfaceView創建好之後 打開攝像頭
* 注意是 android.hardware.Camera
*/
camera = Camera.open();
/*
* This method must be called before startPreview(). otherwise surfaceview沒有圖像
*/
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Camera.Parameters parameters = camera.getParameters();
/* 設置預覽照片的大小,此處設置爲全屏 */
// WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 獲取當前屏幕管理器對象
// Display display = wm.getDefaultDisplay(); // 獲取屏幕信息的描述類
// parameters.setPreviewSize(display.getWidth(), display.getHeight()); // 設置
parameters.setPreviewSize(200, 200);
/* 每秒從攝像頭捕獲5幀畫面, */
parameters.setPreviewFrameRate(5);
/* 設置照片的輸出格式:jpg */
parameters.setPictureFormat(PixelFormat.JPEG);
/* 照片質量 */
parameters.set("jpeg-quality", 85);
/* 設置照片的大小:此處照片大小等於屏幕大小 */
// parameters.setPictureSize(display.getWidth(), display.getHeight());
parameters.setPictureSize(200, 200);
/* 將參數對象賦予到 camera 對象上 */
// camera.setParameters(parameters);
mSeekBar.setMax(100);
camera.startPreview();
/**
* Installs a callback to be invoked for every preview frame in addition to displaying them on the screen.
* The callback will be repeatedly called for as long as preview is active. This method can be called at
* any time, even while preview is live. Any other preview callbacks are overridden.
* a callback object that receives a copy of each preview frame, or null to stop receiving
*/
camera.setPreviewCallback(new Camera.PreviewCallback(){
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
//在視頻聊天中,這裏傳送本地frame數據給remote端
Log.d(TAG, "camera:"+camera);
Log.d(TAG, "byte:"+data);
}
});
preview = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG,"surfaceChanged");
}
/**
* SurfaceView 被銷燬時釋放掉 攝像頭
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera != null) {
/* 若攝像頭正在工作,先停止它 */
if(preview) {
camera.stopPreview();
preview = false;
}
//如果註冊了此回調,在release之前調用,否則release之後還回調,crash
camera.setPreviewCallback(null);
camera.release();
}
}
}
/**
* 處理照片被拍攝之後的事件
*/
private final class TakePictureCallback implements PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
}
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="300dip"
android:layout_height="300dip"
android:visibility="visible"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
我在自己機器上測試surfaceview必須包含在FrameLayout中
manifest文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.edu.wtu"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<!-- android:screenOrientation="landscape" 表示橫向界面 -->
<activity android:name=".CameravedioActivity" android:label="@string/app_name" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
<!-- 在SDCard中創建與刪除文件權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 申請使用攝像頭的權限 -->
<uses-permission android:name="android.permission.CAMERA"/>
</manifest>
注意哦,有些手機是不支持變焦的,所以設置Camera的Parameter會crash,所以要實現變焦邏輯首先判斷手機是否支持smoothzoom
sdk 2.1還是不支持setZoom的,2.3.3可以,2.2沒有測試