近期。在改动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 手册——开胃菜

    如果你写过大规模的Shell脚本,应该会有过这样的体会:你还非常想再加一些别的功能进去,但它已经太大. 太慢.太复杂了:或者这个功能需要调用一个系统函数,或者它只适合通过C来调用……通常这些问题还不足 ...

  2. linux下VI编辑器的使用

    一.VI编辑器简述       VI 编辑器是Linux和Unix上最基本的文本编辑器,工作在字符模式下.由于不需要图形界面,使它成了效率很高的文本编辑器.尽管在Linux上也有很多图形界面的编辑器可 ...

  3. Swift 类和结构体的简单认识

    类和结构体的共同点: 定义属性用于存储值 定义方法用于提供功能 定义附属脚本用于访问值 通过拓展增加默认实现的功能 定义构造器用于生成初始化值 实现协议以提供某种标准功能 类是引用类型 结构体是值类型 ...

  4. iOS 开发常用的一些工具

    http://www.itjhwd.com/ios-tool/ 通用工具 HomeBrew:OS X上非常出色的包管理工具. 源码控制 Git:分布式版本控制系统和源码管理系统,其优点是:快和简单易用 ...

  5. Linux下Java 编译运行说明

    命令行环境下Java编译运行 1. java的运行机制的基本概念: 源文件 也就是我们熟知的.java文件. 类文件  .class文件是编译器由.java文件编译而成.众所周知,Java的跨平台性在 ...

  6. Contest 20140914 Mushroom写情书 字符串雙hash 後綴數組

    0111:Mushroom写情书 查看 提交 统计 提问 总时间限制:  10000ms 内存限制:  256000kB 描述 有一天,Mushroom准备向他的GF表白,为了增加表白成功率,Mush ...

  7. 【POJ11855】 Buzzwords (后缀数组)

    Description The word “the” is the most commonthree-letter word. It evenshows up inside other words, ...

  8. Java System类看到的一点小记

    System类 位置java.lang包中 是final类,不能被继承,不能被修改 ,不能被实例化 private System(){}私有的构造函数,不允许被其他对象进行实例化 public fin ...

  9. java中基本类型封装对象所占内存的大小(转)

    这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字. 实现的想法是这样的:java.lang.Runt ...

  10. Android学习之 UI效果

    探究Android的多分辨率支持以及各种类型图标尺寸大小 - CSDN 各种数字提醒控件-Android 代码仓库-eoe Android ViewBadger - 开源中国社区 Android 微信 ...