Skip to content

Instantly share code, notes, and snippets.

@jraska
jraska / PlayIntegrityTokenVerify.kt
Created December 29, 2022 11:15
Simple console app verifying the client app integrity token with Play API: https://developer.android.com/google/play/integrity/verdict#decrypt-verify
// https://developer.android.com/google/play/integrity/verdict#decrypt-verify
// implementation 'com.google.api-client:google-api-client:1.32.2'
// implementation 'com.google.apis:google-api-services-playintegrity:v1-rev20220211-1.32.1'
package com.jraska.github.client.identity.integrity
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
class PushIntegrationTest {
lateinit var pushClient: PushServerClient
lateinit var thisDeviceToken: String
@get:Rule
val pushRule = PushAwaitRule()
@Before
fun setUp() {
class Dependencies : Plugin<Project> {
override fun apply(project: Project) {
// Possibly common dependencies or can stay empty
}
companion object {
val FIREBASE_MESSAGING = "com.google.firebase:firebase-messaging:20.1.7"
}
}
moduleGraphAssert {
maxHeight = 4
allowed = [':.* -> :core', ':feature.* -> :lib.*'] // regex to match module names - anyone can depend on :core, features can depend on libraries
restricted = [':feature-[a-z]* -X> :forbidden-to-depend-on'] // no feature can depend on :forbidden-to-depend-on
}
fun moduleDependencies(project: Project): List<Project> {
return project.configurations
.filter { it.name == "api" || it.name == "implementation" }
.flatMap { configuration ->
configuration.dependencies.filterIsInstance(DefaultProjectDependency::class.java)
.map { it.dependencyProject }
}
}
class UsersViewModel(val navigator: Navigator) : ViewModel {
fun onUserClicked(user: User) {
// Business logic, analytics, any other compex interactions
navigator.startUserDetail(user.login)
}
}
class AsyncNavigator(val topActivityProvider: TopActivityProvider) : Navigator {
override fun startUserDetail(login: String) {
topActivityProvider.onTopActivity { activity -> UserDetailActivity.start(activity, login) }
}
override fun showSettings() {
topActivityProvider.onTopActivity { activity -> SettingsActivity.start(activity) }
}
}
class TopActivityProvider {
private val pendingActions = mutableListOf<(Activity) -> Unit>()
var topActivity: Activity? = null
private set
@AnyThread
fun onTopActivity(action: (Activity) -> Unit) {
val topActivity = this.topActivity
class NavigatorSync(private val topActivityProvider: TopActivityProvider) : Navigator
override fun startUserDetail(login: String) {
topActivityProvider.topActivity?.let { activity -> UserDetailActivity.start(activity, login) }
}
override fun showSettings() {
topActivityProvider.topActivity?.let { activity -> SettingsActivity.start(activity) }
}
}
class TopActivityProvider {
var topActivity: Activity? = null
private set
private val callbacks: Application.ActivityLifecycleCallbacks = object : ActivityLifecycleCallbacks {
override fun onActivityResumed(activity: Activity) {
topActivity = activity
}