Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.3.7 #346

Merged
merged 27 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a0f01d3
Version Bump
isaacakakpo1 Oct 30, 2023
56b3c4b
Main Stash
isaacakakpo1 Nov 6, 2023
69a444e
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Nov 16, 2023
f4804a5
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Nov 17, 2023
6ebf7ee
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Feb 20, 2024
e3cc5c1
Update build.gradle
isaacakakpo1 Apr 15, 2024
a032282
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Apr 23, 2024
d261055
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Apr 25, 2024
09d68da
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Apr 25, 2024
6b3baab
Merge remote-tracking branch 'origin/main'
isaacakakpo1 May 6, 2024
89c42c2
Merge remote-tracking branch 'origin/main'
isaacakakpo1 May 20, 2024
3f6868b
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Jun 11, 2024
c4fd1cb
Implement WebRTC Stats
isaacakakpo1 Jun 23, 2024
953aec5
Update WebRTC Stats to Start when enabled
isaacakakpo1 Jun 23, 2024
06c7cdf
Update WebRTC Stats to Start when enabled
isaacakakpo1 Jul 5, 2024
c55897b
Implement peer Stop
isaacakakpo1 Jul 9, 2024
90ca301
Push Notifications Fix
isaacakakpo1 Jul 21, 2024
8cd1a29
Merge remote-tracking branch 'origin/main'
isaacakakpo1 Jul 21, 2024
44731b7
- Update ReadMe
isaacakakpo1 Jul 24, 2024
05acbd7
- Post `telnyx_rtc.media` to livedata
isaacakakpo1 Jul 24, 2024
498681c
- Update isDev Logic
isaacakakpo1 Jul 24, 2024
b5db379
Merge branch 'main' into WebRTCStats
isaacakakpo1 Jul 24, 2024
8233b26
- Refactor Code format
isaacakakpo1 Jul 24, 2024
31f625a
- Fix UnitTest Failures
isaacakakpo1 Jul 24, 2024
7d704a0
Push Notifications Update
isaacakakpo1 Jul 25, 2024
c4c1ed0
Push Notifications Update
isaacakakpo1 Jul 25, 2024
79d3470
Push Notifications Update
isaacakakpo1 Jul 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ We can then use this method to create a listener that listens for an invitation
SocketMethod.BYE.methodName -> {
// Handle a call rejection or ending - Update UI or Navigate to new screen, etc.
}
SocketMethod.RINGING.methodName -> {
// Client Can simulate ringing state
}

SocketMethod.RINGING.methodName -> {
// Ringback tone is streamed to the caller
// early Media - Client Can simulate ringing state
}
}
}

Expand Down Expand Up @@ -239,6 +247,49 @@ The `txPushMetaData` is neccessary for push notifications to work.

For a detailed tutorial, please visit our official [Push Notification Docs](https://developers.telnyx.com/docs/voice/webrtc/push-notifications)

## Best Practices

1. Handling Push Notifications : In order to properly handle push notifications, we recommend using a call type (Foreground Service)[https://developer.android.com/develop/background-work/services/foreground-services]
with broadcast receiver to show push notifications. An answer or reject call intent with `telnyxPushMetaData` can then be passed to the MainActivity for processing.
- Play a ringtone when a call is received from push notification using the `RingtoneManager`
``` kotlin
val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
RingtoneManager.getRingtone(applicationContext, notification).play()
```
- Make Sure to set these flags for your pendingIntents, so the values get updated anytime when the notification is clicked
``` kotlin
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
```

### Android 14 Requirements
In order to receive push notifications on Android 14, you will need to add the following permissions to your AndroidManifest.xml file and request a few at runtime:
``` xml
// Request this permission at runtime
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

// If you need to use foreground services, you will need to add the following permissions
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"/>

// Configure foregroundservice and set the foreground service type
// Remember to stopForegroundService when the call is answered or rejected
<service
android:name=".ForegroundService"
android:foregroundServiceType="phoneCall"
android:exported="true" />
```
2. Handling Multiple Calls : The Telnyx WebRTC SDK allows for multiple calls to be handled at once.
You can use the callId to differentiate the calls.
``` kotlin
import java.util.UUID
// Retrieve all calls from the TelnyxClient
val calls: Map<UUID,Call> = telnyxClient.calls

// Retrieve a specific call by callId
val currentCall: Call? = calls[callId]
```



## ProGuard changes
NOTE:
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.telnyx.webrtc.sdk">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"/>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Expand All @@ -13,6 +15,9 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>

<application
android:allowBackup="true"
Expand All @@ -23,7 +28,10 @@
android:name=".App"
android:theme="@style/Theme.TelnyxAndroidWebRTCSDK">

<activity android:name=".ui.MainActivity"/>
<activity android:name=".ui.MainActivity"
android:launchMode="singleInstance"

/>

<activity android:name=".ui.SplashScreenActivity"
android:theme="@style/SplashScreenTheme"
Expand Down Expand Up @@ -60,5 +68,12 @@
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="telnyx_channel" />

<service
android:enabled="true"
android:exported="true"
android:foregroundServiceType="phoneCall"
android:name=".NotificationsService"
/>

</application>
</manifest>
1 change: 1 addition & 0 deletions app/src/main/java/com/telnyx/webrtc/sdk/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package com.telnyx.webrtc.sdk

import android.app.Application
import android.content.Context
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber

Expand Down
175 changes: 175 additions & 0 deletions app/src/main/java/com/telnyx/webrtc/sdk/NotificationsService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package com.telnyx.webrtc.sdk

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.content.res.Resources.NotFoundException
import android.graphics.Color
import android.media.Ringtone
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.google.gson.Gson
import com.telnyx.webrtc.sdk.di.AppModule
import com.telnyx.webrtc.sdk.model.PushMetaData
import com.telnyx.webrtc.sdk.ui.MainActivity
import com.telnyx.webrtc.sdk.utility.MyFirebaseMessagingService
import timber.log.Timber


class NotificationsService : Service() {


companion object {
private const val CHANNEL_ID = "PHONE_CALL_NOTIFICATION_CHANNEL"
private const val NOTIFICATION_ID = 1
const val STOP_ACTION = "STOP_ACTION"
}

override fun onCreate() {
super.onCreate()
createNotificationChannel()
}
private var ringtone:Ringtone? = null

private fun playPushRingTone() {
try {
val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
ringtone = RingtoneManager.getRingtone(applicationContext, notification)
ringtone?.play()
} catch (e: NotFoundException) {
Timber.e("playPushRingTone: $e")
}
}



override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

val stopAction = intent?.action
if (stopAction != null && stopAction == STOP_ACTION) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE)
ringtone?.stop()
} else {
stopForeground(true)
}
return START_NOT_STICKY
}

val metadata = intent?.getStringExtra("metadata")
val telnyxPushMetadata = Gson().fromJson(metadata, PushMetaData::class.java)
telnyxPushMetadata?.let {
showNotification(it)
playPushRingTone()

}
return START_STICKY
}

override fun onBind(intent: Intent?): IBinder? {
return null
}

private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Phone Call Notifications"
val description = "Notifications for incoming phone calls"
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(CHANNEL_ID, name, importance)
channel.description = description

val notificationManager = getSystemService(NotificationManager::class.java)
channel.apply {
lightColor = Color.RED
enableLights(true)
enableVibration(true)
setSound(null, null)
}
notificationManager.createNotificationChannel(channel)
}
}

private fun showNotification(txPushMetaData: PushMetaData) {
val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)

val customSoundUri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)

val rejectResultIntent = Intent(this, MainActivity::class.java)
rejectResultIntent.action = Intent.ACTION_VIEW
rejectResultIntent.putExtra(
MyFirebaseMessagingService.EXT_KEY_DO_ACTION,
MyFirebaseMessagingService.ACT_REJECT_CALL
)
rejectResultIntent.putExtra(
MyFirebaseMessagingService.TX_PUSH_METADATA,
txPushMetaData.toJson()
)
val rejectPendingIntent = PendingIntent.getActivity(
this,
MyFirebaseMessagingService.REJECT_REQUEST_CODE,
rejectResultIntent,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

val answerResultIntent = Intent(this, MainActivity::class.java)
answerResultIntent.setAction(Intent.ACTION_VIEW)

answerResultIntent.putExtra(
MyFirebaseMessagingService.EXT_KEY_DO_ACTION,
MyFirebaseMessagingService.ACT_ANSWER_CALL
)

answerResultIntent.putExtra(
MyFirebaseMessagingService.TX_PUSH_METADATA,
txPushMetaData.toJson()
)

val answerPendingIntent = PendingIntent.getActivity(
this,
MyFirebaseMessagingService.ANSWER_REQUEST_CODE,
answerResultIntent,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
Timber.d("showNotification: ${txPushMetaData.toJson()}")


val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_contact_phone)
.setContentTitle("Incoming Call")
.setContentText("Incoming call from: ")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setSound(customSoundUri)
.addAction(
R.drawable.ic_call_white,
MyFirebaseMessagingService.ACT_ANSWER_CALL, answerPendingIntent
)
.addAction(
R.drawable.ic_call_end_white,
MyFirebaseMessagingService.ACT_REJECT_CALL, rejectPendingIntent
)
.setOngoing(true)
.setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(pendingIntent, true)

startForeground(
NOTIFICATION_ID,
builder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL
)
}


}
2 changes: 1 addition & 1 deletion app/src/main/java/com/telnyx/webrtc/sdk/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
object AppModule {

private const val SHARED_PREFERENCES_KEY = "TelnyxSharedPreferences"
const val SHARED_PREFERENCES_KEY = "TelnyxSharedPreferences"

@Singleton
@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ class CallInstanceFragment : Fragment(), NumberKeyboardListener {
when (data?.method) {
SocketMethod.INVITE.methodName -> {
//NOOP
}
SocketMethod.RINGING.methodName -> {

}
SocketMethod.MEDIA.methodName -> {

}
SocketMethod.BYE.methodName -> {

Expand Down
Loading
Loading