Log with Rust in React Native Android Apps
Log Rust Libraries code in react native android apps
Suyash Singh
Posted by Suyash Singh
on April 16, 2024
Photo by Casey on Unsplash

If you need to create an Android mobile app that calls Rust methods for extra performance, this post is for you. Let’s see how to log messages in Android directly from Rust code. For a complete guide on setting up a React Native Android app that calls Rust code, follow this post I have written about it, as we will use the app from that post as the foundation for this tutorial.

Install Required Crates

First, you need to add the following dependencies to your cargo.toml file. These crates will help us with logging:

backend/cargo.toml
[package]
name = "backend"
version = "0.1.0"
edition = "2021"
 
[lib]
crate-type = ["cdylib"]
name = "backend"
 
[dependencies]
log = "0.4"
android_logger = "0.13.1"
uniffi = { version = "0.28.0", features = ["cli"] }
 
[build-dependencies]
uniffi = { version = "0.28.0", features = ["build"]}
uniffi_build = { version = "0.28.0", features = ["builtin-bindgen"] }
 
[[bin]]
name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"

Update lib.rs to Initialize Logging

ℹ️

Note: In this post, we are setting up a very basic logging foundation for our library. For a more comprehensive set of options, read the docs for android_logger.

backend/lib.rs
#![allow(unused)]
 
#[macro_use]
extern crate log;
extern crate android_logger;
 
use android_logger::Config;
use log::LevelFilter;
 
uniffi::include_scaffolding!("backend");
 
pub fn rusty_hello(text: String) -> String {
    format!("Hello {text}")
}
 
pub fn rusty_init() {
  android_logger::init_once(Config::default().with_max_level(LevelFilter::Debug));
  // ... more initialization code
  info!("Initialized logs for android using rust");
}
 

Update UDL for init:

Let’s update our backend/src/backend.udl:

ℹ️

Note: This post is an extension of a different post I have written. It assumes the presence of backend/src/backend.udl file.

backend/src/backend.udl
namespace backend {
  string rusty_hello(string text);
  void rusty_init();
};

Let’s now call rusty_init rust function in our react native typescript layer through kotlin:

android/app/src/main/java/com/sampleapp/BackendModule.kt
package com.sampleapp
import com.facebook.react.bridge.Promise
import android.util.Log
import com.sampleapp.uniffi.rustyHello
import com.sampleapp.uniffi.rustyInit
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
 
class BackendModule internal constructor(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) {
 
    override fun getName(): String {
        return "BackendModule"
    }
 
    @ReactMethod
    fun hello(text: String, promise: Promise) {
        var response = rustyHello(text)             
        Log.d("Kotlin BackendModule says:", "${response}")
        promise.resolve(response)
    }
 
 
    @ReactMethod
    fun init() {
       rustyInit();
    }
}
App.tsx
import React, {useEffect, useState} from 'react';
import {Button, NativeModules, SafeAreaView, Text} from 'react-native';
 
const {BackendModule} = NativeModules;
 
const HelloFromRust = () => {
  const [value, setValue] = useState('');
 
  useEffect(() => {
    BackendModule.init();
  }, []);
 
  const onPress = async () => {
    let helloFromRust = await BackendModule.hello('from rust!');
    setValue(helloFromRust);
  };
  return (
    <>
      <Button
        title="Click To invoke Kotlin Native Module Code"
        color="#241584"
        onPress={onPress}
      />
      <Text style={{fontSize: 40}}>{value}</Text>
    </>
  );
};
 
function App(): JSX.Element {
  return (
    <SafeAreaView>
      <HelloFromRust />
    </SafeAreaView>
  );
}
export default App;
 

If you have followed along successfully up to this point, it would log Initialized logs for android using rust to android logs, you can verify this using adb logcat

adb logcat | grep 'android using rust'
 
04-16 21:39:20.532 15096 15162 I backend : Initialized logs for android using rust