Le TechnIKO, c’est quoi ?

Chez IKOMOBI, nos experts sont tous les jours confrontés à des problématiques nouvelles qui les amènent à concevoir des solutions innovantes pour nos clients. Grâce à TechnIKO nous allons vous faire découvrir les coulisses de ces différentes innovations, au travers notamment la diffusion des techniques et méthodes de développements chères à nos développeurs.

Passons sans attendre à notre premier sujet.

Communiquer avec du Javascript via une WebView au sein d’une application mobile native développée avec Kotlin

Le besoin est simple : l’application native charge une page web, développée par notre client, qui contient des méthodes Javascript, et doit appeler ces méthodes pour effectuer des traitements ou récupérer des données. Par exemple, on peut modifier un style sur la page web via une action dans l’application, ou récupérer une donnée à tracker.

La méthode simple : evaluateJavascript

Cette méthode peut être utilisée si on a besoin d’appeler une méthode javascript de manière isolée, car elle est facile à mettre en place mais peu structurée et très basique, notamment car elle ne permet de recevoir qu’une valeur maximum.

Dans l’exemple suivant, on récupère une Webview de la MainActivity qui appelle une URL, et on utilise un bouton pour récupérer la valeur donnée par une fonction Javascript et l’afficher via un Toast :

val name = "John Doe"
webview.settings.javaScriptEnabled = true
webview.loadUrl(myUrl)
button.setOnClickListener {
    webview.evaluateJavascript("javascript:myJsFunction(\"$name\");") { value ->
        Toast.makeText(this@MainActivity, value, Toast.LENGTH_SHORT).show()
    }
}

Côté web, on a une simple page avec la fonction Javascript demandée :

<script type="text/javascript">
	function myJsFunction(name) {
		return "Hello " + name + "!";
	}
</script>

La méthode musclée : @JavascriptInterface

Cette méthode est légèrement plus complexe à mettre en place et nécessite une version d’Android 16 et supérieure, mais permet de regrouper plusieurs méthodes dans une même classe afin d’avoir un code plus propre et organisé.

Pour l’exemple qui suit, on crée une classe qui agira comme interface Web, afin de tracker un évènement de connexion :

class MyWebInterface(private val context: Context) {
	private lateinit var firebaseAnalytics: FirebaseAnalytics

	init {
	  firebaseAnalytics = FirebaseAnalytics.getInstance(this)
  }

	@JavascriptInterface
  fun userLoggedIn(name: String) {
	  val bundle = bundleFromJson(jsonValue)
	  bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, name)
	  firebaseAnalytics.logEvent(FirebaseAnalytics.Event.LOGIN.name(), bundle)
  }
}

Ce code implique que la page web appellera une méthode Android.userLoggedIn en Javascript, que l’application native interceptera :

<script type="text/javascript">
  // Fonction appelée par la page web
	function onUserLogin(name) {
		// Fonction détectée par Android
		Android.userLoggedIn(name)
	}
</script>

Enfin on lie cette interface à la WebView :

webview.settings.javaScriptEnabled = true
webview.addJavascriptInterface(MyWebInterface(this), "Android")
webview.loadUrl(myUrl)

En conclusion, il est très facile de lier Javascript et le natif Kotlin au sein d’une application mobile Android. Il ne reste plus qu’à choisir la bonne méthode :

  • Une seule fonction simple à appeler ? On utilisera evaluateJavascript
  • Plusieurs fonctions et des retours à traiter ? On préfèrera @JavascriptInterface

N’hésitez pas à nous contacter si vous souhaitez en savoir plus ou mettre à profit tout notre savoir-faire en conception, réalisation et exploitation d’applications mobiles natives.