Android 自定義相機及分析源碼
Android 自定義相機及分析源碼
使用Android 系統(tǒng)相機的方法:
要想讓應(yīng)用有相機的action,咱們就必須在清單文件中做一些聲明,好讓系統(tǒng)知道,如下
<intent-filter>
<action android:name="android.intent.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
action的作用就是聲明action的類型,便于Intent的使用,category的作用就是注冊,沒有它。相關(guān)操作將不起作用。
一種方式是簡單粗暴的實現(xiàn),如下
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_1);
//然后在 onActivityResult方法中實現(xiàn)數(shù)據(jù)的獲取,此處是展示在了一個ImageView上
if(resultCode==RESULT_OK){
if(requestCode==REQ_1){
Bundle bundle=data.getExtras();
Bitmap bitmap=(Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);
}
小總結(jié):這樣的好處是簡單快捷,但是在現(xiàn)在的android智能機中,好多相片都是很大的,這里獲得的僅僅是一個縮略圖罷了
另外一種方式是稍微溫婉一點了,而且效果也更好一點,好處就在于它是先將照片信息存儲到本地一個臨時文件中,然后讓ImageView去相關(guān)路徑下進行讀取,這樣就可以獲得清晰度很高的圖片了。如下
/*
* 此方法的存在意義就是不在onActivityResult方法的data中獲取我們拍照的縮略圖,而是從我們的文件輸出目錄下直接查看原圖
* 這樣的好處就是可以對大容量的照片進行便捷的準確的操作
*/
public void onStartCarema2(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//見你給你路徑傳遞回需要的處理方法中
Uri uri=Uri.fromFile(new File(myFilePath));
//設(shè)置文件的輸出路徑
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, REQ_2);
}
//然后在onActivityResult方法中進行相關(guān)的處理就可以了
else if(requestCode==REQ_2){
FileInputStream fis=null;
try {
fis=new FileInputStream(myFilePath);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//記得最后一定要關(guān)閉相關(guān)的流操作。否則會引起相關(guān)的異常的。
開發(fā)自定義的相機
由于開發(fā)自定義的相機要進行相關(guān)的權(quán)限的生命,所以一定不要忘記在清單文件中做相關(guān)的處理,如下
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/>
然后有以下幾個步驟:
- 創(chuàng)建Camera,并完成初始化Camera,開始預(yù)覽,釋放資源三個方法
- 與Activity的SurfaceView進行綁定。
- 在系統(tǒng)的onPause(),onResume()方法中進行相關(guān)狀態(tài)設(shè)置
- 對Camera進行參數(shù)設(shè)置,作用就是對照片類型和狀態(tài)進行相關(guān)的設(shè)置
- 將拍得的照片進行展示,一般會新開一個Activity,用ImageView進行承載,我們還可以在此Activity上添加TextView,實現(xiàn)水印效果等其他的美化操作
- 另外,如果想加入自動聚焦的功能,就可以在SurfaceView上添加onClickListener(),對屏幕進行偵聽,調(diào)用myCamera.autoFocus(null);方法即可
以上就是整個思路
接下來就是使用系統(tǒng)Camera的代碼展示
(可以直接copy相關(guān)代碼塊,添加到你的應(yīng)用中去,實現(xiàn)Camera這一功能。)
首先是MainActivity
布局
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="@+id/startCarema"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="StartCarema"
android:onClick="onStartCarema"
/>
<Button
android:id="@+id/startCarema2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="StartCarema2"
android:onClick="onStartCarema2"
/>
<Button
android:id="@+id/customCarema"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="CustomCarema"
android:onClick="onCustomCarema"
/>
<ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
代碼
package com.example.camerademo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity {
//為下面的獲取請求所用
private static int REQ_1=1;
private static int REQ_2=2;
Button btn_startCareme,btn_startCarema2,btn_customCarema;
ImageView imageView;
//定義照片存儲的路徑
private String myFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_startCareme=(Button) findViewById(R.id.startCarema);
btn_startCarema2=(Button) findViewById(R.id.startCarema2);
btn_customCarema=(Button) findViewById(R.id.customCarema);
imageView=(ImageView) findViewById(R.id.imageview);
//初始化不同手機的SD卡的路徑
myFilePath=Environment.getExternalStorageDirectory().getPath();
myFilePath=myFilePath+"/"+"temperature.png";
}
public void onCustomCarema(View view){
Intent intent=new Intent(this,CustomCarema.class);
startActivity(intent);
}
public void onStartCarema(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_1);
}
/*
* 此方法的存在意義就是不在onActivityResult方法的data中獲取我們拍照的縮略圖,而是從我們的文件輸出目錄下直接查看原圖
* 這樣的好處就是可以對大容量的照片進行便捷的準確的操作
*/
public void onStartCarema2(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//見你給你路徑傳遞回需要的處理方法中
Uri uri=Uri.fromFile(new File(myFilePath));
//設(shè)置文件的輸出路徑
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, REQ_2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK){
if(requestCode==REQ_1){
Bundle bundle=data.getExtras();
Bitmap bitmap=(Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);
}else if(requestCode==REQ_2){
FileInputStream fis=null;
try {
fis=new FileInputStream(myFilePath);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
接下來是自定義相機的代碼
主界面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/capture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="Capture"
android:onClick="onCapture"
/>
<SurfaceView
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
ResultActivity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Capture Result"
android:textSize="28dp"
android:textColor="#BFAACD"
android:gravity="center"
/>
<ImageView
android:id="@+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
/>
</LinearLayout>
代碼
首先是CustomCamera類,
package com.example.camerademo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@SuppressWarnings("unused")
public class CustomCarema extends Activity implements SurfaceHolder.Callback{
private Camera myCamera;
private SurfaceView preview;
private SurfaceHolder myHolder; //myHolder勇于展現(xiàn)surfaceView的圖像
private Camera.PictureCallback myPictureCallBack=new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera arg1) {
//將拍照得到的數(shù)據(jù)信息存儲到本地
File tempFile=new File("/sdcard/temp.png");
try {
FileOutputStream fos=new FileOutputStream(tempFile);
fos.write(data);
fos.close();
//然后將這個照片的數(shù)據(jù)信息傳送給要進行展示的Activity即可
Intent intent=new Intent(CustomCarema.this,ResultActivity.class);
intent.putExtra("PicturePath", tempFile.getAbsolutePath());
startActivity(intent);
//拍照結(jié)束之后銷毀當前的Activity,進入到圖片展示界面
CustomCarema.this.finish();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.customcarema);
preview=(SurfaceView) findViewById(R.id.preview);
myHolder=preview.getHolder();
myHolder.addCallback(this);
//實現(xiàn)點擊屏幕自動聚焦的功能,此處并不需要拍照,故只是聚焦
preview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
myCamera.autoFocus(null);
}
});
}
@Override
protected void onResume() {
super.onResume();
if(myCamera==null){
myCamera=getCamera();
if(myHolder != null ){
setStartPreview(myCamera, myHolder);
}
}
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
releaseCamera();
}
/**
* 釋放相機的資源
*/
private void releaseCamera(){
if(myCamera !=null ){
myCamera.setPreviewCallback(null);
myCamera.stopPreview();
myCamera.release();
myCamera=null;
}
}
/**
* 拍照的一些參數(shù)設(shè)置,點擊此按鈕之后會觸發(fā)拍照的會掉,進而實現(xiàn)拍照的效果
* @param view
*/
public void onCapture(View view){
Camera.Parameters parameters=myCamera.getParameters();
//設(shè)置照片的類型
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setPictureSize(800, 600);
//設(shè)置為自動聚焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
//設(shè)置為自動聚焦是不夠的,因為我們先得到的是最為清晰的圖片,所以要在聚焦成功的時候才進行拍照
myCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
if(success){
myCamera.takePicture(null, null, myPictureCallBack);
}
}
});
}
/**
* 獲取系統(tǒng)的一個Camera對象
*/
private Camera getCamera(){
Camera camera=null;
try{
camera=Camera.open();
}catch(Exception e){
e.printStackTrace();
}
return camera;
}
/**
* 開始預(yù)覽相機的內(nèi)容,其實就是講surfaceHolder與之綁定
*/
private void setStartPreview(Camera camera,SurfaceHolder holder){
//直接調(diào)用系統(tǒng)方式綁定預(yù)覽
try {
camera.setPreviewDisplay(holder);
//由于系統(tǒng)默認使用橫屏預(yù)覽,,所以要進行設(shè)置
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
myCamera.stopPreview();
setStartPreview(myCamera, myHolder);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
setStartPreview(myCamera, myHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
releaseCamera();
}
}
然后是結(jié)果界面代碼:
package com.example.camerademo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.widget.ImageView;
public class ResultActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.resultactivity);
String path=getIntent().getStringExtra("PicturePath");
ImageView imageview=(ImageView) findViewById(R.id.picture);
//由于這樣稚嫩獲得橫屏,所以我們要使用流的形式來轉(zhuǎn)換
// Bitmap bitmap=BitmapFactory.decodeFile(path);
// imageview.setImageBitmap(bitmap);
FileInputStream fis;
try {
fis = new FileInputStream(path);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
Matrix matrix=new Matrix();
matrix.setRotate(90);
bitmap=Bitmap.createBitmap(bitmap, 0,0, bitmap.getWidth()
,bitmap.getHeight(),matrix,true);
imageview.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上代碼中已經(jīng)做了下關(guān)的代碼注釋
總結(jié):
安卓6.0以上版本記得加動態(tài)權(quán)限,不然會報空指針哦,還有點擊拍照事件那里 別忘了加進去,不然拍照沒反應(yīng)
以上就是Android 自定義相機的實例詳解,如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
android表格效果之ListView隔行變色實現(xiàn)代碼
首先繼承SimpleAdapter再使用重載的Adapter來達到效果,其實主要是需要重載SimpleAdapter,感興趣的朋友可以研究下,希望本文可以幫助到你2013-02-02
Android中用RxJava和ViewPager實現(xiàn)輪播圖
現(xiàn)在App中實現(xiàn)一個輪播圖已經(jīng)是很多產(chǎn)品的標配了,這篇文章給大家詳細介紹了如何利用RxJava和ViewPager實現(xiàn)輪播圖,有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-09-09
Android ListView的item背景色設(shè)置和item點擊無響應(yīng)的解決方法
在Android開發(fā)中,listview控件是非常常用的控件,在大多數(shù)情況下,大家都會改掉listview的item默認的外觀。2013-11-11
Android基于廣播事件機制實現(xiàn)簡單定時提醒功能代碼
這篇文章主要介紹了Android基于廣播事件機制實現(xiàn)簡單定時提醒功能代碼,較為詳細的分析了Android廣播事件機制及提醒功能的相關(guān)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10
Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)
大家在用Android手機的時候肯定都遇到過內(nèi)存剩余空間越來越小的情況,所以下面這篇文章主要給大家介紹了關(guān)于Android徹底清除APP數(shù)據(jù)的兩種方案,需要的朋友可以參考下2021-11-11

