Search code examples
androidopencvandroid-ndkadb

android NDK adb executable without java


I am trying to run a c++ executable on android emulator through adb shell.

I am using opencv.

Everything works fine and the code works fine but I need to know how to display an image using cv::imshow(...). I understand this might not be possible without going through JNI and attaching this code to an actual android app that can be built into an apk. But that is NOT what I am looking to do at the moment.

I simply need to be able to do something like

adb shell am start -d file:///path/to/someimage/someimage.jpg -t image/jpg -a android.intent.action.VIEW

through c++ code.

I currently get the following error when i try calling cv::imshow(...) through my c++ code and then run the exe through adb shell:

terminate called after throwing an instance of 'cv::Exception'
what(): openCV(3.4.3) /build/3_4_pack-android/opencv/modules/highgui/src/window.cpp:632:error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.X or Carbon support. If you are on Ubutu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script function in 'cvShowImage'

Is there a linker flag I can add to LOCAL_LDLIBS or some other small fix I can use to get this to work without having to use java/JNI crutches?


Solution

  • To a pretty large, extent, you are "going about this all wrong". But if you want to do what you seem to be trying to do regardless of the limitations, and are willing to be permanently tied to running under the adb shell then there is a way.

    Essentially:

    • You have a shell command that works.
    • You have a program that wants to execute this command.
    • The execution contexts of the program and the shell command are the same

    This is a job for the system() syscall

    #include <stdlib.h>
    int system(const char *command);
    

    So you would just do something like

    system("am start -d file:///path/to/someimage/someimage.jpg -t image/jpg -a android.intent.action.VIEW)
    

    ...presumably where the command string is something you construct at runtime filling in the filename, etc.

    Of course this is a long way from having anything deployable on Android, unless you mean to always operate via adb. To get to where you should be the greater challenge is going to be to turn your executable into a jni subroutine, or possibly invoke it as a subprocess. And as a subprocess you probably won't be able to send Intents - but you could still communicate back to the owning app with pipes or sockets, and have it display the image or send an Intent on your behalf so that something else will.