skm
skm

Reputation: 609

How to capture an image and save it in storage and show in ImageView?

I´m for several hours trying to take picture and save it to internal storage of phone and set it into an ImageView.

I tried several Codes from Stackoverflow and youtube but just getting an FileUriExposedException ... i don´t know why. Maybe you have an idea.

I read that you should use content:// instead of file://, but is this the reason of my problem?

Im getting:

Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/test.jpg exposed beyond app through ClipData.Item.getUri()
                                                             at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
                                                             at android.net.Uri.checkFileUriExposed(Uri.java:2346)
                                                             at android.content.ClipData.prepareToLeaveProcess(ClipData.java:845)
                                                             at android.content.Intent.prepareToLeaveProcess(Intent.java:8941)
                                                             at android.content.Intent.prepareToLeaveProcess(Intent.java:8926)
                                                             at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
                                                             at android.app.Activity.startActivityForResult(Activity.java:4225)
                                                             at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
                                                             at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
                                                             at android.app.Activity.startActivityForResult(Activity.java:4183)
                                                             at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
                                                             at ibas.orosol.BildActivity.takePicture(BildActivity.java:86)
                                                             at java.lang.reflect.Method.invoke(Native Method) 
                                                             at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                                                             at android.view.View.performClick(View.java:5637) 
                                                             at android.view.View$PerformClick.run(View.java:22429) 
                                                             at android.os.Handler.handleCallback(Handler.java:751) 
                                                             at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                             at android.os.Looper.loop(Looper.java:154) 
                                                             at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                             at java.lang.reflect.Method.invoke(Native Method) 
                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

Here´s my Activity

final private int REQUEST_CODE_ASK_PERMISSION = 123; //kann jegliche Zahl sein. Wir benutzens halt später
final private int CAMERA_REQUEST = 555; //kann jegliche Zahl sein. Wir benutzens halt später

private File imageFile;

private ImageView mImageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bild);
    getSupportActionBar().setTitle("");
    getSupportActionBar().setBackgroundDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.kopf_app, null));
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    mImageView = (ImageView) findViewById(R.id.imageView);

    // wenn die Permission NICHT gegeben wurde... und was wir dann machen kommt in diesem Block
    if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){

        if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)){

            //Hier können wir eintragen, wieso wir eigentlich die Permission brauchen/verlangen
        }else{

            //Permission anfragen
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_ASK_PERMISSION);
        }
    }
    //---------------------------------------------------------------------------------------------
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_ASK_PERMISSION);

}

public void takePicture(View view) throws IOException {

    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    File file = getFile();

    imageFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "test.jpg");

    Uri tempUri = Uri.fromFile(imageFile);
    String path = "sdcard/orosol/captured_image.jpg";

    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
    startActivityForResult(cameraIntent, CAMERA_REQUEST);

}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    String path = "sdcard/orosol/captured_image.jpg";
    if(imageFile.exists()){
        Log.i("imagefile", "exists in: " + imageFile.getAbsolutePath());
    }else{
        Log.i("imagefile", "existiert nicht!");
    }

}

Upvotes: 0

Views: 714

Answers (1)

Anmol317
Anmol317

Reputation: 1376

If your targetSdkVersion is 24 or higher, we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps.

Steps to replace file:// uri with content:// uri:

Add this to your manifest

 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 ...
 <application
...
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>

then create a provider_paths.xml file in xml folder under res folder. Folder may be needed to create if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

The final step is to change the line of code below in

Uri photoURI = Uri.fromFile(createImageFile());

to

Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", createImageFile());

Upvotes: 1

Related Questions