Skip to content

Commit

Permalink
Merge pull request #91 from namra25/rel3.13
Browse files Browse the repository at this point in the history
Release 3.13.0
  • Loading branch information
ciscoRankush authored Aug 21, 2024
2 parents 7baf279 + 6082646 commit 773f129
Show file tree
Hide file tree
Showing 13 changed files with 365 additions and 31 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,19 @@ This demo support Android device with **Android 7.0** or later
- For Full SDK
```
dependencies {
implementation 'com.ciscowebex:webexsdk:3.12.0'
implementation 'com.ciscowebex:webexsdk:3.13.0'
}
```
- For Meeting SDK
```
dependencies {
implementation 'com.ciscowebex:webexsdk-meeting:3.12.0'
implementation 'com.ciscowebex:webexsdk-meeting:3.13.0'
}
```
- For WebexCalling SDK
```
dependencies {
implementation 'com.ciscowebex:webexsdk-wxc:3.12.0'
implementation 'com.ciscowebex:webexsdk-wxc:3.13.0'
}
```
Expand Down
11 changes: 5 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ android {
applicationId "com.cisco.sdk_android"
minSdkVersion Versions.minSdk
targetSdkVersion Versions.targetSdk
versionCode 3120000
versionName "3.12.0"
versionCode 3130000
versionName "3.13.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -121,10 +121,9 @@ android {

dependencies {
//At a time only one WebexSDK should be used.
implementation 'com.ciscowebex:webexsdk:3.12.0' // For full flavor
//implementation 'com.ciscowebex:webexsdk-wxc:3.12.0' //For webexCalling flavor
//implementation 'com.ciscowebex:webexsdk-meeting:3.12.0' // For meeting flavor

implementation 'com.ciscowebex:webexsdk:3.13.0' // For full flavor
//implementation 'com.ciscowebex:webexsdk-wxc:3.13.0' //For webexCalling flavor
//implementation 'com.ciscowebex:webexsdk-meeting:3.13.0' // For meeting flavor
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation Dependencies.kotlinStdLib
implementation Dependencies.coreKtx
Expand Down
7 changes: 5 additions & 2 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,17 @@
*;
}

-keep public enum com.webex.scf.commonhead.models.**{
-keep public enum com.ciscowebex.androidsdk.omniusenums.**{
*;
}

-keep public class com.webex.scf.commonhead.models.**{
-keep public class com.ciscowebex.androidsdk.omniusmodels.**{
*;
}

-keep enum com.ciscowebex.androidsdk.utils.internal.NetTypes{
*;
}
-keep class com.ciscowebex.androidsdk.phone.internal.RenderSink{
*;
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ class TeamFragmentTest : KitchenSinkTest() {
onView(withId(R.id.teamsRecyclerView)).check(matches(hasDescendant(withText(testTeam))))
}

// @Test
// fun addPersonToTeam_teamFragment(){
// goToMessagingActivity()
// onView(withId(R.id.teamsRecyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<TeamsClientViewHolder>(0, clickChildViewWithId(R.id.iv_add_to_team)))
// WaitUtils.sleep(TIME_1_SEC)
// intended(hasComponent(MessagingSearchActivity::class.java.name))
// }
@Test
fun addPersonToTeam_teamFragment(){
goToMessagingActivity()
onView(withId(R.id.teamsRecyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<TeamsClientViewHolder>(0, clickChildViewWithId(R.id.iv_add_to_team)))
WaitUtils.sleep(TIME_1_SEC)
intended(hasComponent(MessagingSearchActivity::class.java.name))
}

@Test
fun testBottomSheetOptions_teamsFragment(){
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,15 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

<service
android:name=".KitchenSinkForegroundService"
android:exported="false" />

<service android:name=".CallManagementService"
android:foregroundServiceType="phoneCall"
android:exported="false" />

<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/app_notification_icon" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.ciscowebex.androidsdk.kitchensink

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.ciscowebex.androidsdk.kitchensink.utils.CallObjectStorage
import com.ciscowebex.androidsdk.phone.Call
import com.ciscowebex.androidsdk.phone.CallObserver


class CallManagementService : Service() {
private val tag = "CallManagementService"
private var receiver: BroadcastReceiver? = null

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

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (isForegroundServiceSupported()) {
startForeground(1, getNotification())
}
return START_STICKY
}

override fun onTaskRemoved(rootIntent: Intent?) {
Log.d(tag, "onTaskRemoved called!")
super.onTaskRemoved(rootIntent)
val call = getOngoingCall()
if (call != null) {
endCall(call)
} else {
Log.d(tag, "No call found in connected state. Killing service!")
stopSelf()
}
}

override fun onDestroy() {
super.onDestroy()
if (receiver != null) {
unregisterReceiver(receiver)
}
}

@RequiresApi(Build.VERSION_CODES.O)
private fun getNotification(): Notification {
// Create a notification for the foreground service
val channelId = "ks_02"
val notificationChannel =
NotificationChannel(
channelId, "Call Management Service Notifications",
NotificationManager.IMPORTANCE_MIN
)
notificationChannel.enableLights(false)
notificationChannel.lockscreenVisibility = Notification.VISIBILITY_SECRET
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.createNotificationChannel(notificationChannel)

val title = getString(R.string.call_management_service_notification_title)
return NotificationCompat.Builder(
this,
channelId
).setSmallIcon(R.drawable.app_notification_icon)
.setWhen(0)
.setContentTitle(title)
.setOngoing(true)
.build()
}

private fun getOngoingCall(): Call? {
var call: Call? = null

for (i in 0 until CallObjectStorage.size()) {
val callObj = CallObjectStorage.getCallObjectFromIndex(i)
val status = callObj?.getStatus()
if (status == Call.CallStatus.CONNECTED || status == Call.CallStatus.RINGING
|| status == Call.CallStatus.WAITING || status == Call.CallStatus.INITIATED) {
Log.d(tag, "Call with id = ${callObj.getCallId()} found in ${status.name} state. ")
call = callObj
break
}
}
return call
}

private fun endCall(call: Call) {
Log.d(tag, "Ending call with id = ${call.getCallId()}")
call.setObserver(object : CallObserver {
override fun onDisconnected(event: CallObserver.CallDisconnectedEvent?) {
Log.d(tag, "Call disconnected fired, stopping callManagementService!")
stopSelf()
}

})
if (call.getDirection() == Call.Direction.INCOMING && call.getStatus() == Call.CallStatus.RINGING) {
call.reject {
if (it.isSuccessful) {
Log.d(tag, "Call rejected successfully. Waiting for call disconnected event")
} else {
Log.e(tag, "Call reject failed, reason : ${it.error?.errorMessage}")
stopSelf()
}
}
} else {
call.hangup { result ->
if (result.isSuccessful) {
Log.d(tag, "Call hung up success. Waiting for call disconnected event")
} else {
Log.e(tag, "Call hangup failed, reason : ${result.error?.errorMessage}")
stopSelf()
}
}
}

}

private fun isForegroundServiceSupported(): Boolean {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ class WebexRepository(val webex: Webex) : WebexUCLoginDelegate, WebexAuthDelegat
var _startAssociationLiveData: MutableLiveData<CallLiveData>? = null
var _startShareLiveData: MutableLiveData<Boolean>? = null
var _stopShareLiveData: MutableLiveData<Boolean>? = null

var _startAudioDumpLiveData: MutableLiveData<Boolean>? = null
var _stopAudioDumpLiveData: MutableLiveData<Boolean>? = null
var _canStartAudioDumpLiveData: MutableLiveData<Boolean>? = null
var _spaceEventLiveData: MutableLiveData<Pair<SpaceEvent, Any?>>? = null
var spaceEventListener : SpaceEventListener? = null
var _membershipEventLiveData: MutableLiveData<Pair<MembershipEvent, Membership?>>? = null
Expand Down Expand Up @@ -196,6 +198,9 @@ class WebexRepository(val webex: Webex) : WebexUCLoginDelegate, WebexAuthDelegat
_startAssociationLiveData = null
_startShareLiveData = null
_stopShareLiveData = null
_startAudioDumpLiveData = null
_stopAudioDumpLiveData = null
_canStartAudioDumpLiveData = null
}

fun clearSpaceData(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import com.ciscowebex.androidsdk.phone.MediaStream
import com.ciscowebex.androidsdk.phone.MediaStreamQuality
import com.ciscowebex.androidsdk.phone.BreakoutSession
import com.ciscowebex.androidsdk.phone.Breakout
import com.ciscowebex.androidsdk.phone.CompanionMode
import com.ciscowebex.androidsdk.phone.DirectTransferResult
import com.ciscowebex.androidsdk.phone.InviteParticipantError
import com.ciscowebex.androidsdk.phone.SwitchToAudioVideoCallResult
Expand Down Expand Up @@ -74,6 +73,9 @@ class WebexViewModel(val webex: Webex, val repository: WebexRepository) : BaseVi
val _setCompositeLayoutLiveData = MutableLiveData<Pair<Boolean, String>>()
val _setRemoteVideoRenderModeLiveData = MutableLiveData<Pair<Boolean, String>>()
val _forceSendingVideoLandscapeLiveData = MutableLiveData<Boolean>()
val _startAudioDumpLiveData = MutableLiveData<Boolean>()
val _stopAudioDumpLiveData = MutableLiveData<Boolean>()
val _canStartAudioDumpLiveData = MutableLiveData<Boolean>()

var callMembershipsLiveData: LiveData<List<CallMembership>> = _callMembershipsLiveData
val muteAllLiveData: LiveData<Boolean> = _muteAllLiveData
Expand All @@ -86,6 +88,9 @@ class WebexViewModel(val webex: Webex, val repository: WebexRepository) : BaseVi
val setCompositeLayoutLiveData: LiveData<Pair<Boolean, String>> = _setCompositeLayoutLiveData
val setRemoteVideoRenderModeLiveData: LiveData<Pair<Boolean, String>> = _setRemoteVideoRenderModeLiveData
val forceSendingVideoLandscapeLiveData: LiveData<Boolean> = _forceSendingVideoLandscapeLiveData
val startAudioDumpLiveData: LiveData<Boolean> = _startAudioDumpLiveData
val stopAudioDumpLiveData: LiveData<Boolean> = _stopAudioDumpLiveData
val canStartAudioDumpLiveData: LiveData<Boolean> = _canStartAudioDumpLiveData

private val _incomingListenerLiveData = MutableLiveData<Call?>()
val incomingListenerLiveData: LiveData<Call?> = _incomingListenerLiveData
Expand Down Expand Up @@ -279,6 +284,9 @@ class WebexViewModel(val webex: Webex, val repository: WebexRepository) : BaseVi
repository._startAssociationLiveData = _startAssociationLiveData
repository._startShareLiveData = _startShareLiveData
repository._stopShareLiveData = _stopShareLiveData
repository._startAudioDumpLiveData = _startAudioDumpLiveData
repository._stopAudioDumpLiveData = _stopAudioDumpLiveData
repository._canStartAudioDumpLiveData = _canStartAudioDumpLiveData
}

fun setLogLevel(logLevel: String) {
Expand Down Expand Up @@ -1458,4 +1466,42 @@ class WebexViewModel(val webex: Webex, val repository: WebexRepository) : BaseVi
repository.printObservers(writer)
}

fun startAudioDump() {
getCall(currentCallId.orEmpty())?.startRecordingAudioDump(KitchenSinkApp.applicationContext()) {
if (it.isSuccessful) {
Log.d(tag, "[AudioDump] startAudioDump successful")
} else {
Log.d(tag, "[AudioDump] startAudioDump error: ${it.error?.errorMessage}")
}
_startAudioDumpLiveData.postValue(it.isSuccessful)
}
}

fun stopAudioDump() {
getCall(currentCallId.orEmpty())?.stopRecordingAudioDump() {
if (it.isSuccessful) {
Log.d(tag, "[AudioDump] stopAudioDump successful")
} else {
Log.d(tag, "[AudioDump] stopAudioDump error: ${it.error?.errorMessage}")
}
_stopAudioDumpLiveData.postValue(it.isSuccessful)
}

}

fun canStartRecordingAudioDump() {
getCall(currentCallId.orEmpty())?.canStartRecordingAudioDump {
if (it.isSuccessful) {
Log.d(tag, "[AudioDump] canStartRecordingAudioDump successful")
} else {
Log.d(tag, "[AudioDump] canStartRecordingAudioDump error: ${it.error?.errorMessage}")
}
_canStartAudioDumpLiveData.postValue(it.isSuccessful)
}
}


fun isRecordingAudioDump(): Boolean {
return getCall(currentCallId.orEmpty())?.isRecordingAudioDump() ?: false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class CallBottomSheetFragment(val showIncomingCallsClickListener: (Call?) -> Uni
val sendDTMFClickListener: (Call?) -> Unit,
val claimHostClickListener: () -> Unit,
val showBreakoutSessions: () -> Unit,
val closedCaptionOptions: (Call?) -> Unit): BottomSheetDialogFragment() {
val closedCaptionOptions: (Call?) -> Unit,
val startAudioDumpListener: () -> Unit): BottomSheetDialogFragment() {
companion object {
val TAG = "CallBottomSheetFragment"
}
Expand Down Expand Up @@ -227,6 +228,11 @@ class CallBottomSheetFragment(val showIncomingCallsClickListener: (Call?) -> Uni
closedCaptionOptions(call)
}

startAudioDump.setOnClickListener {
dismiss()
startAudioDumpListener()
}

cancel.setOnClickListener { dismiss() }
}.root
}
Expand Down
Loading

0 comments on commit 773f129

Please sign in to comment.