这是使用Fragment在Android Studio开发相机应用系列文章5篇中的第4篇。如果你没有读过之前的文章,先从GitHub上复制一份我的工程,这篇教程主要讨论”NativeCameraFragment“。 
作者语:由于设备厂商庞多繁杂,不同版本相机API不同,一个完整健壮的相机应用是很复杂的。如果你想实现一个完整可行的,可以考虑以CWAC Camera为基础进行开发。我的目标仅仅是演示相机开发的一些基础。 
除了安卓的原生相机应用,你也可以在自己的项目中使用相机功能。这涉及到直接利用安卓相机接口并把结果投射到“预览”界面或者SurfaceView上。 
  
开启相机
一旦Fragment视图对象被创建,首先做的就是把相机和相机预览界面关联起来。你可以在谷歌的开发者网站上阅读相关的文档,下面是一个参考实现: 
    
        
            | 
             1 
            2 
            3 
            4 
            5 
            6 
            7 
            8 
            9 
            10 
             | 
            
            
            private boolean safeCameraOpenInView(View view) { 
                boolean qOpened = false; 
                releaseCameraAndPreview(); 
                mCamera = getCameraInstance(); 
                qOpened = (mCamera != null); 
                mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera); 
                FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview); 
                preview.addView(mPreview); 
                return qOpened; 
            } 
             
             | 
         
    
 
 
 
该函数用来获取一个相机的实例对象并和我们的CameraPreview对象关联起来。 
相机预览界面
例子中的CameraPreview 对象继承了SurfaceView 并实现了SurfaceHolder.callback接口,预览界面将显示相机的输入。在你看到正在拍摄的画面的同时,它将处理SurfaceHolder的生命周期: 
    
        
            | 
             1 
            2 
            3 
            4 
            5 
            6 
            7 
            8 
            9 
            10 
            11 
            12 
            13 
            14 
            15 
            16 
            17 
            18 
            19 
            20 
            21 
            22 
            23 
            24 
            25 
            26 
            27 
            28 
            29 
            30 
            31 
            32 
            33 
            34 
            35 
            36 
            37 
            38 
            39 
            40 
            41 
            42 
            43 
            44 
            45 
            46 
            47 
            48 
            49 
            50 
            51 
            52 
            53 
            54 
            55 
            56 
            57 
            58 
            59 
            60 
            61 
            62 
             | 
            
            
            /** 
              * Surface on which the camera projects it's capture results. 
              */ 
             class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
                 SurfaceHolder mHolder; 
                 Camera mCamera; 
              
                 public CameraPreview(Context context, Camera camera) { 
                     super(context); 
                     mCamera = camera; 
              
                      
                      
                     mHolder = getHolder(); 
                     mHolder.addCallback(this); 
                      
                     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
                 } 
              
                 public void surfaceCreated(SurfaceHolder holder) { 
                      
                     try { 
                         mCamera.setPreviewDisplay(holder); 
                         mCamera.startPreview(); 
                     } catch (IOException e) { 
                         e.printStackTrace(); 
                     } 
                 } 
              
                 public void surfaceDestroyed(SurfaceHolder holder) { 
                      
                 } 
              
                 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
                      
                      
              
                     if (mHolder.getSurface() == null){ 
                          
                         return; 
                     } 
              
                      
                     try { 
                         mCamera.stopPreview(); 
                     } catch (Exception e){ 
                          
                     } 
              
                      
                      
              
                      
                     try { 
                         mCamera.setPreviewDisplay(mHolder); 
                         mCamera.startPreview(); 
              
                     } catch (Exception e){ 
                         e.printStackTrace(); 
                     } 
                 } 
             } 
             
             | 
         
    
 
 
 
相机拍照回调
Camera.PictureCallback是安卓用来判断何时相机拍摄了照片,并且获取了输出结果的回调接口。在我的示例项目工程中实现如下: 
    
        
            | 
             1 
            2 
            3 
            4 
            5 
            6 
            7 
            8 
            9 
            10 
            11 
            12 
            13 
            14 
            15 
            16 
            17 
            18 
            19 
            20 
            21 
            22 
            23 
             | 
            
            
            private Camera.PictureCallback mPicture = new Camera.PictureCallback() { 
              
                @Override 
                public void onPictureTaken(byte[] data, Camera camera) { 
              
                    File pictureFile = getOutputMediaFile(); 
                    if (pictureFile == null){ 
                        Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT) 
                        .show(); 
                        return; 
                    } 
              
                    try { 
                        FileOutputStream fos = new FileOutputStream(pictureFile); 
                        fos.write(data); 
                        fos.close(); 
                    } catch (FileNotFoundException e) { 
                        e.printStackTrace(); 
                    } catch (IOException e) { 
                        e.printStackTrace(); 
                    } 
                } 
            }; 
             
             | 
         
    
 
 
 
免责声明和补充
文章一发布我就从安卓相机跨设备开发专家那得到了反馈,我的目标是提供高质量的内容,所以不说清楚下面的这些问题文章就不完整 。 
在我的例子中假定设备支持jpeg格式,这种假定存在风险,真实的实现需要检查是否支持jpeg格式。另一个问题 CameraHolder.PreviewCallback接口直到API版本18许多厂商才支持,这使得API 18以前PreviewCallback 将难以起作用。 
此例中,我使用的默认CameraPreview 格式是NV21,已经有人推荐我使用YV12(从API 12开始支持),一定要检查下相机支持的CameraPreview格式。实现格式因设备厂商不同而不同,是不一致行为的潜在根源。 
还有包括闪光灯和聚焦模式在内的很多细节问题没有探讨,这些可能需要设置一些相机的参数,我已经在GitHub上更新了代码。 
以上就是我直接使用安卓原生相机的例子,随便获取例子代码,同样,如果你觉得这篇文章对你有帮助欢迎分享。非常感谢。 
原文链接: airpair   翻译: 伯乐在线 - 黄瓜 
译文链接: http://blog.jobbole.com/72858/  |