App Signature helper class (Kotlin)

import android.content.Context
import android.content.ContextWrapper
import android.content.pm.PackageManager
import android.util.Base64
import timber.log.Timber
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*


/**
* This is a helper class to generate your message hash to be included in your SMS message.
*
* Without the correct hash, your app won't recieve the message callback. This only needs to be
* generated once per app and stored. Then you can remove this helper class from your code.
*/
class AppSignatureHelper(context: Context?) : ContextWrapper(context) {// Get all package signatures for the current package

// For each signature create a compatible hash
/**
* Get all the app signatures for the current package
* @return
*/
val appSignatures: ArrayList<String>
get() {
val appCodes = ArrayList<String>()
try {
// Get all package signatures for the current package
val packageName = packageName
val packageManager = packageManager
val signatures = packageManager.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES).signatures

// For each signature create a compatible hash
for (signature in signatures) {
val hash = hash(packageName, signature.toCharsString())
if (hash != null) {
appCodes.add(String.format("%s", hash))
}
}
} catch (e: PackageManager.NameNotFoundException) {
Timber.e(e, "Unable to find package to obtain hash.")
}
return appCodes
}

companion object {
val TAG = AppSignatureHelper::class.java.simpleName
private const val HASH_TYPE = "SHA-256"
const val NUM_HASHED_BYTES = 9
const val NUM_BASE64_CHAR = 11
private fun hash(packageName: String, signature: String): String? {
val appInfo = "$packageName $signature"
try {
val messageDigest = MessageDigest.getInstance(HASH_TYPE)
messageDigest.update(appInfo.toByteArray(StandardCharsets.UTF_8))
var hashSignature = messageDigest.digest()

// truncated into NUM_HASHED_BYTES
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES)
// encode into Base64
var base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING or Base64.NO_WRAP)
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR)
Timber.e(String.format("pkg: %s -- hash: %s", packageName, base64Hash))
return base64Hash
} catch (e: NoSuchAlgorithmException) {
Timber.e(e, "hash:NoSuchAlgorithm")
}
return null
}
}
}

--

--

--

Android development

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Redux Source Part III: .subscribe(fn)

ACA Web 101 BlogPost #17

Jessica Rose joins the Program Committee

My food truck tracker app, FoodTrucks.Show, and how Vue.js’ emit function helped

React to Captain Hook, aye aye!

Event Source with Angular

How to Easily Use JavaScript and ArcGIS to Create Beautiful Rich Maps

Map of the world with ArcGIS showing volcanoes

Gatsby + Apollo + GraphCool + Netlify: The Web’s Promised Land

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Appcaesars

Appcaesars

Android development

More from Medium

Android Kotlin Trigger Notification

How to set Default Editor Mode to Code for Composable files in Android Studio

Why Kotlin for Android Development?

Callback function to suspend function and Flow (Part 1)