Skip to content

Commit

Permalink
Merge pull request #234 from shogo4405/feature/compose-playback
Browse files Browse the repository at this point in the history
Support jetpack compose module.
  • Loading branch information
shogo4405 authored Mar 28, 2024
2 parents c9b84b7 + 506454d commit 210807c
Show file tree
Hide file tree
Showing 12 changed files with 270 additions and 78 deletions.
37 changes: 29 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
plugins {
id 'com.android.application'
id "org.jetbrains.kotlin.android"
id 'kotlin-kapt'
}

android {
namespace 'com.haishinkit.app'

compileSdk 34

compileOptions {
Expand All @@ -22,10 +27,13 @@ android {
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
buildFeatures {
buildConfig = true
}
}

buildFeatures {
compose true
buildConfig = true
}

buildTypes {
release {
minifyEnabled false
Expand All @@ -37,15 +45,27 @@ android {
lint {
abortOnError false
}
namespace 'com.haishinkit.app'
composeOptions {
kotlinCompilerExtensionVersion = "1.5.11"
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "com.airbnb.android:lottie:6.4.0"
// compose
implementation platform('androidx.compose:compose-bom:2024.03.00')
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material:material'
implementation 'androidx.compose.foundation:foundation'
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-tooling-preview'
debugImplementation 'androidx.compose.ui:ui-tooling'
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-test-manifest'

implementation 'com.google.android.material:material:1.11.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
implementation 'androidx.compose.ui:ui-android:1.6.4'
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
Expand All @@ -54,6 +74,7 @@ dependencies {
implementation project(':haishinkit')
implementation project(':lottie')
implementation project(':vulkan')
implementation project(':compose')
testImplementation 'junit:junit:4.13.2'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.13'
}
Expand Down
54 changes: 54 additions & 0 deletions app/src/main/java/com/haishinkit/app/PlaybackScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.haishinkit.app

import android.util.Log
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.haishinkit.compose.HaishinKitView
import com.haishinkit.compose.rememberConnectionState
import com.haishinkit.compose.rememberStreamState
import com.haishinkit.rtmp.RtmpConnection

@Composable
fun PlaybackScreen(
command: String,
streamName: String,
modifier: Modifier
) {
val connectionState = rememberConnectionState()
val streamState = rememberStreamState(
context = LocalContext.current,
connectionState = connectionState,
connectionStateChange = { stream, data ->
val code = data["code"].toString()
if (code == RtmpConnection.Code.CONNECT_SUCCESS.rawValue) {
stream.play(streamName)
}
}
)
Box(modifier = modifier) {
HaishinKitView(
streamState = streamState,
modifier = Modifier.fillMaxSize()
)
Button(
modifier = Modifier
.width(100.dp)
.height(50.dp),
onClick = {
Log.w(TAG, "GO LIVE!!")
connectionState.connect(command)
}) {
Text("GO LIVE")
}
}
}

private const val TAG = "PlaybackScreen"
82 changes: 12 additions & 70 deletions app/src/main/java/com/haishinkit/app/PlaybackTabFragment.kt
Original file line number Diff line number Diff line change
@@ -1,87 +1,29 @@
package com.haishinkit.app

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import com.haishinkit.event.Event
import com.haishinkit.event.EventUtils
import com.haishinkit.event.IEventListener
import com.haishinkit.graphics.VideoGravity
import com.haishinkit.media.StreamView
import com.haishinkit.rtmp.RtmpConnection
import com.haishinkit.rtmp.RtmpStream

class PlaybackTabFragment : Fragment(), IEventListener {
private lateinit var connection: RtmpConnection
private lateinit var stream: RtmpStream
private lateinit var playbackView: StreamView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

connection = RtmpConnection()
stream = RtmpStream(requireContext(), connection)

connection.addEventListener(Event.RTMP_STATUS, this)
}

@SuppressLint("SetTextI18n")
class PlaybackTabFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

val v = inflater.inflate(R.layout.fragment_playback, container, false)
val button = v.findViewById<Button>(R.id.button)
button.setOnClickListener {
if (button.text == "Play") {
connection.connect(Preference.shared.rtmpURL)
button.text = "Stop"
} else {
connection.close()
button.text = "Play"
): View {
return ComposeView(requireContext()).apply {
setContent {
PlaybackScreen(
command = Preference.shared.rtmpURL,
streamName = Preference.shared.streamName,
modifier = Modifier.fillMaxSize()
)
}
}

playbackView = if (Preference.useSurfaceView) {
v.findViewById(R.id.surfaceView)
} else {
v.findViewById(R.id.textureView)
}
playbackView.videoGravity = VideoGravity.RESIZE_ASPECT
playbackView.attachStream(stream)

return v
}

override fun onResume() {
super.onResume()
stream.receiveVideo = true
}

override fun onPause() {
super.onPause()
stream.receiveVideo = false
}

override fun onDestroy() {
super.onDestroy()
connection.dispose()
}

override fun handleEvent(event: Event) {
Log.i("$TAG#handleEvent", event.toString())
val data = EventUtils.toMap(event)
val code = data["code"].toString()
if (code == RtmpConnection.Code.CONNECT_SUCCESS.rawValue) {
stream.play(Preference.shared.streamName)
}
}

companion object {
Expand Down
1 change: 1 addition & 0 deletions compose/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
48 changes: 48 additions & 0 deletions compose/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}

android {
namespace 'com.haishinkit.compose'
compileSdk 34

defaultConfig {
minSdk 21

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.11"
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
}

dependencies {
api project(':haishinkit')
implementation platform('androidx.compose:compose-bom:2024.03.00')
implementation 'androidx.compose.foundation:foundation:1.6.4'
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
Empty file added compose/consumer-rules.pro
Empty file.
21 changes: 21 additions & 0 deletions compose/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
4 changes: 4 additions & 0 deletions compose/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
26 changes: 26 additions & 0 deletions compose/src/main/java/com/haishinkit/compose/ConnectionState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.haishinkit.compose

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.haishinkit.rtmp.RtmpConnection
import com.haishinkit.rtmp.RtmpStream

@Composable
fun rememberConnectionState(): ConnectionState = remember { ConnectionState() }.apply {

}

class ConnectionState {
internal val connection: RtmpConnection by lazy {
RtmpConnection()
}

fun connect(command: String) {
connection.connect(command)
}

internal fun createStream(context: Context): RtmpStream {
return RtmpStream(context, connection)
}
}
24 changes: 24 additions & 0 deletions compose/src/main/java/com/haishinkit/compose/HaishinKitView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.haishinkit.compose

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import com.haishinkit.graphics.VideoGravity
import com.haishinkit.view.HkSurfaceView

@Composable
fun HaishinKitView(
streamState: StreamState,
modifier: Modifier = Modifier,
videoGravity: VideoGravity = VideoGravity.RESIZE_ASPECT
) {
AndroidView(
factory = {
HkSurfaceView(it).apply {
this.videoGravity = videoGravity
attachStream(streamState.stream)
}
},
modifier = modifier
)
}
Loading

0 comments on commit 210807c

Please sign in to comment.