利用SurfaceView预览,拍照且保存至相册

简介: mainActivity如下: package c.c; import java.io.IOException; import java.util.

mainActivity如下:

package c.c;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
/**
 *需求描述:
 *利用SurfaceView预览,且拍照.
 *将拍摄后的图片保存至相册
 *
 *注意
 *1 权限
 *  <uses-permission android:name="android.permission.CAMERA"/>
 *2 屏幕旋转后SurfaceView中预览的图片有90度的旋转
 *  解决方式:
 *  2.1将屏幕设置为竖屏
 *  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 *  2.2设置相机的Orientation
 *  mCamera.setDisplayOrientation(90);
 *  注意:
 *  该问题虽然解决了,但是会带来以下的一个问题.
 *3 拍照保存的图片可能被旋转90度.
 *  解决方式:
 *  http://blog.csdn.net/walker02/article/details/8211628
 *  http://www.cnblogs.com/andgoo/archive/2012/08/29/2661896.html
 *  
 *  此Demo中如下解决该问题
 *  
 *  关于以上问题解决的说明:
 *  1 相机拍照默认的是横屏的
 *     以ME525+为例,默认的是LOGO在左边
 *     平常的竖屏LOGO在上边.所以,需要将相机旋转90度.
 *     即mCamera.setDisplayOrientation(90);
 *     这样才能在横竖屏切换后预览画面正常显示.
 *  2  最好不要在代码中设置Activity以什么方式(横/竖屏)显示,比如:
 *     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 *     应该写在配置文件中,这样效率更高.
 *  3  现在已经把Activity设置为竖屏了.所以onConfigurationChanged()
 *     方法已经不能起到期望的作用.
 *     但是还需要监听现在屏幕是横屏还是竖屏.所以在此采用了重力感应的
 *     方式来实现.应该还有其他更好的办法,待调查.
 *  4 小bug:LOGO朝右边的时候,拍出的照片仍然被旋转了
 */
public class MainActivity extends Activity 
implements SurfaceHolder.Callback,OnClickListener,Camera.PictureCallback{
	private SensorManager mSensorManager;
	private AccSensorListener mAccSensorListener=null;
	private Sensor mSensor;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;
    private float y=0;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//设置Activity竖屏显示
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		setContentView(R.layout.main);
		init();
	}

	private void init(){
		mSensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
		mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		mSensorManager.registerListener
		(new AccSensorListener(), mSensor, SensorManager.SENSOR_DELAY_NORMAL);
		mAccSensorListener=new AccSensorListener();
		mSurfaceView=(SurfaceView) findViewById(R.id.surfaceView);
		mSurfaceView.setFocusable(true);
		mSurfaceView.setFocusableInTouchMode(true);
		mSurfaceView.setClickable(true);
		mSurfaceView.setOnClickListener(this);
		mSurfaceHolder=mSurfaceView.getHolder();
		//设置该SurfaceView是一个"推送"类型的SurfaceView
		mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		mSurfaceHolder.addCallback(this);
		
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		//取消重力感应
		mSensorManager.unregisterListener(mAccSensorListener);
	}
 private class AccSensorListener implements SensorEventListener{
	public void onSensorChanged(SensorEvent event) {
           //System.out.println("xxxxxx event.values[1]="+event.values[1]);
           y=event.values[1];
	}

	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}
	 
 }

	//2 parameters.getSupportedXXX的到相机支持的一些效果或者模式,比如:
   //parameters.getSupportedPictureFormats();
   //parameters.getSupportedColorEffects();
   //parameters.getSupportedFocusModes();
   //parameters.getSupportedWhiteBalance();
	public void surfaceCreated(SurfaceHolder holder) {
		final int LARGEST_WIDTH=200;
		final int LARGEST_HEIGHT=200;
		int bestWidth=0;
		int bestHeight=0;
		mCamera=Camera.open();
		Camera.Parameters parameters=mCamera.getParameters();
		
		//操作1 为相机设置某种特效
		List<String> colorEffects=parameters.getSupportedColorEffects();
		Iterator<String> iterator1=colorEffects.iterator();
		while (iterator1.hasNext()) {
			String effect = (String) iterator1.next();
			if (effect.equals(Camera.Parameters.EFFECT_SOLARIZE)) {
				//若支持过度曝光效果,则设置该效果
				//parameters.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);
				break;
			}
		}
		//操作2 改变SurfaceView的大小
		List<Camera.Size> previewSizes=parameters.getSupportedPreviewSizes();
		if (previewSizes.size()>1) {
			Iterator<Camera.Size> iterator2=previewSizes.iterator();
			while (iterator2.hasNext()) {
				Camera.Size size = (Camera.Size) iterator2.next();
				if (size.width>bestWidth&&size.width<=LARGEST_WIDTH&&
					size.height>bestHeight&&size.height<=LARGEST_HEIGHT) {
					bestWidth=size.width;
					bestHeight=size.height;
				}
			}
			if (bestWidth!=0&&bestHeight!=0) {
				parameters.setPreviewSize(bestWidth, bestHeight);
				mSurfaceView.setLayoutParams
				(new RelativeLayout.LayoutParams(bestWidth, bestHeight));
			}
		}
		//操作3 当屏幕变化时,旋转角度.否则不对
		//因为刚开始时竖屏的 
		mCamera.setDisplayOrientation(90);
		
		//操作结束
		try {
			//将摄像头的预览显示设置为mSurfaceHolder
			mCamera.setPreviewDisplay(mSurfaceHolder);
		} catch (IOException e) {
			mCamera.release();
		}
		//设置输出格式
		parameters.setPictureFormat(PixelFormat.JPEG);
		//设置摄像头的参数.否则前面的设置无效
		mCamera.setParameters(parameters);
		//摄像头开始预览
		mCamera.startPreview();
	}
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		mCamera.startPreview();
		
	}
	public void surfaceDestroyed(SurfaceHolder holder) {
		mCamera.stopPreview();
		mCamera.release();
	}

	//处理SurfaceView的点击事件
	public void onClick(View v) {
       mCamera.takePicture(null, null, this);
	}
	public void onPictureTaken(byte[] data, Camera camera) {
	   //将图片保存至相册
       if (y>0) {
    	   System.out.println("竖屏  竖屏  竖屏  竖屏  竖屏  竖屏  ");
    	   ContentResolver resolver = getContentResolver();
    	   Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    	   Matrix matrix=new Matrix();
    	   matrix.setRotate(90);
    	   Bitmap bitmap2=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
           MediaStore.Images.Media.insertImage(resolver, bitmap2, "xxoo", "des");
	}else {
		System.out.println("横屏 横屏 横屏 横屏 横屏 横屏 ");
		ContentResolver resolver = getContentResolver();
		Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
	    MediaStore.Images.Media.insertImage(resolver, bitmap, "xxoo", "des");
	}
       //mSensorManager.unregisterListener(mAccSensorListener);
	   //拍照后重新开始预览
	   camera.startPreview();
	}

}


 


 


main.xml如下:

<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"
    tools:context=".MainActivity" >

    <SurfaceView 
        android:id="@+id/surfaceView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    />

</RelativeLayout>


 

相关文章
|
12月前
|
应用服务中间件 Linux nginx
FFmpeg学习笔记(一):实现rtsp推流rtmp以及ffplay完成拉流操作
这篇博客介绍了如何使用FFmpeg实现RTSP推流到RTMP服务器,并使用ffplay进行拉流操作,包括在Windows和Linux系统下的命令示例,以及如何通过HTML页面显示视频流。
2507 0
|
SQL 开发框架 .NET
深入解析Entity Framework Core中的自定义SQL查询与Raw SQL技巧:从基础到高级应用的全面指南,附带示例代码与最佳实践建议
【8月更文挑战第31天】本文详细介绍了如何在 Entity Framework Core (EF Core) 中使用自定义 SQL 查询与 Raw SQL。首先,通过创建基于 EF Core 的项目并配置数据库上下文,定义领域模型。然后,使用 `FromSqlRaw` 和 `FromSqlInterpolated` 方法执行自定义 SQL 查询。此外,还展示了如何使用 Raw SQL 进行数据更新和删除操作。最后,通过结合 LINQ 和 Raw SQL 构建动态 SQL 语句,处理复杂查询场景。本文提供了具体代码示例,帮助读者理解和应用这些技术,提升数据访问层的效率和灵活性。
697 0
|
SQL 关系型数据库 MySQL
【Go语言专栏】使用Go语言连接MySQL数据库
【4月更文挑战第30天】本文介绍了如何使用Go语言连接和操作MySQL数据库,包括选择`go-sql-driver/mysql`驱动、安装导入、建立连接、执行SQL查询、插入/更新/删除操作、事务处理以及性能优化和最佳实践。通过示例代码,展示了连接数据库、使用连接池、事务管理和性能调优的方法,帮助开发者构建高效、稳定的Web应用。
1952 0
|
12月前
|
SQL 存储 缓存
SQL数据库查询详解
数据库是现代信息社会的基石,它们存储和管理着大量的数据。而SQL(StructuredQueryLanguage)作为一种强大的数据库查询语言,广泛应用于各种数据库系统中。本文将详细介绍SQL数据库查询的基本概念、语法、常用操作以及优化策略。一、SQL数据库查询概述SQL是一种用于管理关系数据库的标
734 3
|
Android开发 Windows
android studio开发时提示 TLS 握手错误解决办法
在Windows环境下遇到TLS协议版本不支持的错误,Gradle构建失败。解决方案是在build.gradle.kts中设置系统属性`https.protocols`为`TLSv1.2`,而非遵循误导信息设置为TLSv1.1。
|
API Android开发
55. 【Android教程】位图:Bitmap
55. 【Android教程】位图:Bitmap
249 0
|
数据可视化 大数据
【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面
【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面
【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面
|
API Android开发 UED
56. 【Android教程】媒体播放器:MediaPlayer
56. 【Android教程】媒体播放器:MediaPlayer
575 0
|
机器学习/深度学习 人工智能 自然语言处理
人工智能(AI)技术的发展史
人工智能 (AI) 的发展历程从20世纪50年代起步,历经初始探索、早期发展、专家系统兴起、机器学习崛起直至深度学习革命。1950年图灵测试提出,1956年达特茅斯会议标志着AI研究开端。60-70年代AI虽取得初步成果但仍遭遇困境。80年代专家系统如MYCIN展现AI应用潜力。90年代机器学习突飞猛进,1997年深蓝战胜国际象棋冠军。21世纪以来,深度学习技术革新了AI,在图像、语音识别等领域取得重大成就。尽管AI已广泛应用,但仍面临数据隐私、伦理等挑战。未来AI将加强人机协作、增强学习与情感智能,并在医疗、教育等领域发挥更大作用。
|
SQL 数据管理 API
数据管理DMS产品使用合集之阿里云DMS提供API接口来进行数据导出功能吗
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。