简体   繁体   中英

Why checkSelfPermission() is throwing a NullPointerException

I'm checking for phone call permission when a call button in listview is pressed. For some reason the Context I'm passing as a parameter in checkSelfPermission() method is causing the null pointer exception. I've used this , ActivityName.this , getContext() , getApplicationContext() . None of them is working for me.

Note: Call to the makephonecall() method is initiated from my adapter class on listview button pressed.

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:

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

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

Also, 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 :

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

Btw a better approach for interaction between Activity & Adapter is using interface. 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

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 .


First I caught the context of my adapter class using:

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:

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

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