Android Camera(摄像头)
通过以下两种方式,可以在应用程序中使用摄像机
-
使用现有应用程序中Android摄像头应用程序
-
直接使用应用程序提供的Android摄像头API
使用现有应用程序的Android摄像头应用程序
使用 MediaStore.ACTION_IMAGE_CAPTURE 启动安装在手机上的摄像头应用程序。它的语法下面给出:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
除了以上,也可以通过 MediaStore 提供其它可用的意图。它们列出如下
Sr.No | 意图类型和说明 |
---|---|
1 |
ACTION_IMAGE_CAPTURE_SECURE 它返回照相机拍摄到的图像,设备被固定 |
2 |
ACTION_VIDEO_CAPTURE 它调用已有的视频应用程序在Android中捕获视频 |
3 |
EXTRA_SCREEN_ORIENTATION 它是用来在屏幕的方向设置:垂直或横向 |
4 |
EXTRA_FULL_SCREEN 它被用来控制ViewImage的用户接口 |
5 |
INTENT_ACTION_VIDEO_CAMERA 这个意图是用来启动摄像机在视频模式 |
6 |
EXTRA_SIZE_LIMIT 它用于指定的视频或图像捕获尺寸大小限制 |
现在使用startActivityForResult()函数推出活动,并等待它的结果。它的语法下面给出:
startActivityForResult(intent,0)
这种方法已在活动 activity 类被定义。从主活动调用它。有在做同样的工作的活动类中定义的方法,但是当它不是从活动要求,但在其他地方使用。它们被列在下面:
Sr.No | 活动功能说明 |
---|---|
1 |
startActivityForResult(Intent intent, int requestCode, Bundle options) 它开始的活动,但可以利用它选择额外的包 |
2 |
startActivityFromChild(Activity child, Intent intent, int requestCode) 启动活动时,活动是任何其他活动的子活动 |
3 |
startActivityFromChild(Activity child, Intent intent, int requestCode, Bundle options) 它的工作与上述相同,但它可以在捆绑与它的形状采取额外的值 |
4 |
startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) 它启动的碎片活动当前所在内部 |
5 |
startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options) 它不仅启动从碎片的活性,但可以采用额外的值 |
不管用来启动其活动功能,它们都返回结果。其结果可以通过覆盖 onActivityResult 方法获得。
例子
这里有一个例子,说明如何启动现有的摄像机应用程序捕获的图像和位图的形式显示结果
为了试验这个例子,需要在支持摄像机的实际设备上运行此应用程序。
Steps | 描述 |
---|---|
1 | 使用Eclipse IDE创建Android应用程序,并将其命名为Camera。在创建这个项目,确保目标SDK编译在Android SDK中的最新版本或使用更高级别的API。 |
2 | 修改src/MainActivity.java 文件中添加意图启动活动代码,由result方法来接受输出。 |
3 | 修改所需的布局XML文件 res/layout/activity_main.xml 添加GUI组件。在这里,我们只添加ImageView和一个TextView |
4 | 修改res/values/strings.xml 定义所需的常量值 |
5 | 运行应用程序并选择运行Android设备,并在其上安装的应用和验证结果。 |
以下是修改后的主活动文件的内容:src/com.yiibai.camera/MainActivity.java.
package com.example.camera; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; public class MainActivity extends Activity { ImageView imgFavorite; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgFavorite = (ImageView)findViewById(R.id.imageView1); imgFavorite.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { open(); } }); } public void open(){ Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, 0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); Bitmap bp = (Bitmap) data.getExtras().get("data"); imgFavorite.setImageBitmap(bp); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
以下是文件 res/layout/activity_main.xml file 的内容:
<RelativeLayout 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" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="34dp" android:layout_marginTop="36dp" android:contentDescription="@string/hello_world" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignRight="@+id/imageView1" android:text="@string/tap" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>
以下将是 res/values/strings.xml 的内容,以定义一个新的常量
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Camera</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="tap">Tap the image to open the camera!!</string> </resources>
以下是 AndroidManifest.xml 的默认内容:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yiibai.camera" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.yiibai.camera.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
让我们试着运行相机应用程序。假设已经连接实际的Android移动设备到计算机。显示如下窗口,选择要运行的Android应用程序的选项。
选择移动设备作为一个选项,然后检查您的移动设备将显示如下界面:
现在只需轻点图标的android的图像,相机将被打开。只需拍摄一张照片。捕获后,两个按钮就会出现或者把它丢弃
只需按下抽动(绿色)按钮,将被带回应用程序使用Android图标拍摄的图像
直接使用应用程序提供的Android摄像头API
使用照相机API给摄像机整合在应用中
首先,需要使用静态方法通过API calledCamera.open提供并初始化相机对象。它的语法如下:
Camera object = null; object = Camera.open();
除了上述功能,也有这是下面列出由Camera类提供的其它功能
Sr.No | 方法 & 描述 |
---|---|
1 |
getCameraInfo(int cameraId, Camera.CameraInfo cameraInfo) 它返回一个特定摄像机信息 |
2 |
getNumberOfCameras() 它返回限定的可用的设备上的照相机的整数 |
3 |
lock() 它被用来锁定相机,所以没有其他应用程序可以访问它 |
4 |
release() 它被用来释放在镜头锁定,所以其他应用程序可以访问它 |
5 |
open(int cameraId) 它是用来打开特定相机时,支持多个摄像机 |
6 |
enableShutterSound(boolean enabled) 它被用来使能/禁止图像俘获的默认快门声音 |
现在,需要做一个独立的类和SurfaceView扩展它并实现SurfaceHolder接口。
已经使用的两种类具有以下目的
类 | 描述 |
---|---|
Camera | 它是用来控制摄像机和拍摄图像或从相机拍摄的视频 |
SurfaceView | 这个类是用来展示实时摄像头预览给用户 |
必须调用摄像机类的预览方法来启动摄像机的预览给用户
public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback { private Camera theCamera; public void surfaceCreated(SurfaceHolder holder) { theCamera.setPreviewDisplay(holder); theCamera.startPreview(); } public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3){ } public void surfaceDestroyed(SurfaceHolder arg0) { } }
除了预览,可以使用照相机API提供的其它功能中设置的摄像机的其它选项
Sr.No | 方法 & 描述 |
---|---|
1 |
startFaceDetection() 此功能启动人脸检测相机 |
2 |
stopFaceDetection() 它是用来阻止其通过上述功能启用的脸部检测 |
3 |
startSmoothZoom(int value) 这需要一个整数值,并调整摄像机的焦距非常顺畅的值 |
4 |
stopSmoothZoom() 它是用来阻止摄像机的变焦 |
5 |
stopPreview() 它是用来阻止相机的预览给用户 |
6 |
takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg) 它被用来使能/禁止图像拍摄的默认快门声音 |
例子
下面的例子演示了摄像机API的应用程序中的使用
为了试验这个例子中,需要搭载最新的Android OS实际的移动设备,因为摄像机不支持模拟器
Steps | 描述 |
---|---|
1 | 使用Android Studio创建Android应用程序,并将其命名为:Camera。在创建这个项目,确保目标SDK和编译在Android SDK的最新版本或使用更高级别的API。 |
2 | 修改src/MainActivity.java文件引用添加摄像机的代码,并获得了XML的组件 |
3 | 创建一个新的文件ShowCamera.java使用SurfaceView扩展和实现SurfaceHolder接口。 |
4 | 修改所需的布局XML文件res/layout/activity_main.xml 添加GUI组件。在这里我们只添加FrameView,一个按钮和一个ImageView。 |
5 | 修改 res/values/strings.xml 定义所需的常量值 |
6 | 修改 AndroidManifest.xml 如下图所示,添加必要的权限摄像机 |
7 | 运行应用程序并选择运行Android的设备,并在其上安装的应用和验证结果。 |
下面是修改后的主活动文件 src/com.yiibai.camera1/MainActivity.java. 的内容。
package com.example.camera1; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private Camera cameraObject; private ShowCamera showCamera; private ImageView pic; public static Camera isCameraAvailiable(){ Camera object = null; try { object = Camera.open(); } catch (Exception e){ } return object; } private PictureCallback capturedIt = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length); if(bitmap==null){ Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show(); } cameraObject.release(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pic = (ImageView)findViewById(R.id.imageView1); cameraObject = isCameraAvailiable(); showCamera = new ShowCamera(this, cameraObject); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(showCamera); } public void snapIt(View view){ cameraObject.takePicture(null, null, capturedIt); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
创建新java文件:src/com.yiibai.camera1/ShowCamera.java. 并添加以下代码
package com.example.camera1; import java.io.IOException; import android.content.Context; import android.hardware.Camera; import android.view.SurfaceHolder; import android.view.SurfaceView; public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holdMe; private Camera theCamera; public ShowCamera(Context context,Camera camera) { super(context); theCamera = camera; holdMe = getHolder(); holdMe.addCallback(this); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } @Override public void surfaceCreated(SurfaceHolder holder) { try { theCamera.setPreviewDisplay(holder); theCamera.startPreview(); } catch (IOException e) { } } @Override public void surfaceDestroyed(SurfaceHolder arg0) { } }
修改 res/layout/activity_main.xml 的内容
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="0.30" android:orientation="vertical" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="199dp" /> <Button android:id="@+id/button_capture" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="snapIt" android:text="@string/Capture" /> <ImageView android:id="@+id/imageView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitXY" android:src="@drawable/ic_launcher" /> </LinearLayout> < /LinearLayout>
修改 res/values/string.xml 的内容
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Camera1</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="Capture">Capture</string> </resources>
修改AndroidManifest.xml 的内容,并添加必要的权限,如下图所示。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yiibai.camera1" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.yiibai.camera1.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
让我们试着运行 Camera 应用程序。假设已经连接实际的Android移动设备到计算机。启动应用程序之前会显示如下窗口,选择要运行的Android应用程序的选项。
选择移动设备作为一个选项,然后检查移动设备将显示如下界面:
相机将开始显示在上半屏的预览。只需点击捕捉按钮。现在,可以存储所拍摄的图像,将其上传到网上或者是放弃它。