My targetSDKVersion is 28 and I couldnt implement "Take Picture" function on this sdk version

194 views Asked by At

I was told that this may because that if targetSdkVersion is >= Android 6.0(API level 23), developer need to add some code for request related permissions from the user at the runtime.

"If you still want to implement the "Open Camera/Take Picture" function, you should request the permisson of CAMERA for take pictures and storage related permisson for saving pictures at the runtime. And maybe FileProvider can be used to store pictures."

How can I implement this suggestion in my project?

This is my SelectImageActivity where the code for TAKEPICTURE involves

package com.microsoft.projectoxford.face.samples.ui;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.microsoft.projectoxford.face.samples.R;

import java.io.File;
import java.io.IOException;

// The activity for the user to select a image and to detect faces in the image.
public class SelectImageActivity extends AppCompatActivity {
    // Flag to indicate the request of the next task to be performed
    private static final int REQUEST_TAKE_PHOTO = 0;
    private static final int REQUEST_SELECT_IMAGE_IN_ALBUM = 1;

    // The URI of photo taken with camera
    private Uri mUriPhotoTaken;

    // When the activity is created, set all the member variables to initial state.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_select_image);
    }

    // Save the activity state when it's going to stop.
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("ImageUri", mUriPhotoTaken);
    }

    // Recover the saved state when the activity is recreated.
    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mUriPhotoTaken = savedInstanceState.getParcelable("ImageUri");
    }

    // Deal with the result of selection of the photos and faces.
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode)
        {
            case REQUEST_TAKE_PHOTO:
            case REQUEST_SELECT_IMAGE_IN_ALBUM:
                if (resultCode == RESULT_OK) {
                    Uri imageUri;
                    if (data == null || data.getData() == null) {
                        imageUri = mUriPhotoTaken;
                    } else {
                        imageUri = data.getData();
                    }
                    Intent intent = new Intent();
                    intent.setData(imageUri);
                    setResult(RESULT_OK, intent);
                    finish();
                }
                break;
            default:
                break;
        }
    }

    // When the button of "Take a Photo with Camera" is pressed.
    public void takePhoto(View view) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if(intent.resolveActivity(getPackageManager()) != null) {
            // Save the photo taken to a temporary file.
            File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
            try {
                File file = File.createTempFile("IMG_", ".jpg", storageDir);
                mUriPhotoTaken = Uri.fromFile(file);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriPhotoTaken);
                startActivityForResult(intent, REQUEST_TAKE_PHOTO);
            } catch (IOException e) {
                setInfo(e.getMessage());
            }
        }
    }

    // When the button of "Select a Photo in Album" is pressed.
    public void selectImageInAlbum(View view) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(intent, REQUEST_SELECT_IMAGE_IN_ALBUM);
        }
    }

    // Set the information panel on screen.
    private void setInfo(String info) {
        TextView textView = (TextView) findViewById(R.id.info);
        textView.setText(info);
    }
}

This is my build gradle (:app)

apply plugin: 'com.android.application'

android {

    compileSdkVersion 28


    defaultConfig {
        applicationId "com.microsoft.projectoxford.faceapisample"
        minSdkVersion 22
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')

    // Include local lib mostly for debug purpose.
    // implementation project(':lib')

    // Use the following line to include client library for Face API from Maven Central Repository

    implementation 'com.microsoft.projectoxford:face:1.4.4'
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.android.support.constraint:constraint-layout:2.0.4'

    compile project(':voicetwo')
    implementation project(':voicetwo')


}

My error log :

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.microsoft.projectoxford.faceapisample, PID: 16272
    java.lang.IllegalStateException: Could not execute method for android:onClick
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
        at android.view.View.performClick(View.java:7167)
        at android.view.View.performClickInternal(View.java:7140)
        at android.view.View.access$3500(View.java:813)
        at android.view.View$PerformClick.run(View.java:27597)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7519)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
        at android.view.View.performClick(View.java:7167) 
        at android.view.View.performClickInternal(View.java:7140) 
        at android.view.View.access$3500(View.java:813) 
        at android.view.View$PerformClick.run(View.java:27597) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:224) 
        at android.app.ActivityThread.main(ActivityThread.java:7519) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995) 
     Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.microsoft.projectoxford.faceapisample/files/Pictures/IMG_2029674407291738623.jpg exposed beyond app through ClipData.Item.getUri()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:2089)
        at android.net.Uri.checkFileUriExposed(Uri.java:2388)
        at android.content.ClipData.prepareToLeaveProcess(ClipData.java:977)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10780)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10765)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1710)
        at android.app.Activity.startActivityForResult(Activity.java:5258)
        at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:767)
        at android.app.Activity.startActivityForResult(Activity.java:5216)
        at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754)
        at com.microsoft.projectoxford.face.samples.ui.SelectImageActivity.takePhoto(SelectImageActivity.java:103)
        at java.lang.reflect.Method.invoke(Native Method) 
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
        at android.view.View.performClick(View.java:7167) 
        at android.view.View.performClickInternal(View.java:7140) 
        at android.view.View.access$3500(View.java:813) 
        at android.view.View$PerformClick.run(View.java:27597) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:224) 
        at android.app.ActivityThread.main(ActivityThread.java:7519) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995) 
E/MQSEventManagerDelegate: failed to get MQSService.
D/OOMEventManagerFK: checkEventAndDumpForJE: 0
E/MQSEventManagerDelegate: failed to get MQSService.

The line in the error log at com.microsoft.projectoxford.face.samples.ui.SelectImageActivity.takePhoto(SelectImageActivity.java:103) is

startActivityForResult(intent, REQUEST_TAKE_PHOTO);
0

There are 0 answers