12

How can we access the phone number of an incoming call in flutter, like the one Truecaller does.

I referenced this query over the web and found that flutter currently doesn't supports that feature. Is it true or there is some way to access the phone number of an incoming call?

daddy_
  • 1,657
  • 1
  • 12
  • 17

1 Answers1

11

You would have to implement it through platform channel:

Android

add to File android/app/src/main/AndroidManifest.xml

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<receiver android:name=".ServiceReceiver" >
<intent-filter>
    <action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>

create File android/app/src/main/java/{your_package}/ServiceReceiver.java

public class ServiceReceiver extends BroadcastReceiver {

@Override
public void onReceive(final Context context, Intent intent) {
    TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    telephony.listen(new PhoneStateListener(){
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            System.out.println("incomingNumber : "+incomingNumber);
        }
    },PhoneStateListener.LISTEN_CALL_STATE);
}

Iphone

To provide identifying information about incoming callers, you use the addIdentificationEntry(withNextSequentialPhoneNumber:label:) method in the implementation of beginRequest(with:).

class CustomCallDirectoryProvider: CXCallDirectoryProvider {
    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        let labelsKeyedByPhoneNumber: [CXCallDirectoryPhoneNumber: String] = [ … ]
        for (phoneNumber, label) in labelsKeyedByPhoneNumber.sorted(by: <) {
            context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)        
        }

        context.completeRequest()
    }
}

Now the bad news: For Iphone, as far as I know (2021), developers apps do not have access to the incoming phone number if its not part of the user's contact or social network, this is arguably something that would deserve to change.

Maybe you could potentially do something like a background process that takes a screen capture when you receive a call, and then process the image to extract the phone number. But I have very little experience with IOS so I don't even know if Apple would allow that. Anyways good luck and don't hesite to publish a package if you are successful with that, it would be definitely a great one!

Finally you have to implement typesafe platform channels via Pigeon:

import 'generated_pigeon.dart'

void onClick() async {
  SearchRequest request = SearchRequest()..query = 'test';
  Api api = Api();
  SearchReply reply = await api.search(request);
  print('reply: ${reply.result}');
}

Using Pigeon eliminates the need to match strings between host and client for the names and datatypes of messages. It supports: nested classes, grouping messages into APIs, generation of asynchronous wrapper code and sending messages in either direction. The generated code is readable and guarantees there will be no conflicts between multiple clients of different versions. Supported languages are Objective-C, Java, Kotlin and Swift (via Objective-C interop).

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
  • android/app/src/main/java/{your_package}/ServiceReceiver.java What should be used there in your_package . – daddy_ Feb 14 '21 at 08:50
  • the name of your package, like ```com.example.myapp``` you can find the exact name in build.gradle – Antonin GAVREL Feb 14 '21 at 14:32
  • And how to use/call that inside the main function? – daddy_ Feb 14 '21 at 14:42
  • you have to follow the tutorial at https://flutter.dev/docs/development/platform-integration/platform-channels?tab=android-channel-java-tab. I would recommend to use the pigeon package as it is typesafe, I edited the answer – Antonin GAVREL Feb 14 '21 at 15:16