Как запросить разрешение на телефонный звонок с Android, начиная с версии Android Marshmallow?

Я пытаюсь сделать телефонный звонок с Android, и я также установил разрешения во время выполнения. И спрашивает, разрешить ли делать телефонные звонки. Но когда я нажимаю разрешить, приложение вылетает:

Вот как я это реализовал:

private static final int REQUEST_PHONE_CALL = 1;
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "+918511812660"));

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE},REQUEST_PHONE_CALL);
    }
    else
    {
        startActivity(intent);
    }
}
else
{
    startActivity(intent);
}


@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_PHONE_CALL: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startActivity(intent);
            }
            else
            {

            }
            return;
        }
    }
}

Это то, что я получаю в logcat:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, 
     request=1, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} 
     to activity {com.devpost.airway/com.devpost.airway.activities.MainActivity}: 
     java.lang.NullPointerException: Attempt to invoke virtual method 
     'java.lang.String android.content.Intent.toString()' on a null object reference

      at android.app.ActivityThread.deliverResults(ActivityThread.java:3733)
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3776)
      at android.app.ActivityThread.-wrap16(ActivityThread.java)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:148)
      at android.app.ActivityThread.main(ActivityThread.java:5461)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 
    'java.lang.String android.content.Intent.toString()' on a null object reference
      at android.app.Instrumentation.execStartActivity(Instrumentation.java:1485)
      at android.app.Activity.startActivityForResult(Activity.java:3930)
      at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
      at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
      at android.app.Activity.startActivityForResult(Activity.java:3890)
      at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:856)
      at android.app.Activity.startActivity(Activity.java:4213)
      at android.app.Activity.startActivity(Activity.java:4181)
      at com.devpost.airway.activities.MainActivity.onRequestPermissionsResult(MainActivity.java:140)
      at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582)
      at android.app.Activity.dispatchActivityResult(Activity.java:6460)
      at android.app.ActivityThread.deliverResults(ActivityThread.java:3729)
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3776) 
      at android.app.ActivityThread.-wrap16(ActivityThread.java) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:148) 
      at android.app.ActivityThread.main(ActivityThread.java:5461) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Что может быть причиной этого?


person OBX    schedule 19.10.2016    source источник
comment
Внутри действия или фрагмента?   -  person vidulaJ    schedule 19.10.2016
comment
вы можете проверить это для своего ответа. stackoverflow.com/a/39646644/6812027   -  person Vishal Puri    schedule 19.10.2016


Ответы (6)


Трассировка стека, кажется, указывает на то, что ваш поток разрешений работает нормально, но вызов startActivity из onRequestPermissionsResult() дает сбой. Правильно ли установлен Intent, который вы передаете startActivity? Я не вижу, чтобы он был установлен в этой части кода.

Также обратите внимание, что ContextCompat.checkSelfPermission выполняет проверку версии SDK от вашего имени, поэтому вы должны иметь возможность использовать

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE},REQUEST_PHONE_CALL);
}
else
{
    startActivity(intent);
}

сам по себе, без оборачивающего кода проверки версии SDK.

person Fabian Tamp    schedule 19.10.2016
comment
спасибо, проблема возникла из-за того, что намерение не было установлено должным образом, я голосую за ответ, поскольку он помог решить проблему. - person OBX; 19.10.2016
comment
Hy @OBX Можете ли вы объяснить, в каком разделе намерение не было установлено должным образом. У меня есть проблема. Спасибо - person fanjavaid; 15.06.2017
comment
Отличный ответ. Это работало для Android Jelly Bean 4.1. - person Val; 19.03.2018

Я бы лучше предложил использовать ACTION_DIAL, а не ACTION_CALL при построении Intent для вызова определенного номера. Используя ACTION_DIAL , вам не потребуются разрешения на вызовы в вашем приложении, поскольку ACTION_DIAL открывает номеронабиратель с уже введенным номером, а также позволяет пользователю решить, действительно ли совершать вызов или изменять номер телефона перед вызовом или вообще не звонить.

Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + "Your Phone_number"));// Initiates the Intent 
startActivity(intent);
person Abhishek Luthra    schedule 03.04.2018
comment
Идеальный! Спасибо - person Shujat Munawar; 22.09.2018

Вам нужно создать свой Intent в onRequestPermissionsResult


@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_PHONE_CALL: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "+918511812660"));
                startActivity(intent);
            }
            else
            {

            }
            return;
        }
    }
} 
person Tin Tran    schedule 19.10.2016

добавить новый метод

public static boolean hasPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
    for (String permission : permissions) {
        if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
}
return true;
}

добавить это в Global

int PERMISSION_ALL = 1; 
String[] PERMISSIONS = {Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE};

и напишите ниже код в onCreate

if(!hasPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
person Ganesh Pokale    schedule 19.10.2016

Измените свой onRequestPermissionsResult на приведенный ниже, вам в основном нужно сначала создать intent, а затем вызвать его при предоставленном разрешении. Вот где вы делаете это неправильно.

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_PHONE_CALL : {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "+918511812660"));

                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
                    startActivity(intent);
                }
            }
        }
    }
}
person himanshu1496    schedule 19.10.2016

person    schedule
comment
Пожалуйста, предоставьте немного текста, чтобы объяснить, как этот ответ полезен. Объясните, какие изменения вы внесли и так далее. - person darclander; 06.09.2020