Can't dial a phone on the event of a button press in Android Studio

倾然丶 夕夏残阳落幕 提交于 2019-12-13 07:19:24

问题


In my android app, I have a navigation drawer with a few buttons that open different fragments with associated layouts.

One of the buttons is supposed to call a function which in theory should perform a phone dial. It just doesn't seem to work. Nothing happens, and the navigation drawer just closes. I already implemented this permission in the manifest, which should do the work for the sake of permissions:

<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>

My code that executes pieces of code based on the button events in the navigation drawer looks like this:

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    android.app.FragmentManager fragmentmanager = getFragmentManager();

    if (id == R.id.nav_forside) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new MainFragment())
                .commit();

    } else if (id == R.id.nav_matif) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new MatifFragment())
                .commit();

    } else if (id == R.id.nav_om) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new OmFragment())
                .commit();

    } else if (id == R.id.nav_rk) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new RkFragment())
                .commit();

    } else if (id == R.id.nav_bd) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new BdFragment())
                .commit();

    } else if (id == R.id.nav_rf) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new RfFragment())
                .commit();

    } else if (id == R.id.nav_kontakt_os) {
        fragmentmanager.beginTransaction()
                .replace(R.id.content_frame
                        , new KontaktOsFragment())
                .commit();

    } else if (id == R.id.nav_call_number) {
    callNumber();

    }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

And last but not least, the function the performs the phone call looks like this; I must point out that it threw an error if I didn't check if the package manager had granted access to perform the phone call. That is why the code checks if permission is granted:

public void callNumber () {
            //Tries to call the phone number, and catches any errors that might be present
            try {
                //Checking if the the permission to call a phone is granted
                if (ActivityCompat.checkSelfPermission(MainActivity.this.getApplicationContext(), Manifest.permission.CALL_PHONE) ==
                        PackageManager.PERMISSION_GRANTED) {

                    Intent i = new Intent(Intent.ACTION_DIAL);
                    String p = "tel:12345678";
                    i.setData(Uri.parse(p));
                    startActivity(i);
                }
            } catch (Exception exLog) {
                //Catches error that prevents phone from calling, and expresses itself in form of a alertdialog
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
                alertDialog.setTitle("Opkaldet kunne ikke gennemføres");
                alertDialog.setMessage(exLog.toString());
                alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                alertDialog.show();
            }
        }

回答1:


I know that Amiars answer works, but it's not really the correct answer.

The thing is: you don't need any permission for Intent.ACTION_DIAL. You need the permission CALL_PHONE to use Intent.ACTION_CALL.

The difference is that ACTION_CALL actually executes the call, which is somewhat dangerous as it normally incur fees/charges for the user, while ACTION_DIAL only opens the dialer and the user will explicitly complete the action by pressing the call button. It's all in the docs: https://developer.android.com/reference/android/content/Intent.html

ACTION_CALL

Activity Action: Perform a call to someone (...)

Note: there will be restrictions on which applications can initiate a call; most applications should use the ACTION_DIAL.

Note: if you app targets M and above and declares as using the CALL_PHONE permission which is not granted, then attempting to use this action will result in a SecurityException.

and

ACTION_DIAL

Activity Action: Dial a number as specified by the data. This shows a UI with the number being dialed, allowing the user to explicitly initiate the call

So the right answer is:

remove that if have permission and just directly invoke the startActivity(i);

edit:

I just typed that on latest AndroidStudio without any permission on manifest and it works as it should. No warning, and executing on device it opens the dialer.

 public static void call(Context context, String number) {
    Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + number));
    try {
      context.startActivity(i);
    } catch (Exception e) {
      // this can happen if the device can't make phone calls
      // for example, a tablet
    }
  }

I can also point you to several other SO questions that are asking the same thing:

How do I get the dialer to open with phone number displayed?

Permission required when using Intent to call phone?

How to open dialer on phone with a selected number in android

Intent call action doesn't works on Marshmallow

https://stackoverflow.com/a/13123613/906362

I hope it helps.




回答2:


what if permission is not granted ?

in new versions of android after marshmallow you need to check for permission in code as you did, but you need to request for permission if its not granted. cuz for this versions of android the permission in manifest wont work.

if (ActivityCompat.checkSelfPermission(MainActivity.this.getApplicationContext(), Manifest.permission.CALL_PHONE) ==
                    PackageManager.PERMISSION_GRANTED) {

                Intent i = new Intent(Intent.ACTION_DIAL);
                String p = "tel:12345678";
                i.setData(Uri.parse(p));
                startActivity(i);
}
else
{
  ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CALL_PHONE}, 0);
}

you can also have a callback for the case permission granted, in your activity like below :

@Override
public void onRequestPermissionsResult(int requestCode,
                                   String permissions[], int[] grantResults) 
{
  if(requestCode==0 && ActivityCompat.checkSelfPermission(MainActivity.this.getApplicationContext(), Manifest.permission.CALL_PHONE) ==
                PackageManager.PERMISSION_GRANTED) {
   Intent i = new Intent(Intent.ACTION_DIAL);
                String p = "tel:12345678";
                i.setData(Uri.parse(p));
                startActivity(i);
   }
}


来源:https://stackoverflow.com/questions/43436120/cant-dial-a-phone-on-the-event-of-a-button-press-in-android-studio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!