简体   繁体   中英

FileProvider.getUriForFile context throwing NullPointer exeption

I am getting the following error from FileProvider.getUriForFile

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResource()' on a null object reference

However, when I display context.toString() I get this which (I think) proves that the object is not null:

uk.co.letsdelight.letsdelight.MainActivity@8eec139

The code writes Completed download of update file to logcat but doesn't write URI successfully set on an API 24 device. It works on API 23. Here is the important part of the code. The Update class is invoked from MainActivity with new Update(status, message).check(this);

public class Update extends Activity {

    private File outputFile;
    private TextView status;
    private TextView message;
    private String TAG = "LETSDELIGHT";

    public Update(TextView status){
        this.status = status;
    }
    public Update(TextView status, TextView message){
        this.status  = status;
        this.message = message;
    }

    public void check(final Context c) {
        status.setText("Checking for updates");

        // Check for updates and give user option to update

            // UPDATE button pressed
            UpdateApp updateApp = new UpdateApp();
            updateApp.setContext(c);
            updateApp.execute(c.getString(R.string.apk_uri));
            status.setText("Downloading update");
    }

    public class UpdateApp extends AsyncTask<String,Void,Void> {
        private Context context;
        private Throwable thrown = null;
        private String statusMessage;
        public void setContext(Context contextf){
            context = contextf;
        }

        @Override
        protected Void doInBackground(String... arg0) {
            try {
                URL url = new URL(arg0[0]);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setDoOutput(true);
                conn.connect();

                Log.i(TAG,"Starting download of update file");
                statusMessage = "Starting download of update file";

                File file = context.getCacheDir();
                file.mkdirs();
                outputFile = new File(file, "update.apk");
                if(outputFile.exists()){
                    outputFile.delete();
                }
                FileOutputStream fos = new FileOutputStream(outputFile);

                InputStream is = conn.getInputStream();

                byte[] buffer = new byte[1024];
                int len1 = 0;
                while ((len1 = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, len1);
                }
                fos.close();
                is.close();
                outputFile.setReadable(true, false);

                Log.i(TAG, "Completed download of update file");
                statusMessage = "Completed download of update file";

                Uri uri;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    uri = FileProvider.getUriForFile(context, getString(R.string.file_provider_authority), outputFile);
                } else {
                    uri = Uri.fromFile(outputFile);
                }

                Log.i(TAG, "URI successfully set");
                statusMessage = "URI successfully set";

                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);

            } catch (Throwable ex) {
                Log.e(TAG, ex.toString());
                thrown = ex;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void v) {
            status.setText("");
            if (statusMessage != null) {
                status.setText(statusMessage);
            }
            if (thrown != null) {
                status.setText(context.toString());
                message.setText(thrown.toString());
            }
            outputFile.delete();
            super.onPostExecute(v);
        }
    }
}

The AndroidManifest.xml file contains the following entry:

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="@strings/file_provider_authority"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_provider_paths" />
    </provider>

file_provider_paths.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <cache-path name="cache" path="."/>
</paths>

I have tried changing context to both getApplication() and getApplicationContext() which both result in a NullPointerException but with slightly different resource wording.

What else can I try to resolve this problem?

EDIT:

I have modified the code to try and get to the bottom of the problem:

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                statusMessage = "Context is: " + context.getString(R.string.file_provider_authority);
                uri = FileProvider.getUriForFile(context, context.getString(R.string.file_provider_authority), outputFile);
                statusMessage = "uri set";
            } else {
                uri = Uri.fromFile(outputFile);
            }

statusMessage gets set to show the correct Provider Authority string. It does not get set to "uri set". Therefore it is definitely the FileProvider.getUriForFile() that is failing.

Given that context is not null and the Authority is the correct string, what else could be throwing the error here?

You are trying to call getString inside an non activity class try to replace

getString(R.string.file_provider_authority)

with

context.getString(R.string.file_provider_authority)

edit: I see you are extending activity in your Update class did you declare it in the manifests? Why are you extending activity if you are already passing a context?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM