You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PatientApp-KKUMC/SmsOtpAutoVerifyPlugin.kt

217 lines
7.0 KiB
Kotlin

package com.oohyugi.sms_otp_auto_verify
import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentSender
import android.os.Build
import android.telephony.TelephonyManager
import android.util.Log
import androidx.annotation.RequiresApi
import com.google.android.gms.auth.api.credentials.Credential
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.auth.api.phone.SmsRetrieverClient
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.PluginRegistry
import com.google.android.gms.auth.api.credentials.Credentials
import com.google.android.gms.auth.api.credentials.HintRequest
import io.flutter.plugin.common.PluginRegistry.Registrar
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.RECEIVER_EXPORTED
/** SmsOtpAutoVerifyPlugin */
class SmsOtpAutoVerifyPlugin : FlutterPlugin, MethodCallHandler,
MySmsListener, ActivityAware {
private var channel: MethodChannel? = null
private var pendingResult: MethodChannel.Result? = null
private var receiver: SmsBroadcastReceiver? = null
private var alreadyCalledSmsRetrieve = false
private var client: SmsRetrieverClient? = null
private var activity: Activity? = null
private var binding: ActivityPluginBinding? = null
private val activityResultListener: PluginRegistry.ActivityResultListener =
object : PluginRegistry.ActivityResultListener {
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
): Boolean {
if (requestCode == REQUEST_RESOLVE_HINT) {
if (resultCode == Activity.RESULT_OK && data != null) {
val credential: Credential? = data.getParcelableExtra(Credential.EXTRA_KEY)
val phoneNumber: String? = credential?.id
pendingResult?.success(phoneNumber)
} else {
pendingResult?.success(null)
}
return true
}
return false
}
}
companion object {
private const val channelName = "sms_otp_auto_verify"
private const val REQUEST_RESOLVE_HINT = 1256
@JvmStatic
fun setup(plugin: SmsOtpAutoVerifyPlugin, binaryMessenger: BinaryMessenger) {
plugin.channel = MethodChannel(binaryMessenger, channelName)
plugin.channel?.setMethodCallHandler(plugin)
plugin.binding?.addActivityResultListener(plugin.activityResultListener)
}
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
setup(plugin = this, binding.binaryMessenger)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
unregister()
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"getAppSignature" -> {
activity?.let {
val signature = AppSignatureHelper(it).getAppSignatures()[0]
result.success(signature)
}
}
"startListening" -> {
this.pendingResult = result
receiver = SmsBroadcastReceiver()
startListening()
}
"stopListening" -> {
pendingResult = null
unregister()
}
"requestPhoneHint" -> {
this.pendingResult = result
requestHint()
}
else -> result.notImplemented()
}
}
private fun requestHint() {
if (!isSimSupport()) {
pendingResult?.success(null)
return
}
val hintRequest = HintRequest.Builder()
.setPhoneNumberIdentifierSupported(true)
.build()
activity?.apply {
val intent = Credentials.getClient(this).getHintPickerIntent(hintRequest)
try {
startIntentSenderForResult(
intent.intentSender,
REQUEST_RESOLVE_HINT, null, 0, 0, 0
)
} catch (e: IntentSender.SendIntentException) {
e.printStackTrace()
}
}
}
private fun isSimSupport(): Boolean {
val telephonyManager: TelephonyManager =
activity!!.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return (telephonyManager.simState == TelephonyManager.SIM_STATE_ABSENT)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun startListening() {
activity?.let {
client = SmsRetriever.getClient(it)
}
val task = client?.startSmsRetriever()
task?.addOnSuccessListener {
// Successfully started retriever, expect broadcast intent
unregister()
Log.e(javaClass::getSimpleName.name, "task started")
receiver?.setSmsListener(this)
activity?.applicationContext?.let { it1 ->
ContextCompat.registerReceiver(
it1, receiver,
IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION), RECEIVER_EXPORTED)
}
}
}
private fun unregister() {
alreadyCalledSmsRetrieve = false
if (receiver != null) {
try {
activity?.unregisterReceiver(receiver)
Log.d(javaClass::getSimpleName.name, "task stoped")
receiver = null
} catch (e: Exception) {
}
}
}
override fun onOtpReceived(message: String?) {
message?.let {
if (!alreadyCalledSmsRetrieve) {
pendingResult?.success(it)
alreadyCalledSmsRetrieve = true
} else {
Log.d("onOtpReceived: ", "already called")
}
}
}
override fun onOtpTimeout() {
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
this.binding = binding
binding.addActivityResultListener(activityResultListener); }
override fun onDetachedFromActivityForConfigChanges() {
unregister()
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
this.binding = binding
binding.addActivityResultListener(activityResultListener);
}
override fun onDetachedFromActivity() {
unregister()
}
}