In-App rating, In-App review in Kotlin Multiplatform

Discover how to trigger the in-app review within Kotlin Multiplatform and Compose Multiplatform (Android and iOS).

In-App rating, In-App review in Kotlin Multiplatform
In-App rating, In-App review in Kotlin Multiplatform

In this article, you will discover how to trigger the in-app review process within Kotlin Multiplatform and Compose Multiplatform (Android and iOS).

In Android to open In-App review you have to do this :

val reviewManager = ReviewManagerFactory.create(context)
val request = reviewManager.requestReviewFlow()
request.addOnCompleteListener { requestInfo -> 
  if (requestInfo.isSuccessful) { 
  // Launch the in-app review flow 
    val reviewInfo = requestInfo.result 
    val flow = reviewManager.launchReviewFlow(activity, reviewInfo) 
    flow.addOnCompleteListener { _ -> 
      // Review flow completed 
    } 
  } else { 
    // Handle the error
  }
}

And in iOS:

SKStoreReviewController.requestReview()

But Kotlin Multiplatform is all about shared code so how do we call the in app ratings in shared common code?

Expect Actual to the rescue

Using expect/actual you can define a contract to call inAppRating in KMP with Android and iOS specific implementations.

In Common Main define the expect function:

expect class Growth {
  fun inAppRating()
}

In Android you have to pass the Android Context:

actual class Growth(
  private val context: Context
) {
  actual fun inAppRating() {
    val reviewManager = ReviewManagerFactory.create(context)
    context.getActivity()
      ?.let { activity -> 
        // the previous code with reviewManager.launchReviewFlow
      }
  }
}

And iOS it is less verbose:

actual class Growth {
  actual fun inAppRating() {
    SKStoreReviewController.requestReview()
  }
}

The functionnality is done but how do we call this now in our shared view models or in our Compose Multiplatform views ?

Setting up Dependency Injection with Koin in Kotlin Multiplatform

We need to setup dependency injection now to call it in view models (or voyager screen models) or in Compose Multiplatform views.

In Common Main:

expect fun sharedPlatformModule(): Module

In Android and iOS side:

actual fun sharedPlatformModule(): Module = module {
  // automatically pass context into the constructor on Android and calls the no argument constructor in iOS
  singleOf(::Growth) 
}


You can now use the in-app review in screen models such as this after a process :

class RootScreenModel(
  val growth: Growth
): ScreenModel {
  fun operation() {
    screenModelScope.launch {
      // some blocking operation for example
      // blocking()...
      // call whenever you want in app review
      growth.inAppRating()
    }
  }
}

KoinInject in Compose Multiplatform

To go further you can be able to have a basic Compose button with an on click callback and call in-app review in it like this thanks to koinInject function :

val growth: Growth = koinInject()

Button(onClick = { growth.inAppRating()}) { 
  Text("Rate app")
}

You finally managed to make a in-app review in both Android and iOS 🎉

As you can see, even basic tasks require some effort. Now, imagine having to create all the essential yet non-unique features for your app, like payment processing, authentication, and others.

AppKickstarter: Build faster

In AppKickstarter template, you'll find all the essentials required to develop a mobile app. This covers crucial processes such as in-app reviews, as well as a wide array of features including authentication, in-app purchases, onboarding, user management, settings, navigation, native iOS design elements, multiplatform analytics, crash monitoring across multiple platforms, ads integration, resource management, and localization support, among others. By leveraging this template, you can save significant development time that would otherwise be spent reinventing the wheel. This allows you to concentrate on refining the distinctive features that set your app apart from others.