zoukankan      html  css  js  c++  java
  • 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方法。

     private native final void native_setParameters(String params);
    
        /**
         * Changes the settings for this Camera service.
         *
         * @param params the Parameters to use for this Camera service
         * @throws RuntimeException if any parameter is invalid or not supported.
         * @see #getParameters()
         */
        public void setParameters(Parameters params) {
            native_setParameters(params.flatten());
        }

    从这段代码中代码中。我们能够得到什么信息呢,setParameters方法是调用jni方法native_setParameters的方法,事实上看到这里就差并不多了,由于再去查看jni方法是非常麻烦的。毕竟我们日常开发使用大部分是java代码。我们能够发现传输进来的是Parameters參数,调用了Parameters的flatten方法。

    我们查找flatten的代码进行查看。

     /**
             * Creates a single string with all the parameters set in
             * this Parameters object.
             * <p>The {@link #unflatten(String)} method does the reverse.</p>
             *
             * @return a String with all values from this Parameters object, in
             *         semi-colon delimited key-value pairs
             */
            public String flatten() {
                StringBuilder flattened = new StringBuilder();
                for (String k : mMap.keySet()) {
                    flattened.append(k);
                    flattened.append("=");
                    flattened.append(mMap.get(k));
                    flattened.append(";");
                }
                // chop off the extra semicolon at the end
                flattened.deleteCharAt(flattened.length()-1);
                return flattened.toString();
            }

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

    /**
             * Takes a flattened string of parameters and adds each one to
             * this Parameters object.
             * <p>The {@link #flatten()} method does the reverse.</p>
             *
             * @param flattened a String of parameters (key-value paired) that
             *                  are semi-colon delimited
             */
            public void unflatten(String flattened) {
                mMap.clear();
    
                StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
                while (tokenizer.hasMoreElements()) {
                    String kv = tokenizer.nextToken();
                    int pos = kv.indexOf('=');
                    if (pos == -1) {
                        continue;
                    }
                    String k = kv.substring(0, pos);
                    String v = kv.substring(pos + 1);
                    mMap.put(k, v);
                }
            }
    
            /**
             * Sets a String parameter.
             *
             * @param key   the key name for the parameter
             * @param value the String value of the parameter
             */
            public void set(String key, String value) {
                if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
                    Log.e(TAG, "Key "" + key + "" contains invalid character (= or ;)");
                    return;
                }
                if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
                    Log.e(TAG, "Value "" + value + "" contains invalid character (= or ;)");
                    return;
                }
    
                mMap.put(key, value);
            }
    
            /**
             * Sets an integer parameter.
             *
             * @param key   the key name for the parameter
             * @param value the int value of the parameter
             */
            public void set(String key, int value) {
                mMap.put(key, Integer.toString(value));
            }
    
            private void set(String key, List<Area> areas) {
                if (areas == null) {
                    set(key, "(0,0,0,0,0)");
                } else {
                    StringBuilder buffer = new StringBuilder();
                    for (int i = 0; i < areas.size(); i++) {
                        Area area = areas.get(i);
                        Rect rect = area.rect;
                        buffer.append('(');
                        buffer.append(rect.left);
                        buffer.append(',');
                        buffer.append(rect.top);
                        buffer.append(',');
                        buffer.append(rect.right);
                        buffer.append(',');
                        buffer.append(rect.bottom);
                        buffer.append(',');
                        buffer.append(area.weight);
                        buffer.append(')');
                        if (i != areas.size() - 1) buffer.append(',');
                    }
                    set(key, buffer.toString());
                }
            }
    
            /**
             * Returns the value of a String parameter.
             *
             * @param key the key name for the parameter
             * @return the String value of the parameter
             */
            public String get(String key) {
                return mMap.get(key);
            }
    
            /**
             * Sets the dimensions for preview pictures. If the preview has already
             * started, applications should stop the preview first before changing
             * preview size.
             *
             * The sides of width and height are based on camera orientation. That
             * is, the preview size is the size before it is rotated by display
             * orientation. So applications need to consider the display orientation
             * while setting preview size. For example, suppose the camera supports
             * both 480x320 and 320x480 preview sizes. The application wants a 3:2
             * preview ratio. If the display orientation is set to 0 or 180, preview
             * size should be set to 480x320. If the display orientation is set to
             * 90 or 270, preview size should be set to 320x480. The display
             * orientation should also be considered while setting picture size and
             * thumbnail size.
             *
             * @param width  the width of the pictures, in pixels
             * @param height the height of the pictures, in pixels
             * @see #setDisplayOrientation(int)
             * @see #getCameraInfo(int, CameraInfo)
             * @see #setPictureSize(int, int)
             * @see #setJpegThumbnailSize(int, int)
             */
            public void setPreviewSize(int width, int height) {
                String v = Integer.toString(width) + "x" + Integer.toString(height);
                set(KEY_PREVIEW_SIZE, v);
            }
    

    /**
             * <p>Sets the dimensions for EXIF thumbnail in Jpeg picture. If
             * applications set both width and height to 0, EXIF will not contain
             * thumbnail.</p>
             *
             * <p>Applications need to consider the display orientation. See {@link
             * #setPreviewSize(int,int)} for reference.</p>
             *
             * @param width  the width of the thumbnail, in pixels
             * @param height the height of the thumbnail, in pixels
             * @see #setPreviewSize(int,int)
             */
            public void setJpegThumbnailSize(int width, int height) {
                set(KEY_JPEG_THUMBNAIL_WIDTH, width);
                set(KEY_JPEG_THUMBNAIL_HEIGHT, height);
            }
    
          
    
            /**
             * Sets the quality of the EXIF thumbnail in Jpeg picture.
             *
             * @param quality the JPEG quality of the EXIF thumbnail. The range is 1
             *                to 100, with 100 being the best.
             */
            public void setJpegThumbnailQuality(int quality) {
                set(KEY_JPEG_THUMBNAIL_QUALITY, quality);
            }
    
         
            /**
             * Sets Jpeg quality of captured picture.
             *
             * @param quality the JPEG quality of captured picture. The range is 1
             *                to 100, with 100 being the best.
             */
            public void setJpegQuality(int quality) {
                set(KEY_JPEG_QUALITY, quality);
            }
    
          
    
            /**
             * Sets the rate at which preview frames are received. This is the
             * target frame rate. The actual frame rate depends on the driver.
             *
             * @param fps the frame rate (frames per second)
             * @deprecated replaced by {@link #setPreviewFpsRange(int,int)}
             */
            @Deprecated
            public void setPreviewFrameRate(int fps) {
                set(KEY_PREVIEW_FRAME_RATE, fps);
            }
           
    
            /**
             * Sets the maximum and maximum preview fps. This controls the rate of
             * preview frames received in {@link PreviewCallback}. The minimum and
             * maximum preview fps must be one of the elements from {@link
             * #getSupportedPreviewFpsRange}.
             *
             * @param min the minimum preview fps (scaled by 1000).
             * @param max the maximum preview fps (scaled by 1000).
             * @throws RuntimeException if fps range is invalid.
             * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
             * @see #getSupportedPreviewFpsRange()
             */
            public void setPreviewFpsRange(int min, int max) {
                set(KEY_PREVIEW_FPS_RANGE, "" + min + "," + max);
            }
    
           
    
           
    
            /**
             * Sets the image format for preview pictures.
             * <p>If this is never called, the default format will be
             * {@link android.graphics.ImageFormat#NV21}, which
             * uses the NV21 encoding format.</p>
             *
             * @param pixel_format the desired preview picture format, defined
             *   by one of the {@link android.graphics.ImageFormat} constants.
             *   (E.g., <var>ImageFormat.NV21</var> (default),
             *                      <var>ImageFormat.RGB_565</var>, or
             *                      <var>ImageFormat.JPEG</var>)
             * @see android.graphics.ImageFormat
             */
            public void setPreviewFormat(int pixel_format) {
                String s = cameraFormatForPixelFormat(pixel_format);
                if (s == null) {
                    throw new IllegalArgumentException(
                            "Invalid pixel_format=" + pixel_format);
                }
    
                set(KEY_PREVIEW_FORMAT, s);
            }
    
        
           
    
            /**
             * <p>Sets the dimensions for pictures.</p>
             *
             * <p>Applications need to consider the display orientation. See {@link
             * #setPreviewSize(int,int)} for reference.</p>
             *
             * @param width  the width for pictures, in pixels
             * @param height the height for pictures, in pixels
             * @see #setPreviewSize(int,int)
             *
             */
            public void setPictureSize(int width, int height) {
                String v = Integer.toString(width) + "x" + Integer.toString(height);
                set(KEY_PICTURE_SIZE, v);
            }
    
       
    
            /**
             * Sets the image format for pictures.
             *
             * @param pixel_format the desired picture format
             *                     (<var>ImageFormat.NV21</var>,
             *                      <var>ImageFormat.RGB_565</var>, or
             *                      <var>ImageFormat.JPEG</var>)
             * @see android.graphics.ImageFormat
             */
            public void setPictureFormat(int pixel_format) {
                String s = cameraFormatForPixelFormat(pixel_format);
                if (s == null) {
                    throw new IllegalArgumentException(
                            "Invalid pixel_format=" + pixel_format);
                }
    
                set(KEY_PICTURE_FORMAT, s);
            }


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

    当时我的是使用setPictureSize时出现了错误,依据方法说明,我简单解释下。为什么会出错。由于parameters.setPictureSize(320, 480)(设置分辨率)的參数有误,假设不清楚分辨率能够却掉这句话。再执行就OK了。

     

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




  • 相关阅读:
    as3.0 网络通信
    flash显示html
    [javascript]对象
    hibernate
    远程服务
    [mysql]笔记1
    [笔记]深入剖析Tomcat-tomcat的默认连接器,servlet容器
    [java]关于访问权限
    [笔记]http权威指南(2)
    [笔记]http权威指南
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7040000.html
Copyright © 2011-2022 走看看