Skip to content

Instantly share code, notes, and snippets.

@mensly
Last active February 8, 2017 05:17
Show Gist options
  • Save mensly/989e4005a7970e68fd5c8da4a4e079f9 to your computer and use it in GitHub Desktop.
Save mensly/989e4005a7970e68fd5c8da4a4e079f9 to your computer and use it in GitHub Desktop.
Code snippet for setting up an Azure Notification Hub installation (*not* registration) in Kotlin using Retrofit
interface RestApiService {
companion object {
const val PUSH_PLATFORM = "gcm"
}
@PUT
fun installPush(@Url endpoint: String,
@Header("Authorization") authorization: String,
@Body request: PushInstallationRequest): Observable<ResponseBody>
@Keep data class PushInstallationRequest(
val installationId: String,
val pushChannel: String,
val templates: Map<String, PushTemplate>,
val platform: String = PUSH_PLATFORM
) {
@Keep data class PushTemplate(val body: String)
constructor(installationId: String, pushChannel: String, templateName: String,
template: String, platform: String = PUSH_PLATFORM)
: this(installationId, pushChannel, mapOf(templateName to PushTemplate(template)), platform)
}
}
fun RestApiService.installPush(fcmToken: String, installationId: String, templateName: String, template: String)
= Observable.fromCallable {
val endpoint = hubBaseEndpoint.buildUpon()
.scheme("https")
.appendPath(BuildConfig.HUB_NAME)
.appendPath("installations")
.appendPath(installationId)
.appendQueryParameter("api-version", "2016-07")
.toString()
val sasToken = getSasToken(endpoint, 60)
val request = RestApiService.PushInstallationRequest(installationId, fcmToken, templateName, template)
installPush(endpoint, sasToken, request)
}.flatMap { it }
private val hubConnectionParams by lazy {
BuildConfig.HUB_LISTEN_CONNECTION.split(";").associate { it.split("=", limit = 2).let { kv -> kv[0] to kv[1] } }
}
private val hubBaseEndpoint by lazy { Uri.parse(hubConnectionParams["Endpoint"])!! }
private val hubSharedAccessKeyName by lazy { hubConnectionParams["SharedAccessKeyName"]!! }
private val hubSharedAccessKey by lazy { hubConnectionParams["SharedAccessKey"]!! }
private fun getSasToken(uri: String, minUntilExpire: Long): String {
// Encode target Uri
val targetUri = Uri.encode(uri).toLowerCase()
// Set expiry date. 'minUntilExpire' from now (in seconds)
val expiry = (Instant.now() + Duration.standardMinutes(minUntilExpire)).millis / 1000
// Create signature of target uri & expiry date
val signature = Uri.encode(Base64.encodeToString("$targetUri\n$expiry".toHMac256(hubSharedAccessKey), Base64.NO_WRAP))
return "SharedAccessSignature sr=$targetUri&sig=$signature&se=$expiry&skn=$hubSharedAccessKeyName"
}
private fun String.toHMac256(keyString: String): ByteArray {
val encoder = Mac.getInstance("HmacSHA256")
val key = SecretKeySpec(keyString.toByteArray(Charsets.UTF_8), "HmacSHA256")
encoder.init(key)
return encoder.doFinal(toByteArray(Charset.defaultCharset()))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment