web-dev-qa-db-fra.com

FileProvider.getUriForFile renvoie NullPointerException

J'essaie d'écrire ma première Android, qui impliquera de prendre une photo et de faire des choses avec.

J'ai rassemblé du code après avoir consulté plusieurs didacticiels en ligne, mais j'obtiens l'exception NullPointerException suivante chaque fois que le bouton est cliqué:

10-03 14:48:00.284 26310-26310/org.broadinstitute.jsnap E/MainActivity: Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.content.res.XmlResourceParser Android.content.pm.ProviderInfo.loadXmlMetaData(Android.content.pm.PackageManager, Java.lang.String)' on a null object reference
10-03 14:48:00.293 26310-26310/org.broadinstitute.jsnap E/MYAPP: exception
                                                                 Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.content.res.XmlResourceParser Android.content.pm.ProviderInfo.loadXmlMetaData(Android.content.pm.PackageManager, Java.lang.String)' on a null object reference
                                                                     at Android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.Java:583)
                                                                     at Android.support.v4.content.FileProvider.getPathStrategy(FileProvider.Java:557)
                                                                     at Android.support.v4.content.FileProvider.getUriForFile(FileProvider.Java:399)
                                                                     at org.broadinstitute.jsnap.MainActivity.takePhoto(MainActivity.Java:54)
                                                                     at org.broadinstitute.jsnap.MainActivity.access$000(MainActivity.Java:24)
                                                                     at org.broadinstitute.jsnap.MainActivity$1.onClick(MainActivity.Java:43)
                                                                     at Android.view.View.performClick(View.Java:6205)
                                                                     at Android.widget.TextView.performClick(TextView.Java:11103)
                                                                     at Android.view.View$PerformClick.run(View.Java:23653)
                                                                     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:6682)
                                                                     at Java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1520)
                                                                     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1410)

Je ne sais pas trop comment résoudre. Voici mon code pertinent:

manifeste:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="org.broadinstitute.jsnap">

    <uses-permission Android:name="Android.permission.CAMERA" />
    <uses-feature Android:name="Android.hardware.camera" Android:required="true"/>
    <uses-feature Android:name="Android.hardware.camera.autofocus" />
    <uses-feature Android:name="Android.hardware.camera.flash" Android:required="false"/>
    <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        Android:allowBackup="true"
        Android:icon="@mipmap/ic_launcher"
        Android:label="@string/app_name"
        Android:roundIcon="@mipmap/ic_launcher_round"
        Android:supportsRtl="true"
        >
        <activity Android:name=".MainActivity">
            <intent-filter>
                <action Android:name="Android.intent.action.MAIN" />

                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="${applicationId}.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>

</manifest>

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="jsnap_images" path="Android/data/org.broadinstitute.jsnap/files/Pictures" />
</paths>

Et MainActivity:

package org.broadinstitute.jsnap;

import Android.app.Activity;
import Android.content.ContentResolver;
import Android.content.Intent;
import Android.graphics.Bitmap;
import Android.net.Uri;
import Android.os.Build;
import Android.os.Environment;
import Android.provider.MediaStore;
import Android.support.v4.content.FileProvider;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.widget.Button;
import Android.widget.ImageView;
import Android.widget.Toast;
import Java.io.File;
import Java.io.IOException;
import Java.util.jar.Manifest;


public class MainActivity extends Activity {
    private static String logtag = "MainActivity";
    private static int TAKE_PICTURE = 1;
    private static final String AUTHORITY = "org.broadinstitute.jsnap.provider";
    private static final String PHOTOS="photos";
    private static final String FILENAME="jsnap_test.jpeg";
    Uri imageURI;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button cameraButton = (Button)(findViewById(R.id.cam_button));
        cameraButton.setOnClickListener(cameraListener);

    }
    private View.OnClickListener cameraListener = new View.OnClickListener() {
        public void onClick(View v) {
            try {
                takePhoto(v);
            } catch (Exception e) {
                Log.e(logtag, e.toString());
            }
        }
    };
    private void takePhoto(View v){
        Intent intent = new Intent("Android.media.action.IMAGE_CAPTURE");
        File photo = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), FILENAME);
        imageURI=FileProvider.getUriForFile(this, AUTHORITY, photo);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageURI);
        // TAKE_PICTURE is a request code saying we want to use the rear-facing camera.
        startActivityForResult(intent, TAKE_PICTURE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if(resultCode == Activity.RESULT_OK) {
            Uri selectedImage = imageURI;
            getContentResolver().notifyChange(selectedImage, null);

            ImageView imageView = (ImageView)findViewById(R.id.image_camera);
            ContentResolver cr = getContentResolver();
            Bitmap bitmap;

            try {
                bitmap = MediaStore.Images.Media.getBitmap(cr, selectedImage);
                imageView.setImageBitmap(bitmap);
                Toast.makeText(MainActivity.this, selectedImage.toString(), Toast.LENGTH_SHORT).show();
            } catch(Exception e) {
                Log.e(logtag, e.toString());
            }
        }
    }
}

Toute aide est grandement appréciée.

8
Amr A.

Tout d'abord, ceci:

Android:authorities="${applicationId}.fileprovider"

ne correspond pas à ceci:

private static final String AUTHORITY = "org.broadinstitute.jsnap.provider";

Utilisez le même algorithme aux deux endroits. Remplacez donc la deuxième ligne par:

private static final String AUTHORITY = BuildConfig.APPLICATION_ID+".fileprovider";

Cela vous permettra de dépasser le NullPointerException.

Deuxièmement, ceci:

File photo = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), FILENAME);

ne correspond pas à ceci:

<external-path name="jsnap_images" path="Android/data/org.broadinstitute.jsnap/files/Pictures" />

Étant donné que je ne sais pas lequel est ce que vous voulez vraiment, je ne peux pas suggérer de solution.

21
CommonsWare

Je sais que c'est une question assez ancienne, mais cette réponse s'adresse aux futurs téléspectateurs. J'ai donc rencontré un problème similaire et après des recherches, j'ai trouvé une alternative à cette approche.

Votre intention ici, par exemple: pour afficher votre image depuis votre chemin

 val intent = Intent()
 intent.setAction(Intent.ACTION_VIEW)
 val file = File(currentUri)
 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
 val contentURI = getContentUri(context!!, file.absolutePath)
 intent.setDataAndType(contentURI,"image/*")
 startActivity(intent)

Fonction principale ci-dessous

private fun getContentUri(context:Context, absPath:String):Uri? {
        val cursor = context.getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            arrayOf<String>(MediaStore.Images.Media._ID),
            MediaStore.Images.Media.DATA + "=? ",
            arrayOf<String>(absPath), null)
        if (cursor != null && cursor.moveToFirst())
        {
            val id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
            return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(id))
        }
        else if (!absPath.isEmpty())
        {
            val values = ContentValues()
            values.put(MediaStore.Images.Media.DATA, absPath)
            return context.getContentResolver().insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        }
        else
        {
            return null
        }
    }
3
S.Sho