Android
phone call
intent
programming
mobile development

How to make a phone call using intent in Android?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Android gives you two main intent-based ways to start a call flow. ACTION_DIAL opens the dialer with a number filled in and lets the user confirm the call, while ACTION_CALL attempts to place the call directly and therefore requires additional permission handling.

For most apps, ACTION_DIAL is the safer choice. It avoids dangerous permissions and gives the user explicit control over whether the call is placed.

Use ACTION_DIAL When You Can

ACTION_DIAL launches the phone app without placing the call automatically.

java
Intent dialIntent = new Intent(Intent.ACTION_DIAL);
dialIntent.setData(Uri.parse("tel:+1234567890"));
startActivity(dialIntent);

This approach does not require the CALL_PHONE permission because your app is not directly initiating the call. The user still taps the call button.

That makes it the recommended default for customer-support links, contact screens, and general user-facing interfaces.

Use ACTION_CALL Only When Direct Calling Is Required

If your app truly needs to place the call itself, use ACTION_CALL.

java
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:+1234567890"));
startActivity(callIntent);

This requires the dangerous permission android.permission.CALL_PHONE in the manifest:

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

On modern Android versions, manifest declaration alone is not enough. You must also request the permission at runtime.

Runtime Permission Example

java
1private static final int REQUEST_CALL_PERMISSION = 100;
2
3private void makePhoneCall(String phoneNumber) {
4    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
5            == PackageManager.PERMISSION_GRANTED) {
6        Intent intent = new Intent(Intent.ACTION_CALL);
7        intent.setData(Uri.parse("tel:" + phoneNumber));
8        startActivity(intent);
9    } else {
10        ActivityCompat.requestPermissions(
11                this,
12                new String[]{Manifest.permission.CALL_PHONE},
13                REQUEST_CALL_PERMISSION
14        );
15    }
16}

And then handle the permission result:

java
1@Override
2public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
3    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
4
5    if (requestCode == REQUEST_CALL_PERMISSION
6            && grantResults.length > 0
7            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
8        makePhoneCall("+1234567890");
9    }
10}

The exact callback style may differ depending on whether you use the older API or the Activity Result APIs, but the permission requirement stays the same.

Validate the Intent Before Launching

Some Android devices, such as tablets without telephony support, may not have a suitable phone app.

java
1Intent dialIntent = new Intent(Intent.ACTION_DIAL);
2dialIntent.setData(Uri.parse("tel:+1234567890"));
3
4if (dialIntent.resolveActivity(getPackageManager()) != null) {
5    startActivity(dialIntent);
6}

This prevents crashes on devices that cannot handle the intent.

Build the tel: URI Carefully

Phone numbers should be passed through the tel: URI scheme.

java
Uri uri = Uri.parse("tel:+1234567890");

If you need special characters such as # or *, encode them properly.

java
Uri uri = Uri.parse("tel:" + Uri.encode("*#06#"));

This is especially important for service codes and numbers with pauses or extensions.

Kotlin Example

kotlin
1val intent = Intent(Intent.ACTION_DIAL).apply {
2    data = Uri.parse("tel:+1234567890")
3}
4startActivity(intent)

The Android concept is identical in Kotlin and Java. The difference is mostly syntax.

Common Pitfalls

The biggest mistake is using ACTION_CALL when ACTION_DIAL would be sufficient. Direct calling adds permission complexity and a bigger safety burden.

Another common issue is declaring CALL_PHONE in the manifest but forgetting the runtime permission request. That leads to a SecurityException when the call intent is launched.

People also forget to check whether an app can handle the intent, which matters on devices without a real dialer.

Finally, special characters in phone numbers need proper URI encoding. A raw string that works visually may still fail when used in an intent.

Summary

  • 'ACTION_DIAL opens the dialer and usually requires no permission.'
  • 'ACTION_CALL places the call directly and requires CALL_PHONE.'
  • Request dangerous permissions at runtime, not just in the manifest.
  • Use resolveActivity(...) before launching the intent.
  • Pass numbers through a proper tel: URI.
  • Prefer the safer user-confirmed flow unless direct calling is truly necessary.

Course illustration
Course illustration

All Rights Reserved.