Android SDK

Setup

Our Android SDK is hosted as a GitHub package here: https://github.com/hotmic-wp/android-sdkο»Ώ

Make sure when installing that you follow this guide:

In the build.gradle (root), add the following repositories

JSON
|
  • For the personal access token, granting the read: packages permission should be enough
  • In the build.gradle(app), include the following dependency: `implementation 'io.hotmic.player:hotmic-android-sdk:1.4.1'`
  • Minimum SDK version of the player SDK is 21
  • Compile / Target SDK version of the player SDK is 30

ο»Ώο»ΏCode Integration

The player screen in the SDK is implemented as a fragment:

  • Single Activity: If you have a single activity app, then the player fragment can be launched in the desired layout container.
  • Separate Activity: In case you want to launch the player in its own separate activity then you can create the activity in your app and then load the fragment into it

ο»Ώο»ΏPre-Requisites

You will need an API_KEY that has been generated specifically for your application. In case you do not have this, please contact the HotMic team.

ο»Ώο»ΏFetch Streams

For fetching all streams to be listed to the user, call the below code:

Kotlin
|

The data will be returned as a list of HMStreamBasic Objects:

Field

Description

Id

Id of the stream. If the user taps on this listing, then pass this param as the stream id

userId

Uid of the user who is hosting this stream

state

SCHEDULED – The stream has been scheduled but is yet to live

LIVE – The stream is live

VOD – The stream is a past recording

ENDED – The stream has ended (you will not be getting this state in this list)

type

broadcast – The stream is a broadcast

audio_room – The stream is an audio room

watch_party – The stream is a video watch party

title

Title of this stream

thumbnail

An image url of the program thumbnail

scheduledDate

Timestamp of when this program is scheduled to start

viewers

Number of viewers who are currently watching this stream

visitors

Number of users who have visited this stream

eventId

Id of the event to which the stream belongs to

featuredAttendees

List of image uris, each pointing to the profile photo of someone who is viewing/visiting this stream

user

User object holding the information of the host of this stream (name, profile_url)

ο»Ώο»ΏStarting the Player

When the user taps on any of the listed stream, the app can then show the stream player using the following code:

Kotlin
|
  • setStreamId - Mandatory – Sets the stream id (stream.id of the listing the user chose)
  • setUICallback – Mandatory – Provide the callback interface that the SDk will use for fetching certain information, for notifying certain events, or to complete flows that only your app code can handle
  • credential – Mandatory – Provide the api-key
  • setAnalyticHandler – Optional – Provide the analytic callback interface which will be called by SDK whenever an analytic event occurs. The app code can then log the event as necessary
  • show – Starts the player screen. Provide the layout container resource id, where the player fragment needs to be launched into

ο»Ώο»ΏClosing the Player

If the app wants to close the player, then call:

Kotlin
|
  • reason - Analytic reason for the player closure, probable values will be USER_CLOSED, SIGNOUT

Once the player is closed, the SDK will make a call back on PlayerCallback.onPlayerClosed().

The SDK also might trigger a player closure. This may be in response to events like stream getting over, error in fetching the stream or the user leaving the stream from the player. Once the player is closed, the SDK will make a call back to PlayerCallback.onPlayerClosed().

ο»Ώο»ΏHandling Back Press

If the user taps the device back key, and if the player is open, then the app should call:

HotMicPlayer.handleBackKeyPress(activity): Boolean

If the player consumes the key press (say for dismissing an overlay/dialog), then it will return true. The app should not handle the back press in this scenario. Else this will return false, and the app can handle the back press as it wants to.

ο»Ώο»ΏIs the Player open?

The app can check if the player is open in multiple ways. It can check with the sdk by calling:

HotMicPlayer.isPlayerOpen(activity)

Or it can check whether a fragment is loaded in the ui player container:

supportFragmentManager.findFragmentById(R.id.<player_fragment_container>)

ο»Ώο»ΏPicture-in-Picture (PIP) Mode

Picture in Picture Mode can be of two types:

  1. For a single activity app, showing the player fragment in a PIP when navigating to other fragments in the app. This is achieved by reducing the player fragment layout container to the desired size and moving it to the required location.
  2. Placing the app in the background by tapping the device Home button or by navigating to some other app

In both the cases the player has to resize itself so that in the PIP mode, the player displays just the video.

Also if the user taps on the PIP to get back to the expanded mode, the player will have to again change its UI to show all the layouts and controls.

To change the UI, manually (for scenario 1):

Kotlin
|
  • enable: Set it to true for the player to show the PIP mode UI, false if the player is coming out of PIP and being expanded
  • Returns true if the operation was success, false if the player is not open

For scenario 2 (android PIP mode), the player will change the UI itself, triggered by the android PIP callback. Note: this assumes that the activity has been enabled for PIP in the manifest. Refer https://developer.android.com/guide/topics/ui/picture-in-picture for more.

Also, for scenario 2, if the user closes the pip and at a later point of time returns to the app, then the app should show the UI with the player closed. To ensure this, add the below line in the activity onStart:

HotMicPlayer.checkPlayerStateOnStart(activity)

Displaying Ads

For displaying an ad, you can pass the view holding the ad (like the Google AdView) to the Player, using the following api:

Kotlin
|

It is assumed that the click interaction will be implemented in the view that is passed. The SDK is going to display the ad-banner with the passed view. The Ad will be displayed with an initial delay of 0 seconds, i.e., immediate, but this can be changed by passing a displayAfter value (in milliseconds). The Ad will be displayed for 10 seconds by default, this duration can also be changed by passing the right ttl value in the above function (in milliseconds)

If the ad is to be dismissed, before its auto removed, then the below api can be invoked

dismissHotMicAd(activity: FragmentActivity)

Styles

Text Styling

The below table lists the TextAppearance styles used in the app. The SDK does not have any fonts packaged with it, and hence the lack of font definitions in the below styles. You can change the appearance by defining the style with the same name in your app theme/style xml file

Style name

Current Definition

TextAppearance.HMPlayerHeadline4

<style name="TextAppearance.HMPlayerHeadline4" parent="TextAppearance.MaterialComponents.Headline4">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">24sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerHeadline5

<style name="TextAppearance.HMPlayerHeadline5" parent="TextAppearance.MaterialComponents.Headline5">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">20sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerHeadline6

<style name="TextAppearance.HMPlayerHeadline6" parent="TextAppearance.MaterialComponents.Headline6">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">16sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerBody1

<style name="TextAppearance.HMPlayerBody1" parent="TextAppearance.MaterialComponents.Body1">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">16sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerBody2

<style name="TextAppearance.HMPlayerBody2" parent="TextAppearance.MaterialComponents.Body2">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">14sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerBody

<style name="TextAppearance.HMPlayerBody3" parent="TextAppearance.MaterialComponents.Body2">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">14sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerButton

<style name="TextAppearance.HMPlayerButton" parent="TextAppearance.MaterialComponents.Button">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">16sp</item>

<item name="android:letterSpacing">0</item>

</style>

TextAppearance.HMPlayerOverline

<style name="TextAppearance.HMPlayerOverline" parent="TextAppearance.MaterialComponents.Overline">

<item name="android:textStyle">normal</item>

<item name="android:textAllCaps">false</item>

<item name="android:textSize">10sp</item>

<item name="android:letterSpacing">0</item>

</style>

Color Styling

The table below lists the colors used in the app, for both day and night modes. You can change the colors by defining colors with the same name in your colors xml file(s)

Color Style Name

Day

Night

hmp_colorPrimary

#F6F8FA

#121212

hmp_colorSecondary

#FFFFFF

#000000

hmp_colorTertiary

#FFFFFF

#222222

hmp_colorBackground

#FFFFFF

#000000

hmp_colorSurface

#FFFFFF

#121212

hmp_colorHighlight

#D1D1D5

#3A3A3C

ο»Ώ
ο»Ώ
ο»Ώ

hmp_textPrimary

#303234

#FFFFFF

hmp_textSecondary

#86898C

#999999

hmp_tintPrimary

#FF7106

#FF7106

hmp_tintPrimaryContrast

#C93400

#C93400

hmp_tintTertiary

#D0D3D7

#606060

hmp_tintTertiaryContrast

#76767B

#919198

hmp_tintError

#DB3B3C

#DB3B3C

hmp_tintWarning

#EDAC46

#EDAC46

hmp_tintSuccess

#53D973

#53D973

hmp_tintLive

#AD3632

#AD3632

hmp_divider

#D1D1D6

#38383A

ο»Ώ
ο»Ώ
ο»Ώ

hmp_textPrimaryDisabled

#80000000

#80FFFFFF

hmp_textMedia

#FFFFFF

#FFFFFF

hmp_tintDisabled

#90929F

#90929F

hmp_tintDisabled2

#20000000

#20000000

hmp_tintAction

#000000

#FFFFFF

hmp_pollSecondary

#CCCDCE

#A7A8AA

hmp_pollPercentage

#E2E2E3

#484B50

ο»Ώο»ΏPlayer Callback Interface

getPlatformToken

fun getPlatformToken(): String

The platform token is required by the SDK to authenticate any requests with the HotMic Server. The SDK expects the app to return the platform token through this callback. Note that the HotMic Server expects the token to be constructed in a certain format, please contact the HotMic team to learn more.

Params: None

Returns: Platform Token

onRequestBugReport

fun onRequestBugReport()

(OPTIONAL) User has requested to capture bug report. If the app is using any sort of bug capturing (like shake/instabug/etc), then trigger it

Params: None

onPlayerClosed

fun onPlayerClosed()

(OPTIONAL) Called after the player is closed. Player closure can be triggered by the sdk on certain events like stream over, error. Or it can be triggered by the app by calling HotMicPlayer.closePlayer

Params: None

fun getShareLink(context: Context, streamId: String): Observable<String>

(OPTIONAL) User has requested a share/invite message for a stream. The message would be then available to the user to share with others.

Params:

  • context
  • streamId – id of the stream for which the invite link is to be created

Returns: Observable with the message string

isFollowing (Depreciated prior to 1.4.1)

isFollowing was removed in version 1.4, do not use this moving forward. It was replaced with getFollowData.

fun isFollowing(uid: String): Boolean?

(OPTIONAL) If your application has feature to follow a user, then return true if the logged in user is following the user identified by the passed uid, return false if the user is not being followed. Default implementation is to return null, indicating that the follow feature is not available

Params:

  • uid – user id of the user who you may or may not be following

Returns: true if you are following the user, false if not following, null if the feature is not present

getFollowData

getFollowData replaces isFollowing in the current version.

fun getFollowData(uid: String): Observable<HMFollowData>?

(OPTIONAL) Return null or do not implement, if you do not support the follow feature. If implementing, then gather and return the follow information. This information includes,

  • Is the logged in user following the user identified by the passed uid
  • If the logged in user being followed by the specific user
  • How many followers does the specific user have
  • How many people does the specific user follow

Params:

  • uid – user id of the user whose follow information you need

Returns: An observable with the FollowData object. The observable will be invoked in the background by the implementation.

followUser

fun followUser(user: HMUserBasic, shouldFollow: Boolean): Observable<Unit>?

(OPTIONAL) Follow/Unfollow the passed user. Required only if you app is having the follow-user feature

Params:

  • user – User to be followed/unfollowed
  • shouldFollow – true if to be followed, false otherwise

Returns: Observable

onAdClick

fun onAdClick(streamId: String, adId: String)

(OPTIONAL) Called in the event of the user clicking on any advertisement banner on the player.

Params:

  • streamId – id of the stream being played
  • adId – id of the advertisement banner

Returns: Nothing

isBlockedByHost

fun isBlockedByHost(hostId: String): Observable<Boolean>?

(OPTIONAL) Return true in the observable if the host, identified by the host id has blocked the current logged in user from the stream. If true, then the user will not be able to send any chat message. Default implementation returns null, indicating no blocking

Params:

  • hostId – Uid of the host for the current stream being played

Returns: Observable with Boolean value, null will be treated as non-blocked

tipSkus

fun getTipSkus(): LiveData<List<AppSku>>

(OPTIONAL) Return the full list of billing products that is configured for tips in the app

Params: None

Returns: LiveData with the list of billings skus

makeTipPurchase

fun makeTipPurchase(activity: Activity,userId: String,hostId: String,streamId: String,streamType: String,message: String,anonymous: Boolean,appSkuDetail: AppSku)

(OPTIONAL) Make the Google billing purchase for when the user has opted to tip a certain amount in the stream

Params:

  • activity – Parent fragment activity of the player
  • userId – Unique id of the logged in user requesting the cameo
  • hostId – Unique id of the host of the stream being played
  • streamId – Unique id of the stream being played
  • streamType – type of the stream for analytic purposes (broadcast|watch_party|audio_room)
  • message – Message that the user has typed while giving the tip
  • anonymous – True if the user wants to stay anonymous
  • appSkuDetail – Billing product details which the user has agreed to pay for

Returns: Observable with the billing result

makeJoinGuestPurchase

fun makeJoinGuestPurchase(activity: Activity,userId: String,hostId: String,streamId: String,streamType: String,appSkuDetail: AppSku): Observable<AppBillingResult>

(OPTIONAL) Make the Google billing purchase for when the user has opted to pay for joining a stream as a guest (cameo)

Params:

  • activity – Parent fragment activity of the player
  • userId – Unique id of the logged in user requesting the cameo
  • hostId – Unique id of the host of the stream being played
  • streamId – Unique id of the stream being played
  • streamType – type of the stream for analytic purposes (broadcast|watch_party|audio_room)
  • appSkuDetail – Billing product details which the user has agreed to pay for

Returns: Observable with the billing result

fetchSkuDetails

fun fetchSkuDetails(skuId: String?): Flowable<List<AppSku>>

(OPTIONAL) Fetch the billing product details for the given sku id

Params:

  • skuId – id of the app billing product

Returns: FLowable where the list of matching billing products are returned. Ideally only one entry is expected and the sdk is only going to consider the first entry. Emit empty list if no match is found. And emit error exception in case of any error in fetching

ο»Ώο»ΏAnalytics Handler Interface

logEvent

fun logEvent(event: ANEvent, data: Map<String, Any>)

Log the event passed and the associated data using the app analytics

Params:

  • event – Event to be logged
  • data - Param data associated with the event logged

startEventTimer

fun startEventTimer(event: ANEvent)

This is mainly for timed events, where you want to record the duration of the event. This logs the start of an event. The end of the event will be triggered from the above logEvent

Params:

  • event – Event to be logged

ο»Ώ