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:
[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
.
#![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.
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:
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();
}
}
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