简体   繁体   English

为什么checkSelfPermission()抛出NullPointerException

[英]Why checkSelfPermission() is throwing a NullPointerException

I'm checking for phone call permission when a call button in listview is pressed. 按下列表视图中的call button时,我正在检查电话呼叫权限。 For some reason the Context I'm passing as a parameter in checkSelfPermission() method is causing the null pointer exception. 由于某种原因,我在checkSelfPermission()方法中作为参数传递的Context导致了空指针异常。 I've used this , ActivityName.this , getContext() , getApplicationContext() . 我已经使用过thisActivityName.thisgetContext()getApplicationContext() None of them is working for me. 他们都没有为我工作。

Note: Call to the makephonecall() method is initiated from my adapter class on listview button pressed. 注意:在我按下列表视图按钮时,从我的适配器类启动对makephonecall()方法的调用。

public void makephonecall()
    {
        try {
            if (ContextCompat.checkSelfPermission(BloodVaultActivity2.this,
                    Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(BloodVaultActivity2.this,
                        new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL);
            } else {
                Intent intent = new Intent(Intent.ACTION_CALL);
                intent.setData(Uri.parse("tel:" + number));
                startActivity(intent);
            }
        }
        catch (NullPointerException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_CALL)
        {
            if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                makephonecall();
            }
            else
            {
                Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
            }
        }
    }


Adapter class: 适配器类:

package bd.edu.bubt.regup;

import android.*;
import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class BloodVaultAdapter extends ArrayAdapter<BloodVaultItem> {

    ArrayList<BloodVaultItem> adapterlist = new ArrayList<>();
    int REQUEST_CALL = 1;

    public BloodVaultAdapter(Context context, int textViewResourceId, ArrayList<BloodVaultItem> objects){

        super(context, textViewResourceId, objects);
        adapterlist = objects;
    }

    @Override
    public int getCount(){

        return super.getCount();
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent){

        View v = convertView;
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.blood_vault_list_view_layout, null);

        TextView name = (TextView) v.findViewById(R.id.name);
        TextView group = (TextView) v.findViewById(R.id.group);
        Button call = (Button) v.findViewById(R.id.call);

        call.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                BloodVaultItem bloodVaultItem = getItem(position);

                String number = bloodVaultItem.getContact();

                BloodVaultActivity2 bloodVaultActivity2 = new BloodVaultActivity2();
                bloodVaultActivity2.number = number;
                bloodVaultActivity2.makephonecall();
            }
        });

        name.setText("Name: " +adapterlist.get(position).getName());
        group.setText("Blood Group: " +adapterlist.get(position).getGroup());

        return v;
    }
}


Logcat: logcat的:

06-13 01:42:36.920 13102-13102/bd.edu.bubt.regup W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkPermission(java.lang.String, int, int)' on a null object reference
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at android.support.v4.content.ContextCompat.checkSelfPermission(ContextCompat.java:430)
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at bd.edu.bubt.regup.BloodVaultActivity2.makephonecall(BloodVaultActivity2.java:182)
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at bd.edu.bubt.regup.BloodVaultAdapter$1.onClick(BloodVaultAdapter.java:63)
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at android.view.View.performClick(View.java:5637)
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at android.view.View$PerformClick.run(View.java:22429)
06-13 01:42:36.921 13102-13102/bd.edu.bubt.regup W/System.err:     at android.os.Handler.handleCallback(Handler.java:751)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at android.os.Looper.loop(Looper.java:154)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6119)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
06-13 01:42:36.922 13102-13102/bd.edu.bubt.regup W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
06-13 01:42:36.928 1382-1455/? W/audio_hw_generic: Not supplying enough data to HAL, expected position 137954329 , only wrote 137954160
06-13 01:42:36.975 1382-1455/? W/audio_hw_generic: Hardware backing HAL too slow, could only write 0 of 720 frames
06-13 01:42:40.154 1382-1456/? W/audio_hw_generic: Not supplying enough data to HAL, expected position 138261974 , only wrote 138108960
06-13 01:43:28.433 2223-8977/com.google.android.apps.nexuslauncher I/ClearcutLoggerApiImpl: disconnect managed GoogleApiClient
01-01 00:00:00.000 0-0/? E/Internal: device offline

Try passing context (received in Constructor of Adapter) in place of BloodVaultActivity2.this ie 尝试传递context (在Adapter的构造函数中接收)代替BloodVaultActivity2.this

ContextCompat.checkSelfPermission(context,Manifest.permission.CALL_PHONE)

Also, BloodVaultActivity2 bloodVaultActivity2 = new BloodVaultActivity2(); 另外,BloodVaultActivity2 bloodVaultActivity2 = new BloodVaultActivity2(); is incorect way of calling method as this will create new instance of your activity, instead typeCast your context to BloodVaultActivity2 & pass this from your Activity in constructor of Adapter : 调用方法的方法不正确,因为这将创建您的活动的新实例,而将您的context BloodVaultActivity2BloodVaultActivity2并将this从您的Activity中传递给Adapter的构造函数:

if(mContext instanceof YourActivityName){
       ((YourActivityName)mContext).yourActivityMethod();
}

Btw a better approach for interaction between Activity & Adapter is using interface. 在Activity和Adapter之间进行交互的更好方法是使用接口。 https://android.jlelse.eu/click-listener-for-recyclerview-adapter-2d17a6f6f6c9 https://android.jlelse.eu/click-listener-for-recyclerview-adapter-2d17a6f6f6c9

Update : The root cause is you are creating a new Instance of the activity on item click, hence you are seeing the null pointer. 更新 :根本原因是您在单击项目时创建活动的新实例,因此看到空指针。 Since you are already passing context in your adapter do it in the way shown by Manoj in https://stackoverflow.com/a/56573418/3318025 由于您已经在适配器中传递了上下文,因此请按照Manoj在https://stackoverflow.com/a/56573418/3318025中显示的方式进行操作

If you create an object of a class using 如果您使用创建类的对象

BloodVaultActivity2 bloodVaultActivity2 = new BloodVaultActivity2();
            bloodVaultActivity2.number = number;
            bloodVaultActivity2.makephonecall();

It won't call the function, since it is an activity class which has life cycle aware methods, one way is to create an interface invoke the function using context or cast the context to your activity which has the method you want to run Change it like, 它不会调用该函数,因为它是一个具有生命周期感知方法的活动类,所以一种方法是创建一个使用上下文调用该函数的接口,或者将上下文转换为具有您要运行的方法的活动。喜欢,

   public class BloodVaultAdapter extends ArrayAdapter<BloodVaultItem> {
   Context context;

   public BloodVaultAdapter(Context context, int textViewResourceId, 
   ArrayList<BloodVaultItem> objects){
    super(context, textViewResourceId, objects);
    this.context=context;
    adapterlist = objects;
}

then, 然后,

call.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            BloodVaultItem bloodVaultItem = getItem(position);

            String number = bloodVaultItem.getContact();
            (( BloodVaultActivity2)context).makephonecall();
        }
    });

Finally I got a solution for this problem. 终于我找到了解决这个问题的方法。 I just combined the solution of Astha and Manoj from their answers link1 and link2 . 我只是根据他们的答案link1link2组合了AsthaManoj的解决方案。


First I caught the context of my adapter class using: 首先,我使用以下命令捕获了adapter类的context

Context context;

    public BloodVaultAdapter(Context context, int textViewResourceId, ArrayList<BloodVaultItem> objects){

        super(context, textViewResourceId, objects);
        this.context = context;
        adapterlist = objects;
    }


Second pass that context as a parameter of makephonecallmethod() from adapter class: adapter类第二次将该context作为makephonecallmethod()的参数传递:

call.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                BloodVaultItem bloodVaultItem = getItem(position);

                String number = bloodVaultItem.getContact();

                BloodVaultActivity2 bloodVaultActivity2 = new BloodVaultActivity2();
                bloodVaultActivity2.number = number;
                bloodVaultActivity2.makephonecall(context);
            }
        });


Third use the passed context as a parameter of checkSelfPermission() inside Activity class: 第三,使用传递的context作为Activity类中的checkSelfPermission()的参数:

Context mcontext;

public void makephonecall(Context context)
    {
        this.mcontext = context;

        try {
            if (ContextCompat.checkSelfPermission(context,
                    Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(BloodVaultActivity2.this,
                        new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL);
            } else {
                String dial = "tel:" + number;
                context.startActivity(new Intent(Intent.ACTION_CALL, Uri.parse(dial)));
            }
        }
        catch (NullPointerException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_CALL)
        {
            if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                makephonecall(mcontext);
            }
            else
            {
                Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
            }
        }
    }

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

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