0

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();
            }
        }
AndreasWT
  • 163
  • 3
  • 13
  • And what exactly is your question? Be more specific. What error did you get? What actually happens? – Ispas Claudiu Apr 16 '17 at 10:20
  • @IspasClaudiu Is I stated in the fourth line of text: Nothing happens, just as if no function is called at all. – AndreasWT Apr 16 '17 at 10:22
  • Check the actual app's permissions from settings->application manager -> your app. You may have to grant the permission manually. – TDG Apr 16 '17 at 10:22
  • You don't need the `CALL_PHONE` permission for `ACTION_DIAL`. – Mike M. Apr 16 '17 at 10:24

2 Answers2

2

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.

Community
  • 1
  • 1
Budius
  • 39,391
  • 16
  • 102
  • 144
  • As for now, my code that calls a phone is an exact replica of Amirs code. It does not perform the call, it only opens the dialer. If I remove the if statement, i'm unable to compile my code, because i get an error that tells me to check if access is granted. – AndreasWT Apr 16 '17 at 20:22
  • Your answer works just as described, and seems a bit more perfected than Amir's answer, therefore I'll mark your answer as the right one. – AndreasWT Apr 17 '17 at 14:29
1

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);
   }
}
Amir Ziarati
  • 14,248
  • 11
  • 47
  • 52
  • After replacing "activity" with "this" in the line that requests permission, it finally worked! I can't thank your enough! – AndreasWT Apr 16 '17 at 10:35