Integrations & SDKs
Android SDK
installing and setup our android sdk is hosted as a github package here https //github com/hotmic wp/hotmic android sdk https //github com/hotmic wp/hotmic android sdk make sure when installing that you follow this guide in the build gradle (root), add the following repositories maven { url 'https //jitpack io' } maven { url "https //maven pkg github com/hotmic wp/android sdk" credentials { username "git" password "\<github personal access token>" } } 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 enable microphone permissions if you want to support tv sync or guest call in android sample app hotmic offers a sample app to see how to use our android sdk in your application here is a step by step guide to downloading and running the hotmic sdk sample applications for android requirements a link to the hotmic sdk sample application provided by hotmic an api key provided by hotmic a jwt token created using a secret provided by hotmic instructions for how to create the token can be found below a white labeled production dashboard where you will produce streams authentication with jwt token for security, when using the sdk your app controls authentication with a jwt token, which you pass to hotmic json web tokens are an open, industry standard rfc 7519 https //tools ietf org/html/rfc7519 method for representing claims securely between two parties jwt io http //jwt io/ you will receive an api secret from hotmic, which you will use to create the token the token will be used to authenticate the user, as well as provide information such as their name, an avatar, a unique id, or another information which is needed by the sdk this is the expected format of the jwt token // nodejs example const jwt = require('jsonwebtoken'); accesstoken = jwt sign({identity { user id user id, // should be consistent for the user (uuid4) display name user display name, // name displayed in chat/profiles profile pic user profile pic, // image url (https //ui avatars com/api/?name=test\&background=0dcad6\&color=fff) }}, \[api secret], { expiresin '7d'}) note, the user id field should be consistent for each invocation of the sdk for that particular user quick steps to generate a jwt token online you can also generate jwt tokens online! this is good for test purposes while getting started, or to use the sample app here is one way to do it we do not recommend using this method with any sensitive data go to https https //jwt io/ and scroll down add a payload like the following into the "payload" section paste your secret into the "verify signature" section this screenshot shows how it looks and here is a sample payload that should work for your application { "identity" { "user id" "3d5567c2 603c 4b08 b917 7e9f05c8ebb5", "display name" "tester1", "profile pic" "https //ui avatars com/api/?name=test\&background=0dcad6\&color=fff", "badge" "https //hotmic content s3 us west 1 amazonaws com/badges/10 badge png?c251fece c08f 48a0 931e 70cfe8ea7ed4" }, "iat" 1657658555, "exp" 1821724014 } then copy the code from the "encoded" section of this page, and use that in the sample app how the sdk is implemented 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 using the hotmic android sdk at a high level, you can use the android sdk to do things like get a list of streams open a stream take actions inside a stream receive callback & analytics events for actions taken inside the sdk fetch streams for fetching all streams to be listed to the user, call the below code hotmicplayer getstreams(context, api key)? let { api > api 	 subscribeon(schedulers io()) 	 subscribe({ slist > 	 log d(“list streams”, "streams fetched ${slist size}") 	 //update ui },{ e > 	 log e("error in fetching streams", e) }) } you can optionally pass in params to filter the results of the streams streams are returned in reverse chronological order the possible filters are userid the userid you want to filter the streams by type string default null (all possible streams) limit the max number of streams to return type integer example 40 default 30 skip the number of results to skip you want to not return in the results, typically used for pagination type integer example 10 default 0 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 hotmicplayer builder(this) 	 setstreamid(streamid) 	 setuicallback(playeruihandler) 	 credential(api key) 	 setanalytichandler(analytics) 	 show(r id player fragment container) 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 hotmicplayer closeplayer(activity, reason, allowstateloss) reason analytic reason for the player closure, probable values will be user closed, signout allowstateloss setting this to true will result in the fragment being removed with state loss the default is false for most scenarios, the default value of false is recommended, especially if the parent activity is having features/fragments other than the player 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() stream menu options inside the menu, there are several options which can be used to leave the leave button stops the player in the sdk and gives a callback in the onplayerclosed method, so the parent app can remove the fragment this should be handled on the host app, but most of the time you would want to "go back" to the prior page troubleshoot when this is enabled, the troubleshoot button allows you to allow the end user to report any technical issue back to the app owner for example, if a video was not loading or a chat was missing, the user can tap on troubleshoot, which in turn will invoke a 3rd party diagnostic sdk the sdk will capture parameters like device logs, etc and make a ticket in the system which the app owner can access the option is hidden behind a flag which can be set while building the player, default is false let the hotmic team know your diagnostic sdk and we can help you set this up handling back press if the user taps the device back key, and if the player is open 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>) full screen mode to allow your video player to go into full screen mode with a tap, you need to enable it in your application to do so properly, add android\ configchanges="orientation|keyboardhidden|screensize" to the activity hosting the fragment picture in picture (pip) mode picture in picture mode can be of two types 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 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) setplayerinpipmode(activity fragmentactivity, enable boolean) boolean 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 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 fun loadhotmicad( activity fragmentactivity, view view, displayafter long = 0, ttl long = 10000 ) 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 pollprimary set in your app set in your app hmp pollprimarycontrast set in your app set in your app 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 getsharelink 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 sha re with others params context streamid – id of the stream for which the invite link is to be created returns observable with the message string getfollowdata (depreciated in version 1 7 0) getfollowdata has been replaced by getuserprofile 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 getuserprofile (new in version 1 7 0) getuserprofile has replaced getfollowdata, please use this moving forward (optional) return the user profile information, including meta data like name, profile pic return null or do not implement, if you do not want to provide information from your application if implementing, then gather and return all information for the user profile, such as following 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 profile info is needed restriction type of restriction on this account (if any), possible values are "none", "view and polls only", "read only" a null value on this can be interpreted as no restriction "view and polls only" user can view and answer polls, but cannot chat, join a stream, follow, tip, view a profile "read only" same as "view and polls only", plus the user cannot answer polls ishost boolean is the user id that of the host of this stream iscohost boolean is the user one of the cohost in this stream fun getuserprofile( uid string, restriction string?, ishost boolean, iscohost boolean ) observable\<hmprofile>? returns an observable with the hmprofile object the observable will be invoked in the background by the implementation here is what the return looks like data class hmprofile( val name string? = null, val displayname string? = null, val profilepic string? = null, val badge string? = null, val bio string? = null, val location string? = null, val instagramhandle string? = null, val tiktokhandle string? = null, val twitchhandle string? = null, val twitterhandle string? = null, val youtubehandle string? = null, val followerscount int? = null, val followingcount int? = null, val isfollowingme boolean? = null, val isfollowedbyme boolean? = null, val showfullprofileoption boolean? = null ) seefullprofiletapped if showfullprofileoption is returned to getuserprofile(), then there will be a button displayed to "see full profile" if a user taps that button, they trigger seefullprofiletapped params uid user id of the user whose profile info is needed restriction type of restriction on this account (if any), possible values are "none", "view and polls only", "read only" a null value on this can be interpreted as no restriction "view and polls only" user can view and answer polls, but cannot chat, join a stream, follow, tip, view a profile "read only" same as "view and polls only", plus the user cannot answer polls ishost boolean is the user id that of the host of this stream iscohost boolean is the user one of the cohost in this stream fun seefullprofiletapped( uid string, restriction string?, ishost boolean, iscohost boolean ) boolean returns true if you want the profile panel shown by the sdk to be dismissed, false otherwise 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 fun followuser(user hmuserbasic, shouldfollow boolean) observable\<hmfollowdata>? the return for followuser is data class hmfollowdata( val followerscount int?, val followingcount int?, val isfollowingme boolean?, val isfollowedbyme boolean? ) 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