android 6.0 权限问题问题

汇总Android视频录制中常见问题
作者:yh_thu
字体:[ ] 类型:转载 时间:
这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下
本文分享自己在视频录制播放过程中遇到的一些问题,主要包括:
视频录制流程
视频预览及SurfaceHolder
视频清晰度及文件大小
视频文件旋转
一、视频录制流程
&&& 以微信为例,其录制触发为按下(住)录制按钮,结束录制的触发条件为松开录制按钮或录制时间结束,其流程大概可以用下图来描述。
1.1、开始录制
&& 根据上述流程及项目的编程惯例,可在onCreate()定义如下函数来完成功能:
初始化过程主要包括View,Data以及Listener三部分。在初始化View时,添加摄像头预览,添加倒计时文本组件,设置初始状态UI组件的可见;初始化Data时,从Intent中获取初始数据;初始化Listener时,分别对录制触发按钮,保存/取消视频录制按钮以及视频预览界面添加监听。
&&& 当系统初始化成功后,等待用户按下录制按钮,因此在录制按钮的监听中,需要完成以下功能:录制,计时,更新界面组件。
if(isRecording) {
mMediaRecorder.stop();
releaseMediaRecorder();
mCamera.lock();
isRecording =
if(startRecordVideo()) {
startTimeVideoRecord();
isRecording =
&&& 首先判断当前录制状态,如果正在录制,则先停止录制,释放MediaRecorder资源,锁定摄像头,置位录制状态;然后开始视频录制startRecordVideo,其boolean型返回值表征是否启动成功,启动成功后,开始视频录制计时,并且置位录制状态。startRecordVideo涉及MediaRecorder的配置,准备以及启动。
翻译成代码如下:
private boolean startRecordVideo() {
configureMediaRecorder();
if(!prepareConfiguredMediaRecorder()) {
mMediaRecorder.start();
1.2、结束录制
根据上述流程图可知,结束录制的触发条件为松开录制按钮或计时时间到。在结束录制方法中,需要释放MediaRecorder,开始循环播放已录制视频,设置界面更新等。
&&& 翻译成代码如下:
private void stopRecordVideo() {
releaseMediaRecorder();
// 录制视频文件处理
if(currentRecordProgress & MIN_RECORD_TIME) {
Toast.makeText(VideoInputActivity.this, "录制时间太短", Toast.LENGTH_SHORT).show();
startVideoPlay();
isPlaying =
setUiDisplayAfterVideoRecordFinish();
currentRecordProgress = 0;
updateProgressBar(currentRecordProgress);
releaseTimer();
// 状态设置
isRecording =
&二、视频预览及SurfaceHolder
&&&&& 视频预览采用SurfaceView,相比于普通的View,SurfaceView在一个新起的单独线程中绘制画面,该实现的优点是更新画面不会阻塞UI主线程,缺点是会带来事件同步的问题。当然,这涉及到UI事件的传递以及线程同步。
&&&&& 在实现中,通过继承SurfaceView组件来实现自定义预览控件。首先,SurfaceView的getHolder()方法会返回SurfaceHolder,需要为SurfaceHolder添加SurfaceHolder.Callback回调;其次,重写surfaceCreated、surfaceChanged和surfaceDestroyed实现。
2.1、构造器
&&&&& 构造器包含了初始化域以及添加上述回调的过程。
public CameraPreview(Context context, Camera camera) {
super(context);
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
&&&&& 这里需要说明mSupportedPreviewSizes,由于摄像头支持的预览尺寸由Camera本身的参数决定,因此需要首先获取其所支持的预览尺寸。
2.2、预览尺寸的设置
&&&&& 从Google官方的Camera示例程序中可以看出,选择预览尺寸的标准是(1)摄像头支持的预览尺寸的宽高比与SurfaceView的宽高比的绝对差值小于0.1;(2)在(1)获得的尺寸中,选取与SurfaceView的高的差值最小的。通过代码对这两个标准进行了实现,这里贴一下官方的代码:
public Camera.Size getOptimalPreviewSize(List&Camera.Size& sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w /
if (sizes == null) {
Camera.Size optimalSize =
double minDiff = Double.MAX_VALUE;
int targetHeight =
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.
if (Math.abs(ratio - targetRatio) & ASPECT_TOLERANCE)
if (Math.abs(size.height - targetHeight) & minDiff) {
optimalSize =
minDiff = Math.abs(size.height - targetHeight);
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) & minDiff) {
optimalSize =
minDiff = Math.abs(size.height - targetHeight);
return optimalS
&&&&& 在加载预览画面时,需要考虑Camera支持的尺寸(getSupportedPreviewSizes)和加载预览画面的SurfaceView的尺寸(layout_width/layout_height),在预览阶段,两者之间的关系直接影响清晰度及图像拉伸。对于Camera的尺寸,由于设备的硬件差异,不同设备支持的尺寸存在差异,但在默认情况(orientation=landscape)下,其width&height。以HTC609d为例,Camera支持的分辨率为:9)……640*480(4:3)……480*320(3:2)等十多种,而其屏幕的分辨率为960*540(16:9)。因此,很容易得到以下结论:(1)当Camera预览尺寸小于SurfaceView尺寸较多时,预览画面就不清晰;(2)Camera预览尺寸宽高比与SurfaceView宽高比相差较大时,预览画面就会拉伸。
&&&&& 上述代码在手机设置为横屏时并没有问题,在设置为竖屏时,为获得最优的预览尺寸,需要在调用此方法前比较SurfaceView的宽高。
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
Math.max(width, height), Math.min(width, height));
&&&&& 获得与当前SurfaceView匹配的预览尺寸后,即可通过Camera.Parameters进行设置。
Camera.Parameters mParams = mCamera.getParameters();
mParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setDisplayOrientation(90);
List&String& focusModes = mParams.getSupportedFocusModes();
if(focusModes.contains("continuous-video")){
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
mCamera.setParameters(mParams);
&三、视频清晰度及文件大小
&&&&& 在第一节中讲到startRecordVideo,包括配置MediaRecorder,准备MediaRecorder以及启动,其中配置MediaRecorder是视频录制的重点,需要了解每项配置参数的作用,根据业务场景灵活配置。这里参考Google官方的示例给出一个可行的配置方案,然后再对其进行解释。
private void configureMediaRecorder() {
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setOrientationHint(90);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a Camera Parameters
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
/* Fixed video Size: 640 * 480*/
mMediaRecorder.setVideoSize(640, 480);
/* Encoding bit rate: 1 * 1024 * 1024*/
mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
// Step 4: Set output file
mMediaRecorder.setMaxFileSize(maxFileSizeInBytes);
mMediaRecorder.setOutputFile(videoFilePath);
// END_INCLUDE (configure_media_recorder)
// Set MediaRecorder ErrorListener
mMediaRecorder.setOnErrorListener(this);
1.setCamera参数能够使得在预览和录制中快速切换,避免Camera对象的重新加载。在某些Android手机自带的照相机程序中,切换预览与录制中的短暂卡顿,读者可自行体会。
2.mMediaRecorder.setOrientationHint(90)在录制方向为竖直(portrait)时使用,它能使视频文件的沿顺时针方向旋转90度,如果不设置此项,播放视频时,画面会发生90度的旋转。不过这里更重要的是,即使设置了此项,在某些播放器上,画面依然会有90度的旋转(比如将在手机上正常播放的视频导入到PC中进行播放,或者嵌入H5的video标签中),这可是为什么呢?注意setOrientationHint的说明:Note that some video players may choose to ignore the compostion matrix in a video during playback. 那么如何做到在所有播放器上都能以正常方向播放呢?稍等,后续专门对其进行说明。
1.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION),VOICE_RECOGNITION相比于MIC会根据语音识别的需要做一些调谐,当然,这需要在系统支持的情况下。
2.setVideoSource自然是VideoSource.CAMERA,只是在此两项设置必须在设置编码器之前设置,这无需说明。
1.setOutputFormat需要在Step 2之后,并且在prepare()之前。这里采用OutputFormat.MPEG_4格式。
2.setVideoSize需要权衡的因素较多,主要包括三方面:MediaRecorder支持的录制尺寸、视频文件的大小以及兼容不同Android机型。这里采用640 * 480(微信小视频的尺寸是320*240),文件大小在500-1000kb之间,并且市面上99%以上机型支持此录制尺寸。
3.setVideoEncodingBitRate与视频的清晰度有关,设置此参数需要权衡清晰度与文件大小的关系。太高,文件大不易传输;太低,文件清晰度低,识别率低。需要根据实际业务场景灵活调整。
4.setVideoEncoder采用H264编码,MPEG4、H263、H264等不同编码的差别比较,实际使用中,H264的压缩率较高,推荐使用。
5.setAudioEncoder采用AudioEncoder.AAC,该设置主要是考虑其通用性、兼容性。
setMaxFileSize指定录制文件的大小限制,当然还可以限制其最大录制时间。
setOutputFile指定输出视频的路径。
setOnErrorListener指定错误监听器。
&& 在完成上述配置之后,即可准备MediaRecorder,并在返回成功后开始视频录制。
private boolean prepareConfiguredMediaRecorder() {
// Step 5: Prepare configured MediaRecorder
mMediaRecorder.prepare();
} catch (Exception e) {
releaseMediaRecorder();
&四、视频文件旋转
&&&&& 第三节中Step 1提到对视频文件的旋转,因为某些播放器会忽略录制视频时的配置参数,因此可尝试通过第三方库对视频文件进行旋转,例如:OpenCV,fastCV等,在Camera对象的Camera.PreviewCallback中截取每帧数据byte[] data,然后对其进行处理,然后输出。该方法需要考虑处理方法的高效性,在编程时一般采用NDK,在C++中完成关键的处理,这里贴出fastCV中该处理方法的逻辑。
public void onPreviewFrame( byte[] data, Camera c ) {
// Increment FPS counter for camera.
util.cameraFrameTick();
// Perform processing on the camera preview data.
update( data, mDesiredWidth, mDesiredHeight );
// Simple IIR filter on time.
mProcessTime = util.getFastCVProcessTime();
if( c != null )
// with buffer requires addbuffer each callback frame.
c.addCallbackBuffer( mPreviewBuffer );
c.setPreviewCallbackWithBuffer( this );
// Mark dirty for render.
requestRender();
&&&&& 其中,update为native方法,其实现由jni中对应的文件完成,其中调用了libfastcv.a中相应的API。这里涉及NDK编程的基本方法步骤:(1)开发环境;(2)编写Java代码、C/C++代码;(3)编译C/C++文件生成.so库;(4)重新编译工程,生成apk。由于本章不重点讲述NDK,这里不再展开。
&&&&& 除上述方法以外,笔者采用了另外一种思路进行了探索,上述方法处理的数据为每帧图像数据,可以理解为在线处理,而如果在录制完成之后再处理,可以理解为离线处理。这里采用了第三方库mp4parser,mp4parser是一款支持在Android中进行视频分割的库,这里通过其进行视频旋转。至于具体效果如何,读者有兴趣可自行尝试,这里留个悬念。
private boolean rotateVideoFileWithClockwiseDegree(String sourceFilePath, int degree) {
if(!isFileAndDegreeValid(sourceFilePath, degree)) {
rotateVideoFile(sourceFilePath, degree);
对输入参数进行合法性检测之后,根据检测结果判断是否进行旋转。
private boolean isFileAndDegreeValid(String sourceFilePath, int degree) {
if(sourceFilePath == null || (!sourceFilePath.endsWith(".mp4"))
|| (!new File(sourceFilePath).exists())) {
if (degree == 0 || (degree % 90 != 0)) {
private void rotateVideoFile(String sourceFilePath, int degree) {
List&TrackBox& trackBoxes = getTrackBoxesOfVideoFileByPath(sourceFilePath);
Movie rotatedMovie = getRotatedMovieOfTrackBox(trackBoxes);
writeMovieToModifiedFile(rotatedMovie);
通过mp4parser旋转视频主要分为三步:
(1)获取视频文件对应的TrackBoxes;
(2)根据TrackBoxes获取旋转后的Movie对象;
(3)将Movie对象写入文件。
private List&TrackBox& getTrackBoxesOfVideoFileByPath(String sourceFilePath) {
IsoFile isoFile =
List&TrackBox& trackBoxes =
isoFile = new IsoFile(sourceFilePath);
trackBoxes = isoFile.getMovieBox().getBoxes(TrackBox.class);
isoFile.close();
} catch (IOException e) {
e.printStackTrace();
return trackB
private Movie getRotatedMovieOfTrackBox(List&TrackBox& trackBoxes) {
Movie rotatedMovie = new Movie();
for (TrackBox trackBox : trackBoxes) {
trackBox.getTrackHeaderBox().setMatrix(Matrix.ROTATE_90);
rotatedMovie.addTrack(new Mp4TrackImpl(trackBox));
return rotatedM
private void writeMovieToModifiedFile(Movie movie) {
Container container = new DefaultMp4Builder().build(movie);
File modifiedVideoFile = new File(videoFilePath.replace(".mp4", "_MOD.mp4"));
FileOutputS
fos = new FileOutputStream(modifiedVideoFile);
WritableByteChannel bb = Channels.newChannel(fos);
container.writeContainer(bb);
// 关闭文件流
fos.close();
} catch (Exception e) {
e.printStackTrace();
本文对Android视频录制中常见的问题进行了说明,希望对大家的学习有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具面试时,问哪些问题能试出一个 Android 应用开发者真正的水平?
注:1、是Android应用开发,不是操作系统级移植;2、做App的;3、主要是学习能力和人品;4、你懂的,面试前从网上都会找些面试宝典。。。
按投票排序
这几年面过的各种Android开发也有三位数了,failed的不敢说,pass的基本都没有看走眼,来得晚了也想说说我的体会。一般面试时间短则30分钟,多则1个小时,这么点时间要全面考察一个人难度很大,需要一些技巧,这里我不局限于回答题主的问题,而是分享一下我个人关于如何做好Android技术面试的一些经验:面试前的准备1. 简历调查简历到你手上的时候,你要做好充分的调查分析,不仅仅是对公司负责,也是对自己与候选人时间的尊重,明显不match的简历,就不要抱着“要不喊过来试试看”的想法了,候选人也许很不错,但如果跟你的岗位不match, 也不要浪费大家时间,你要想清楚现在需要的人是有潜力可以培养的,还是亟需帮忙干活的。另外如果简历里附带了博客链接,GitHub地址,相关作品的,可以提前去看看,直接看人家多年积累的文章与代码,比这短短一小时的面试来得靠谱的多。2. 准备问题了解清楚候选人背景后,要根据简历,有针对性的准备问题,可以是他作品或做过项目里的某个技术细节的实现方式,也可以是他声称精通的某些领域的相关问题。总之不要等到面试过程中现想问题,特别是刚开始面试别人的同学,往往经验不足稍带紧张导致大脑短路,其实也是很尴尬的,把要问的问题提前写下来,准备充分。考察哪些点?1. 简历是否真实这其实是面试第一要务,面试的过程其实就是看简历是否属实的过程,因为能到面试环节,说明这个人是符合要求的,不满足要求的早就被剔除了,如果他真的如简历描述的那样,100%会招过来,如果人人都如此,那就不需要有面试这种过程了。需要注意的是这里的真实有三层含义:一是他如实描述了自身经历,很多人只在一些大项目里做一个很小的螺丝钉,但简历里往往夸张这段经历。二是不知道自己不知道,常见于简历里各种“精通”开头的描述,因为知识体系与视野的局限,明明只是了解很浅却夸口精通,很多时候他并不认为自己说的有问题,而是真的以为自己已然精通,有点井底之蛙的感觉。三是简历里的真实要与你的期望相匹配,一门技术了解到怎样的程度才算精通,很难有定论,所以这里的“真实”只能是候选人与面试官标准之间的契合,这种有主观运气成分,也许面试官水平不够错误判断了你,也不用感到不爽,面试何尝不是种双向选择呢。2. 技术的深度技术的深度一向是我最看重的部分,当今任何一个技术领域都非常宽广,一个人要同时掌握那么多知识并且都深入几乎不可能,那都需要拼学习效率与工作年限了。而你曾经做过的东西,正在做的东西,是绝对可以了解得更深入的,一个对技术有好奇心,有技术热情的人,都不会仅仅停留在这个东西挺好用,而是会忍不住去探究它背后的技术原理,即便不是亲自去看源码,也会花点时间了解别人整理过的经验,所以单凭考察技术上的深度,就可以考察一个人是否对技术有热情,是否有技术好奇心等等这些很多大牛认为的所谓“优秀程序员的特征”。之前曾看到过一句话:“一个人对他所做的事情了解得越深,他就能做的越好”。放在这里再合适不过了。3. 技术的广度深度是有了,还需要广度吗?我个人的理解是:深度是必要条件,广度是加分项。同样的有技术好奇心的优秀程序员,也不会满足于仅仅局限于自己的一亩三分地,工作之余,也会想要尝试一些其它的领域和方向,因为投入问题也许不够深入,但很多领域知识你知道与不知道,对你个人知识体系的形成关系很大。比如你要实现一个功能,在你当前熟悉的技术领域上很困难或者效果不佳,在你就要放弃时你的同事告诉你,这用一个简单sql语句就可以实现啦,为什么要搞得那么麻烦?这个例子虽然举得很蹩脚,但是我想意思大家应该已经明白了。知识越有广度,头脑里的技术体系就越完备,同样的问题,你就可以想到N个解,思考一下就得出最优解了,如果你听都没听过一些东西,就会经常说出“这个好难搞啊”,“这根本就不可能”,其实有的时候真是知识的局限问题,所谓的从0到1难,也是这个意思。4. 逻辑思维能力这也是我比较看重的一点,这里并不是指那些臭名昭彰的脑经急转弯问题,而是通过交流观察,判断一个人表达观点逻辑是否清晰,回答问题是否有章法,这个很难描述,但如果你细心观察,你会发现很容易通过一些简单的交流,就可以看出一个人是否逻辑清晰。有时候你会觉得某个人表达沟通很不错,其实不是沟通的问题,是他说出去的话,经过了他大脑的条理清晰的整理,让你很容易就能明白。这种习惯不是一朝一夕就能养成的,所以面试过程中这点装不出来。另外一个人如果逻辑清晰,而且反应又敏捷,语速很快,那是大大的加分项,恭喜你,碰到一个聪明人了。具体问哪些问题?前面提到的是要重点考察的点,那么具体的Android开发,有没有一些通用的问题可以问的呢?我个人一般会从这几个角度考察候选人:1. Android经验如果不是校招,Android经验是必须的,我比较喜欢问一些基础概念与技术原理,比如Activity、View、Window的理解,各LaunchMode的使用场景,View的绘制流程,Touch事件机制,Android动画的原理,Handler, Looper的理解,Android跨进程通讯的方式,Binder的理解,Android Mashup设计的理解等等。2. Java水平基本上就是Effective Java那本书里提到的东西,如果你背完那本书里的问题,并且对答如流,没问题,就要你这样的。其实也会考察关于final用法,反射原理,注解原理,java编译过程,GC等一些常见问题。 3. IT基础知识其实就是计算机科班学生学校里学到的一些东西,在校招时这块是重点,社招会放宽,但一些基本的常识是要有的,比如不少人都不知道http的get post有啥区别,https的那个s是什么意思,讲不清进程与线程的概念,不知道二分算法是个啥东西。这些简单问题的筛选,可以过滤一些所谓野路子的程序员,是不是科班出身不重要,搞这行就得对一些基本常识有概念,不然以后怎么愉快的交流呢?4. 代码质量的认识我们需要的是一个对代码味道有感觉的人,关于这点,看下《Clean Code》就够了,面试中这点其实不好考察,可以让他聊一聊对代码质量的认识,虽然不能排除对方夸夸其谈,至少想法不多,只能提到命名风格这一点的人是不符合要求的,也可以在写Code的环节中观察。5. 技术视野比如对Android开发新技术的了解与学习,对其它流行技术领域的了解,这其实与我刚才提到的技术广度的考察有关,就我面试过程中,发现很多非互联网行业的从业人员,因为公司各种操蛋规定与公司技术氛围的原因,技术视野相当狭窄。我个人对这点深有体会,2011年我还在传统行业从事软件研发,当时的公司因为担心技术信息泄露,不让上网,相当封闭,我个人虽然自认为已在那个行业内做到业内专家的级别,但总感觉哪里不对,有一天我很兴奋的打算跟身边同事聊一聊Android的时候,发现他们居然都不知Android为何物?2011年啊同志们,当时的震惊无法言表,深切感觉到需要作出改变了,毅然放弃多年行业积累,转战移动互联网,直到现在。时至今日,多年前的小伙伴也有很多混出了名党,开始走向人生巅峰,我也从来没有后悔当初做出的选择。6. 技术想象力一个优秀的技术人,如果知识的深度与广度足够,知识已成体系,那么他对于一些从未接触过的领域,也是可以做出足够合理的想象与判断,面试过程中如果问到一些领域候选人没有涉猎,这时候一般不用过多纠缠,但如果你想借这个问题考察下他的技术想象力,可以深入下去,比如问他:“你觉得这个东西应该是什么原理呢?”,“这个酷炫的控件,如果要你来做,你会怎么实现?”。在这方面表现出色的同学无疑是有深厚基础与足够广度的人。7. 技术习惯好的程序员都会有好的习惯,比如各种快捷键的熟练应用,各种命令行的掌握,一些提高开发效率的工具与习惯,碰到问题是baidu还是google,有没有做一些小工具帮助减少重复工作,工作之余有没有继续学习?有没有看什么不错的书等等,这些小细节很大程度上决定了程序员的开发效率,这也是为什么很多人说一个优秀程序员抵得上100个普通程序员,这也是重要原因之一。面试后的反馈:面试一般不止一轮,你需要给出你的反馈,多轮面试结果一起考量,减少误判的风险,反馈一般怎么写呢?以下是我的建议:1. 面试纪录面试过程中的完整纪录,尽量客观评价,让其它面试官知道你问了哪些问题,回答的怎么样,也避免了重复问题的尴尬。2. 优点与缺点你的主观评价,亮点有哪些,你觉得哪些地方不够好?3. 综合评价你对候选人的综合评价,hire或者no hire的根本原因,如果有些地方感觉没考察清楚,期望其它面试官继续加强考察,也可以写上。4. 怎样才给通过?通过标准因人而异,每个人都有自己心中的bar, 但还是有些可直观考量的因素的:一是岗位的要求,不同的岗位标准当然不一样,校招与设招肯定也不一样。二是岗位的紧急程度,兄弟们天天加班忙死了,赶紧找人过来帮忙吧哈哈。三是候选人的年龄,大龄程序员莫怪,一把年纪了还跟刚毕业一两年的同事一个水平,说明成长太慢,做技术的潜力有限,这个大家应该能理解。四是前面提到的做技术的深度,这个是必须的,广度也要有一些,视野不能太窄。五是要有亮点,大家在面试的过程中要注意发掘亮点,有时候他问题很多但有一个足够的亮点也够了,用心观察也发现不了什么亮点的,就要注意了。说了这么多,其实最重要的就是一句话,问问你自己:你真的原意跟那个家伙一起并肩战斗吗?我最近运营了一个微信公众号AndroidTrending,主要专注Android最佳实践,经验分享等,大家有兴趣的欢迎前往关注,我会定期更新一些开发经验到上面。
首先,面试官们一定要知道,每个人由于经历不同,擅长的方向是千差万别的,所以一定不要抓住自己擅长的某个方面去问的很深,觉得“如果连这个都不会还算毛程序员啊”。所以我问问题的时候,往往是“两步走”的循环:1. 问他做过什么,如果有成品的话,我能看看更好。2. 从他做过的东西里面,找到问题进行提问。具体的问题要看情况,可以是界面或效果的实现方式、相关bug的排除、该部分原理的分析。举一次面试时的对话作为例子吧:我先开始:“这份简历和网上投过来的那份是一样的吧?”“嗯,应该是一样的。”“嗯好。你在之前的团队的位置是什么?”“中高级吧。”“具体的工作呢?”“写框架,让新人比较容易上手,能够轻松工作。”“你说的框架具体包括什么呢?”“一些会共用的东西,写出来可以让新人就算是刚来也能很好的完成工作。”“联网是你封装的吗?”“是。”“你们联网用的是什么?”“就是……安卓自带的……HttpClient。”“直接用的?”“嗯。”“那你们的网络请求是怎么做的异步呢?”“嗯……用Handler嘛,还有AsyncTask。”“能具体一点吗?”“嗯……就是……额……”“例如什么情况下用Handler,什么情况下用AsyncTask,你是怎么决定的呢?”“嗯……”“或者说,他们有什么区别呢?谷歌为什么要造他们两个出来,而不是只造一个呢?”“区别……区别……他们肯定是有区别的,不然谷歌不可能造两个。嗯……”(到这里,这个问题就可以结束了。评级减一。)“这样吧,你的简历上提到‘熟悉大图片的加载’,能说一下大图片加载有什么需要注意的吗?”“缓存嘛。”“缓存?”“嗯,大图片的加载不就是ListView里面的大图片加载吗?要防止内存溢出。”“ListView里面一定是大图?”“嗯……”(不了解的东西却说自己熟悉,评级减一。继续顺着问。)“那么ListView中图片的缓存你是怎么做的呢?”“三级缓存嘛。”“哪三级?”“如果内存里面有,就用内存里面的;如果没有就用本地的;如果本地也没有就从网络上取。三级。”“网络上的也叫缓存?”“啊。你可以把他看作缓存,也可以不看作缓存嘛。”(这个……)(最近收到的简历看到很多说自己熟悉三级缓存的,于是我在网上搜了一下,终于找到“三级缓存”的出处了:原来是
写的,难怪这么火。不过他在文中提到了,“其实网络不算cache,这里姑且也把它划到缓存的层次结构中”。)“内存缓存你是怎么实现的?”“用的一个HashMap。”“直接用的HashMap吗?”“嗯……嗯。”“直接用HashMap的话,怎么防止你刚才提到的内存溢出呢?”“你可以用软引用嘛。”(首先答案有问题,另外当听到关键词“你可以”,多数情况下这个问题也可以结束了——八成是不会,仅仅听说过。不过出于谨慎还是继续问了)“软引用就能防止内存溢出吗?”“还有……还有谷歌出的一个叫LRUCache的。”(回避正面回答,确认他是不会。这个问题结束。评级减一。到此就再没必要聊下去了。)然后简单过渡一下,就结束了面试。所以你看,只需要简单提问,然后接着对方的回答继续往深了问,就什么都问出来了。--------------------------------------------------------------------------------评论中有人问到这次面试中我没有问完的问题的答案,那简单就说一下,想了解更多还请自行谷歌。Handler和AsyncTask:这俩类都是用来实现异步的,其中AsyncTask的集成度较高,使用简单,Handler则需要手动写Runnable或者Thread的代码;另外,由于AsyncTask内部实现了一个非常简单的线程池,实际上是只适用于轻量级的异步操作的,一般不应该用于网络操作。(感谢网友指正,AsyncTask 通过重写的方式是可以用于长耗时操作的,而我只考虑了直接使用的情况就说它不适合网络操作,是不对的。)我问他Handler和AsyncTask的区别,一方面是因为他说用AsyncTask联网,因此我认为他对AsyncTask并不熟悉;但更重要的是在我问他实现异步的具体手段的时候,他同时提到了Handler和AsyncTask——用这种“混搭”的使用方式来写联网框架,就算不考虑AsyncTask的可用性,也显得非常怪异,这听起来更像是在“列举Android实现异步操作最常用的类”,而非“讲述实现网络异步操作的具体方式”。也就是说,我听了这句话后开始怀疑他封装过联网框架这件事的真实性。但我只是怀疑,并不确定,因此接着问了我想问的。图片缓存:大多数情况下,内存中使用LRUCache是最合适的。如果用HashMap来实现,不是不可以,但完全没必要嘛!需要注意在合适的时候释放缓存。至于具体怎么释放,我没考虑过,但用软引用的问题在于,你很难控制缓存的大小,也就是说,只有等到你的内存快要撑爆,你的图片缓存才会被回收。是不是感觉傻傻的?(经网友指出,LRUCache 的内部实现就是用的 HashMap。由于我没有读过 LRUCache 的源码不知道这点,在评论里被大家骂惨了。)对于初级和中级工程师,我更倾向于考虑对方的学习能力,也就是你对于自己所做过的东西是否足够了解,而非要求你那里都强,因为就像我开头说的,每个人由于经历不同,擅长的方向是千差万别的,我不喜欢挑别人的软肋问。只要你学习能力强,我就安全感满满哒!至于高级工程师么……我还没面过呐!^_^
1,让他描述一个曾经解决的最难的问题2,如果他没遇到过难的问题,就给他一个难问题,看他如何思考。3,他的产品观。其实第3点非常非常重要。所有技能都可以学,但是看法和视野需要太长的时间来训练。
你用什么翻墙?
提供几个供参考:1. 什么是ANR,如何避免ANR。2. 什么是FC?如何避免FC的发生,另外FC发生时如何捕获相应的uncaught exception?3. Asynctask的优缺点?能否同时并发100+asynctask呢?4. Handler有何作用?如何使用之(具体讲需要实现什么function)?5. 有哪些实现自定义控件的方法?6. CMWAP, CMNET有何区别,网络通讯时是否要特殊处理?如何切换接入点?7. 能否讲讲你用过的adapter?8. 已经发布了软件版本A,使用sqlite存储用户数据其DB version为1包含某张表T1,则其后需要发布版本B,在版本A的T1表结构的基础上又增加了2个新的字段,则能否在保存用户已经安装的版本A的数据的前提下,更新安装新版本B?9. 你怎么看待在android上面应用MVC框架,是否有必要抽象独立于activity的C?10. 各种基础问题--侧重考察熟练度,例如有几种在activity之间切换的方法?能否描述一下android平台的framework的层次结构?etc。。。11.直接问候选人你准备下面让其开展的工作的内容,问问他会如何实现?大概需要多少工时?12. 最关键的还是候选人的学习能力&基本功,介个多花点时间和候选人沟通,深入的讨论一些技术问题相信你自会有结论的。
关于新API的了解程度(FingerManger等),listview优化(至少说出2种),联网机制,断点续传,缓存机制,回收机制等...我是新手,勿信...
感觉大家更多的是从拷问第三方应用开发者的角度来看。我稍微补充一句吧,系统应用开发的话(比如phone app),绝大部分时候,对某些模块的流程和结构的熟悉和理解程度,遇到问题对root cause的定位精度,是比具体的某些控件如何使用等等更加有意义的。
题目神马的都是浮云,看他做过的项目,界面,功能再问几个原理上的问题就能看出他的能力啊。
聊下我面 Android 开发的时候的基本过程吧。1. 先谈谈最简单的东西,包括不限于:最基本的 App 生命流程,Context 的理解(Application Context 和 Activity Context 异同), ANR 处理,BitMap 和 OOM 的处理,函数调用Trace 怎么玩,客户端怎么请求网络等等。2.聊聊项目,让对方描述下做过的项目里面的自己觉得最有印象的一到两个点3.如果觉得不错,就给一个小作业,一般是不超过2小时就能做完的东西,比如做个简单的小游戏(贪吃蛇,扫雷)会给予一些资源图。允许上网,允许带回家完成。
Just shut up and show me the app!
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 android兼容性问题 的文章

 

随机推荐