Android调用camera错误setParameters failed深层解析

1. Camera

Camera是Android framework里面支持的,允许你拍照和拍摄视频的设备,那么,在使用camera开发中总是会遇到一些问题,例如以下这样子的:

E/AndroidRuntime(1542): java.lang.RuntimeException: setParameters failed
E/AndroidRuntime(1542):  at android.hardware.Camera.native_setParameters(Native Method)
E/AndroidRuntime(1542):  at android.hardware.Camera.setParameters(Camera.java:914)
出现这种错误,根据错误提示我们可以知道是android的setParameters方法出错了。

2、那该如何解决呢?

我们知道camera的parameters中也有很多参数设置的,是哪个出错了呢?很多人不知所以然就上网开始找,找不到就开始各种猜测,一个个参数设置过去,其实最有效的方式是到底层找原因。ok,让我们打开android代码找到camera类。然后查找setParameters方法。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. private native final void native_setParameters(String params);  
  2.   
  3.    /** 
  4.     * Changes the settings for this Camera service. 
  5.     * 
  6.     * @param params the Parameters to use for this Camera service 
  7.     * @throws RuntimeException if any parameter is invalid or not supported. 
  8.     * @see #getParameters() 
  9.     */  
  10.    public void setParameters(Parameters params) {  
  11.        native_setParameters(params.flatten());  
  12.    }  

从这段代码中代码中,我们可以得到什么信息呢,setParameters方法是调用jni方法native_setParameters的方法,其实看到这里就差并不多了,因为再去查看jni方法是很麻烦的,毕竟我们日常开发使用大部分是java代码。我们可以发现传输进来的是Parameters参数,调用了 Parameters的flatten方法。我们查找flatten的代码进行查看。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.         * Creates a single string with all the parameters set in 
  3.         * this Parameters object. 
  4.         * <p>The {@link #unflatten(String)} method does the reverse.</p> 
  5.         * 
  6.         * @return a String with all values from this Parameters object, in 
  7.         *         semi-colon delimited key-value pairs 
  8.         */  
  9.        public String flatten() {  
  10.            StringBuilder flattened = new StringBuilder();  
  11.            for (String k : mMap.keySet()) {  
  12.                flattened.append(k);  
  13.                flattened.append("=");  
  14.                flattened.append(mMap.get(k));  
  15.                flattened.append(";");  
  16.            }  
  17.            // chop off the extra semicolon at the end  
  18.            flattened.deleteCharAt(flattened.length()-1);  
  19.            return flattened.toString();  
  20.        }  

从这段代码中,我们又能得到什么信息呢。我们可以看到提供数据的时候,数据都是从mMap中获取的。ok,接下来,我们查看一下mMap是有几个方法对其进行了赋值呢。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.          * Takes a flattened string of parameters and adds each one to 
  3.          * this Parameters object. 
  4.          * <p>The {@link #flatten()} method does the reverse.</p> 
  5.          * 
  6.          * @param flattened a String of parameters (key-value paired) that 
  7.          *                  are semi-colon delimited 
  8.          */  
  9.         public void unflatten(String flattened) {  
  10.             mMap.clear();  
  11.   
  12.             StringTokenizer tokenizer = new StringTokenizer(flattened, ";");  
  13.             while (tokenizer.hasMoreElements()) {  
  14.                 String kv = tokenizer.nextToken();  
  15.                 int pos = kv.indexOf('=');  
  16.                 if (pos == -1) {  
  17.                     continue;  
  18.                 }  
  19.                 String k = kv.substring(0, pos);  
  20.                 String v = kv.substring(pos + 1);  
  21.                 mMap.put(k, v);  
  22.             }  
  23.         }  
  24.   
  25.         /** 
  26.          * Sets a String parameter. 
  27.          * 
  28.          * @param key   the key name for the parameter 
  29.          * @param value the String value of the parameter 
  30.          */  
  31.         public void set(String key, String value) {  
  32.             if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {  
  33.                 Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");  
  34.                 return;  
  35.             }  
  36.             if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {  
  37.                 Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");  
  38.                 return;  
  39.             }  
  40.   
  41.             mMap.put(key, value);  
  42.         }  
  43.   
  44.         /** 
  45.          * Sets an integer parameter. 
  46.          * 
  47.          * @param key   the key name for the parameter 
  48.          * @param value the int value of the parameter 
  49.          */  
  50.         public void set(String key, int value) {  
  51.             mMap.put(key, Integer.toString(value));  
  52.         }  
  53.   
  54.         private void set(String key, List<Area> areas) {  
  55.             if (areas == null) {  
  56.                 set(key, "(0,0,0,0,0)");  
  57.             } else {  
  58.                 StringBuilder buffer = new StringBuilder();  
  59.                 for (int i = 0; i < areas.size(); i++) {  
  60.                     Area area = areas.get(i);  
  61.                     Rect rect = area.rect;  
  62.                     buffer.append('(');  
  63.                     buffer.append(rect.left);  
  64.                     buffer.append(',');  
  65.                     buffer.append(rect.top);  
  66.                     buffer.append(',');  
  67.                     buffer.append(rect.right);  
  68.                     buffer.append(',');  
  69.                     buffer.append(rect.bottom);  
  70.                     buffer.append(',');  
  71.                     buffer.append(area.weight);  
  72.                     buffer.append(')');  
  73.                     if (i != areas.size() - 1) buffer.append(',');  
  74.                 }  
  75.                 set(key, buffer.toString());  
  76.             }  
  77.         }  
  78.   
  79.         /** 
  80.          * Returns the value of a String parameter. 
  81.          * 
  82.          * @param key the key name for the parameter 
  83.          * @return the String value of the parameter 
  84.          */  
  85.         public String get(String key) {  
  86.             return mMap.get(key);  
  87.         }  
  88.   
  89.         /** 
  90.          * Sets the dimensions for preview pictures. If the preview has already 
  91.          * started, applications should stop the preview first before changing 
  92.          * preview size. 
  93.          * 
  94.          * The sides of width and height are based on camera orientation. That 
  95.          * is, the preview size is the size before it is rotated by display 
  96.          * orientation. So applications need to consider the display orientation 
  97.          * while setting preview size. For example, suppose the camera supports 
  98.          * both 480x320 and 320x480 preview sizes. The application wants a 3:2 
  99.          * preview ratio. If the display orientation is set to 0 or 180, preview 
  100.          * size should be set to 480x320. If the display orientation is set to 
  101.          * 90 or 270, preview size should be set to 320x480. The display 
  102.          * orientation should also be considered while setting picture size and 
  103.          * thumbnail size. 
  104.          * 
  105.          * @param width  the width of the pictures, in pixels 
  106.          * @param height the height of the pictures, in pixels 
  107.          * @see #setDisplayOrientation(int) 
  108.          * @see #getCameraInfo(int, CameraInfo) 
  109.          * @see #setPictureSize(int, int) 
  110.          * @see #setJpegThumbnailSize(int, int) 
  111.          */  
  112.         public void setPreviewSize(int width, int height) {  
  113.             String v = Integer.toString(width) + "x" + Integer.toString(height);  
  114.             set(KEY_PREVIEW_SIZE, v);  
  115.         }  

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.          * <p>Sets the dimensions for EXIF thumbnail in Jpeg picture. If 
  3.          * applications set both width and height to 0, EXIF will not contain 
  4.          * thumbnail.</p> 
  5.          * 
  6.          * <p>Applications need to consider the display orientation. See {@link 
  7.          * #setPreviewSize(int,int)} for reference.</p> 
  8.          * 
  9.          * @param width  the width of the thumbnail, in pixels 
  10.          * @param height the height of the thumbnail, in pixels 
  11.          * @see #setPreviewSize(int,int) 
  12.          */  
  13.         public void setJpegThumbnailSize(int width, int height) {  
  14.             set(KEY_JPEG_THUMBNAIL_WIDTH, width);  
  15.             set(KEY_JPEG_THUMBNAIL_HEIGHT, height);  
  16.         }  
  17.   
  18.         
  19.   
  20.         /** 
  21.          * Sets the quality of the EXIF thumbnail in Jpeg picture. 
  22.          * 
  23.          * @param quality the JPEG quality of the EXIF thumbnail. The range is 1 
  24.          *                to 100, with 100 being the best. 
  25.          */  
  26.         public void setJpegThumbnailQuality(int quality) {  
  27.             set(KEY_JPEG_THUMBNAIL_QUALITY, quality);  
  28.         }  
  29.   
  30.        
  31.         /** 
  32.          * Sets Jpeg quality of captured picture. 
  33.          * 
  34.          * @param quality the JPEG quality of captured picture. The range is 1 
  35.          *                to 100, with 100 being the best. 
  36.          */  
  37.         public void setJpegQuality(int quality) {  
  38.             set(KEY_JPEG_QUALITY, quality);  
  39.         }  
  40.   
  41.         
  42.   
  43.         /** 
  44.          * Sets the rate at which preview frames are received. This is the 
  45.          * target frame rate. The actual frame rate depends on the driver. 
  46.          * 
  47.          * @param fps the frame rate (frames per second) 
  48.          * @deprecated replaced by {@link #setPreviewFpsRange(int,int)} 
  49.          */  
  50.         @Deprecated  
  51.         public void setPreviewFrameRate(int fps) {  
  52.             set(KEY_PREVIEW_FRAME_RATE, fps);  
  53.         }  
  54.          
  55.   
  56.         /** 
  57.          * Sets the maximum and maximum preview fps. This controls the rate of 
  58.          * preview frames received in {@link PreviewCallback}. The minimum and 
  59.          * maximum preview fps must be one of the elements from {@link 
  60.          * #getSupportedPreviewFpsRange}. 
  61.          * 
  62.          * @param min the minimum preview fps (scaled by 1000). 
  63.          * @param max the maximum preview fps (scaled by 1000). 
  64.          * @throws RuntimeException if fps range is invalid. 
  65.          * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback) 
  66.          * @see #getSupportedPreviewFpsRange() 
  67.          */  
  68.         public void setPreviewFpsRange(int min, int max) {  
  69.             set(KEY_PREVIEW_FPS_RANGE, "" + min + "," + max);  
  70.         }  
  71.   
  72.          
  73.   
  74.          
  75.   
  76.         /** 
  77.          * Sets the image format for preview pictures. 
  78.          * <p>If this is never called, the default format will be 
  79.          * {@link android.graphics.ImageFormat#NV21}, which 
  80.          * uses the NV21 encoding format.</p> 
  81.          * 
  82.          * @param pixel_format the desired preview picture format, defined 
  83.          *   by one of the {@link android.graphics.ImageFormat} constants. 
  84.          *   (E.g., <var>ImageFormat.NV21</var> (default), 
  85.          *                      <var>ImageFormat.RGB_565</var>, or 
  86.          *                      <var>ImageFormat.JPEG</var>) 
  87.          * @see android.graphics.ImageFormat 
  88.          */  
  89.         public void setPreviewFormat(int pixel_format) {  
  90.             String s = cameraFormatForPixelFormat(pixel_format);  
  91.             if (s == null) {  
  92.                 throw new IllegalArgumentException(  
  93.                         "Invalid pixel_format=" + pixel_format);  
  94.             }  
  95.   
  96.             set(KEY_PREVIEW_FORMAT, s);  
  97.         }  
  98.   
  99.       
  100.          
  101.   
  102.         /** 
  103.          * <p>Sets the dimensions for pictures.</p> 
  104.          * 
  105.          * <p>Applications need to consider the display orientation. See {@link 
  106.          * #setPreviewSize(int,int)} for reference.</p> 
  107.          * 
  108.          * @param width  the width for pictures, in pixels 
  109.          * @param height the height for pictures, in pixels 
  110.          * @see #setPreviewSize(int,int) 
  111.          * 
  112.          */  
  113.         public void setPictureSize(int width, int height) {  
  114.             String v = Integer.toString(width) + "x" + Integer.toString(height);  
  115.             set(KEY_PICTURE_SIZE, v);  
  116.         }  
  117.   
  118.      
  119.   
  120.         /** 
  121.          * Sets the image format for pictures. 
  122.          * 
  123.          * @param pixel_format the desired picture format 
  124.          *                     (<var>ImageFormat.NV21</var>, 
  125.          *                      <var>ImageFormat.RGB_565</var>, or 
  126.          *                      <var>ImageFormat.JPEG</var>) 
  127.          * @see android.graphics.ImageFormat 
  128.          */  
  129.         public void setPictureFormat(int pixel_format) {  
  130.             String s = cameraFormatForPixelFormat(pixel_format);  
  131.             if (s == null) {  
  132.                 throw new IllegalArgumentException(  
  133.                         "Invalid pixel_format=" + pixel_format);  
  134.             }  
  135.   
  136.             set(KEY_PICTURE_FORMAT, s);  
  137.         }  


ok,错误的地方,我们就定位在这么几个地方了。在自己写的代码里面,查看一下是否调用了这几个方法~~~。android源码还是注释得比较清晰的,看看方法英文说明,看是否参数有出现了错误。

当时我的是使用setPictureSize时出现了错误,根据方法说明,我简单解释下,为什么会出错。因为parameters.setPictureSize(320, 480)(设置分辨率)的参数有误,如果不清楚分辨率可以却掉这句话,再运行就OK了。 

注:最后找了一下原因,感觉很简单,在实际 开发中,有时候一个小问题,就让人忙乎一个下午也是正常滴。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值