Java 从 Android 版本 Marshmallow 开始,如何请求允许从 Android 拨打电话?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40125931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:25:36  来源:igfitidea点击:

How to ask permission to make phone call from Android from Android version Marshmallow onwards?

javaandroidphone-callruntime-permissions

提问by OBX

I am trying to make a phone call from Android, and I've set run time permissions as well. And it asks whether to allow making phone calls. But when I press allow, the app crashes:

我正在尝试从 Android 拨打电话,并且我也设置了运行时权限。它询问是否允许拨打电话。但是当我按下允许时,应用程序崩溃了:

This is how I implemented it:

我是这样实现的:

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

This is what I obtain in logcat:

这是我在 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) 

What is possibly causing this?

什么可能导致这种情况?

采纳答案by Fabian Tamp

The stack trace seems to indicate that your permissions flow is working ok, but the call to startActivityfrom onRequestPermissionsResult()is crashing. Is the Intentyou're passing to startActivityset correctly? I can't see it being set in that part of the code.

堆栈跟踪似乎表明您的权限流工作正常,但对startActivityfrom的调用onRequestPermissionsResult()正在崩溃。是Intent你传递到startActivity设置是否正确?我看不到它被设置在代码的那部分。

Note also that ContextCompat.checkSelfPermissionhandles the SDK version checking on your behalf, so you should be able to use

另请注意,它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);
}

by itself, without the wrapping SDK version check code.

本身,没有包装 SDK 版本检查代码。

回答by Ganesh Pokale

add new method

添加新方法

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

add this in Global

在全局中添加这个

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

and write below code in onCreate

并在 onCreate 中编写以下代码

if(!hasPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}

回答by himanshu1496

Change your onRequestPermissionsResultto below, you basically need to create the intentfirst and then call it on permission granted. That's where you are doing it wrong.

将您更改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);
                }
            }
        }
    }
}

回答by Tin Tran

You need to create your Intentin onRequestPermissionsResult

你需要创建你IntentonRequestPermissionsResult


@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;
        }
    }
} 

回答by Abhishek Luthra

I would better suggest to use ACTION_DIAL rather than ACTION_CALL while constructing Intent to call a particular number . Using ACTION_DIAL , you will need no call permissions in your app, as ACTION_DIAL opens the dialer with the number already entered, and further allows the user to decide whether to actually make the call or modify the phone number before calling or not call at all.

我建议在构建 Intent 以呼叫特定号码时使用 ACTION_DIAL 而不是 ACTION_CALL 。使用 ACTION_DIAL ,您将不需要您的应用程序中的呼叫权限,因为 ACTION_DIAL 使用已经输入的号码打开拨号器,并进一步允许用户决定是否在呼叫之前实际拨打电话或修改电话号码或根本不拨打电话。

Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + "Your Phone_number"));// Initiates the Intent 
startActivity(intent);