Skip to content

Commit

Permalink
Merge pull request #564 from 100mslive/dev
Browse files Browse the repository at this point in the history
dev to release
  • Loading branch information
PratimMallick authored Dec 15, 2023
2 parents f9f6928 + a42f580 commit f41f1d6
Show file tree
Hide file tree
Showing 25 changed files with 373 additions and 373 deletions.
193 changes: 35 additions & 158 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,171 +19,48 @@ Sample App of 100ms can be downloaded from Play store : https://play.google.com/

Meeting links can be generated using [dashboard](https://dashboard.100ms.live/)

## ☝️ Pre-requisites

- Android Studio 3.0 or higher
- Support for Android API level 24 or higher
- Support for Java 8
- This application uses build tool version `30.0.2`

## 📱 Supported Devices

The Android SDK supports Android API level 21 and higher. It is built for armeabi-v7a, arm64-v8a, x86, and x86_64 architectures.

## 🚂 Setup Guide

- Clone this repository

```bash
git clone --depth 1 https://github.com/100mslive/sample-app-android.git
## 📦 Prebuilt (Room Kit)

Room Kit is library built to take even building the UI off your hands. It uses 100ms SDK to and a dynamic layout decided by Prebuilt in the dashboard to have fully functional video up and running in your app in minutes.
To add the library to your own app, take a look at the [Prebuilt Quickstart](https://www.100ms.live/docs/android/v2/quickstart/prebuilt-android) in the docs.

#### 🛠️ Developing against Prebuilt Room Kit
We don't intend this to be a very common as Room Kit is updated very frequently with new features but the benefit of open source is that if you don't like how something works you can change it yourself! If you wanted to change anything in the Prebuilt library here's how.
1. Clone this repo.
2. Find the line in `app/build.gradle` that says `implementation "live.100ms:room-kit:$HMS_ROOM_KIT_VERSION"` and change it to
``implementation project(":room-kit")``
3. Run the app.

Now you'll be loading the room kit library locally with your own changes rather than from the maven library that 100ms publishes to.

To use this in your own code, you can put the library in your local computer and import it in your app.
To put the room kit library in your computer as a library locally:
1. Open a terminal and cd into the root of this project. Opening the terminal from Android Studio works as well.
2. Run the following command to build and put the library in your local storage. `./gradlew clean publishToMavenLocal`
3. Verify the library was built correctly by seeing if it is in `ls ~/.m2/repository/live/100ms/room-kit`
4. In your app find where the `mavenCentral()` repository is referenced and add `mavenLocal()` before it. Eg:
```
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
```

- Get your token generation endpoint [by following this guide](https://docs.100ms.live/server-side/v2/foundation/authentication-and-tokens)

- Create `app/gradle.properties`

```bash
cp app/example.gradle.properties app/gradle.properties
```

- Put your endpoint URL as `TOKEN_ENDPOINT` in `app/gradle.properties`. Make sure it ends with a backslash (`/`) For example:
```env
TOKEN_ENDPOINT="https://prod-in.100ms.live/hmsapi/<your-subdomain>/" # Valid
TOKEN_ENDPOINT="https://prod-in.100ms.live/hmsapi/<your-subdomain>" # Invalid
```
- Create [firebase project](https://firebase.google.com/docs/android/setup#console) and save the [`google-services.json`](https://support.google.com/firebase/answer/7015592?hl=en) in `app/google-services.json`

## 🏎 Run the application

### 🤖 Run using Emulator

Follow the official guide at [developers.android.com](https://developer.android.com/studio/run/emulator) to download and deploying app in a emulator.

### 📱 Run on Device (**recommended**)

Follow the official guide at [developers.android.com](https://developer.android.com/studio/run/device) to setup your mobile device for development.

On the first time of launch, user will be prompted with permissions. Then you are good to go to run the application.

## 🏞 Layout

In the launch screen, here we have `Enter Name` and `Join Room`:

We have many examples for each mode in the sample app using [`RecyclerView`](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView), [`ViewPage2`](https://developer.android.com/jetpack/androidx/releases/viewpager2), [`LiveData](https://developer.android.com/topic/libraries/architecture/livedata) handling all data the right way with smooth updates.

### 📞 Join meeting

- Paste the exact Room ID as obtained after signing up for the [100ms Dashboard] (https://dashboard.100ms.live/register)

- Click `Join Now`.
- Video Conversation will be started 🎉
5. Add the import for `room kit` as you would do for any library `implementation "live.100ms:room-kit:$HMS_ROOM_KIT_VERSION"`

<img src="assets/home-page.jpg?raw=true" width="300">
That's it. Once you sync, the library should be available to your app.
This is the recommended method since adding the module to your own app directly would make it difficult to sync with our changes.

### Active Speaker Mode

Shows the most actively speaking `Peer`'s in the room. Max number of peer's to be displayed can be configured be `Max Rows` and `Max Columns` setting in the Home Page.

Each `Peer`'s VideoTile shows following updates in real-time:

1. Blue border if speaking at that moment
2. Audio/Video track's mute/unmute status
3. Live Updates of `Peer`'s joining and leaving

Related classes/files in this app:
1. [`ActiveSpeakerFragment`](app/src/main/java/live/hms/app2/ui/meeting/activespeaker/ActiveSpeakerFragment.kt)
2. [`ActiveSpeakerLRU`](app/src/main/java/live/hms/app2/ui/meeting/activespeaker/ActiveSpeakerLRU.kt)
3. [`fragment_active_speaker.xml`](app/src/main/res/layout/fragment_active_speaker.xml)
4. [`video_card.xml`](app/src/main/res/layout/video_card.xml)

<p>
<img src="assets/active-speaker-screen-share.gif" width="300"/>
<img src="assets/active-speaker.gif" width="300"/>
</p>

### 🎵 Audio Only Mode

Groups all `Peer`'s by their `Peer::role` and shows them using a nested `RecyclerView`:

Each `Peer`'s AudioTile shows following updates in real-time:

1. Blue border if speaking at that moment
2. Audio/Video track's mute/unmute status
3. Live Updates of `Peer`'s joining and leaving

Related classes/files in this app:
1. [`AudioCollection`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioCollection.kt)
2. [`AudioCollectionAdapter`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioCollectionAdapter.kt)
3. [`AudioCollectionDiffUtil`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioCollectionDiffUtil.kt)
4. [`AudioItem`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioItem.kt)
5. [`AudioItemsAdapter`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioItemsAdapter.kt)
6. [`AudioItemsDiffUtil`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioItemsDiffUtil.kt)
7. [`AudioModeFragment`](app/src/main/java/live/hms/app2/ui/meeting/audiomode/AudioModeFragment.kt)
8. [`fragment_audio.xml`](app/src/main/res/layout/fragment_audio.xml)
9. [`list_item_audio.xml`](app/src/main/res/layout/list_item_audio.xml)
10. [`list_item_chat.xml`](app/src/main/res/layout/list_item_chat.xml)

<p>
<img src="assets/audio-only-mode.gif" width="300">
<img src="assets/audio-only-large-room.gif" width="300">
</p>

### 📚 Grid View

Show's all `Peer`'s in a 2x2 (default) Grid paginated using a `ViewPager`.

Each `Peer`'s VideoTile shows following updates in real-time:

1. Blue border if speaking at that moment
2. Audio/Video track's mute/unmute status
3. Live Updates of `Peer`'s joining and leaving
4. Subscribes/Unsubscribe videos which are not visible in the viewport
5. Handles updating the peer tracks status and peer-list smoothly without causing any re-renders

Related classes/files in this app:
1. [`VideoGridBaseFragment`](app/src/main/java/live/hms/app2/ui/meeting/commons/VideoGridBaseFragment.kt)
2. [`VideoGridAdapter`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridAdapter.kt)
3. [`VideoGridFragment`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridFragment.kt)
4. [`VideoGridPageFragment`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridPageFragment.kt)
5. [`VideoGridPageItem`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridPageItem.kt)
6. [`VideoGridPageDiffUtil`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridPagerDiffUtil.kt)
7. [`VideoGridPageViewModel`](app/src/main/java/live/hms/app2/ui/meeting/videogrid/VideoGridPageViewModel.kt)
8. [`fragment_video_grid_page.xml`](app/src/main/res/layout/fragment_video_grid_page.xml)
9. [`fragment_grid_video.xml`](app/src/main/res/layout/fragment_grid_video.xml)
10. [`grid_item_video.xml`](app/src/main/res/layout/grid_item_video.xml)

<img src="assets/grid-view.gif" width="300"/>

### 🙋🙋‍♀️ Hero View (experimental support 🧪)

Allows pinning any `Peer` video tile by clicking on respective `Peer`'s VideoTile from the
bottom tray. The bottom tray is implemented using a `RecyclerView`

Related classes/files in this app:
1. [`PinnedVideoFragment`](app/src/main/java/live/hms/app2/ui/meeting/pinnedvideo/PinnedVideoFragment.kt)
2. [`VideoListAdapter`](app/src/main/java/live/hms/app2/ui/meeting/participants/VideoListAdapter.kt)
3. [`VideoListItem`](app/src/main/java/live/hms/app2/ui/meeting/pinnedvideo/VideoListItem.kt)
4. [`VideoListItemDiffUtil`](app/src/main/java/live/hms/app2/ui/meeting/pinnedvideo/VideoListItemDiffUtil.kt)
5. [`fragment_pinned_video.xml`](app/src/main/res/layout/fragment_pinned_video.xml)
6. [`fragment_pinned_video.xml`](app/src/main/res/layout-land/fragment_pinned_video.xml)
7. [`list_item_video.xml`](app/src/main/res/layout/list_item_video.xml)

<img src="assets/hero-view.gif" width="300"/>
## ☝️ Pre-requisites

### ✋ Participant List View
- Android Studio
- Support for Java 11

Shows a list of all `Peer`'s in the room.
1. Entire list can be filter by `name` of the `Peer`
2. Updates the list in real-time as `Peer`'s joins/leaves
2. Show real-time status of `Peer` tracks and screen-share
## 📱 Supported Devices

Related classes/files in this app:
1. [`ParticipantsAdapter`](app/src/main/java/live/hms/app2/ui/meeting/participants/ParticipantsAdapter.kt)
2. [`ParticipantsFragment`](app/src/main/java/live/hms/app2/ui/meeting/participants/ParticipantsFragment.kt)
3. [`fragment_participants.xml`](app/src/main/res/layout/fragment_participants.xml)
4. [`list_item_peer_list.xml`](app/src/main/res/layout/list_item_peer_list.xml)

<img src="assets/participants-list.gif" width="300"/>
The Android SDK supports Android API level 21 and higher. It is built for armeabi-v7a, arm64-v8a, x86, and x86_64 architectures.

## 📑 100ms SDK Documentation

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ kotlin.code.style=official
100MS_APP_VERSION_CODE=643
100MS_APP_VERSION_NAME=5.8.872
hmsRoomKitGroup=live.100ms
HMS_ROOM_KIT_VERSION=1.1.6
HMS_ROOM_KIT_VERSION=1.1.7
android.suppressUnsupportedCompileSdk=33
2 changes: 1 addition & 1 deletion room-kit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.percentlayout:percentlayout:1.0.0'

def hmsVersion = "2.8.2"
def hmsVersion = "2.8.4"
// To add dependencies of specific module
implementation "live.100ms:android-sdk:$hmsVersion"
implementation "live.100ms:video-view:$hmsVersion"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package live.hms.roomkit.ui.meeting

import android.graphics.PorterDuff
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
Expand All @@ -15,6 +16,9 @@ import live.hms.roomkit.databinding.DialogTrackSelectionBinding
import live.hms.roomkit.util.viewLifecycle
import live.hms.hls_player.HmsHlsPlayer
import live.hms.hls_player.HmsHlsLayer
import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.getColorOrDefault
import live.hms.roomkit.ui.theme.trackTintList


class HlsVideoQualitySelectorBottomSheet(
Expand All @@ -34,6 +38,32 @@ class HlsVideoQualitySelectorBottomSheet(

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.root.setBackgroundColor(getColorOrDefault(
HMSPrebuiltTheme.getColours()?.backgroundDefault,
HMSPrebuiltTheme.getDefaults().background_default))

binding.startConversationTv.setTextColor(
getColorOrDefault(
HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
HMSPrebuiltTheme.getDefaults().onsurface_high_emp
)
)


binding.closeBtn.drawable.setTint(
getColorOrDefault(
HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
HMSPrebuiltTheme.getDefaults().onsurface_high_emp
)
)

binding.divider.setBackgroundColor(
getColorOrDefault(
HMSPrebuiltTheme.getColours()?.borderDefault,
HMSPrebuiltTheme.getDefaults().border_bright
)
)

dialog?.let {
val sheet = it as BottomSheetDialog
sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
Expand All @@ -51,7 +81,7 @@ class HlsVideoQualitySelectorBottomSheet(
is HmsHlsLayer.LayerInfo -> {
addTrackView("${layer.resolution.height}", index, currentLayer == layer) {
hlsPlayer.setHmsHlsLayer(layer)
dismiss()
dismissAllowingStateLoss()
}
}
}
Expand All @@ -61,7 +91,7 @@ class HlsVideoQualitySelectorBottomSheet(
private fun addAutoView(isSelected : Boolean) {
addTrackView("Auto",-1,isSelected) {
hlsPlayer.setHmsHlsLayer(HmsHlsLayer.AUTO)
dismiss()
dismissAllowingStateLoss()
}
}

Expand All @@ -70,12 +100,26 @@ class HlsVideoQualitySelectorBottomSheet(
val trackView = LayoutInflater.from(requireContext())
.inflate(R.layout.track_selection_view, null, false)

trackView.findViewById<TextView>(R.id.track_label).text = "$title"
trackView.findViewById<RadioButton>(R.id.track_radio_btn).isChecked = isSelected
trackView.findViewById<TextView>(R.id.track_label).apply {
setTextColor(
getColorOrDefault(
HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
HMSPrebuiltTheme.getDefaults().onsurface_high_emp
)
)
text = "$title"
}

trackView.findViewById<RadioButton>(R.id.track_radio_btn).apply {
buttonTintList = trackTintList()
isChecked = isSelected
}

trackView.setOnClickListener {
onSelectedListener.invoke(index)
}


binding.trackViewsParent.addView(trackView)
}
}
Loading

0 comments on commit f41f1d6

Please sign in to comment.