On Android NDK project we need to access bluetooth using a HAL interface. Our intention is to do something like this:
#include <hardware/hardware.h>
#include <hardware/bluetooth.h>
....
void load_Module(....)
{
hw_module_t* module;
hw_device_t* device;
bdt_log("Loading HAL lib + extensions");
err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0){
err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
if (err == 0) {
bt_device = (bluetooth_device_t *)device;
sBtInterface = bt_device->get_bluetooth_interface();
}
}
}
Everybody seems to do the same (in google example code). There appears to be a problem when we try to compile:
#include <hardware/hardware.h> no such file
We properly added a permission to manifest and properly added libraries at Android.mk
Do we need to add something more? Is there a working project that I can refer to?
You're trying to use libhardware on Android NDK project. libhardware is a part of Android framework, not a part of NDK.
https://github.com/android/platform_hardware_libhardware
So your project doesn't have true binary compatibility of Android if you can build your project with libhardware. It would work on some devices, some versions, but no guarantee.
From my experience, I believe you can build your code on AOSP. You need to modify Android.mk for AOSP not NDK.
Related
I am attempting to use Gstreamer library on multiple platforms with my Qt project (for audio only). I already have it working on macOS with the binary files available online by just adding the framework to my .pro file:
LIBS += -F$$PWD/macOS/libs/ -framework GStreamer
INCLUDEPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/Headers
DEPENDPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/include
But now I want to use the binaries available at the same page for android. But because it is not "bundled" in a framework like on OS X I can't add it as easily. Furthermore the official explanations are made for a gradle build (which I don't know anything and don't use in Qt creator) and for use in Java. But, because I want to directly use the C API in Qt C++ I don't need JNI, and would like to directly use the library in my app like on OSX.
Thus, I tried to add the library like I would do it on any other linux, but recursively, since there is a multitude of library and header folders:
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
GSTREAMER_INCLUDE_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR = $$dirname(FILE)
if(!contains(INCLUDEPATH, $$BASEDIR)){
INCLUDEPATH += $$BASEDIR
}
}
GSTREAMER_DEPEND_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR_DEP = $$dirname(FILE)
if(!contains(DEPENDPATH, $$BASEDIR_DEP)){
DEPENDPATH += $$BASEDIR_DEP
}
}
GSTREAMER_LIB_FILES = $$files($$PWD/android/libs/gstreamer/arm64/lib/*.a, true)
for(FILE, GSTREAMER_LIB_FILES) {
BASENAME = $$basename(FILE)
LIBS += -l$$replace(BASENAME,\.a,)
}
}
But when I try the include
#include <gst/gst.h>
, it doesn't work and output 37 errors on unknown members of the global namespace related to time management like :
/Users/user/Library/Android/sdk/ndk/19.2.5345600/sources/cxx-stl/llvm-libc++/include/ctime:70:9: error: no member named 'asctime' in the global namespace
using ::asctime;
~~^
I really don't know how to use gstreamer and bundle it for android from the available official binaries and don't want to use any wrapper like qt-gstreamer (which isn't maintained by the way) or JNI.
Thanks for any help or input !
It's the first time I try to create a library c++ for Android/iOS.
I'm using Visual Studio 2015 - Xamarin.
First I created a project : Visual C++ -> Cross Platform -> Shared Library. In the hared library, I created 2 files.
SayHello.h :
#pragma once
#include <string.h>
class SayHello {
public:
SayHello();
~SayHello();
static char* Hello();
};
SayHello.cpp :
#include "SayHello.h"
extern "C"
{
SayHello::SayHello(){}
SayHello::~SayHello(){}
char * SayHello::Hello()
{
return "Hello !";
}
}
Then I generated a file libSayHello.so and created a project Android with xamarin to try to call the function hello.
There is my MainActivity.cs :
[DllImport("libSayHello.so")]
static extern String Hello();
protected override void OnCreate(Bundle bundle)
{
// I paste only my added code :
String hello = Hello();
Toast.MakeText(this.ApplicationContext, hello, ToastLength.Long);
}
I did all steps in this tutorial, but I have an exception :
System.DllNotFoundException: libSayHello.so
I searched for this, but I must be so noob cause I did not find anything. How should I use my libSayHello.so ?
EDIT:
There is my libSayHello.so seen with 7zip:
And my project :
I think this will be the best sample for you.
This all works according to the following scheme:
Android supports 7 CPU architectures.
But Xamarin supports 5 of them. So in the settings of your Xamarin.Android project check which architectures you will support:
[Xamarin.Droid.project]->[Properties]->[Android Options]->[Advanced]->[Supported architectures]
Check which archs are necessary for your project. According to this your shared library should be compiled for these archs. And you should put your shared libraries in Xamarin.Droid.project's folder lib:
To see them in Solution Explorer you should mention them in your Xamarin.Android project's .CSPROJ.
Add there next item groups:
<ItemGroup>
<AndroidNativeLibrary Include="lib\{ARCH}\libCLib.so">
<Abi>{ARCH}</Abi>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AndroidNativeLibrary>
</ItemGroup>
{ARCH} could be next: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64.
Now you can put DllImport in your code:
[DllImport("libCLib", EntryPoint = "clib_add")]
public static extern int Add(int left, int right);
I think you have to tell about entry point, because i had runtime errors without this statement System.EntryPointNotFoundException.
And don't forget to add next in your code:
using System.Runtime.InteropServices;
Confirm the library is put in "/lib/{arch}/" folder.
Try [DllImport("SayHello")]. the engine may add "lib" and ".so" automatically.
The title says it all. I'm using NDK to build a native library for use with Unity (the game engine, not the Ubuntu shell). I already have much of the code in place and it works on my Xperia Z Ultra which runs Android 4.4.4. However, recently I sent the app to some other people to test on their phones, and it worked on none of their phones. They were using Android 4.0 and 4.1, so I tried running the app on my own Android 4.0.4 device (an old Xperia Mini Pro) and had the same problem. After much narrowing down, I've found out that the root of the problem is including OpenCV in the build, even if it's not referenced at all.
Here's the code I have now. First, the simplest CPP file you've seen:
//Test.cpp:
extern "C"
{
int Test(int a, int b)
{
return a + b;
}
}
Note how it doesn't even include anything from OpenCV. The makefile (or whatever it's called in the context of NDK, I'm mostly a Windows/Visual Studio person) is:
#Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#---------------------------
#note: if I comment these lines out, the library works just fine.
#if I don't, it won't load at all.
#---------------------------
OPENCV_PACKAGE_DIR := D:\Eclipse\OpenCVAndroid\OpenCV-2.4.9-android-sdk
include $(OPENCV_PACKAGE_DIR)/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
Building this project gives me a "libTest.so" file. I put this into my Unity project, at Assets/Plugins/Android/ (I've also tried putting it in Plugins/Android/libs/armeabi-v7a/, no luck). I also have a script inside unity which invokes the library:
//TestNative.cs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class TestNative : MonoBehaviour
{
[DllImport("Test")]
public static extern int Test(int a, int b);
void OnGUI()
{
try
{
GUI.Label(new Rect(0, 0, 100, 100), "2 + 3 = " + Test(2, 3));
}
catch (System.Exception e)
{
GUI.Label(new Rect(0, 0, 600, 400), e.GetType().ToString() + " " + e.Message + "\n" + e.StackTrace);
}
}
}
When I run this on my Z Ultra, it works just fine. When I run it on the Mini Pro, it fails with the exception "DllNotFoundException: Test". I've checked logcat for errors, and this is what it says:
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: E/Unity(11135): Unable to find Test
It doesn't say anything else, it just fails. The fact that it works on 4.4.4 makes me think it might have something to do with build configurations or something like that, but I can't figure out what it is. Any ideas? Thanks.
I found out, after much trial and error, that the reason for the error is that Android somehow manages to mess the library dependencies up. The work-around is to manually load the libraries in the specific order of their dependencies, using LoadLibrary. This can be done in Unity using AndroidJavaClass to avoid having to write an entire jar library just for loading the native ones.
You have to build a .so that correspond to the architecture of the device your are using.
You should look at this link :
https://developer.nvidia.com/AndroidWorks
It provides useful tools to develop on Android with Visual Studio
You can easily configure an Android Dynamic Library (.so) that correspond to the architecture you need :)
I made a Unity3d project working with C/C++ Dll.
So first I made the dll in Visual studio.
// mydll.cpp
#define EXPORT_API __declspec(dllexport)
extern "C" {
int EXPORT_API add(int a, int b)
{
return a+b;
}
}
And I added this dll into my Unity3D project and called
// C# script in Unity3D
public class TestDll : MonoBehaviour {
[DllImport("mydll")]
private static extern int add (int a, int b);
void Start() {
int a = add (100, 200);
}
}
This code works well and I got the correct result in Unity3D editor.
So I built this project to android platform and got an apk.
I installed and run this apk on my android device but the app doesn't work.
The app didn't run the Dll function.
Whats the matter? I tried to find out the solution in Google and here, but didn't get anything, yet.
Please help me.
Thanks.
Your dll must be in Plugins folder for Windows, it can work for Editor too. for Android you must replace in Plugins/Android folder. Build and write me ok
LearnCocos2D's comment is accurate.
To get Unity to DllImport() a shared library on Android, you must use an NDK compiler and specify a compile config for your target Android platform. Moreover, Unity requires you to specify the architecture of the Android platform in the build settings, eg.. "arm v7" vs "arm64".
As an aside, in Unity 2019.4 - selecting "Load on Startup" in the inspector page of my .so elicits a "DLLNotFoundException".
Overview of this: https://docs.unity3d.com/2019.4/Documentation/Manual/AndroidNativePlugins.html
NDK's CMake guide for getting you started on compiling correctly: https://developer.android.com/ndk/guides/cmake
I'm trying to use QtCreator (2.7.2) + QT (5.1.0) to build an application that runs on both desktop (Linux) and mobile (Android) platforms.
To achieve this, I need to use different pre-built libraries depending on the target platform.
How do I specify this in the .pro file?
The wizard only offers linux/mac/windows as platform choice like
unix:!mac {
message("* Using settings for Unix/Linux.")
LIBS += -L/path/to/linux/libs
}
I've tried
android {
message("* Using settings for Android.")
LIBS += -L/path/to/android/libs
}
But with both build targets only the unix:!mac gets executed/evaluated.
So my question is: How to detect the build target (called "Kits" now in QtCreator) in the .pro file and change library definitions accordingly?
I've so far only found out how to specify the platform (which seems to be the platform I'm building ON and not FOR) or the build variant RELEASE/DEBUG.
Other things I've found say I should prefix the LIB+= with the target platform like win32:LIB+=. But again, this won't work with android. Maybe I'm using a wrong syntax for the platform (android 4.2 on an arm-v7).
this works for me (Qt 5.3.2)
linux:!android {
message("* Using settings for Unix/Linux.")
LIBS += -L/path/to/linux/libs
}
android {
message("* Using settings for Android.")
LIBS += -L/path/to/android/libs
}
I'm using this in a .pro file, maybe it helps:
unix:!macx:
{
android:
{
INCLUDEPATH += "/usr/lib/boost/boost_1_47_0" \
inkscape
}
!android:
{
INCLUDEPATH += $$(BOOST_PATH) \
inkscape
}
}
macx:
{
INCLUDEPATH += "../../../../boost_1_54_0" \#$$(BOOST_PATH) \
inkscape
}