Skip to content

07.Notification and Message

Kilnn edited this page Jul 8, 2023 · 19 revisions

Notification

Use FcMessageFeature.sendNotification to send a notification to the device.

You can send a variety of different notifications, such as Telephony,SMS,Facebook,Twittwe, etc. But at first, you should use FcDeviceInfo.isSupportNotification to ensure this type is supported. And ensure that the type is enabled in FcNotificationConfig.

Flag.TELEPHONY,Flag.SMS and Flag.OTHERS_APP are always supported and can be used without using FcDeviceInfo.isSupportNotification to judged.

The flags in FcNotificationConfig are not one-to-one corresponding to the types in FcNotificationType. This is because there are four types of notifications for telephony types: incoming calls, answering , hanging up and missed calls.

Usually, we use TelephonyManager and PhoneStateListener to monitor the telephony status. Use BroadcastReceiver to monitor SMS. Other third-party notifications such as Facebook, Twitter messages, etc., consider using NotificationListenerService to capture.

Telephony

sample project: MyTelephonyControl.kt

When FcNotificationConfig.Flag.TELEPHONY is enabled, you can send telephony notification to device. There are 4 types of telephony notifications:

  • FcNotificationType.TELEPHONY_INCOMING
  • FcNotificationType.TELEPHONY_ANSWERED
  • FcNotificationType.TELEPHONY_REJECTED:Whether it is an hang up or a missed call, it needs to be sent.
  • FcNotificationType.TELEPHONY_MISSED:Need send after TELEPHONY_REJECTED if it is a missed call.

When the device receives an incoming call notification, users can hang up the telephony on the device and need to use FcMessageFeature.observerMessage to listen the FcMessageType.TELEPHONY_HANG_UP and FcMessageType.TELEPHONY_HANG_UP_SMS message to handle hang ups from the device.

In addition, if you listen to FcMessageType.MEDIA_SILENT_MODE message and mute the device, you should exit the mute mode when the telephony enters an idle state. Such as exit mute mode in PhoneStateListener.onCallStateChanged when state is TelephonyManager.CALL_STATE_IDLE.

The SDK provides various ways to help you achieve this function, and you can choose any suitable method.

Use FcBuiltInFeatures.telephonyControl

//1. Enable FcBuiltInFeatures.telephonyControl
FcSDK.Builder(context).setBuiltInFeatures(
   FcBuiltInFeatures(
       telephonyControl= true,
   )
)

//2. Check after request runtime permissions
requestPermission(fragment, getTelephony(), descriptors, listener = {
    if (hasPermissions(context, listOf(Manifest.permission.READ_PHONE_STATE))) {
        fcSDK.connector.telephonyControlPhoneStatePermission()
    }
})

//3. Check after app enter foreground
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        fcSDK.connector.telephonyControlPhoneStatePermission()
    }

    override fun onStop(owner: LifecycleOwner) {

    }
})

Extend AbsTelephonyControl and AbsPhoneStateListener

//1.  Extend AbsTelephonyControl and AbsPhoneStateListener
class MyTelephonyControl(
    context: Context,
    connector: FcConnector,
    factory: PhoneStateListenerFactory<MyPhoneStateListener>,
) : AbsTelephonyControl<MyPhoneStateListener>(context, connector, factory)

class MyPhoneStateListener(
    context: Context,
    connector: FcConnector,
) : AbsPhoneStateListener(context, connector) {

    override fun isTelephonyEnabled(context: Context): Boolean {
        return connector.configFeature().getNotificationConfig().isFlagEnabled(FcNotificationConfig.Flag.TELEPHONY)
    }
}

//2. Init and hold reference in YourApplication or any gloabl instance
var myTelephonyControl: MyTelephonyControl? = null
myTelephonyControl= MyTelephonyControl(this, fcSDK.connector, object : PhoneStateListenerFactory<MyPhoneStateListener> {
    override fun createInstance(context: Context, connector: FcConnector): MyPhoneStateListener {
        return MyPhoneStateListener(context, connector)
    }
})

//3. Check after request runtime permissions
requestPermission(fragment, getTelephony(), descriptors, listener = {
    if (hasPermissions(context, listOf(Manifest.permission.READ_PHONE_STATE))) {
       myTelephonyControl.checkInitialize()
    }
})

//4. Check after app enter foreground
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        myTelephonyControl.checkInitialize()
    }

    override fun onStop(owner: LifecycleOwner) {

    }
})

Do it all yourself

//1. Extend PhoneStateListener and register it in TelephonyManager
abstract class MyPhoneStateListener(
    val context: Context,
    val connector: FcConnector
) : PhoneStateListener() {

    override fun onCallStateChanged(state: Int, phoneNumber: String?) {
        super.onCallStateChanged(state, phoneNumber)
        if (state == TelephonyManager.CALL_STATE_IDLE) {
            connector.mediaControlExitSilentMode()//exit silent mode If you enabled [FcBuiltInFeature.mediaControl]
            sendTelephonyNotification(connector, FcNotificationType.TELEPHONY_REJECTED)
            if(isMissedCall){
                sendTelephonyNotification(connector, FcNotificationType.TELEPHONY_REJECTED)
            }
        } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
            sendTelephonyNotification(connector, FcNotificationType.TELEPHONY_ANSWERED)
        } else if (state == TelephonyManager.CALL_STATE_RINGING) {
            sendTelephonyNotification(connector, FcNotificationType.TELEPHONY_INCOMING)
        }
    } 
}

//2. Handle hang up message
private val messageDisposable = connector.messageFeature().observerMessage().subscribe {
    if (it.type == FcMessageType.TELEPHONY_HANG_UP) {//hang up
        doHangUp()
    } else if (it.type == FcMessageType.TELEPHONY_HANG_UP_SMS) {//hang up and send a sms
        val sms = it.data as? String
        if (!sms.isNullOrEmpty()) {
            doHangUpSms()
        }
    }
}

We strongly recommend using FcBuiltInFeatures.telephonyControl or the util class AbsTelephonyControl to do this feature. You only need to handle permissions in a few places.

Don't forget request runtime permissions for this feature

SMS

sample project: Refer to MySmsBroadcastReceiver.kt

When FcNotificationConfig.Flag.SMS is enabled, you can send FcNotificationType.SMS notification to device.

You can use util class AbsSmsBroadcastReceiver or do it all yourself.

class MySmsBroadcastReceiver : AbsSmsBroadcastReceiver() {

    override fun getFcSDK(context: Context): FcSDK {
        return context.fcSDK
    }

    override fun isSmsEnabled(context: Context): Boolean {
        return getFcSDK(context).connector.configFeature().getFunctionConfig().isFlagEnabled(FcNotificationConfig.Flag.SMS)
    }

}

Don't forget request runtime permissions for this feature

Third-party app notification

Message

The device may send various messages to the phone, and use FcMessageFeature.observerMessage to listen for these messages.

The message type define in FcMessageType

Find phone

sample project: Refer to FindPhoneManager.kt

When receiving FcMessageType.FINE_PHONE type message indicating that the device is finding for the phone.

Usually, after receiving this message on your phone, you need to make a ring or vibration to respond to the device's finding. And when you start responding, you need to send FcMessageFeature.replayFindPhone.

After the finding starts, both parties can actively stop the finding process. Listen FcMessageType.STOP_FINE_PHONE message to stop phone finding, and send FcMessageFeature.stopFindPhone to stop device finding.

Find device

sample project: Refer to OtherFeaturesFragment.kt

Use FcMessageFeature.findDevice to find device.

Camera control

sample project: Refer to CameraActivity.kt

Use FcMessageFeature.observerMessage to listen the camera message:

  • FcMessageType.CAMERA_WAKE_UP: Launch your camera activity
  • FcMessageType.CAMERA_EXIT: Exit your camera activity
  • FcMessageType.CAMERA_TAKE_PHOTO: Take photo in your camera activity.

Use FcMessageFeature.setCameraStatus to send you camera status to device. Such as setCameraStatus(true) on activity resume, setCameraStatus(false) on activity pause.

Media control

Use FcMessageFeature.observerMessage to listen for the following messages to for media control

  • FcMessageType.MEDIA_PLAY_PAUSE
  • FcMessageType.MEDIA_NEXT
  • FcMessageType.MEDIA_PREVIOUS
  • FcMessageType.MEDIA_VOLUME_UP
  • FcMessageType.MEDIA_VOLUME_DOWN
  • FcMessageType.MEDIA_SILENT_MODE

For example, when you receive FcMessageType.MEDIA_VOLUME_UP message, use AudioManager.adjustVolume to increase the ringer volume.

You can use FcBuiltInFeatures.mediaControl without having to handle the messages yourself. See also Built-in features

Music control

When receiving FcMessageType.MUSIC_STATE and FcMessageType.MUSIC_INFO messages, you should use FcMessageFeature.setMusicState and FcMessageFeature.setMusicInfo to send music state/info to device. Usually, MediaSessionManager is used to obtain the current music info and status of the phone.

You can use FcBuiltInFeatures.musicControl without having to handle the message yourself. See also Built-in features.

This feature relies on NotificationListenerService, you need to use FcConnector.musicControlNotificationListenerService to pass in this instance in your NotificationListenerService.Like this:

class MyNotificationListenerService : NotificationListenerService() {

    override fun onCreate() {
        super.onCreate()
        getFcSDK(this).connector.musicControlNotificationListenerService(null)
    }

    override fun onListenerConnected() {
        super.onListenerConnected()
        getFcSDK(this).connector.musicControlNotificationListenerService(this)
    }

    override fun onListenerDisconnected() {
        super.onListenerDisconnected()
        getFcSDK(this).connector.musicControlNotificationListenerService(null)
    }
}

If you extend the FitCloud SDK util class AbsNotificationListenerService, you don't need to call musicControlNotificationListenerService.

Clone this wiki locally