Search code examples
javaandroidphone-call

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


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

Solution

  • 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.