android Learning (XIV) Photo Capture

Keywords: Android FileProvider xml Google

Request camera privileges

<manifest ... >
    <uses-feature android:name="android.hardware.camera"
                  android:required="true" />
    ...
</manifest>

Google Play will allow applications to be downloaded on devices without cameras. Then you have the responsibility to check the availability of the camera hasSystem Feature (PackageManager. FEATURE_CAMERA) by calling it at runtime. If the camera cannot be used, the camera function should be disabled.

Open Photo Application for Photography

static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent(){
        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            //Disabling related items
        }else {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if(takePictureIntent.resolveActivity(getPackageManager())!= null){
                startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
            }
        }
    }

Note: Before calling the startActivityForResult() method, call resolveActivity(), which checks if you can handle the Intent's activity. Just this check is necessary, because if you call startActivityForResult(), your app crash es without an app that can handle your Intent. So as long as the return is not null, triggering Intent is safe.

Get thumbnails

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==REQUEST_IMAGE_CAPTURE&&resultCode==RESULT_OK){
            Bundle extras = data.getExtras();
            //date corresponds to the picture taken.
            Bitmap imageBitmap = (Bitmap) extras.get("date");
            mimageView.setImageBitmap(imageBitmap);
        }
    }

Note: The captured image is a thumbnail. Due to compatibility problems, some mobile phones may not display properly, so they can be saved and processed by file.

Save full-size pictures

Usually, images taken by users and device cameras should be stored outside the public so that they can be accessed by all applications.

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

However, if you want to keep photos private only with your application, you can change to the directory getExternal FilesDir (). WRITE_EXTERNAL_STORAGE license is also required to write this directory below Android 4.3. Starting with Android 4.4, licenses are no longer required because the directory is not accessible by other applications, so you can declare permissions only by adding the request maxSdkVersion attribute for a lower Android version

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
    ...
</manifest>

Once you decide on the files in the directory, you need to create conflict-resistant file names. You might as well save the path for a member variable. Following is an example solution to the method of returning a unique filename from a new photo using a date-time stamp:

 private File createImageFile() throws IOException{
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* Suffix */
                storageDir      /* Catalog */
        );
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }

Because using files to get Intent now should be like this

static final int REQUEST_TAKE_PHOTO = 1;

    private void dispatchTakePictureIntent(){
        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            //Disabling related items
        }else {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if(takePictureIntent.resolveActivity(getPackageManager())!= null){
                File photoFile = null;
                try {
                    photoFile = createImageFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if(photoFile!=null){
                    Uri photoURI = FileProvider
                    .getUriForFile(this,"com.example.android.fileprovider",photoFile);
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,photoURI);
                    startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
                }
            }
        }
    }

And the configuration of FileProvider

<application>
   ...
   <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.android.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"></meta-data>
    </provider>
    ...
</application>
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

For FileProvider, see android Learning (12) FileProvider

Add pictures to the gallery

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

Note: If you save an image through getExternal FilesDir (), the gallery is not available because it is a private directory.

Analytical image

This is just an example.

    private void srtPic(){
        //Get the dimension of the view
        int targetW = mimageView.getWidth();
        int targetH = mimageView.getHeight();
        //Getting the dimension of bitmap
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath,bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;
        //Determine how to zoom in or out of a picture
        //The following example is narrowed down
        int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
        //Decode the image file into bitmaps of the size of the filled view
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;
        Bitmap bitmap  =BitmapFactory.decodeFile(mCurrentPhotoPath,bmOptions);
        mimageView.setImageBitmap(bitmap);
    }

Note the size of bitmap and view. If the image is smaller than view, an error will be reported.

Excerpt from android developer

Posted by X.Cyclop on Wed, 10 Jul 2019 12:55:01 -0700