拍照参数设置 —— 调用Camera.Parameters对象。 拍照参数控制 —— 调用Camera的setParameters(),并将Camera.Parameters对象作为参数传入。注:Android2.3.3之后不用设置。 预览取景 —— 调用Camera的startPreview()方法,在之前注意调用Camera的setPreviewDisplay(SurfaceHolder holder)设置使用哪个SurfaceView来显示取得的图片。 拍照 —— 调用Camera的takePicture() 停止预览 —— 调用Camera的stopPreview()方法 资源释放 —— Camera.release()

开启和关闭预览的联系如下:Camera ---- SurfaceHolder ------ SurfaceView

关于SurfaceHolder.Callback必须实现的3个方法:

surfaceCreated() 该方法在surfaceView被Create时调用

surfaceChanged() 该方法是当surfaceView发生改变后调用

surfaceDestroyed() 这个不用说了,销毁时调用

surfaceHolder通过addCallBack()方法将响应的接口绑定

注:必要Camera权限,例如:

关于Camera下的Parameters类,其中封装了我们需要的大部分功能,下面做个简单介绍:

setPictureFormat() 方法用于设置相机照片的格式,其参数是一个字符型参数,位于PixelFormat类中,如:PixelFormat.JPEG。 setSceneMode() 方法用于设置相机场景类型,其参是是一个字符型参数,位于Parameters类中,以SCENE_MODE_开头。 setZoom() 方法用于设置相机焦距,其参数是一个整型的参数,该参数的范围是0到Camera.getParameters().getMaxZoom()。 setPictureSize() 方法用于设置相机照片的大小,参数为整型。 setWhiteBalance() 方法用于设置相机照片白平衡,其参数是一个字符型,位于Parameters类中,以WHITE_BALANCE开头。 setJpegQuality() 方法用于设置相机照片的质量,其参数是一个整型参数,取值范围为1到100。 setFlashMode() 方法用于设置闪光灯的类型,其参数是一个字符型参数,位于Parameters类中,以FLASH_MODE_开头。 setColorEffect() 方法用于设置照片颜色特效的类型,其参数是一个字符型参数,位于Parameters类中,以EFFECT_开头。

本程序模块效果图及示例

===============

下面分享本篇Blog的示例相机模块,此功能模块并非上面开源项目中的剥离出来的,看下效果图咯:

         

         

效果看着还可以吧(不点赞也太不给面子了吧  - . - ),下面个出主界面的布局代码:

android:id=“@+id/layout”

android:layout_width=“match_parent”

android:layout_height=“match_parent” >

android:id=“@+id/surfaceView”

android:layout_width=“match_parent”

android:layout_height=“match_parent” />

android:layout_width=“match_parent”

android:layout_height=“match_parent” >

android:id=“@+id/camera_grid”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:layout_alignParentTop=“true” />

android:id=“@+id/focus_index”

android:layout_width=“40dp”

android:layout_height=“40dp”

android:background=“@drawable/camera_focus”

android:visibility=“invisible” />

android:id=“@+id/flash_view”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_alignParentLeft=“true”

android:onClick=“onClick”

android:padding=“15dp”

android:scaleType=“centerCrop”

android:src=“@drawable/camera_flash_off” />

android:id=“@+id/camera_flip_view”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_alignParentRight=“true”

android:onClick=“onClick”

android:padding=“15dp”

android:scaleType=“centerCrop”

android:src=“@drawable/camera_flip” />

android:layout_width=“fill_parent”

android:layout_height=“70dp”

android:layout_alignParentBottom=“true”

android:background=“#a0000000”

android:padding=“5dp” >

android:id=“@+id/search”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginLeft=“30dp”

android:background=“@null”

android:drawablePadding=“3dp”

android:drawableTop=“@drawable/ic_search_selector”

android:onClick=“onClick”

android:text=“搜图”

android:textColor=“@drawable/row_selector_text” />

android:id=“@+id/action_button”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_centerInParent=“true”

android:clickable=“true”

android:onClick=“onClick”

android:src=“@drawable/btn_shutter_photo” />

android:id=“@+id/takephoto”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_alignParentRight=“true”

android:layout_marginRight=“30dp”

android:background=“@null”

android:drawablePadding=“3dp”

android:drawableTop=“@drawable/ic_takephoto_selector”

android:onClick=“onClick”

android:text=“拍照”

android:textColor=“@drawable/row_selector_text” />

下面是核心模块 CameraPreview 类:

public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback, Camera.AutoFocusCallback {

private SurfaceView mSurfaceView;

private SurfaceHolder mHolder;

private Size mPreviewSize;

private Size adapterSize;

//private List mSupportedPreviewSizes;

private Camera mCamera;

private boolean isSupportAutoFocus = false;

private Camera.Parameters parameters = null;

private Context mContext;

//private int mCurrentCameraId = 0;

private int screenWidth;

private int screenHeight;

CameraPreview(Context context, SurfaceView sv) {

super(context);

mContext = context;

mSurfaceView = sv;

mHolder = mSurfaceView.getHolder();

mHolder.addCallback(this);

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

mHolder.setKeepScreenOn(true);

isSupportAutoFocus = context.getPackageManager().hasSystemFeature(

PackageManager.FEATURE_CAMERA_AUTOFOCUS);

DisplayMetrics dm = new DisplayMetrics();

((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(dm);

screenWidth = dm.widthPixels;

screenHeight = dm.heightPixels;

}

public void setCamera(Camera camera) {

mCamera = camera;

initCamera();

}

public void initCamera() {

if (mCamera != null) {

Camera.Parameters params = mCamera.getParameters();

//mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

requestLayout();

if (mPreviewSize == null) {

mPreviewSize = findBestPreviewResolution();

}

if (adapterSize == null) {

adapterSize = findBestPictureResolution();

}

if (adapterSize != null) {

params.setPictureSize(adapterSize.width, adapterSize.height);

}

if (mPreviewSize != null) {

params.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

}

params.setPictureFormat(PixelFormat.JPEG);

List focusModes = params.getSupportedFocusModes();

if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {

// set the focus mode

params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

// set Camera parameters

mCamera.setParameters(params);

}

setDispaly(params, mCamera);

//setCameraDisplayOrientation((Activity) mContext, mCurrentCameraId, mCamera);

mCamera.setParameters(params);

}

}

//控制图像的正确显示方向

private void setDispaly(Camera.Parameters parameters, Camera camera) {

if (Build.VERSION.SDK_INT >= 8) {

setDisplayOrientation(camera, 90);

} else {

parameters.setRotation(90);

}

}

//实现的图像的正确显示

private void setDisplayOrientation(Camera camera, int i) {

Method downPolymorphic;

try {

downPolymorphic = camera.getClass().getMethod(“setDisplayOrientation”,

new Class[]{int.class});

if (downPolymorphic != null) {

downPolymorphic.invoke(camera, new Object[]{i});

}

} catch (Exception e) {

e.printStackTrace();

}

}

public static void setCameraDisplayOrientation(Activity activity,

int cameraId, android.hardware.Camera camera) {

android.hardware.Camera.CameraInfo info =

new android.hardware.Camera.CameraInfo();

android.hardware.Camera.getCameraInfo(cameraId, 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;

}

camera.setDisplayOrientation(result);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);

final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);

setMeasuredDimension(width, height);

// if (mSupportedPreviewSizes != null) {

// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);

// }

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

if (changed && getChildCount() > 0) {

final View child = getChildAt(0);

final int width = r - l;

final int height = b - t;

int previewWidth = width;

int previewHeight = height;

if (mPreviewSize != null) {

previewWidth = mPreviewSize.width;

previewHeight = mPreviewSize.height;

}

// Center the child SurfaceView within the parent.

if (width * previewHeight > height * previewWidth) {

final int scaledChildWidth = previewWidth * height / previewHeight;

child.layout((width - scaledChildWidth) / 2, 0,

(width + scaledChildWidth) / 2, height);

} else {

final int scaledChildHeight = previewHeight * width / previewWidth;

child.layout(0, (height - scaledChildHeight) / 2,

width, (height + scaledChildHeight) / 2);

}

}

}

public void surfaceCreated(SurfaceHolder holder) {

// The Surface has been created, acquire the camera and tell it where

// to draw.

try {

if (mCamera != null) {

mCamera.setPreviewDisplay(holder);

}

} catch (IOException e) {

if (null != mCamera) {

mCamera.release();

mCamera = null;

}

e.printStackTrace();

}

}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

if (holder.getSurface() == null) {

return;

}

if (mCamera != null) {

Camera.Parameters parameters = mCamera.getParameters();

parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

mCamera.setParameters(parameters);

try {

mCamera.setPreviewDisplay(holder);

} catch (IOException e) {

e.printStackTrace();

}

mCamera.startPreview();

reAutoFocus();

}

}

public void surfaceDestroyed(SurfaceHolder holder) {

// Surface will be destroyed when we return, so stop the preview.

if (mCamera != null) {

mCamera.stopPreview();

}

}

/**

最小预览界面的分辨率

*/

private static final int MIN_PREVIEW_PIXELS = 480 * 320;

/**

最大宽高比差

*/

private static final double MAX_ASPECT_DISTORTION = 0.15;

/**

找出最适合的预览界面分辨率 @return

*/

private Camera.Size findBestPreviewResolution() {

Camera.Parameters cameraParameters = mCamera.getParameters();

Camera.Size defaultPreviewResolution = cameraParameters.getPreviewSize();

List rawSupportedSizes = cameraParameters.getSupportedPreviewSizes();

if (rawSupportedSizes == null) {

return defaultPreviewResolution;

}

// 按照分辨率从大到小排序

List supportedPreviewResolutions = new ArrayList(rawSupportedSizes);

Collections.sort(supportedPreviewResolutions, new Comparator() {

@Override

public int compare(Camera.Size a, Camera.Size b) {

int aPixels = a.height * a.width;

int bPixels = b.height * b.width;

if (bPixels < aPixels) {

return -1;

}

if (bPixels > aPixels) {

return 1;

}

return 0;

}

});

StringBuilder previewResolutionSb = new StringBuilder();

for (Camera.Size supportedPreviewResolution : supportedPreviewResolutions) {

previewResolutionSb.append(supportedPreviewResolution.width).append(‘x’).append(supportedPreviewResolution.height)

.append(’ ');

}

// 移除不符合条件的分辨率

double screenAspectRatio = (double) screenWidth

/ screenHeight;

Iterator it = supportedPreviewResolutions.iterator();

while (it.hasNext()) {

Camera.Size supportedPreviewResolution = it.next();

int width = supportedPreviewResolution.width;

int height = supportedPreviewResolution.height;

// 移除低于下限的分辨率,尽可能取高分辨率

if (width * height < MIN_PREVIEW_PIXELS) {

it.remove();

continue;

}

// 在camera分辨率与屏幕分辨率宽高比不相等的情况下,找出差距最小的一组分辨率

// 由于camera的分辨率是width>height,我们设置的portrait模式中,width

// 因此这里要先交换然preview宽高比后在比较

boolean isCandidatePortrait = width > height;

int maybeFlippedWidth = isCandidatePortrait ? height : width;

int maybeFlippedHeight = isCandidatePortrait ? width : height;

double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;

double distortion = Math.abs(aspectRatio - screenAspectRatio);

if (distortion > MAX_ASPECT_DISTORTION) {

it.remove();

continue;

}

// 找到与屏幕分辨率完全匹配的预览界面分辨率直接返回

if (maybeFlippedWidth == screenWidth

&& maybeFlippedHeight == screenHeight) {

return supportedPreviewResolution;

}

}

// 如果没有找到合适的,并且还有候选的像素,则设置其中最大比例的,对于配置比较低的机器不太合适

if (!supportedPreviewResolutions.isEmpty()) {

Camera.Size largestPreview = supportedPreviewResolutions.get(0);

return largestPreview;

}

// 没有找到合适的,就返回默认的

return defaultPreviewResolution;

}

private Camera.Size findBestPictureResolution() {

Camera.Parameters cameraParameters = mCamera.getParameters();

List supportedPicResolutions = cameraParameters.getSupportedPictureSizes(); // 至少会返回一个值

StringBuilder picResolutionSb = new StringBuilder();

for (Camera.Size supportedPicResolution : supportedPicResolutions) {

picResolutionSb.append(supportedPicResolution.width).append(‘x’)

.append(supportedPicResolution.height).append(" ");

}

Camera.Size defaultPictureResolution = cameraParameters.getPictureSize();

// 排序

List sortedSupportedPicResolutions = new ArrayList(

supportedPicResolutions);

Collections.sort(sortedSupportedPicResolutions, new Comparator() {

@Override

public int compare(Camera.Size a, Camera.Size b) {

int aPixels = a.height * a.width;

int bPixels = b.height * b.width;

if (bPixels < aPixels) {

return -1;

}

if (bPixels > aPixels) {

return 1;

}

return 0;

}

});

// 移除不符合条件的分辨率

double screenAspectRatio = screenWidth

/ (double) screenHeight;

Iterator it = sortedSupportedPicResolutions.iterator();

while (it.hasNext()) {

Camera.Size supportedPreviewResolution = it.next();

int width = supportedPreviewResolution.width;

int height = supportedPreviewResolution.height;

// 在camera分辨率与屏幕分辨率宽高比不相等的情况下,找出差距最小的一组分辨率

// 由于camera的分辨率是width>height,我们设置的portrait模式中,width

// 因此这里要先交换然后在比较宽高比

boolean isCandidatePortrait = width > height;

int maybeFlippedWidth = isCandidatePortrait ? height : width;

int maybeFlippedHeight = isCandidatePortrait ? width : height;

double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;

double distortion = Math.abs(aspectRatio - screenAspectRatio);

if (distortion > MAX_ASPECT_DISTORTION) {

it.remove();

continue;

}

}

// 如果没有找到合适的,并且还有候选的像素,对于照片,则取其中最大比例的,而不是选择与屏幕分辨率相同的

if (!sortedSupportedPicResolutions.isEmpty()) {

return sortedSupportedPicResolutions.get(0);

}

// 没有找到合适的,就返回默认的

return defaultPictureResolution;

}

private Size getOptimalPreviewSize(List sizes, int w, int h) {

final double ASPECT_TOLERANCE = 0.1;

double targetRatio = (double) w / h;

if (sizes == null)

return null;

Size optimalSize = null;

double minDiff = Double.MAX_VALUE;

int targetHeight = h;

// Try to find an size match aspect ratio and size

for (Size size : sizes) {

double ratio = (double) size.width / size.height;

if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)

continue;

if (Math.abs(size.height - targetHeight) < minDiff) {

optimalSize = size;

minDiff = Math.abs(size.height - targetHeight);

}

}

// Cannot find the one match the aspect ratio, ignore the requirement

if (optimalSize == null) {

minDiff = Double.MAX_VALUE;

for (Size size : sizes) {

if (Math.abs(size.height - targetHeight) < minDiff) {

optimalSize = size;

minDiff = Math.abs(size.height - targetHeight);

}

}

}

return optimalSize;

}

public void reAutoFocus() {

if (isSupportAutoFocus) {

mCamera.autoFocus(new Camera.AutoFocusCallback() {

@Override

public void onAutoFocus(boolean success, Camera camera) {

}

});

}

}

public List getResolutionList() {

return mCamera.getParameters().getSupportedPreviewSizes();

}

public Camera.Size getResolution() {

Camera.Parameters params = mCamera.getParameters();

Camera.Size s = params.getPreviewSize();

return s;

}

/*public void setCurrentCameraId(int current) {

mCurrentCameraId = current;

}*/

//定点对焦的代码

public void pointFocus(MotionEvent event) {

mCamera.cancelAutoFocus();

parameters = mCamera.getParameters();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

//showPoint(x, y);

focusOnTouch(event);

}

mCamera.setParameters(parameters);

autoFocus();

}

//实现自动对焦

public void autoFocus() {

new Thread() {

@Override

public void run() {

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

if (mCamera == null) {

return;

}

mCamera.autoFocus(new Camera.AutoFocusCallback() {

@Override

public void onAutoFocus(boolean success, Camera camera) {

if (success) {

initCamera();//实现相机的参数初始化

}

}

});

}

};

}

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)

private void showPoint(int x, int y) {

if (parameters.getMaxNumMeteringAreas() > 0) {

List areas = new ArrayList();

WindowManager wm = (WindowManager) getContext()

.getSystemService(Context.WINDOW_SERVICE);

//xy变换了

int rectY = -x * 2000 / wm.getDefaultDisplay().getWidth() + 1000;

int rectX = y * 2000 / wm.getDefaultDisplay().getHeight() - 1000;

int left = rectX < -900 ? -1000 : rectX - 100;

int top = rectY < -900 ? -1000 : rectY - 100;

int right = rectX > 900 ? 1000 : rectX + 100;

int bottom = rectY > 900 ? 1000 : rectY + 100;

Rect area1 = new Rect(left, top, right, bottom);

areas.add(new Camera.Area(area1, 800));

parameters.setMeteringAreas(areas);

}

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

}

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)

public void focusOnTouch(MotionEvent event) {

Rect focusRect = calculateTapArea(event.getRawX(), event.getRawY(), 1f);

Rect meteringRect = calculateTapArea(event.getRawX(), event.getRawY(), 1.5f);

Camera.Parameters parameters = mCamera.getParameters();

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

if (parameters.getMaxNumFocusAreas() > 0) {

List focusAreas = new ArrayList();

focusAreas.add(new Camera.Area(focusRect, 1000));

parameters.setFocusAreas(focusAreas);

}

if (parameters.getMaxNumMeteringAreas() > 0) {

List meteringAreas = new ArrayList();

meteringAreas.add(new Camera.Area(meteringRect, 1000));

parameters.setMeteringAreas(meteringAreas);

}

mCamera.setParameters(parameters);

mCamera.autoFocus(this);

}

/**

Convert touch position x:y to {@link Camera.Area} position -1000:-1000 to 1000:1000.

*/

private Rect calculateTapArea(float x, float y, float coefficient) {

float focusAreaSize = 300;

int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();

int centerX = (int) (x / getResolution().width * 2000 - 1000);

int centerY = (int) (y / getResolution().height * 2000 - 1000);

int left = clamp(centerX - areaSize / 2, -1000, 1000);

int right = clamp(left + areaSize, -1000, 1000);

int top = clamp(centerY - areaSize / 2, -1000, 1000);

int bottom = clamp(top + areaSize, -1000, 1000);

return new Rect(left, top, right, bottom);

}

private int clamp(int x, int min, int max) {

if (x > max) {

return max;

}

if (x < min) {

return min;

}

return x;

}

@Override

public void onAutoFocus(boolean success, Camera camera) {

}

public void setNull() {

adapterSize = null;

mPreviewSize = null;

}

}

以下是CameraActivity类:

public class CameraActivity extends Activity implements View.OnTouchListener,OnClickListener {

public static final String CAMERA_PATH_VALUE1 = “PHOTO_PATH”;

public static final String CAMERA_PATH_VALUE2 = “PATH”;

public static final String CAMERA_TYPE = “CAMERA_TYPE”;

public static final String CAMERA_RETURN_PATH = “return_path”;

private int PHOTO_SIZE_W = 2000;

private int PHOTO_SIZE_H = 2000;

public static final int CAMERA_TYPE_1 = 1;

public static final int CAMERA_TYPE_2 = 2;

private final int PROCESS = 1;

private CameraPreview preview;

private Camera camera;

private Context mContext;

private View focusIndex;

private ImageView flashBtn;

private int mCurrentCameraId = 0; // 1是前置 0是后置

private SurfaceView mSurfaceView;

private CameraGrid mCameraGrid;

private int type = 1; //引用的矩形框

private Button mBtnSearch;

private Button mBtnTakePhoto;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mContext = this;

//requestWindowFeature(Window.FEATURE_NO_TITLE);

//getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏

//getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮

setContentView(R.layout.camera_home);

type = getIntent().getIntExtra(CAMERA_TYPE, CAMERA_TYPE_2);

initView();

InitData();

}

private void initView() {

focusIndex = (View) findViewById(R.id.focus_index);

flashBtn = (ImageView) findViewById(R.id.flash_view);

mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);

mCameraGrid = (CameraGrid) findViewById(R.id.camera_grid);

mBtnSearch = (Button) findViewById(R.id.search);

mBtnTakePhoto = (Button) findViewById(R.id.takephoto);

}

private void InitData() {

preview = new CameraPreview(this, mSurfaceView);

preview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,

LayoutParams.MATCH_PARENT));

((FrameLayout) findViewById(R.id.layout)).addView(preview);

preview.setKeepScreenOn(true);

mSurfaceView.setOnTouchListener(this);

mCameraGrid.setType(type);

}

private Handler handler = new Handler();

private void takePhoto() {

try {

camera.takePicture(shutterCallback, rawCallback, jpegCallback);

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

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

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

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

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

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

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

2021大厂面试真题:

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

ENT));

((FrameLayout) findViewById(R.id.layout)).addView(preview);

preview.setKeepScreenOn(true);

mSurfaceView.setOnTouchListener(this);

mCameraGrid.setType(type);

}

private Handler handler = new Handler();

private void takePhoto() {

try {

camera.takePicture(shutterCallback, rawCallback, jpegCallback);

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

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

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。 [外链图片转存中…(img-i6a0Dha9-1711922752215)] [外链图片转存中…(img-Tjq3UeV9-1711922752216)] [外链图片转存中…(img-zRb6jrwy-1711922752217)] [外链图片转存中…(img-17WmVGlT-1711922752217)] [外链图片转存中…(img-4MySvwXf-1711922752217)] [外链图片转存中…(img-fIdS84pS-1711922752218)]

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

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

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android) [外链图片转存中…(img-woR0ByG5-1711922752218)]

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

[外链图片转存中…(img-xQkq9O8f-1711922752218)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-infljLnu-1711922752219)]

2021大厂面试真题:

[外链图片转存中…(img-MVKTQffG-1711922752219)]

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

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

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: