Recent wiringpi/JNI build

Post Reply
Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Recent wiringpi/JNI build

Post by Gus189 »

Hello,
Wondering if anyone had a fairly recent example of setting up wiringPi/JNI in Android Studio...

Been hacking away at some examples I found here but they won't build in recent Android Studio with Android 8+...

I'm not a super expert on JNI stuff and was wondering if anyone had any recent examples or howTos.

I'm running Android 9 on the C4, sdk 27+

Thanks,
Gus

User avatar
joerg
Posts: 1306
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 82 times
Been thanked: 180 times
Contact:

Re: Recent wiringpi/JNI build

Post by joerg »

Are you using Java or Kotlin?
I can set up an example and guide you through the first steps.

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

Java. Thanks!

User avatar
joerg
Posts: 1306
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 82 times
Been thanked: 180 times
Contact:

Re: Recent wiringpi/JNI build

Post by joerg »

OK. So I recommend to first clone the wiringPi from github and compile it:

Code: Select all

git clone https://github.com/hardkernel/wiringPi.git
cd wiringPi
The to make it compile with the NDK add a jni folder and add a Application.mk and a Android.mk there.
wiringPi/jni/Android.mk

Code: Select all

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
    $(LOCAL_PATH)/../wiringPi

LOCAL_MODULE    := wiringPi
LOCAL_SRC_FILES := \
        ../wiringPi/ads1115.c        \
        ../wiringPi/mcp23008.c        \
        ../wiringPi/mcp4802.c        \
        ../wiringPi/piHiPri.c        \
        ../wiringPi/sr595.c        \
        ../wiringPi/bmp180.c        \
        ../wiringPi/mcp23016.c        \
        ../wiringPi/odroidc1.c        \
        ../wiringPi/odroidn2.c        \
        ../wiringPi/piThread.c        \
        ../wiringPi/wiringPi.c        \
        ../wiringPi/mcp23017.c        \
        ../wiringPi/odroidc2.c        \
        ../wiringPi/odroidc4.c        \
        ../wiringPi/odroidhc4.c        \
        ../wiringPi/drcSerial.c        \
        ../wiringPi/mcp23s08.c        \
        ../wiringPi/odroidn1.c        \
        ../wiringPi/wiringPiI2C.c        \
        ../wiringPi/ds18b20.c        \
        ../wiringPi/mcp23s17.c        \
        ../wiringPi/sn3218.c        \
        ../wiringPi/wiringPiSPI.c        \
        ../wiringPi/htu21d.c        \
        ../wiringPi/mcp3002.c        \
        ../wiringPi/odroidxu3.c        \
        ../wiringPi/softPwm.c        \
        ../wiringPi/wiringSerial.c        \
        ../wiringPi/max31855.c        \
        ../wiringPi/mcp3004.c        \
        ../wiringPi/pcf8574.c        \
        ../wiringPi/softServo.c        \
        ../wiringPi/wiringShift.c        \
        ../wiringPi/max5322.c        \
        ../wiringPi/mcp3422.c        \
        ../wiringPi/pcf8591.c        \
        ../wiringPi/softTone.c



LOCAL_CFLAGS    += -UNDEBUG -DANDROID -Wno-return-type

LOCAL_LDLIBS    := -ldl -llog
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
    $(LOCAL_PATH)/../wiringPi

LOCAL_MODULE    := wiringPiDev
LOCAL_SRC_FILES := \
    ../devLib/ds1302.c     \
    ../devLib/maxdetect.c  \
    ../devLib/piNes.c      \
    ../devLib/gertboard.c  \
    ../devLib/lcd128x64.c  \
    ../devLib/lcd.c        \
    ../devLib/piGlow.c     \
    ../devLib/scrollPhat.c \
    ../devLib/piFace.c 

LOCAL_SHARED_LIBRARIES := libwiringPi

LOCAL_LDLIBS    := -ldl -llog

LOCAL_CFLAGS    += -DEBUG -DANDROID  -Wno-return-type
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)

LOCAL_MODULE    := gpio
LOCAL_SRC_FILES := ../gpio/gpio.c ../gpio/readall.c
LOCAL_C_INCLUDES +=   $(LOCAL_PATH)/../wiringPi $(LOCAL_PATH)/../devLib/

LOCAL_CFLAGS    += -DEBUG -DANDROID -Wno-return-type
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := libwiringPi libwiringPiDev

include $(BUILD_EXECUTABLE)
wiringPi/jni/Application.mk

Code: Select all

NDK_TOOLCHAIN_VERSION=clang
APP_ABI :=  armeabi-v7a arm64-v8a
APP_PLATFORM := android-21
It's old style, but it works. ;)
Compile it:

Code: Select all

/path/to/Android/Sdk/ndk-bundle/ndk-build -B
...
[arm64-v8a] Install        : gpio => libs/arm64-v8a/gpio
[arm64-v8a] Install        : libwiringPi.so => libs/arm64-v8a/libwiringPi.so
[arm64-v8a] Install        : libwiringPiDev.so => libs/arm64-v8a/libwiringPiDev.
Do it, meanwhile I will write nexte steps...
These users thanked the author joerg for the post (total 3):
tobetter (Fri Feb 19, 2021 2:02 am) • Gus189 (Fri Feb 19, 2021 2:27 am) • odroid (Fri Feb 19, 2021 9:22 am)

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

Cool, I'll try to get started tonight.

Thanks,
Paul

User avatar
joerg
Posts: 1306
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 82 times
Been thanked: 180 times
Contact:

Re: Recent wiringpi/JNI build

Post by joerg »

Then create a new project in AndroidStudio.
You need to add a folder cpp under src/main. Then add file CmakeLists.txt with right mouse click on it: New - File and a file wpi_android.cpp with New - C/C++ Source File.
src/main/cpp/CmakeLists.txt

Code: Select all

cmake_minimum_required(VERSION 3.4.1)
find_library( log-lib log )

//set path to the parent folder of wiringPi:
set(distribution_DIR /home/joerg/Development/Ndk)

add_library( wiring SHARED IMPORTED )
set_target_properties( wiring PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/wiringPi/libs/${ANDROID_ABI}/libwiringPi.so )

add_library( wpi_android  SHARED  wpi_android.cpp )

target_include_directories( wpi_android PUBLIC /home/joerg/Development/Ndk/wiringPi/wiringPi )

target_link_libraries( wpi_android ${log-lib} wiring )
The wpi_android is a library that interfaces the wiringPi with Java.
src/main/cpp/wpi_android.cpp

Code: Select all

//
// Created by joerg on 18.02.21.
//

#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>

#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOG_TAG "wpi_android"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/system_properties.h>

#include <softPwm.h>
#include <dlfcn.h>
#include "wiringPi.h"

#ifdef __cplusplus
extern "C" {
#endif

#define I2C_DEVICE  "/dev/i2c-1"


jint Java_com_jw_wiringpi_wpiAndroid_wiringPiSetupSys(JNIEnv* env, jobject obj) {
    LOGI("Entering wiringPiSetup");
    return wiringPiSetupSys();
}


jint Java_com_jw_wiringpi_wpiAndroid_wiringPiSetup(JNIEnv* env, jobject obj) {
    return wiringPiSetup();
}

//void pullUpDnControl (int pin, int pud)
void Java_com_jw_wiringpi_wpiAndroid_pullUpDnControl(JNIEnv* env, jobject obj, jint port, jint pud) {
    return pullUpDnControl(port, pud);
}

//void pinMode (int pin, int mode)
void Java_com_jw_wiringpi_wpiAndroid_pinMode(JNIEnv* env, jobject obj, jint port, jint mode) {
    return pinMode(port, mode);
}

//void pinModeAlt (int pin, int mode)
void Java_com_jw_wiringpi_wpiAndroid_pinModeAlt(JNIEnv* env, jobject obj, jint port, jint mode) {
    pinModeAlt(port, mode);
}

jint Java_com_jw_wiringpi_wpiAndroid_digitalRead(JNIEnv* env, jobject obj, jint port) {
    return digitalRead(port);
}

//int getAlt (int pin)
jint Java_com_jw_wiringpi_wpiAndroid_getAlt(JNIEnv* env, jobject obj, jint port) {
    return getAlt(port);
}

void Java_com_jw_wiringpi_wpiAndroid_digitalWrite(JNIEnv* env, jobject obj, jint port, jint onoff) {
    digitalWrite(port, onoff);
}

jint Java_com_jw_wiringpi_wpiAndroid_analogRead(JNIEnv* env, jobject obj, jint port) {
    return analogRead(port);
}

jint Java_com_jw_wiringpi_wpiAndroid_softPwmCreate(JNIEnv* env, jobject obj, jint port, jint value, jint range) {
    return softPwmCreate(port, value, range);
}

void Java_com_jw_wiringpi_wpiAndroid_softPwmWrite(JNIEnv* env, jobject obj, jint port, jint value) {
    softPwmWrite(port, value);
}

void Java_com_jw_wiringpi_wpiAndroid_softPwmStop(JNIEnv* env, jobject obj, jint port) {
    softPwmStop(port);
}

void Interrupt(void) {
    LOGI("Interrupt");
}

jint Java_com_jw_wiringpi_wpiAndroid_wiringPiISR(JNIEnv* env, jobject obj, jint port, jint edge) {
    return wiringPiISR (port, edge, &Interrupt);
}


#ifdef __cplusplus
}
#endif
Note this syntax: Java_com_jw_wiringpi_wpiAndroid. You can change to your own com_jw, but I recommend to stay with wiringpi_wpiAndroid.
Therefore it's needed to add a package to your folder src/main/java: xxx.xx.wiringPi and there a Java class wpiAndroid.
wpiAndroid.java

Code: Select all

package com.jw.wiringpi;

public final class wpiAndroid {
    static {
        System.loadLibrary("wpi_android");
    }
    static public native int wiringPiSetup();
    static public native int wiringPiSetupSys();
    static public native void digitalWrite(int port, int onoff);
    static public native int digitalRead(int port);
    static public native void pullUpDnControl(int port, int pud);
    static public native void pinMode(int port, int mode);
    static public native void pinModeAlt(int port, int mode);
    static public native int getAlt(int port);
    static public native int softPwmCreate(int port, int value, int range);
    static public native void softPwmWrite  (int port, int value) ;
    static public native void softPwmStop   (int port) ;
}
You see the syntax is needed as path to the function.

Now it's missing some entry in app/build.gradle, to make AndroidStudio compile it.

Code: Select all

    defaultConfig {
        ...
        ndk {
            ldLibs "log"
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
    }
    
    externalNativeBuild {
        // Encapsulates your CMake build configurations.
        cmake {

            // Provides a relative path to your CMake build script.
            path "src/main/cpp/CMakeLists.txt"
        }
    }
Now you should be able to use the functions in wpiAndroid with your Java code.
These users thanked the author joerg for the post:
odroid (Fri Feb 19, 2021 9:22 am)

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

Thanks again for this!

I'm getting a duplicate symbol error building it...

$ ....AppData/Local/Android/sdk/ndk-bundle/ndk-build.cmd -B
[armeabi-v7a] Compile thumb : gpio <= gpio.c
[armeabi-v7a] Compile thumb : gpio <= readall.c
[armeabi-v7a] Compile thumb : wiringPi <= ads1115.c
[armeabi-v7a] Compile thumb : wiringPi <= mcp23008.c
[armeabi-v7a] Compile thumb : wiringPi <= mcp4802.c
...

[armeabi-v7a] Compile thumb : wiringPi <= pcf8591.c
[armeabi-v7a] Compile thumb : wiringPi <= softTone.c
[armeabi-v7a] SharedLibrary : libwiringPi.so
ld: error: duplicate symbol: phyToGpio
>>> defined at odroidn2.c:165 (C:/WiringPIBuild/wiringPi/jni/../wiringPi\odroidn2.c:165)
>>> C:/WiringPIBuild/wiringPi/obj/local/armeabi-v7a/objs/wiringPi/__/wiringPi/odroidn2.o:(phyToGpio)
>>> defined at odroidc2.c:142 (C:/WiringPIBuild/wiringPi/jni/../wiringPi\odroidc2.c:142)
>>> C:/WiringPIBuild/wiringPi/obj/local/armeabi-v7a/objs/wiringPi/__/wiringPi/odroidc2.o:(.bss.phyToGpio+0x0)

ld: error: duplicate symbol: pinToGpio
>>> defined at odroidn2.c:165 (C:/WiringPIBuild/wiringPi/jni/../wiringPi\odroidn2.c:165)
>>> C:/WiringPIBuild/wiringPi/obj/local/armeabi-v7a/objs/wiringPi/__/wiringPi/odroidn2.o:(pinToGpio)
>>> defined at odroidc2.c:142 (C:/WiringPIBuild/wiringPi/jni/../wiringPi\odroidc2.c:142)
>>> C:/WiringPIBuild/wiringPi/obj/local/armeabi-v7a/objs/wiringPi/__/wiringPi/odroidc2.o:(.bss.pinToGpio+0x0)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

User avatar
joerg
Posts: 1306
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 82 times
Been thanked: 180 times
Contact:

Re: Recent wiringpi/JNI build

Post by joerg »

On what system you are compiling? >>> C:/WiringPIBuild/... looks like Windows?
I have compiled it on my Linux system without error.
What happens if you change NDK_TOOLCHAIN_VERSION to gcc in Application.mk?

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

Yep, Windows. Still fails same way with gcc but, I can try to set this up on a Linux system....

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

It built ok on Linux. Do I need to run Android Studio on Linux as well or can I copy the wiringpi I built on linux to my Windows Android Studio? Sorry for the dumb questions....

User avatar
joerg
Posts: 1306
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 82 times
Been thanked: 180 times
Contact:

Re: Recent wiringpi/JNI build

Post by joerg »

It might work this way. But I don‘t have any experience with AndrodStudio on Windows.

Gus189
Posts: 13
Joined: Fri Feb 12, 2021 4:43 am
languages_spoken: english
ODROIDs: C4
Has thanked: 5 times
Been thanked: 0
Contact:

Re: Recent wiringpi/JNI build

Post by Gus189 »

I'll try to make it work, but if not, I'll just use Linux. Thanks for the help and I'll let you know how it goes.


Gus

Post Reply

Return to “Android”

Who is online

Users browsing this forum: No registered users and 0 guests