近期。在改动Android4.4的原生相机Camera2,非常习惯的去寻找SurfaceView。结果任凭我使用grep还是ack。都无法搜索到SurfaceView,最后还是通过代码CameraActivity-->CameraModule-->PhotoUI-->R.layout.photo_module找到。原来是使用了TextureView。不是非常了解此控件,百度之。在官方API文档中找到此控件:

http://android.toolib.net/reference/android/view/TextureView.html

官方文档大概的意思是:

TextureView能够用来显示内容流。这样一个内容流比如能够视频或者OpenGL的场景。

内容流能够来自本应用程序以及其它进程。

Textureview必须在硬件加速开启的窗体中。

与SurfaceView相比,TextureView不会创建一个单独的窗体。这使得它能够像一般的View一样运行一些变换操作,比方移动、动画等等,比如,你能够通过调用myView.setAlpha(0.5f)将TextureView设置成半透明。

使用TextureView非常easy:你须要使用的就是SurfaceTexture,SurfaceTexture能够用于呈现内容。

以下是我写一个小样例来演示怎样渲染相机预览到TextureView,在官方文档样例的基础上略微修改了一下:

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" > <FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" /> <Button
android:id="@+id/button_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Capture" /> </LinearLayout>

CameraPreview.java:

import java.io.IOException;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.view.TextureView; @SuppressLint("NewApi")
public class CameraPreview extends TextureView implements
TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
public CameraPreview(Context context , Camera camera) {
super(context);
mCamera = camera;
// TODO Auto-generated constructor stub
} public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height) {
// mCamera = Camera.open();
try {
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch (IOException ioe) {
// Something bad happened
}
} public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
// Ignored, Camera does all the work for us
} public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
} public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
} }

CameraTest.java:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast; import com.example.mycamera.R.id; @SuppressLint("NewApi")
public class CameraTest extends Activity {
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
private Camera mCamera;
private CameraPreview mPreview;
private static final String TAG = "ERROR";
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: "
+ "e.getMessage()");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建Camera实例
mCamera = getCameraInstance();
// 创建Preview view并将其设为activity中的内容
mPreview = new CameraPreview(this, mCamera);
mPreview.setSurfaceTextureListener(mPreview);
//设置浑浊
mPreview.setAlpha(0.5f);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
// preview.setAlpha(0.0f);
preview.addView(mPreview);
// 在Capture按钮中增加listener
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 从摄像头获取图片
mCamera.takePicture(null, null, mPicture);
}
});
} /** 安全获取Camera对象实例的方法 */ public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // 试图获取Camera实例
}
catch (Exception e) {
// 摄像头不可用(正被占用或不存在)
}
return c; // 不可用则返回null
} /** 为保存图片或视频创建File */
private static File getOutputMediaFile(int type) {
// 安全起见,在使用前应该
// 用Environment.getExternalStorageState()检查SD卡是否已装入
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// 假设期望图片在应用程序卸载后还存在、且能被其他应用程序共享,
// 则此保存位置最合适
// 假设不存在的话,则创建存储文件夹
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
Log.d("MyCameraApp", "failed to create directory");
}
// 创建媒体文件名称
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的图像保存到Intent指定的fileUri
Toast.makeText(this, "Image saved to:\n" + data.getData(),
Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了图像捕获
} else {
// 图像捕获失败,提示用户
}
} if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的视频保存到Intent指定的fileUri
Toast.makeText(this, "Video saved to:\n" + data.getData(),
Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了视频捕获
} else {
// 视频捕获失败。提示用户
}
}
} @Override
protected void onPause() {
super.onPause();
releaseCamera(); // 在暂停事件中马上释放摄像头
} private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // 为其他应用释放摄像头
mCamera = null;
}
} }

Android之TextureView浅析的更多相关文章

  1. Android使用TextureView播放视频

    1.引言 如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的TextureView做到. 1).TextureView的兄弟SurfaceView 应用 ...

  2. Android源码浅析(六)——SecureCRT远程连接Linux,配置端点和字节码

    Android源码浅析(六)--SecureCRT远程连接Linux,配置端点和字节码 需要编译源码的同学,一般都是win+虚拟机吧,但是再虚拟机里体验并不是很好,所有市面上有很多的软件能够做到在wi ...

  3. Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名

    Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...

  4. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  5. Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机

    Android源码浅析(三)--Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机 最近比较忙,而且又要维护自己的博客,视频和公众号,也就没 ...

  6. Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

    Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Andr ...

  7. Android源码浅析(一)——VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置

    Android源码浅析(一)--VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置 最近地方工作,就是接触源码的东西了,所以好东西还是要分享,系列开了这 ...

  8. Android 自定义 View 浅析

    Android 自定义 View 浅析 概括 说到自定义 View ,就一定得说说 android 系统的UI绘制流程.再说这个流程之前,我们先看一下在每一个 activity 页面中我们的布局 ui ...

  9. Android应用框架浅析

    http://blog.csdn.net/yanbober/article/category/3206943 Android应用层View绘制流程与源码分析   http://blog.csdn.ne ...

随机推荐

  1. [python]获取字符串类型

    >>>type(value) <class 'type'> >>>isinstance(value,type) True/False

  2. Lambda表达式, 可以让我们的代码更优雅.

    在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...

  3. ios开发之C语言第一天

    最近在学习ios开发,先学习C语言,再学习OC和swift.正所谓"万丈高楼平地起",打好基础是很重要的,所以C语言也必须好好学习.学习中所使用的操作系统是OS X,开发工具是Xc ...

  4. Java基础——异常机制

    [捕获异常] 硬件的错误.输入错误.物理限制等问题,都可能导致程序运行时的异常出现. 1.异常的分类层次 在java中,异常对象都是由Throwable类继承而来的,主要分为两大类: Error和Ex ...

  5. redis问题解决

    一, redis的奇葩问题:我使用命令 redis-cli shutdown 关闭redis之后就再也灭洋启动了! 尝试1: 使用命令 sudo /etc/init.d/redis-server st ...

  6. [BZOJ 1058] [ZJOI2007] 报表统计 【平衡树】

    题目链接:BZOJ - 1058 题目分析 这道题看似是需要在序列中插入一些数字,但其实询问的内容只与相邻的元素有关. 那么我们只要对每个位置维护两个数 Ai, Bi, Ai 就是初始序列中 i 这个 ...

  7. 微软HoloLens技术解谜

    HoloLens 是什么? HoloLens 是微软发布的可穿戴式增强现实计算设备,它拥有这么几个关键要素: 它是增强现实产品,即 Augmented Reality(AR),AR 技术将计算机生成的 ...

  8. 传智播客C语言视频第一季(有效下载期为10.1-10.7,10.8关闭)

     J:\传智播客_尹成_C语言从菜鸟到高手├─传智播客_尹成_C语言从菜鸟到高手_第一章C语言概述A│      第一讲1.1C语言第一阶段.mp4│      第二讲1.2c语言入门教程.mp4 ...

  9. jQuery.extend方法和开发中变量的复用

    最近在用commonJS规范进行客户端开发,遇到如下问题: 一般一个模块内部可能会定义一系列变量或一系列相关变量,比如写了一个颜色选择弹框模块大概会有如下变量定义 var settings = { / ...

  10. Mac下搭建Eclipse Android开发环境

    之前一直是用windows搞android开发,但windows这个性能也真是让人醉了,终于一狠心,砸锅卖铁买了Mac.然后就开始在Mac上搭建android开发环境, 其实也不麻烦,关键是找准下载地 ...