Android Snippet
When you need a real-time response to a Missed-call OTP, you can set the listener on your Android code. The code format is available on Kotlin and Java.
On this page
Kotlin
The files consist of AndroidManifest.xml, Helper.kt, MainActivity.kt and PhoneStateReceiver.kt
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
Helper.kt
private fun isAirplaneModeOn(): Boolean {
return Settings.System.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
}
MainActivity.kt
import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
var key: String? = null //OTP
val digits: Int = 4 // 4 or 6 digits to pass verification
private val phoneStateReceiver = PhoneStateReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//check READ_PHONE_STATE and READ_CALL_LOG permission
val permissions: MutableList = mutableListOf()
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED
) {
permissions.add(Manifest.permission.READ_PHONE_STATE)
}
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_CALL_LOG
) != PackageManager.PERMISSION_GRANTED
) {
permissions.add((Manifest.permission.READ_CALL_LOG))
}
if (permissions.isEmpty()) {
//register receivers if all permissions have been granted
registerReceiver(phoneStateReceiver, IntentFilter("android.intent.action.PHONE_STATE"))
registerReceiver(keyReceiver, IntentFilter(PhoneStateReceiver.KEY_RECEIVER))
} else {
//request permission(s) that has not been granted
ActivityCompat.requestPermissions(this, permissions.toTypedArray(), 100)
}
}
//receiver to get the key
private var keyReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val phoneNumber = intent.extras?.getString(PhoneStateReceiver.PHONE_NUMBER)
key = phoneNumber?.takeLast(digits)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
var allGranted = true
if (requestCode == 100) {
grantResults.forEach {
if (it != PackageManager.PERMISSION_GRANTED) allGranted = false
}
if (allGranted) {
registerReceiver(
phoneStateReceiver,
IntentFilter("android.intent.action.PHONE_STATE")
)
}
}
}
override fun onDestroy() {
super.onDestroy()
//unregister receivers
unregisterReceiver(keyReceiver)
unregisterReceiver(phoneStateReceiver)
}
}
PhoneStateReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
class PhoneStateReceiver : BroadcastReceiver() {
companion object {
var phoneStateListener: CustomPhoneStateListener? = null
const val PHONE_NUMBER = "PHONE_NUMBER"
const val KEY_RECEIVER = "KeyReceiver"
}
override fun onReceive(context: Context, intent: Intent) {
val telephonyManager =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
//onReceive will called multiple time, so we have to make sure the listener is only made once
if (phoneStateListener == null) {
phoneStateListener = CustomPhoneStateListener(context)
telephonyManager.listen(
phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE
)
}
}
inner class CustomPhoneStateListener(private val context: Context) : PhoneStateListener() {
private var incomingNumber: String = ""
override fun onCallStateChanged(state: Int, phoneNumber: String) {
if (phoneNumber.isNotEmpty()) incomingNumber = phoneNumber
when (state) {
//ringing
TelephonyManager.CALL_STATE_RINGING -> {
val intent = Intent(KEY_RECEIVER)
intent.putExtra(PHONE_NUMBER, incomingNumber)
context.sendBroadcast(intent)
}
}
}
}
}
Java
The files consist of Helper.java, MainActivity.java and PhoneStateReceiver.java
Helper.java
private boolean isAirplaneModeOn() {
return Settings.System.getInt(getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
MainActivity.java
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
String key; //OTP
int digits = 6; // 4 or 6 digits to pass verification
private PhoneStateReceiver phoneStateReceiver = new PhoneStateReceiver();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//check READ_PHONE_STATE and READ_CALL_LOG permission
List permissions = new ArrayList<>();
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED
) {
permissions.add(Manifest.permission.READ_PHONE_STATE);
}
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_CALL_LOG
) != PackageManager.PERMISSION_GRANTED
) {
permissions.add((Manifest.permission.READ_CALL_LOG));
}
if (permissions.isEmpty()) {
//register receivers if all permissions have been granted
registerReceiver(phoneStateReceiver, new IntentFilter("android.intent.action.PHONE_STATE"));
registerReceiver(keyReceiver, new IntentFilter(PhoneStateReceiver.KEY_RECEIVER));
} else {
//request permission(s) that has not been granted
ActivityCompat.requestPermissions(this, permissions.toArray(new String[0]), 100);
}
}
//receiver to get the key
private BroadcastReceiver keyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String phoneNumber = intent.getExtras().getString(PhoneStateReceiver.PHONE_NUMBER);
key = phoneNumber.substring(phoneNumber.length()-digits);
}
};
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean allGranted = true;
if (requestCode == 100) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
registerReceiver(
phoneStateReceiver,
new IntentFilter("android.intent.action.PHONE_STATE")
);
}
}
}
private boolean isAirplaneModeOn() {
return Settings.System.getInt(getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
@Override
protected void onDestroy() {
super.onDestroy();
//unregister receivers
unregisterReceiver(keyReceiver);
unregisterReceiver(phoneStateReceiver);
}
}
PhoneStateReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class PhoneStateReceiver extends BroadcastReceiver {
static CustomPhoneStateListener phoneStateListener;
static String PHONE_NUMBER = "PHONE_NUMBER";
static String KEY_RECEIVER = "KeyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//onReceive will called multiple time, so we have to make sure the listener is only made once
if (phoneStateListener == null) {
phoneStateListener = new CustomPhoneStateListener(context);
telephonyManager.listen(
phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE
);
}
}
class CustomPhoneStateListener extends PhoneStateListener {
Context context;
private String incomingNumber;
public CustomPhoneStateListener(Context context) {
this.context = context;
}
@Override
public void onCallStateChanged(int state, String phoneNumber) {
if (!phoneNumber.isEmpty()) incomingNumber = phoneNumber;
//ringing
if (state == TelephonyManager.CALL_STATE_RINGING) {
Intent intent = new Intent(KEY_RECEIVER);
intent.putExtra(PHONE_NUMBER, incomingNumber);
context.sendBroadcast(intent);
}
}
}
}