java FileProvider.getUriForFile 返回 NullPointerException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46550472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:16:18  来源:igfitidea点击:

FileProvider.getUriForFile returns NullPointerException

javaandroidnullpointerexceptioncameraandroid-fileprovider

提问by Amr A.

I'm trying to write my first android app, which will involve taking a picture and doing stuff with it.

我正在尝试编写我的第一个 android 应用程序,这将涉及拍照并用它做一些事情。

I've put together some code after looking at several tutorials online but am getting the following NullPointerException whenever the button is clicked:

我在网上看了几个教程后整理了一些代码,但是每当单击按钮时都会收到以下 NullPointerException :

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
<?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>
0(MainActivity.java:24) at org.broadinstitute.jsnap.MainActivity.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)

I'm not quite sure how to resolve. Here's my relevant code:

我不太确定如何解决。这是我的相关代码:

manifest:

显现:

<?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>

file_paths.xml

文件路径.xml

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());
            }
        }
    }
}

And MainActivity:

和主要活动:

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

Any help is greatly appreciated.

任何帮助是极大的赞赏。

回答by CommonsWare

First, this:

首先,这个:

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

does not match this:

与此不符:

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

Use the same algorithm in both places. So, replace the second line with:

在两个地方使用相同的算法。因此,将第二行替换为:

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

That will get you past the NullPointerException.

这将使您通过NullPointerException.

Second, this:

二、这个:

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

does not match this:

与此不符:

 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)

Since I don't know which of those is what you really want, I cannot suggest a fix.

由于我不知道其中哪一个是您真正想要的,因此我无法建议修复。

回答by Amr A.

I know this is a pretty old question but this answer is for future viewers. So I've encountered a similar problem and after researching, I've found an alternative to this approach.

我知道这是一个很老的问题,但这个答案是为未来的观众准备的。所以我遇到了类似的问题,经过研究,我找到了这种方法的替代方法。

Your Intent here for eg: To view your image from your path

您的意图例如:从您的路径查看您的图像

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
        }
    }

Main Function below

下面的主要功能

##代码##