Hello.
I’m trying to program an AT-10A tablet using Unity for this. The Unity version is 2022.3.21f1.
The tablet manufacturer provided me with a file “canbus_api.aar”, which contains the CanBus communication functions that I need to access.
I was able to communicate with their API successfully, using the code below:
using UnityEngine;
public class JavaClassCAN : MonoBehaviour {
AndroidJavaObject canBusHelper;
private void Start() {
canBusHelper = new AndroidJavaObject("com.android.canbus.CanBusHelper");
//config serial baudrate
var retConfigSerial = canBusHelper.Call<int>("setSerialBaudrate", 1, 115200, 8, 0, 1); //OK - it works
if (retConfigSerial < 0) {
Debug.Log("ERROR - Config Serial Baudrate");
}
Debug.Log("Return 'setSerialBaudrate': " + retConfigSerial.ToString());
//initialize canbus
var retInitCAN = canBusHelper.Call<int>("initialize", 1, 115200, 500000, false); //OK - it works
if (retInitCAN < 0) {
Debug.Log("ERROR - Config CAN");
}
Debug.Log("Return 'initialize': " + retInitCAN.ToString());
//Start read CanBus
if (canBusHelper != null) {
var retReadCan = canBusHelper.Call<int>("readCan", 1, new CanBusCallbackProxy()); //OK - it works
Debug.Log(retReadCan);
}
else {
Debug.LogError("AndroidJavaObject canBusHelper is null");
}
}
public class CanBusCallbackProxy : AndroidJavaProxy {
public CanBusCallbackProxy() : base("com.android.canbus.CanBusHelper$CanBusCallback") {
}
public void onSetError() {
Debug.Log("zyz0 --> onSetError");
}
public void onSendError() {
Debug.Log("zyz0 --> onSendError");
}
public void onIdError(int count) {
Debug.Log("onIdError: " + count);
}
public void onReceiveCanbusData(int FF, int RTR, int DLC, int ID, int[] DATA) {
Debug.Log("onReceiveCanbusData: FF=" + FF + ", RTR=" + RTR + ", DLC=" + DLC + ", ID=" + ID.ToString("X"));
string dataString = "DATA: ";
for (int i = 0; i < DATA.Length; i++) {
dataString += DATA[i].ToString("X") + " ";
}
Debug.Log(dataString);
}
}
}
It’s quite simple and it works, as shown in logcat:
However, the “readCan” function is blocking, leaving the program stuck inside a while while waiting to receive data, and this obviously blocks the main unity thread and blocks the execution of the program itself.
The solution to this is apparently simple, just move the “readCan” function to a separate thread and everything will work fine. So I created this code below, making the function initialize in a new Thread.
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class JavaClassCAN : MonoBehaviour {
AndroidJavaObject canBusHelper;
private Thread canReadThread;
private bool runThread;
private void Start() {
canBusHelper = new AndroidJavaObject("com.android.canbus.CanBusHelper");
//config serial baudrate
var retConfigSerial = canBusHelper.Call<int>("setSerialBaudrate", 1, 115200, 8, 0, 1);
if (retConfigSerial < 0) {
Debug.Log("ERROR - Config Serial Baudrate");
}
Debug.Log("Return 'setSerialBaudrate': " + retConfigSerial.ToString());
//initialize canbus
var retInitCAN = canBusHelper.Call<int>("initialize", 1, 115200, 500000, false);
if (retInitCAN < 0) {
Debug.Log("ERROR - Config CAN");
}
Debug.Log("Return 'initialize': " + retInitCAN.ToString());
//Start thread
runThread = true;
canReadThread = new Thread(ReadCanData);
canReadThread.Start();
}
private void OnDisable() {
runThread = false;
if (canReadThread != null && canReadThread.IsAlive) {
canReadThread.Join();
}
}
private void ReadCanData() {
Thread.Sleep(1000);
if (runThread) {
if (canBusHelper != null) {
var retReadCan = canBusHelper.Call<int>("readCan", 1, new CanBusCallbackProxy()); //HERE - BUG
Debug.Log(retReadCan);
}
else {
Debug.LogError("AndroidJavaObject canBusHelper is null");
}
}
}
public class CanBusCallbackProxy : AndroidJavaProxy {
public CanBusCallbackProxy() : base("com.android.canbus.CanBusHelper$CanBusCallback") {
}
public void onSetError() {
Debug.Log("zyz0 --> onSetError");
}
public void onSendError() {
Debug.Log("zyz0 --> onSendError");
}
public void onIdError(int count) {
Debug.Log("onIdError: " + count);
}
public void onReceiveCanbusData(int FF, int RTR, int DLC, int ID, int[] DATA) {
Debug.Log("onReceiveCanbusData: FF=" + FF + ", RTR=" + RTR + ", DLC=" + DLC + ", ID=" + ID.ToString("X"));
string dataString = "DATA: ";
for (int i = 0; i < DATA.Length; i++) {
dataString += DATA[i].ToString("X") + " ";
}
Debug.Log(dataString);
}
}
}
However, this time, when trying to run the readCan function, I get the error “Error Unity Exception: JNI: Init’d AndroidJavaObject with null ptr!”