Reputation: 55
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
Upvotes: 0
Views: 884
Reputation: 55
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();
}
}
}
Upvotes: 0
Reputation: 915
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
Upvotes: 0
Reputation: 1122
Try passing context
(received in Constructor of Adapter) in place of BloodVaultActivity2.this
i.e.
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
Upvotes: 1
Reputation: 10214
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();
}
});
Upvotes: 0