腾讯android开发面试题,[-综合篇-] 相机,2024大厂Android面试经验

mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
mCameraDevice = camera;
startPreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
mCameraDevice.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
mCameraOpenCloseLock.release();
mCameraDevice.close();
}
};
}

private void initHandler() {
HandlerThread handlerThread = new HandlerThread(“Camera2”);
handlerThread.start();
mainHandler = new Handler(getMainLooper());//主线程Handler
childHandler = new Handler(handlerThread.getLooper());//子线程Handler
}

/**

  • 开启预览
    */
    private void startPreview() {
    try {
    // 创建预览需要的CaptureRequest.Builder
    final CaptureRequest.Builder reqBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    // 将SurfaceView的surface作为CaptureRequest.Builder的目标
    reqBuilder.addTarget(getHolder().getSurface());

// 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
CameraCaptureSession.StateCallback stateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
if (null == mCameraDevice) return;
mCameraCaptureSession = cameraCaptureSession; // 当摄像头已经准备好时,开始显示预览
try {// 显示预览
mCameraCaptureSession.setRepeatingRequest(reqBuilder.build(), null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

}
};
mCameraDevice.createCaptureSession(Collections.singletonList(getHolder().getSurface()),
stateCallback, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}


3.OpenGL中GLSurfaceView使用

GLSurfaceView作为SurfaceView的子类,打开了一扇叫作OpenGL的大门。

它实现了SurfaceHolder.Callback2接口,需要传入一个GLSurfaceView.Render接口

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

public class TriangleGLView extends GLSurfaceView implements GLSurfaceView.Renderer {
private Triangle mTriangle;

public TriangleGLView(Context context) {
this(context, null);
}

public TriangleGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2);//设置OpenGL ES 2.0 context
setRenderer(this);//设置渲染器
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
mTriangle=new Triangle();
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);//rgba
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);//GL视口
}

@Override
public void onDrawFrame(GL10 gl) {
//清除颜色缓存和深度缓存
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT);
mTriangle.draw();
}
}


OpenGL的绘制可谓让人望而却步,下面是最简单的三角形绘制,

如果有兴趣可以看一下笔者OpenGL相关文章,仔细看完,基本上可以入门
Android多媒体之GL-ES战记第一集–勇者集结
Android多媒体之GL-ES战记第二集–谜团立方
Android多媒体之GLES2战记第三集–圣火之光
Android多媒体之GLES2战记第四集–移形换影
Android多媒体之GLES2战记第五集–宇宙之光
Android多媒体之GLES2战记第六集–九层之台

public class Triangle {
private FloatBuffer vertexBuffer;//顶点缓冲
private final String vertexShaderCode =//顶点着色代码
“attribute vec4 vPosition;” +
“void main() {” +
" gl_Position = vPosition;" +
“}”;
private final String fragmentShaderCode =//片元着色代码
“precision mediump float;” +
“uniform vec4 vColor;” +
“void main() {” +
" gl_FragColor = vColor;" +
“}”;
private final int mProgram;
private int mPositionHandle;//位置句柄
private int mColorHandle;//颜色句柄
private final int vertexCount = sCoo.length / COORDS_PER_VERTEX;//顶点个数
private final int vertexStride = COORDS_PER_VERTEX * 4; // 34=12
// 数组中每个顶点的坐标数
static final int COORDS_PER_VERTEX = 3;
static float sCoo[] = { //以逆时针顺序
0.0f, 0.0f, 0.0f, // 顶部
-1.0f, -1.0f, 0.0f, // 左下
1.0f, -1.0f, 0.0f // 右下
};
// 颜色,rgba
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};
public Triangle() {
//初始化顶点字节缓冲区
ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length * 4);//每个浮点数:坐标个数
4字节
bb.order(ByteOrder.nativeOrder());//使用本机硬件设备的字节顺序
vertexBuffer = bb.asFloatBuffer();// 从字节缓冲区创建浮点缓冲区
vertexBuffer.put(sCoo);// 将坐标添加到FloatBuffer
vertexBuffer.position(0);//设置缓冲区以读取第一个坐标
int vertexShader = loadShader(
GLES20.GL_VERTEX_SHADER,//顶点着色
vertexShaderCode);
int fragmentShader = loadShader
(GLES20.GL_FRAGMENT_SHADER,//片元着色
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();//创建空的OpenGL ES 程序
GLES20.glAttachShader(mProgram, vertexShader);//加入顶点着色器
GLES20.glAttachShader(mProgram, fragmentShader);//加入片元着色器
GLES20.glLinkProgram(mProgram);//创建可执行的OpenGL ES项目
}

private int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);//创建着色器
GLES20.glShaderSource(shader, shaderCode);//添加着色器源代码
GLES20.glCompileShader(shader);//编译
return shader;
}

public void draw() {
// 将程序添加到OpenGL ES环境中
GLES20.glUseProgram(mProgram);
//获取顶点着色器的vPosition成员的句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, “vPosition”);
//启用三角形顶点的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角坐标数据
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// 获取片元着色器的vColor成员的句柄
mColorHandle = GLES20.glGetUniformLocation(mProgram, “vColor”);
//为三角形设置颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁用顶点数组
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}


4.OpenGL在相机中的使用

现在捋一下,相机需要一个SurfaceHolder,而GLSurfaceView是一个SurfaceView,郎情妾意。 但好事多磨,并没有想象中的这么简单…

在CameraGLView主类中创建SurfaceTexture对象,并将纹理绑定其上
而通过SurfaceTexture作为入参可以创建SurfaceHolder,一条路就通了。

public class CameraGLView extends GLSurfaceView implements GLSurfaceView.Renderer {

private CameraDrawer cameraDrawer;
public SurfaceTexture surfaceTexture;
private int[] textureId = new int[1];

//----------------------------相机操作------------------------------
private Handler mainHandler;
private Handler childHandler;
private String mCameraID;
private CameraManager mCameraManager;
private CameraDevice mCameraDevice;//相机设备
private CameraCaptureSession mCameraCaptureSession;

private CameraDevice.StateCallback mStateCallback;
private Size mVideoSize;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);//以防止在关闭相机之前应用程序退出
private Surface surface;

public CameraGLView(Context context) {
this(context,null);
}

public CameraGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(3);//设置OpenGL ES 3.0 context
setRenderer(this);//设置渲染器
}

private void initHandler() {
HandlerThread handlerThread = new HandlerThread(“Camera2”);
handlerThread.start();
mainHandler = new Handler(getMainLooper());//主线程Handler
childHandler = new Handler(handlerThread.getLooper());//子线程Handler
}

private void initCamera() {

mCameraID = “” + CameraCharacteristics.LENS_FACING_FRONT;//后摄像头
//获取摄像头管理器
mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
mVideoSize=getCameraOutputSizes(mCameraManager,mCameraID,SurfaceTexture.class).get(0);

mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
mCameraDevice = camera;
startPreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
mCameraOpenCloseLock.release();
mCameraDevice.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
mCameraOpenCloseLock.release();
mCameraDevice.close();
}
};
}

/**

  • 根据输出类获取指定相机的输出尺寸列表,降序排序
    /
    public List getCameraOutputSizes(CameraManager cameraManager, String cameraId, Class clz){
    try {
    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
    StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    List sizes = Arrays.asList(configs.getOutputSizes(clz));
    Collections.sort(sizes, (o1, o2) -> o1.getWidth() * o1.getHeight() - o2.getWidth() * o2.getHeight());
    Collections.reverse(sizes);
    return sizes;
    } catch (CameraAccessException e) {
    e.printStackTrace();
    }
    return null;
    }
    /
    *
  • 开启预览
    */
    private void startPreview() {
    surfaceTexture.setDefaultBufferSize(mVideoSize.getWidth(), mVideoSize.getHeight());
    surfaceTexture.setOnFrameAvailableListener(surfaceTexture -> requestRender());
    surface = new Surface(surfaceTexture);

try {
// 创建预览需要的CaptureRequest.Builder
final CaptureRequest.Builder reqBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 将SurfaceView的surface作为CaptureRequest.Builder的目标
reqBuilder.addTarget(surface);
// 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
CameraCaptureSession.StateCallback stateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
if (null == mCameraDevice) return;
mCameraCaptureSession = cameraCaptureSession; // 当摄像头已经准备好时,开始显示预览
try {// 显示预览
mCameraCaptureSession.setRepeatingRequest(reqBuilder.build(), null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

}
};
mCameraDevice.createCaptureSession(Collections.singletonList(surface), stateCallback, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

@Override

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2021最新面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

2020面试真题解析
腾讯面试真题解析

阿里巴巴面试真题解析

字节跳动面试真题解析
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》]( )收录**

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值