Android java.lang.IllegalArgumentException: previewSize must not be taller than activeArray

妖精的绣舞 提交于 2020-01-03 19:35:05

问题


My application was working good in large number of phones. However, when I installed it in my old android phone the following error is thrown and application crashes while taking the photo.

Android java.lang.IllegalArgumentException: previewSize must not be taller than activeArray

Photo Capturing code:

public class Camera1 extends AppCompatActivity {
    private static final String TAG = "AndroidCameraApi";
    private TextureView textureView;
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    static {
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
        ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    private Bitmap scaled;
    private Bitmap mBitmapToSave;
    private Bitmap mBitmapToSave1;
    private String cameraId;
    protected CameraDevice cameraDevice;
    protected CameraCaptureSession cameraCaptureSessions;
    protected CaptureRequest captureRequest;
    protected CaptureRequest.Builder captureRequestBuilder;
    private Size imageDimension;
    private ImageReader imageReader;
    private File file;
    private com.google.android.gms.vision.face.FaceDetector detector;
    private static final int REQUEST_CAMERA_PERMISSION = 200;
    private boolean mFlashSupported;
    private Handler mBackgroundHandler;
    private HandlerThread mBackgroundThread;
    private int width = 640;
    private int height = 480;
    private int index;
    //Image request code
    private int PICK_IMAGE_REQUEST = 1;
    private int a=0;

    //storage permission code
    private static final int STORAGE_PERMISSION_CODE = 123;

    //Bitmap to get image from gallery
    private Bitmap bitmap;

    //Uri to store the image uri
    private Uri filePath;
    private String name,dl_no,truck_id, tstatus;
    private float l_value;
    private String dl;
    private int c=0;
    File fileToUpload;
    int f=0;
    private String uuid;
    String latitude;
    String longitude;
    String time1;
    String date1;
    private int mSensorOrientation;
    CameraCharacteristics characteristics;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_camera2_api);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        textureView = (TextureView) findViewById(R.id.texture);
        assert textureView != null;
        textureView.setSurfaceTextureListener(textureListener);
        detector = new FaceDetector.Builder(getApplicationContext())
                .setMode(FaceDetector.ACCURATE_MODE)
                .build();
        uuid = UUID.randomUUID().toString();
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            l_value=extras.getFloat("v");
            tstatus=extras.getString("status");
            name=extras.getString("name");
            dl_no=extras.getString("dl");
            truck_id=extras.getString("tid");
            latitude=extras.getString("lat");
            longitude=extras.getString("lon");
            time1 =extras.getString("t");
            date1=extras.getString("d");
        }

        fileToUpload = new File(Environment.getExternalStorageDirectory() + "/" + "/Faceapp/"+name+"_"+dl_no+"_"+truck_id+"_"+latitude+"_"+longitude+"_"+time1+"_"+date1+"_"+a+".jpg");
        //Intent uplaod_intent = new Intent(Camera1.this, uploadRest.class);
        // Add extras to the bundle
        // Start the service
       // Camera1.this.startService(uplaod_intent);
    }

    private int getOrientation(int rotation) {
        // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X
        // We have to take that into account and rotate JPEG properly.
        // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
        // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
        return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
    }

    TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            //open your camera here
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            // Transform you image captured size according to the surface width and height
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        }
    };

    private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(CameraDevice camera) {
            //This is called when the camera is open
            Log.e(TAG, "onOpened");
            cameraDevice = camera;
            createCameraPreview();
        }

        @Override
        public void onDisconnected(CameraDevice camera) {
            cameraDevice.close();
        }

        @Override
        public void onError(CameraDevice camera, int error) {
            cameraDevice.close();
            cameraDevice = null;
        }
    };

    final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
        @Override
        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
            super.onCaptureCompleted(session, request, result);
            Toast.makeText(Camera1.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
            createCameraPreview();
        }
    };

    protected void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("Camera Background");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }

    protected void stopBackgroundThread() {
        mBackgroundThread.quitSafely();
        try {
            mBackgroundThread.join();
            mBackgroundThread = null;
            mBackgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void goToCompletedActivity(Context mContext) {
        Intent login = new Intent(mContext, Completed.class);
        mContext.startActivity(login);
    }

    private void userLogin() {
        //first getting the values
        final String Driver_id = dl_no;

        class UserLogin extends AsyncTask<Void, Void, String> {

            ProgressBar progressBar;

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressBar = (ProgressBar) findViewById(R.id.progressBar);
                //progressBar.setVisibility(View.VISIBLE);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                // progressBar.setVisibility(View.GONE);


                try {
                    //converting response to json object
                    JSONObject obj = new JSONObject(s);

                    //if no error in response
                    if (!obj.getBoolean("error")) {
                        Toast.makeText(getApplicationContext(), obj.getString("message"), Toast.LENGTH_SHORT).show();

                        //getting the user from the response
                        JSONObject userJson = obj.getJSONObject("user");

                        //creating a new user object
                        User user = new User(
                                userJson.getString("Driver_id"),
                                userJson.getString("Driver_name"),
                                userJson.getString("Truck_id"),
                                userJson.getString("Trainingstatus")

                        );

                        //storing the user in shared preferences
                        SharedPrefManager.getInstance(getApplicationContext()).userLogin(user);

                        //starting the profile activity
                        finish();
                        startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
                    } else {
                        Toast.makeText(getApplicationContext(), "Invalid Driver ID", Toast.LENGTH_SHORT).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            protected String doInBackground(Void... voids) {
                //creating request handler object
                RequestHandler requestHandler = new RequestHandler();

                //creating request parameters
                HashMap<String, String> params = new HashMap<>();
                params.put("Driver_id", Driver_id);


                //returing the response
                return requestHandler.sendPostRequest(URLs.URL_LOGIN, params);
            }
        }

        UserLogin ul = new UserLogin();
        ul.execute();

    }

    public void launchuploadservice() {
        // Construct our Intent specifying the Service
        Intent i = new Intent(this, Upload.class);
        // Add extras to the bundle
        i.putExtra("name", name);
        i.putExtra("dl", dl_no);
        i.putExtra("tid", truck_id);
        i.putExtra("lat", latitude);
        i.putExtra("lon", longitude);
        i.putExtra("status", tstatus);
        i.putExtra("t", time1);
        i.putExtra("d", date1);
        // Start the service
        startService(i);
    }

    protected void takePicture() {
        if (null == cameraDevice) {
            Log.e(TAG, "cameraDevice is null");
            return;
        }

        final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
            Size[] jpegSizes = null;
            if (characteristics != null) {
                jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
            }
            if (jpegSizes != null && 0 < jpegSizes.length) {
                width = jpegSizes[0].getWidth();
                height = jpegSizes[0].getHeight();
            }
            ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
            List<Surface> outputSurfaces = new ArrayList<Surface>(2);
            outputSurfaces.add(reader.getSurface());
            outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
            final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(reader.getSurface());
            captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            // Orientation
            int displayRotation = this.getWindowManager().getDefaultDisplay().getRotation();
            int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            boolean swappedDimensions = false;
            switch (displayRotation) {
                case Surface.ROTATION_0:
                case Surface.ROTATION_180:
                    if (sensorOrientation == 90 || sensorOrientation == 270) {
                        if (mSensorOrientation == 90 || mSensorOrientation == 270) {
                            swappedDimensions = true;
                        }
                    }
                    break;
                case Surface.ROTATION_90:
                case Surface.ROTATION_270:
                    if (sensorOrientation == 0 || sensorOrientation == 180) {
                        if (mSensorOrientation == 0 || mSensorOrientation == 180) {
                            swappedDimensions = true;
                        }
                    }
                    break;
            }
            int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));



            ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Image image = null ;
                    try {
                        image = reader.acquireLatestImage();
                        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                        byte[] bytes = new byte[buffer.capacity()];
                        buffer.get(bytes);
                        mBitmapToSave = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                        if (detector.isOperational() && mBitmapToSave != null) {
                            Frame frame = new Frame.Builder()
                                    .setBitmap(mBitmapToSave)
                                    //.setImageData(buffer, width, height, YUV_420_888)
                                    //.setRotation(getWindowManager().getDefaultDisplay().getRotation())
                                    .build();
                            SparseArray<Face> faces = detector.detect(frame);

                            for (index = 0; index < faces.size(); ++index) {
                                Face face = faces.valueAt(index);
                            }
                            if (faces.size() == 0) {
                                Toast.makeText(Camera1.this, "No Face" + "\n", Toast.LENGTH_SHORT).show();
                                saveImageToDisk(bytes);
                                MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.not);
                                mediaPlayer.start();
                               // mBitmapToSave.recycle();

                            } else {
                                saveImageToDisk(bytes);
                                Toast.makeText(Camera1.this, "Face Found " + "\n", Toast.LENGTH_SHORT).show();
                                launchuploadservice();
                            }
                        }
                    } catch (Exception ee) {
                    }
                    finally {
                        if(image!=null)
                            image.close();
                    }


                }


            };
            reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
            final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                    createCameraPreview();

                }
            };
            cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession session) {
                    try {
                        session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession session) {
                }
            }, mBackgroundHandler);

            mBitmapToSave = null;
        } catch(CameraAccessException e){
            e.printStackTrace();
        }
    }
    private void saveImageToDisk(final byte[] bytes) {
        final File file = new File(Environment.getExternalStorageDirectory() + "/"+"/Faceapp/"+name+"_"+dl_no+"_"+truck_id+"_"+longitude+"_"+latitude+"_"+time1+"_"+date1 + "_.jpg");
        try (final OutputStream output = new FileOutputStream(file)) {
            output.write(bytes);
            //this.picturesTaken.put(file.getPath(), bytes);
        } catch (IOException e) {
            Log.e(TAG, "Exception occurred while saving picture to external storage ", e);
        }
    }

    protected void createCameraPreview() {
        try {
            SurfaceTexture texture = textureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
            Surface surface = new Surface(texture);
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureRequestBuilder.addTarget(surface);
            cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    //The camera is already closed
                    if (null == cameraDevice) {
                        return;
                    }
                    // When the session is ready, we start displaying the preview.
                    cameraCaptureSessions = cameraCaptureSession;
                    updatePreview();
                }
                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(Camera1.this, "Configuration change", Toast.LENGTH_SHORT).show();
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private void openCamera() {
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        Log.e(TAG, "is camera open");
        try {
            cameraId = manager.getCameraIdList()[1];
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            assert map != null;
            imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
            // Add permission for camera and let user grant the permission
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(Camera1.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
                return;
            }
            manager.openCamera(cameraId, stateCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

        Log.e(TAG, "openCamera X");
    }
    protected void updatePreview() {
        if(null == cameraDevice) {
            Log.e(TAG, "updatePreview error, return");
        }

        captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        try {
            cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void closeCamera() {
        if (null != cameraDevice) {
            cameraDevice.close();
            cameraDevice = null;
        }
        if (null != imageReader) {
            //image.close();
            imageReader.close();
            imageReader = null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                // close the app
                Toast.makeText(Camera1.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
                finish();
            }
        }
    }

   // @Override
   /* public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                // close the app
                Toast.makeText(Camera1.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
                finish();
            }
        }
    }
    */
    @Override
    protected void onResume() {
        final Intent intent = new Intent(Camera1.this, Completed.class);
        super.onResume();
        Log.e(TAG, "onResume");

        startBackgroundThread();
        if (textureView.isAvailable()) {
            openCamera();
        } else {
            textureView.setSurfaceTextureListener(textureListener);
        }

        final int PICTURES_LIMIT = 1;

        final Timer timer = new Timer();

        timer.schedule(new TimerTask() {
            int pictureNo=0;
            public void run() {
                if (pictureNo>PICTURES_LIMIT){
                    timer.cancel();
                    finish();
                } else {
                    takePicture();
                    pictureNo++;
                }
            }

        },10, 5500);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause");
        closeCamera();
        stopBackgroundThread();
    }
}

回答1:


Based on the code found here, its pretty self explanatory that the old device preview size is less than the size that you're trying to crop.

Check the getPreviewCropRectangleUnzoomed function in the code that I have mentioned above. The documentation of the function says the cause of the error specifically. From the documentation.

 /**
 * Calculate the effective crop rectangle for this preview viewport;
 * assumes the preview is centered to the sensor and scaled to fit across one of the dimensions
 * without skewing.
 *
 * <p>The preview size must be a subset of the active array size; the resulting
 * rectangle will also be a subset of the active array rectangle.</p>
 *
 * <p>The unzoomed crop rectangle is calculated only.</p>
 *
 * @param activeArray active array dimensions, in sensor space
 * @param previewSize size of the preview buffer render target, in pixels (not in sensor space)
 * @return a rectangle which serves as the preview stream's effective crop region (unzoomed),
 *         in sensor space
 *
 * @throws NullPointerException
 *          if any of the args were {@code null}
 * @throws IllegalArgumentException
 *          if {@code previewSize} is wider or taller than {@code activeArray}
 */

Check the part - The preview size must be a subset of the active array size; the resulting rectangle will also be a subset of the active array rectangle. which declares the preview size must be smaller than the actual active array size.

In this case, you might consider having a try/catch block while you are taking picture using the camera.

try {
    takePicture();
} catch (IllegalArgumentException e) {
    Toast.makeText(this, "Your phone is too old", Toast.LENGTH_SHORT).show();
}

Hope that helps.




回答2:


I believe that this may happen in very old devices with small image sensors, although seems to me (only guessing) more like a mistake by the manufacturer when they implemented the camera2 legacy wrapper.

A solution could be that when you are resolving the optimal preview size, then also to take into account that such preview size it doesn't exceed the size specified by SENSOR_INFO_ACTIVE_ARRAY_SIZE, which can be queried in the CameraCharacteristics:

CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE



来源:https://stackoverflow.com/questions/48942403/android-java-lang-illegalargumentexception-previewsize-must-not-be-taller-than

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!