-
Notifications
You must be signed in to change notification settings - Fork 170
VIDCS-3882: ConnectionServices Kotlin sample #548
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
base: main
Are you sure you want to change the base?
Changes from all commits
4d3115d
3447aa0
fec8c03
97e9b3e
1293111
6f2e47b
8891b9a
d016bef
d3ee306
49a2063
786503c
b2912d8
bf050b0
6c912c9
a8c1f8b
1b5df9e
d8f6833
a21bb73
d6368ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: Build Basic-Video-Chat-ConnectionService-Kotlin | ||
|
||
on: | ||
push: | ||
branches: [main] # Just in case main was not up to date while merging PR | ||
pull_request: | ||
types: [opened, synchronize] | ||
|
||
jobs: | ||
run: | ||
continue-on-error: true | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set up JDK | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: 17 | ||
|
||
- name: Build | ||
run: cd Basic-Video-Chat-ConnectionService-Kotlin && ./gradlew app:assembleRelease && cd .. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
*.iml | ||
.gradle | ||
/local.properties | ||
/.idea/caches | ||
/.idea/libraries | ||
/.idea/modules.xml | ||
/.idea/workspace.xml | ||
/.idea/navEditor.xml | ||
/.idea/assetWizardSettings.xml | ||
.DS_Store | ||
/captures | ||
.externalNativeBuild | ||
.cxx | ||
local.properties | ||
app/build | ||
|
||
.settings/ | ||
app/jniLibs/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
plugins { | ||
alias(libs.plugins.android.application) | ||
alias(libs.plugins.kotlin.android) | ||
alias(libs.plugins.kotlin.compose) | ||
alias(libs.plugins.ksp) | ||
alias(libs.plugins.google.dagger.hilt) | ||
} | ||
|
||
android { | ||
namespace = "com.vonage.basic_video_chat_connectionservice" | ||
compileSdk = 36 | ||
|
||
defaultConfig { | ||
applicationId = "com.vonage.basic_video_chat_connectionservice" | ||
minSdk = 24 | ||
targetSdk = 36 | ||
versionCode = 1 | ||
versionName = "1.0" | ||
|
||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
isMinifyEnabled = false | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility = JavaVersion.VERSION_11 | ||
targetCompatibility = JavaVersion.VERSION_11 | ||
} | ||
kotlinOptions { | ||
jvmTarget = "11" | ||
} | ||
buildFeatures { | ||
compose = true | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation(libs.androidx.core.ktx) | ||
implementation(libs.androidx.lifecycle.runtime.ktx) | ||
implementation(libs.androidx.activity.compose) | ||
implementation(platform(libs.androidx.compose.bom)) | ||
implementation(libs.androidx.ui) | ||
implementation(libs.androidx.ui.graphics) | ||
implementation(libs.androidx.ui.tooling.preview) | ||
implementation(libs.androidx.material3) | ||
testImplementation(libs.junit) | ||
androidTestImplementation(libs.androidx.junit) | ||
androidTestImplementation(libs.androidx.espresso.core) | ||
androidTestImplementation(platform(libs.androidx.compose.bom)) | ||
androidTestImplementation(libs.androidx.ui.test.junit4) | ||
debugImplementation(libs.androidx.ui.tooling) | ||
debugImplementation(libs.androidx.ui.test.manifest) | ||
|
||
implementation(libs.hilt.android) | ||
ksp(libs.hilt.compiler) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
<uses-permission android:name="android.permission.CAMERA" /> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.RECORD_AUDIO" /> | ||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> | ||
<uses-permission android:name="android.permission.WAKE_LOCK" /> | ||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> | ||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> | ||
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> | ||
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> | ||
<uses-permission android:name="android.permission.CALL_PHONE" /> | ||
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> | ||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" /> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" /> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let;s also add Bluetooth permission There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have just checked and with the current foreground permissions bluetooth audio devices keep connected and working in the background. |
||
|
||
<uses-feature android:name="android.hardware.camera" /> | ||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> | ||
<uses-feature android:name="android.hardware.telephony" android:required="false" /> | ||
|
||
<application | ||
android:name=".MyApp" | ||
android:allowBackup="true" | ||
android:dataExtractionRules="@xml/data_extraction_rules" | ||
android:fullBackupContent="@xml/backup_rules" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.BasicVideoChatConnectionServiceKotlin"> | ||
<activity | ||
android:name=".MainActivity" | ||
android:exported="true" | ||
android:theme="@style/Theme.BasicVideoChatConnectionServiceKotlin"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
|
||
<meta-data | ||
android:name="android.telecom.connectionService" | ||
android:value="com.vonage.basic_video_chat_connectionservice.connectionservice.VonageConnectionService"> | ||
</meta-data> | ||
|
||
<service | ||
android:name="com.vonage.basic_video_chat_connectionservice.connectionservice.VonageConnectionService" | ||
android:exported="true" | ||
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" | ||
android:foregroundServiceType="microphone|camera"> | ||
<intent-filter> | ||
<action android:name="android.telecom.ConnectionService" /> | ||
</intent-filter> | ||
</service> | ||
|
||
<receiver android:name="com.vonage.basic_video_chat_connectionservice.CallActionReceiver" | ||
android:exported="true"> | ||
<intent-filter> | ||
<action android:name="com.tokbox.sample.basicvideochatconnectionservice.ACTION_ANSWER_CALL" /> | ||
<action android:name="com.tokbox.sample.basicvideochatconnectionservice.ACTION_REJECT_CALL" /> | ||
<action android:name="com.tokbox.sample.basicvideochatconnectionservice.ACTION_END_CALL" /> | ||
</intent-filter> | ||
</receiver> | ||
</application> | ||
|
||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.vonage.basic_video_chat_connectionservice | ||
|
||
data class Call( | ||
val callID: Int, | ||
val name: String, | ||
val state: CallState | ||
) | ||
|
||
enum class CallState { | ||
IDLE, | ||
CONNECTING, | ||
DIALING, | ||
ANSWERING, | ||
CONNECTED, | ||
HOLDING, | ||
DISCONNECTED | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.vonage.basic_video_chat_connectionservice | ||
|
||
import android.content.BroadcastReceiver | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.util.Log | ||
import com.vonage.basic_video_chat_connectionservice.connectionservice.VonageConnectionHolder | ||
|
||
class CallActionReceiver : BroadcastReceiver() { | ||
override fun onReceive(context: Context, intent: Intent?) { | ||
if (intent != null && intent.action != null) { | ||
val action = intent.action | ||
when (action) { | ||
ACTION_ANSWER_CALL -> { | ||
Log.d(TAG, "Action: Answer call") | ||
answerCall() | ||
} | ||
|
||
ACTION_REJECT_CALL -> { | ||
Log.d(TAG, "Action: Reject call") | ||
rejectCall() | ||
} | ||
|
||
ACTION_END_CALL -> { | ||
Log.d(TAG, "Action: End call") | ||
endCall() | ||
} | ||
|
||
else -> Log.w( | ||
TAG, | ||
"Unknown action: $action" | ||
) | ||
} | ||
} | ||
} | ||
|
||
private fun answerCall() { | ||
VonageConnectionHolder.connection?.onAnswer() | ||
} | ||
|
||
private fun rejectCall() { | ||
VonageConnectionHolder.connection?.onReject() | ||
} | ||
|
||
private fun endCall() { | ||
VonageConnectionHolder.connection?.onDisconnect() | ||
} | ||
|
||
companion object { | ||
private const val TAG = "CallActionReceiver" | ||
|
||
const val ACTION_ANSWER_CALL: String = | ||
"com.tokbox.sample.basicvideochatconnectionservice.ACTION_ANSWER_CALL" | ||
const val ACTION_REJECT_CALL: String = | ||
"com.tokbox.sample.basicvideochatconnectionservice.ACTION_REJECT_CALL" | ||
const val ACTION_END_CALL: String = | ||
"com.tokbox.sample.basicvideochatconnectionservice.ACTION_END_CALL" | ||
|
||
const val ACTION_ANSWER_CALL_ID: Int = 2 | ||
const val ACTION_REJECT_CALL_ID: Int = 3 | ||
const val ACTION_END_CALL_ID: Int = 4 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package com.vonage.basic_video_chat_connectionservice | ||
|
||
class CallException(message: String, val code: Int = 0) : Exception(message) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.vonage.basic_video_chat_connectionservice | ||
|
||
import android.view.View | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.asStateFlow | ||
|
||
class CallHolder { | ||
private val _callFlow = MutableStateFlow<Call?>(null) | ||
val callFlow: Flow<Call?> = _callFlow.asStateFlow() | ||
|
||
private val _callStateFlow = MutableStateFlow(CallState.IDLE) | ||
val callStateFlow: Flow<CallState> = _callStateFlow.asStateFlow() | ||
|
||
private val subscriberMap = mutableMapOf<String, View>() | ||
|
||
private val _publisherViewFlow = MutableStateFlow<View?>(null) | ||
val publisherViewFlow: Flow<View?> = _publisherViewFlow.asStateFlow() | ||
|
||
private val _subscriberViewFlow = MutableStateFlow<List<View>>(emptyList()) | ||
val subscriberViewFlow: Flow<List<View>> = _subscriberViewFlow.asStateFlow() | ||
|
||
fun setCall(call: Call?) { | ||
_callFlow.value = call | ||
} | ||
|
||
fun updateCallState(state: CallState) { | ||
_callStateFlow.value = state | ||
} | ||
|
||
fun setPublisherView(view: View?) { | ||
_publisherViewFlow.value = view | ||
} | ||
|
||
fun addSubscriberView(streamId: String, view: View) { | ||
subscriberMap[streamId] = view | ||
|
||
_subscriberViewFlow.value = subscriberMap.values.toList() | ||
} | ||
|
||
fun removeSubscriberView(streamId: String) { | ||
subscriberMap.remove(streamId) | ||
|
||
_subscriberViewFlow.value = subscriberMap.values.toList() | ||
} | ||
|
||
fun clear() { | ||
_callFlow.value = null | ||
_callStateFlow.value = CallState.IDLE | ||
subscriberMap.clear() | ||
_publisherViewFlow.value = null | ||
_subscriberViewFlow.value = emptyList() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed, already ignored in parent gitignore.
you could remove this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After ignoring the /build I see a problems-report-html of the build folder. It may be better to leave it?