简体   繁体   English

抛出NullPointer异常的FileProvider.getUriForFile上下文

[英]FileProvider.getUriForFile context throwing NullPointer exeption

I am getting the following error from FileProvider.getUriForFile 我从FileProvider.getUriForFile得到以下错误

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResource()' on a null object reference java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'android.content.res.Resources android.content.Context.getResource()'

However, when I display context.toString() I get this which (I think) proves that the object is not null: 但是,当我显示context.toString()我得到了这个(我认为)证明该对象不是null:

uk.co.letsdelight.letsdelight.MainActivity@8eec139 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. 该代码将Completed download of update file写入logcat,但没有写入URI successfully set在API 24设备上URI successfully set It works on API 23. Here is the important part of the code. 它适用于API23。这是代码的重要部分。 The Update class is invoked from MainActivity with new Update(status, message).check(this); 使用new Update(status, message).check(this);MainActivity调用Updatenew 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: AndroidManifest.xml文件包含以下条目:

    <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: file_provider_paths.xml看起来像这样:

<?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. 我尝试将context都更改为getApplication()getApplicationContext() ,这两者都会导致NullPointerException但资源措辞略有不同。

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. statusMessage设置为显示正确的提供者授权字符串。 It does not get set to "uri set". 它不会设置为“ uri set”。 Therefore it is definitely the FileProvider.getUriForFile() that is failing. 因此,肯定是失败的FileProvider.getUriForFile()

Given that context is not null and the Authority is the correct string, what else could be throwing the error here? 鉴于context不为null,并且Authority是正确的字符串,还有什么可能在这里引发错误?

You are trying to call getString inside an non activity class try to replace 您正在尝试在非活动类中调用getString尝试替换

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? 编辑:我看到您正在扩展Update类中的活动,您是否在清单中声明了它? Why are you extending activity if you are already passing a context? 如果您已经传递了上下文,为什么还要扩展活动?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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