2024年Android最新Android Camera1相机预览,2024年最新最新Android高级面试题汇总

文末

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

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

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

@Override
public void run() {
camera.setCameraFacing(facing);
}
});
}

@Override
public int getCameraFacing() {
return camera.getCameraFacing();
}

@Override
public void setPreviewSize(Size cameraSize) {
postTask(new Runnable() {
@Override
public void run() {
camera.setPreviewSize(cameraSize);
}
});
}

@Override
public Size getPreviewSize() {
return camera.getPreviewSize();
}

@Override
public void setDisplayOrientation(int displayOrientation) {
postTask(new Runnable() {
@Override
public void run() {
camera.setDisplayOrientation(displayOrientation);
}
});
}

@Override
public int getDisplayOrientation() {
return camera.getDisplayOrientation();
}

@Override
public void releaseCamera() {
if (handler == null) {
return;
}
postTask(new Runnable() {
@Override
public void run() {
camera.releaseCamera();
stopBackground();
}
});
}

@Override
public void addOnCameraListener(OnCameraListener onCameraListener) {
postTask(new Runnable() {
@Override
public void run() {
camera.addOnCameraListener(onCameraListener);
}
});
}

@Override
public void removeOnCameraListener(OnCameraListener onCameraListener) {
postTask(new Runnable() {
@Override
public void run() {
camera.removeOnCameraListener(onCameraListener);
}
});
}

@Override
public void removeAllOnCameraListener() {
postTask(new Runnable() {
@Override
public void run() {
camera.removeAllOnCameraListener();
}
});
}

/**

  • 获取Handler
    */
    private Handler getHandler() {
    if (thread == null || handler == null) {
    startBackground();
    }
    return handler;
    }

/**

  • 开启线程
    */
    private void startBackground() {
    stopBackground();
    thread = new HandlerThread(“camera_manager”);
    thread.start();
    handler = new Handler(thread.getLooper());
    }

/**

  • 关闭线程
    */
    private void stopBackground() {
    if (thread != null) {
    thread.quitSafely();
    thread = null;
    }
    if (handler != null) {
    handler = null;
    }
    }

/**

  • 执行任务
    */
    private void postTask(Runnable runnable) {
    getHandler().post(runnable);
    }
    }

注意到,CameraManager内部开启了Handler,目的是让相机的相关操作都在子线程进行

接下来可以具体实现Camera1

同样,我们新建Camera1,并实现ICamera接口

三、Camera1

全局变量

/**

  • Camera
    /
    private Camera camera;
    /
    *
  • 预览尺寸
    /
    private Size cameraSize = new Size(-1, -1);
    /
    *
  • 默认摄像头方向
    /
    private int facing = CameraConstants.facing.BACK;
    /
    *
  • 旋转角度
    */
    private int displayOrientation = -1;

打开相机

public void openCamera(int facing, Activity activity, SurfaceTexture surfaceTexture) {
// 先关闭相机
closeCamera();
// 判断是否存在摄像头
int cameraNum = Camera.getNumberOfCameras();
if (cameraNum <= 0) {
onCameraError(new IllegalStateException(“camera num <= 0”));
return;
}
// 检查传入的facing
int cameraIndex = -1;
if (facing == CameraConstants.facing.BACK) {
cameraIndex = Camera.CameraInfo.CAMERA_FACING_BACK;
} else if (facing == CameraConstants.facing.FRONT) {
cameraIndex = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
if (cameraIndex == -1) {
onCameraError(new IllegalStateException(“camera facing exception”));
return;
}
// 判断摄像头个数,以决定使用哪个打开方式
if (cameraNum >= 2) {
camera = Camera.open(cameraIndex);
} else {
camera = Camera.open();
}
// 判断Camera是否初始化成功
if (camera == null) {
onCameraError(new IllegalStateException(“camera is null”));
return;
}
this.facing = facing;
try {
// 获取摄像头参数
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();
if (cameraSize.getWidth() <= 0 || cameraSize.getHeight() <= 0) {
Camera.Size size = findTheBestSize(previewSizeList,
activity.getResources().getDisplayMetrics().widthPixels,
activity.getResources().getDisplayMetrics().heightPixels);
cameraSize.setWidth(size.width);
cameraSize.setHeight(size.height);
}
// 设置预览尺寸
parameters.setPreviewSize(cameraSize.getWidth(), cameraSize.getHeight());
// 这里设置使用的对焦模式
if (this.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
// 设置摄像头参数
camera.setParameters(parameters);
camera.setPreviewTexture(surfaceTexture);
if (displayOrientation < 0) {
displayOrientation = CameraUtils.getDisplayOrientation(activity, cameraIndex);
}
camera.setDisplayOrientation(displayOrientation);
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
onCameraOpened(cameraSize, Camera1.this.facing);
}
});
camera.startPreview();
} catch (IOException e) {
onCameraError(e);
}
}

注意到,在对相机参数设置的时候,使用findTheBestSize方法进行选择最佳的尺寸,该方法不是Android原生提供的,是根据相机所支持的所有预览尺寸和当前屏幕的尺寸所计算得到的

private Camera.Size findTheBestSize(List<Camera.Size> sizeList, int screenW, int screenH) {
if (sizeList == null || sizeList.isEmpty()) {
throw new IllegalArgumentException();
}
Log.d(TAG, “findTheBestSize: screenW:” + screenW + " screenH:" + screenH);
Camera.Size bestSize = sizeList.get(0);
for (Camera.Size size : sizeList) {
int width = size.height;
int height = size.width;
Log.d(TAG, “findTheBestSize: width:” + width + " height:" + height);
float ratioW = (float) width / screenW;
float ratioH = (float) height / screenH;
Log.d(TAG, “findTheBestSize: ratioW:” + ratioW + " ratioH:" + ratioH);
if (ratioW == ratioH) {
bestSize = size;
break;
}
}
return bestSize;
}

还注意到,设置相机旋转角度时,有用到CameraUtils.getDisplayOrientation方法,该方法大概长这样

public static int getDisplayOrientation(Activity activity, int facing) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(facing, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return result;
}

关闭相机

public void closeCamera() {
if (camera == null) {
return;
}
camera.stopPreview();
camera.release();
camera = null;
onCameraClosed();
}

切换相机

public void switchCamera() {
if (facing == CameraConstants.facing.BACK) {
facing = CameraConstants.facing.FRONT;
} else {
facing = CameraConstants.facing.BACK;
}
}

注意到,切换相机方法并没有真正的去切换相机,而是改变全局变量facing的值,需要配合使用openCamera方法后,进行切换相机的操作

接下来就是真正实现相机预览

四、TextureView

可以配合TextureView使用,进行相机相关操作

首先在xml中定义TextureView

<?xml version="1.0" encoding="utf-8"?>

Activity中定义CameraManager

private final CameraManager cameraManager = new CameraManager();

打开相机

private void openCamera() {
if (textureView.isAvailable()) {
cameraManager.openCamera(TextureViewCameraActivity.this, textureView.getSurfaceTexture());

面试复习笔记:

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

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

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

)]

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

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

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值