how to implemment auto detect otp using firebase? - android

I have implemented OTP verification using firebase,now I want add auto-detect OTP verification functionality in tha. But before autodetect app should ask about the permission for auto detect. How to do that?

Here You Go
in gradle
implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'
class SMSReceiver : BroadcastReceiver() {
private var otpListener: OTPReceiveListener? = null
fun setOTPListener(otpListener: OTPReceiveListener?) {
this.otpListener = otpListener
}
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == SmsRetriever.SMS_RETRIEVED_ACTION) {
val extras = intent.extras
val status = extras!![SmsRetriever.EXTRA_STATUS] as Status?
when (status!!.statusCode) {
CommonStatusCodes.SUCCESS -> {
val sms = extras[SmsRetriever.EXTRA_SMS_MESSAGE] as String?
sms?.let {
val p = Pattern.compile("\\d+")
val m = p.matcher(it)
if (m.find()) {
val otp = m.group()
if (otpListener != null) {
otpListener!!.onOTPReceived(otp)
}
}
}
}
}
}
}
interface OTPReceiveListener {
fun onOTPReceived(otp: String?)
}
}
Manifest
<receiver
android:name=".SMSReceiver"
android:exported="true"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
</intent-filter>
</receiver>

Related

Kotlin: Starting service after BroadcastReceiver not working

I`m trying to build a service that detects if the screen of a device is locked/unlocked (which I will later user as a native module in React). However, it seems like my service is not starting, and I don't receive the expected logs. Where is my mistake? (It's my first time dealing with native android & Kotlin, so apologies if this is a dumb question, and duplicates were related to java code)..
I have defined a Broadcast Receiver for each event here:
ScreenOnReceiver.kt
class screenOnReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if(intent!!.action == Intent.ACTION_SCREEN_ON) {
val screenOff = false
val i = Intent(context, PowerButtonService::class.java)
i.putExtra("screenState", screenOff)
context!!.startService(i)
}
}
}
ScreenOffReceiver.kt
class screenOffReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if(intent!!.action == Intent.ACTION_SCREEN_ON) {
val screenOff = false
val i = Intent(context, PowerButtonService::class.java)
i.putExtra("screenState", screenOff)
context!!.startService(i)
}
}
}
ScreenChangeService.kt:
class ScreenChangeService: Service() {
override fun onBind(p0: Intent?): IBinder? = null
override fun onCreate() {
val screenOnReceiver = screenONReceiver()
val screenOnFilter = IntentFilter(Intent.ACTION_SCREEN_ON)
registerReceiver(screenOnReceiver, screenOnFilter)
val screenOffReceiver = screenOffReceiver()
val screenOffFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
registerReceiver(screenOffreceiver, screenOffFilter)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val screenState = intent!!.getBooleanExtra("screenState", false)
if (screenState == true) {
Log.d("TAG", "Screen On")
} else {
Log.d("TAG", "Screen Off")
}
return START_NOT_STICKY
}
}
Manifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Test">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".PowerButtonService"/>
</application>

Unresolved supertypes for AppMeasurementReceiver

I'm using Firebase analytics and Firebase BOM. I need to create AppMeasurementReceiver programatically, becasue I have more than one receiver that needs INSTALL_REFERRER. Unfortunately I get an error that class that is implemented by AppMeasurementReceiver is missing. Missing class is com.google.android.gms.measurement.internal.zzff$zza. It's hard to debug and guess what is missing.
class InstallRefererReceiver : BroadcastReceiver() {
private val otherReceivers = listOf(
AppMeasurementReceiver()
)
override fun onReceive(context: Context?, intent: Intent?) {
otherReceivers.forEach {
it.onReceive(context, intent)
}
}
}
<receiver
android:name="co.app.referer.InstallRefererReceiver"
android:exported="true"
android:permission="android.permission.INSTALL_PACKAGES">
<intent-filter android:priority="999">
<action android:name="com.google.android.gms.measurement.UPLOAD" />
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
I get following error:
e: Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class com.google.android.gms.measurement.AppMeasurementReceiver, unresolved supertypes: com.google.android.gms.measurement.internal.zzff$zza
I can find undefined field in play-services-measurement. This undefinedtype type is probably the same type that AppMeasurementReceiver is implementing.
public final class zzff {
private final <undefinedtype> zza;
EDIT
I found really ugly solution, just create AppMeasurementReceiver via reflection.
class InstallRefererReceiver : BroadcastReceiver() {
private val otherReceivers = listOf(
FixedAppMeasurementReceiver()
)
override fun onReceive(context: Context?, intent: Intent?) {
otherReceivers.forEach {
it.onReceive(context, intent)
}
}
private class FixedAppMeasurementReceiver : BroadcastReceiver() {
private val appMeasurementReceiver: BroadcastReceiver? = try {
Class.forName("com.google.android.gms.measurement.AppMeasurementReceiver")
.newInstance() as BroadcastReceiver?
} catch (t: Throwable) {
null
}
override fun onReceive(context: Context?, intent: Intent?) {
try {
appMeasurementReceiver?.onReceive(context, intent)
} catch (t: Throwable) {
doNothing()
}
}
}
}

Android SIP API - Receive Incoming Call

I creating softphone application using Android SIP API (https://developer.android.com/guide/topics/connectivity/sip) and I have successfully registered to my Asterisk server and I can call another peer on another softphone. I can hear voice on both sides and everything works perfect.
Now, I have problem receiving call from another softphone. onRinging method is never executed. On the other softphone I am getting status RINGING, but in my app that call is never received.
I have created IncomingCallReceiver class and also WalkieTalkieActivity, but none of them is doing its job (most probably I am doing something wrong, or I did not initiate some of them, or call or whatever...).
I am stuck on receiving the calls. Also the official documentation is not clear to me.
If there is anyone here to help me and guide me to the solution, I would be very grateful.
Here is my MainActivity class:
class MainActivity: FlutterActivity() {
var mSipProfile: SipProfile? = null
var username: String? = "..." //I have it correct in my code
var password: String? = "..." //I have it correct in my code
var domain: String? = "..." //I have it correct in my code
var builder: SipProfile.Builder? = SipProfile.Builder(username, domain).setPassword(password)
private val CHANNEL = "samples.flutter.dev/registration"
private val mSipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) {
SipManager.newInstance(this)
}
override fun onStart() {
super.onStart()
println("SSSSSTTTTTTTTAAAAAAAAAAARRRRRRRRRRRRRTTTTTTTTTTTTTTTTTTT")
}
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
println("CCCCCCCCRRRRRREEEEEEEEEAAAAAAATTTTTTTTEEEEEEEEEEEEEEEEEEEEEE")
}
private var listenSipSession: SipSession.Listener = object : SipSession.Listener() {
override fun onRinging(session: SipSession?, caller: SipProfile?, sessionDescription: String?) {
super.onRinging(session, caller, sessionDescription)
println("EVVVVVVVOOOOOOOOOOOOOOOO GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
}
}
private var listener: SipAudioCall.Listener = object : SipAudioCall.Listener() {
override fun onCalling(call: SipAudioCall?) {
super.onCalling(call)
println("111111 CALLING CALLING CALLING")
}
override fun onChanged(call: SipAudioCall?) {
super.onChanged(call)
println("CHANGED")
println(call?.state)
}
override fun onError(call: SipAudioCall?, errorCode: Int, errorMessage: String?) {
super.onError(call, errorCode, errorMessage)
println("ERROR ERROR ERROR")
}
override fun onRingingBack(call: SipAudioCall?) {
super.onRingingBack(call)
println("RINGING BACK")
}
/*override fun onRinging(call: SipAudioCall, caller: SipProfile) {
println("RINGING")
try {
call.answerCall(30)
} catch (e: Exception) {
println("ERROR 2: $e")
e.printStackTrace()
}
}*/
override fun onCallEstablished(call: SipAudioCall) {
println("Call established")
call.apply {
startAudio()
setSpeakerMode(false)
// toggleMute()
}
}
override fun onRinging(call: SipAudioCall?, caller: SipProfile?) {
super.onRinging(call, caller)
println("Ringing")
}
override fun onCallEnded(call: SipAudioCall) {
println("Call ended " + call.state)
}
}
override fun onDestroy() {
super.onDestroy()
closeLocalProfile()
}
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
// Note: this method is invoked on the main thread.
mSipProfile = builder?.build()
val intent = Intent("com.example.softphone.INCOMING_CALL")
val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA)
mSipManager?.open(mSipProfile, pendingIntent, null)
if (call.method == "register") {
val registrationStatus = register()
result.success(registrationStatus)
}
if (call.method == "call") {
call()
}
}
}
private fun closeLocalProfile() {
try {
mSipManager?.close(mSipProfile?.uriString)
println("Local profile closed.")
} catch (ee: Exception) {
println("WalkieTalkieActivity/onDestroy. Failed to close local profile.")
}
}
///Method for making call
private fun call(): String {
var status = "Unknown"
try {
println("Making call")
status = "In Call"
val call: SipAudioCall? = mSipManager?.makeAudioCall(
mSipProfile?.uriString,
"...", //I have it correct in my code
listener,
30
)
println(call)
} catch (e: SipException) {
e.printStackTrace()
println(e)
}
return status
}
///Method for registering user
private fun register(): String {
var status = "Unknown"
try {
mSipManager?.setRegistrationListener(mSipProfile?.uriString, object : SipRegistrationListener {
override fun onRegistering(localProfileUri: String) {
status = "Registering with SIP Server..."
println(status)
}
override fun onRegistrationDone(localProfileUri: String, expiryTime: Long) {
status = "Ready"
println(status)
}
override fun onRegistrationFailed(
localProfileUri: String,
errorCode: Int,
errorMessage: String
) {
status = "Registration failed. Please check settings."
println(status)
}
})
} catch (e: SipException) {
e.printStackTrace()
println(e)
}
return status
}
}
Here is my IncomingCallReceiver class:
class IncomingCallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
var incomingCall: SipAudioCall? = null
try {
val listener: SipAudioCall.Listener = object : SipAudioCall.Listener() {
override fun onRinging(call: SipAudioCall, caller: SipProfile) {
try {
call.answerCall(30)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
val wtActivity: WalkieTalkieActivity = context as WalkieTalkieActivity
incomingCall = wtActivity.manager?.takeAudioCall(intent, listener)
incomingCall?.setListener(listener)
incomingCall?.answerCall(30)
incomingCall?.startAudio()
incomingCall?.setSpeakerMode(true)
if (incomingCall?.isMuted!!) {
incomingCall?.toggleMute()
}
} catch (e: Exception) {
incomingCall?.close()
}
}
}
Here is my WalkieTalkieActivity class:
class WalkieTalkieActivity : Activity(), OnTouchListener {
var sipAddress: String? = null
var manager: SipManager? = null
var me: SipProfile? = null
var call: SipAudioCall? = null
lateinit var callReceiver: IncomingCallReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val filter = IntentFilter().apply {
addAction("com.example.softphone.INCOMING_CALL")
}
callReceiver = IncomingCallReceiver()
this.registerReceiver(callReceiver, filter)
}
override fun onTouch(p0: View?, p1: MotionEvent?): Boolean {
TODO("Not yet implemented")
}
}
Here is my AndroidManifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.softphone">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-feature android:name="android.software.sip.voip" android:required="true" />
<uses-feature android:name="android.hardware.wifi" android:required="true" />
<uses-feature android:name="android.hardware.microphone" android:required="true" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="softphone"
android:icon="#mipmap/ic_launcher">
<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="#drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Thank you all in advance!

setExactAndAllowWhileIdle does not on Samsung

I have to wake up my application every 15 minutes. I use setExactAndAllowWhileIdle for that. It sends intent to W2BWakeUpReceiver to do some event.
It works onXiaomi but it does not work on Sumsung
Why it does not work on Samsung???
fun startAlarm() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val pi = PendingIntent.getBroadcast(app_context, 0, Intent(action_wake_up), 0)
alarmManager.setExactAndAllowWhileIdle(RTC_WAKEUP, System.currentTimeMillis() + periodWakeUp, pi)
}
}
Receiver
class W2BWakeUpReceiver : BroadcastReceiver() {
companion object {
val action_wake_up = "AlarmWakeUpW2B"
}
private val service: W2BService?
get() = W2BApp.service
private val testTime: Long?
get() = W2BApp.service?.testTime
override fun onReceive(context: Context?, intent: Intent?) {
service?.startAlarm()
val now = Calendar.getInstance().timeInMillis
if (Repository.selectedDevice?.isConnect == true
&& testTime != null
&& now - testTime!! > 50_000
) {
ControllerThread.getThread(TypeThread.Worker).workInThread {
service?.restartMeasurement()
}
}
}
Manifest
<receiver android:name=".service.wake_up.W2BWakeUpReceiver">
<intent-filter>
<action android:name="AlarmWakeUpW2B" />
</intent-filter>
</receiver>

I added OtpBroadcastReceiver and registred it, but I can't seem to get the messages from it

Here is my fragment -
#SuppressLint("HardwareIds")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mPresenter = VerifyOtpPresenter(this)
androidId = Settings.Secure.getString(activity?.contentResolver, Settings.Secure.ANDROID_ID)
mPresenter.requestOtp(phoneNumber)
initClickAndTextListeners()
initOtpCountdownTimer()
}
/**
* Requesting OTP password for our phone number
*/
override fun requestOtp(phoneNumber: Long) {
OtpNetworking.requestOtp(phoneNumber, object : OtpNetworking.RequestOtpCallback {
override fun onSuccess() {
Toast.makeText(context, getString(R.string.verify_otp_fragment_sms_arrived), Toast.LENGTH_SHORT).show()
startSmsRetriever()
}
override fun onError(reason: String) {
Toast.makeText(context, reason, Toast.LENGTH_SHORT).show()
}
})
}
private fun startSmsRetriever() {
val client = SmsRetriever.getClient(context!!)
val task = client.startSmsRetriever()
task.addOnSuccessListener {
Toast.makeText(context, "Successfully added retriever", Toast.LENGTH_SHORT).show()
}
task.addOnFailureListener {
Toast.makeText(context, "Failed to get SMS", Toast.LENGTH_SHORT).show()
}
}
here is my OtpBroadcastReceiver -
class OtpBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
Toast.makeText(context, "onReceive", Toast.LENGTH_SHORT).show()
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
val extras = intent.extras
val status: Status? = extras!![SmsRetriever.EXTRA_STATUS] as Status?
when (status?.statusCode) {
CommonStatusCodes.SUCCESS -> {
val message: String? = extras[SmsRetriever.EXTRA_SMS_MESSAGE] as String?
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
CommonStatusCodes.TIMEOUT -> {
Toast.makeText(context, "Timeout", Toast.LENGTH_SHORT).show()
}
}
}
}
}
and my manifest file -
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="false"
android:theme="#style/AppTheme">
<activity android:name=".startup.StartupActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".otp.service.OtpBroadcastReceiver" android:exported="true"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>
<meta-data
android:name="preloaded_fonts"
android:resource="#array/preloaded_fonts" />
</application>
I can't seem to get any information from my broadcast receiver, eventhough the toast message of the sms retriever does say Successfully added retriever
I think I am missing the connection between the fragment and the broadcast receiver but I am not sure - does anyone have an idea what I am missing?
You could try to pass some onOtpReceived function into your OtpBroadcastReceiver and see if that helps.
class OtpBroadcastReceiver(onOtpReceived: (String) -> Unit, onOtpTimeout: () -> Unit) : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
val extras = intent.extras
val status: Status? = extras!![SmsRetriever.EXTRA_STATUS] as Status?
when (status?.statusCode) {
CommonStatusCodes.SUCCESS -> {
val message: String? = extras[SmsRetriever.EXTRA_SMS_MESSAGE] as String?
onOtpReceived(message)
}
CommonStatusCodes.TIMEOUT -> {
onOtpTimeout()
}
}
}
}
}

Categories

Resources