1)隐式意图,拍缩略图 Bitmap,上传服务器使用
2)隐式意图,直接生成大图文件,
3)自定义拍照,复古风,这些都是通过自定义拍照来做的 。
开发步骤:
1:设置权限 CAMERA
<自定义照相机时使用的权限>
<use-permission android:name="android.permission.CAMERA"/>
2:如果要发布到应用市场里面, <uses-feature>这个功能
硬件拍照功能的要求,用于告诉应用市场,当前软件需要拍照的功能,是否是必须要有拍照的要求,
<use-feature android:name="android.hardware.camera" android:required="true">
不要写camera2,注意name 属性不是包名
3:使用MediaStore.ACTION_IMAGE_CAPTURE
如果是录像就是使用MediaStore.ACTION_VIDEO_CAPTURE
4: startActivityForResult
在布局上添加一个ImageView,用来显示牌出来的照片
第一个button,隐式意图拍照 ,返回缩略图
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,998);
onActivityResult(int requestCode, int resultCode, intent data){
if(requestCode ==998){
//代表拍照返回缩略图
if(resultCode==RESULT_OK){
// Intent data 中,包含了缩略图,缩略图名称为“”
Bitmap bitmap = data.getParcelableExtra("data");
imageView.setImageBitmap(bitmap);
}
}
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView)findViewById(R.id.preview); } public void btnTakePicture(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent,998); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==998){ if(resultCode==RESULT_OK){ Bitmap bitmap= data.getParcelableExtra("data"); imageView.setImageBitmap(bitmap); } } } }++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--------------------------------------------------------------
第二种:2)隐式意图,直接生成大图文件,
-------------------------------------------------------------
简单一句话:其实相对于上面的方法仅仅是多了一个intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(picFile)),而这个extra后面要接一个Uri的类型的存储图片的文件.
-----------------------------------------------------------------
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//1:考虑extra的设置,名称
//2: extra的内容类型
//3: Uri 存储位置,可以使用文件来保存。
// 获取文件File对象,来创建Uri
//TODO:检测存储卡的状态, 照片目录使用的是StoreagePublicDirectory里面。
记得要设置权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
File directory = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM);
if(!directory.exists()){
directory.mkdirs();
}
//使用成员变量,代表拍照成功的情况下的,文件对象,再进行显示。
File picFile = new File(directory,"Pic"+System.currentTimeMillis()+".jpeg")
//设置EXTRA_OUTPUT参数,只要设置了这个参数,
//那么在回调的时候,Intent中,就不会包含缩略图了;
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(picFile))
startActivityForResult(intent,199);
在onActivitResult里面
else if(requestCode ==199){
//代表直接村文件的方式的排至,返回,data 就没有缩略图了
现在有一个要求,要求拍照之后的大图片显示出来。
把上面的picFile作为成员变量来做。
if(resultCode==RESULT_OK){
mImageView.setImageUri( Uri.fromFile(picFile));
//最好还是使用BitMapFactory 因为可以缩小,
注意:这里如果使用setImageUri 会抱错:4.14-1 图片太大遇到的问题,Bitmap too large to be uploaded into a texture (2340x4160, max=4096x4096)
}
}
完整代码:
public class MainActivity extends AppCompatActivity { private ImageView imageView; private File file; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView)findViewById(R.id.preview); } public void btnTakePicture(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, 998); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==998){ if(resultCode==RESULT_OK){ Bitmap bitmap = data.getParcelableExtra("data"); imageView.setImageBitmap(bitmap); } }else if(requestCode==199){ if(resultCode==RESULT_OK){ //imageView.setImageURI(Uri.fromFile(file)); //02-16 22:28:32.618 19893-19935/com.example.kodulf.devicepicture W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (2340x4160, max=4096x4096) BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 32; Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(),options); imageView.setImageBitmap(bitmap); Log.d("Kodulf", "RESULT_OK" + file.getPath()); } } } public void btnTakeBigPicture(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); if(directory==null){ directory.mkdir(); } file = new File(directory,"Pic"+System.currentTimeMillis()+".jpeg"); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, 199); } }
--------------------------------------------
第三种:自定义拍照的内容:
--------------------------------------------如果想要缩小点,一个像素,
1:使用camera类,进行照相机的控制,
2:照相机必须要设置预览界面,这个预览界面是一个SurfaceView
SurfaceView 有callback的回调接口,onSurfaceCreate,里面基尼系那个设置
3:Camera 设置各种参数。配合SurfaceView,来进行相机的预览。
4:照相机使用完成,必须关系和释放,否则手机只能重启,因为操作照相机是系独占的,
如果不关闭的话,只有关闭手机再重新开才行。也就是说退了但是照相机没有关闭,那么摄像头是用不了的。
新建一个新的activity:CameraActivity
自定义摄像头的功能,使用旧版本的Camera API
需要使用CAMERA权限,
需要SurfaceView 作为拍照的预览窗口。
照相机应该及时的释放,应该,照相机在activity的生命周期中进行相应的打开和释放。
在SurfaceView 准备好,就可以创建照相机,在SurfaceView 销毁的时候,释放照相机。
可以onResume()里面或者在onCreat()里面写打开,最好在SurfaceView create里面打开
onCreate(){
....
Surface furfaceView = (SurfaceView)findViewById()
surfaceView.getHolder().addCallback(this);
//如果是Android 6.0 在onCreate 里面要申请权限
//为了兼容新版Android,
if(Build.VERSION.SDK_INT>=23)
int p=checkSelfPermission(Manifest.permission.CAMERA);//检查自身是否有照相机权限
结果是权限允许,权限不允许
if(Build.VERSION.SDK_INT>=23){ int p = checkSelfPermission(android.Manifest.permission.CAMERA); if(p== PackageManager.PERMISSION_DENIED) requestPermissions(new String[]{android.Manifest.permission.CAMERA},998); }else{ checkPermission(android.Manifest.permission.CAMERA, Binder.getCallingPid(),Binder.getCallingUid()); }
onRequestPermissionsResult(int){
//TODO:
}
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); StringBuilder sb = new StringBuilder(); for(int i=0;i<permissions.length;i++){ sb.append(permissions[i].toString()+";"); } Log.d("Kodulf","getPermission"+sb); }
然后把surfaceView 接口的三个方法创建出来。
surfaceCreated(){//开启照相机,设置照相机,进行预览
mCamera = Camera.open(); //打开第一个后置摄像头,如果只有一个摄像头就写open(0)
//记住要求权限CAMERA
//如果是Android 6.0 在onCreate 里面要申请权限
//获取照相机的参数,例如照相机的闪光灯是开的。
Camera.Parameters parameters = mCamera.getParameters();
//设置自定义的参数
parameters.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
//更新照相机参数
mCamera.setParameters(parameters);
try{
//设置预览的显示界面
mCamera.setPreviewDisplay(holder);
//因为默认的预览是点到的,需要设置方向
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
}
在surfaceView的surfaceDestoryed(){
mCamera.stopPreview();
//释放照相机,否则,手机需要重启,也有的支持自动释放了,为了严谨还是写一下。
mCamera=null;
}
private Camera mCamera;
public void btnTakePhoto(View view){
camera的选择一定不要选graphics的那个。graphics 是控件的摄像,这个在3d里面用到的。
/**
拍照,最终的图片数据,通过回调接口传回来;
mCamera.takePicture(
null,//Camera.ShutterCallback
null,//Camera.PictureCallback raw RAW 格式拍照的时候,数据会回调给这个接口,RAW的格式是没有经过压缩的,有的可鞥44MB大小
null,//Camera.PictureCallback postview postView 拍照之后,显示的回调
null//Camera.PictureCallback jpeg JPEG格式拍照的死后,数据会回调给这个接口。
);
如果没有raw,下面的额才执行
有了raw的,后面的不hi行。
*/
//上面的是4个参数的。一般使用3个参数的,少了一个postView
mCamera.takePicture(
null,
null, //RAW,很多手机也不支持
this //JPEG,Android 的手机上面用是这个。用于接受JPEG格式的拍照的结构
);
}
当PictureCallBack接口,当takePicture 方法执行成功,并且拍照完成
返回数据点额时候,调用这个接口
data 就是图片文件数据
上面的this会写一个onPictureTaken(byte[] data,Camera camera){
Log.d("CameraActivity","onPictureTaken data "+data.length);
//TODO:保存文件,拍照之后,如果还希望继续拍照,那么照相机必须再进入预览才可以拍照。否则就抛出异常
File directory= Environment.getExternalStoragePublicDirectory(Envir);
if(!directory.existes()){
{
directory.mkdirs();
}
File file=new File(directory,"Pic-"+..);
FileOutputStream fout = null;
try{
fout = new FileOutputStream(file);
fout.write(data);
}
finally{
fout.close()
}
//拍照只要要注意的,如果我想要拍一张以后再拍。那么照相机必须再进入预览才可以拍照。否则就抛出异常
camera.startPreview();
}
——————————————————————————————————————
代码:
package com.example.kodulf.devicepicture; import android.content.pm.PackageManager; import android.hardware.Camera; import android.os.Binder; import android.os.Build; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.Manifest; public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PictureCallback { private SurfaceView mSurfaceView; private Camera mCamera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); mSurfaceView = (SurfaceView) findViewById(R.id.preview); mSurfaceView.getHolder().addCallback(this); //记住要求权限CAMERA //如果是Android 6.0 在onCreate 里面要申请权限 if(Build.VERSION.SDK_INT>=23){ int p = checkSelfPermission(android.Manifest.permission.CAMERA); if(p== PackageManager.PERMISSION_DENIED) requestPermissions(new String[]{android.Manifest.permission.CAMERA},998); }else{ checkPermission(android.Manifest.permission.CAMERA, Binder.getCallingPid(),Binder.getCallingUid()); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); StringBuilder sb = new StringBuilder(); for(int i=0;i<permissions.length;i++){ sb.append(permissions[i].toString()+";"); } Log.d("Kodulf","getPermission"+sb); } public void btnTakePhoto(View view) { mCamera.takePicture( null, null, this ); } @Override public void surfaceCreated(SurfaceHolder holder) { //开启照相机,设置照相机,进行预览 mCamera = Camera.open();//打开第一个后置摄像头,如果只有一个摄像头就写open(0) Camera.Parameters parameters = mCamera.getParameters(); parameters.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON); mCamera.setParameters(parameters); try { mCamera.setPreviewDisplay(holder); mCamera.setDisplayOrientation(90); mCamera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); //释放照相机,否则,手机需要重启,也有的支持自动释放了,为了严谨还是写一下。 mCamera=null; } @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d("CameraActivity","onPictureTaken data "+data.length); File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); if(!directory.exists()){ directory.mkdirs(); } File file = new File(directory,"Pic"+System.currentTimeMillis()+".jpeg"); FileOutputStream fout =null; try { fout = new FileOutputStream(file); fout.write(data); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { fout.close(); } catch (IOException e) { e.printStackTrace(); } } //拍照只要要注意的,如果我想要拍一张以后再拍。那么照相机必须再进入预览才可以拍照。否则就抛出异常 camera.startPreview(); } }
——————————————————————————————————————————————
老张的代码:
import android.Manifest;
import android.hardware.Camera;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 自定义照相机的功能(使用旧版本的Camera API)
* 需要使用 CAMERA 权限
* 需要 SurfaceView 作为拍照的预览窗口
*/
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PictureCallback {
/**
* 照相机应该及时的释放,因此,照相机应该在Activity声明
* 周期中,进行相应的打开和释放;
* <p/>
* 在 SurfaceView 准备好,就可以创建照相机,
* 在 SurfaceView 销毁的时候,释放照相机
*/
private Camera mCamera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview);
surfaceView.getHolder().addCallback(this);
// 为了兼容新版Android,需要检查和申请权限
if (Build.VERSION.SDK_INT >= 23) {
// 返回禁止和允许
int p = checkSelfPermission(Manifest.permission.CAMERA); // 检查自身是否有照相机权限;
requestPermissions(new String[]{
Manifest.permission.CAMERA
}, 998);
} else {
checkPermission(Manifest.permission.CAMERA, Binder.getCallingPid(), Binder.getCallingUid());
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// TODO: 再次开始照相机的预览
}
public void btnTakePhoto(View view) {
// 拍照,最终的图片数据,通过回调接口传会来;
//mCamera.takePicture(
// null, // ShutterCallback 快门回调接口
// null, // RAW 格式拍照的时候,数据会回调给这个接口,
// null, // postView 拍照之后,显示的回调
// null // JPEG 格式拍照的时候,数据会回调给这个接口;
//);
mCamera.takePicture(
null,
null, // RAW
this // JPEG 用于接收JPEG格式的拍照结果
);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 开启照相机,设置照相机,进行预览
mCamera = Camera.open(); // 打开第一个后置摄像头,要求权限 CAMERA
// 获取照相机的参数
Camera.Parameters parameters = mCamera.getParameters();
// 设置自定义的参数
parameters.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_SHADE);
// 更新照相机参数
mCamera.setParameters(parameters);
try {
// 设置预览的显示界面
mCamera.setPreviewDisplay(holder);
// 因为默认的预览是颠倒的,需要设置方向
mCamera.setDisplayOrientation(90);
// 开始预览
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
// 释放照相机,否则,手机需要重启;
mCamera.release();
mCamera = null;
}
/**
* PictureCallback 接口,当 takePicture 方法执行成功,并且拍照完成,
* 返回数据的时候,调用这个接口
*
* @param data 图片的文件数据
* @param camera
*/
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.d("CameraActivity", "onPictureTaken data " + data.length);
// TODO: 保存文件, 拍照之后,如果还希望继续拍照,那么,
// 照相机必须再进入预览,才可以拍照,否则抛异常;
File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
if (!directory.exists()) {
directory.mkdirs();
}
File file = new File(directory, "Pic-" + System.currentTimeMillis() + ".jpeg");
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 如果希望继续拍照,必须在这,进行 重新预览的操作
camera.startPreview();
}
}
API Guides