I would like to develop a plugin for the default android browser which would specify the category of sites in the google search result. The android browser dont explicitly show plugin architecture. I would like to know how that can be done and any reference materials related to that.
Thanks,
I recently tried to make an android plugin and found many questions on SO but not many detailed answers, so I'd thought I'd share my research here even though the question is quite old now. I'm not sure if a plugin is really what you want to do here since you could probably use google's JSON/ATOM Custom Search API and parse that, but nonetheless I give details on how to get plugins working on Android. I hope it is useful for others.
If you look here: PluginManager.java you will see the following lines:
// Only plugin matches one of the signatures in the list can be loaded
// inside the WebView process
private static final String SIGNATURE_1 = "308204c5..."
The signature used here is the one for the Adobe Flash plugin (support for which has now been dropped by Adobe.)
and further down here you will see:
if (SystemProperties.getBoolean("ro.secure", false)) {
boolean signatureMatch = false;
for (Signature signature : signatures) {
for (int i = 0; i < SIGNATURES.length; i++) {
if (SIGNATURES[i].equals(signature)) {
signatureMatch = true;
break;
}
}
}
if (!signatureMatch) {
return false;
}
}
This means that if ro.secure=0 then it won't check the signatures - it would only allow the flash plugin otherwise.
ro.secure is a build property that you can set if you have root privaleges for your device or you have a dev build (type adb shell getprop ro.secure to find out what you have). You can research how to change this if necessary. I was using a Qualcomm Snapdragon MDP8960 which is development board which had ro.secure=0 already. To get your plugin signature included in android you'll have to talk to someone in charge - not sure how feasible this is at present.
Now to write a plugin - you can find an example called SampleBrowserPlugin in the android sourcetree (make sure you have a 64 bit linux machine if you want to build it - type make SampleBrowserPlugin from the source tree root. You might need to set up the build configuration first using lunch and you can find instructions on the android source tree site)
I actually grabbed the source I needed from android source on github and made an NDK build of the source as I am more familiar with how to do this than modifying the android build scripts. It will also be a lot faster than downloading the whole android tree - you can see what to download by looking at what is included in Android.mk (see below).
Basically, I pulled the shared object libraries that I needed from the device to make sure my plugin would be compatible. They were in /system/lib on my device: (e.g. type adb pull /system/libnativehelper.so etc from the directory where you want them stored)
get the following:
libnativehelper.so
libandroid.so
libutils.so
libcutils.so
libEGL.so
libGLESv2.so
libskia.so
Put them where SO_LIB_PATH points to in Android.mk (see below and change Path as necessary).
Then after installing the NDK sdk you should be able to use the following build script - don't need a 64 bit machine - (you can install winbash, use cygwin, or a linux virtual machine e.g. Oracle VM VirtualBox:
(Place these files in C:/Path/BrowserPlugin/jni/ and make sure the ndk-build command is on your path)
(if you're on linux remove the .cmd from ndk-build.cmd)
build.sh:
#!/bin/bash
echo -e "Mode\t\t: Debug"
OPTIM=debug
### ---------------- Generic Build Command ----------------
# run NDK build
ndk-build.cmd \
-d \
-B \
NDK_DEBUG=1 \
NDK_PROJECT_PATH=C:/Path/BrowserPlugin/jni \
NDK_APPLICATION_MK=C:/Path/BrowserPlugin/jni/Application.mk \
NDK_MODULE_PATH=C:/Path/BrowserPlugin/jni \
NDK_APP_OUT=C:/Path/BrowserPlugin/jni/Out/ \
APP_BUILD_SCRIPT=C:/Path/BrowserPlugin/jni/Android.mk \
APP_OPTIM=$OPTIM
cp C:/Path/BrowserPlugin/jni/Out/local/armeabi/libsampleplugin.so C:/Path/BrowserPlugin/libs/armeabi/.
echo "copied libsampleplugin.so into PROJECT_ROOT/libs dir"
Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
main.cpp \
PluginObject.cpp \
RenderingThread.cpp \
animation/AnimationPlugin.cpp \
animation/AnimationThread.cpp \
audio/AudioPlugin.cpp \
background/BackgroundPlugin.cpp \
form/FormPlugin.cpp \
navigation/NavigationPlugin.cpp \
paint/PaintPlugin.cpp \
video/VideoPlugin.cpp \
jni-bridge.cpp \
WEBCORE_PATH := C:/Path/AndroidBrowserPlugin/webkit/Source/WebCore
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH) \
$(LOCAL_PATH)/animation \
$(LOCAL_PATH)/audio \
$(LOCAL_PATH)/background \
$(LOCAL_PATH)/form \
$(LOCAL_PATH)/navigation \
$(LOCAL_PATH)/paint \
$(LOCAL_PATH)/video \
$(WEBCORE_PATH)/bridge \
$(WEBCORE_PATH)/plugins \
C:/Path/AndroidBrowserPlugin/webkit/Source/WebKit/android/JavaVM \
C:/Path/AndroidBrowserPlugin/webkit/Source/WebKit/android/plugins \
C:/Path/AndroidBrowserPlugin/platform_external_skia/include/core \
C:/Path/AndroidBrowserPlugin/frameworks_native/include \
C:/Path/AndroidBrowserPlugin/frameworks_native/libs \
C:/Path/AndroidBrowserPlugin/frameworks_native/opengl/libs \
C:/Path/AndroidBrowserPlugin/platform_system_core/include \
C:/Path/AndroidBrowserPlugin/frameworks_native/opengl/include \
C:/Users/user/android-ndk-r8c/platforms/android-14/arch-arm/usr/include \
C:/Path/AndroidBrowserPlugin/BrowserPlugin/jni/libs/armeabi \
C:/Path/AndroidBrowserPlugin/platform_bionic \
C:/Path/AndroidBrowserPlugin/platform_bionic/libc/private \
C:/Path/AndroidBrowserPlugin/platform_hardware_libhardware/include
SO_LIB_PATH := C:/Path/AndroidBrowserPlugin/libs_qualcomm_MDP8960
LOCAL_LDLIBS := \
-L$(SO_LIB_PATH)/ -lnativehelper -landroid -lutils -lcutils -lEGL -lGLESv2 -lskia
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_CFLAGS += -DHAVE_PTHREADS -DANDROID
LOCAL_MODULE:= libsampleplugin
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
Application.mk:
# =============================================================================
#
# Main build file defining the project modules and their global variables.
#
# =============================================================================
# Don't remove this - mandatory
APP_PROJECT_PATH := $(call my-dir)
# The only STL implementation currently working with exceptions
APP_STL := gnustl_static
# Don't optimize for better debugging
APP_OPTIM := debug
You may also need some header files (e.g. JNIHelp.h) which you can place e.g. in the root where you are doing the ndk build BrowserPlugin/jni/.
Hopefully bash build.sh should build your libsampleplugin.so which the build script copies into the app directory. You can then e.g. import the project into eclipse and build the app. Install it on the device, then e.g. use WAMP server to host the following file:
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Test Plugin</title>
</head>
<body>
<object type="application/x-testbrowserplugin" height=50 width=250 id="testPlugin">
<param name="DrawingModel" value="Bitmap" />
<param name="PluginType" value="Form" />
</object>
</body>
</html>
run ipconfig from your host machine to get the IP address e.g. 192.168.x.x
Then point your device browser to e.g. http://192.168.x.x/ and voila you should see a form plugin.
I couldn't get the animation plugins to work properly, and the form plugin didn't work fully, but at least the plugin was recognised and loaded ok.
Now, you can write a webkit NPAPI plugin to do what you like either using the sample plugin browser as a guide, or other internet resources.
This is actually quite interesting topic which was discussed recently during blackhat 2014 (FakeID) but in a bit different context. They've found security bug in signature validation.
In your case there are two helpful links :
1) http://androidxref.com/4.3_r2.1/xref/frameworks/base/tests/BrowserTestPlugin/ This is the newest sample of writing webkit plugins. Try to build it - it will require to have webkit external statically linked otherwise you will get ‘ fatal error: android_npapi.h: No such file or directory’
2) http://androidxref.com/2.2.3/xref/development/samples/BrowserPlugin/ This is older sample but it has wider description of "how to build" browser plugin
Use combination of both link to start your plugin development
However this doesn't solve signature check problem. Even if the plugin is recognised it won't be allowed to run. I'm not sure what is the process with google to do browser plugin development
Related
I've spent a day on this and can't seem to configure my dev environment for a NDK toolchain that will support standard C++ libraries. The story is I'm trying to cross compile libnfnetlink and libnetfilter_queue for ARM (Android).
First I'm using the following:
Nexus 5 with CyanogenMod 11 (I forget, doesn't matter I'm not even on the device yet)
Ubuntu 12.04 32-bit
Android SDK bundle: adt-bundle-linux-x86-20140702
Android NDK: android-ndk-r10c
There is a great blog on doing this here but its incomplete as Netfilter uses stlc++ and there's no word on a NDK install/setup that would work with simply calling ndk-build. Just copying the files into /jni and calling ndk-build won't work alone.
Anyways, my specific problem is when I straight copy the Netfilter lib source structure into an empty Project's /jni directory, I get this:
user#ubuntu:~/Projects/NetfilterTest/NetfilterNativeTest/jni$ ndk-build
[armeabi] Compile thumb : netfilter_queue <= libnetfilter_queue.c
In file included from /home/user/Projects/NetfilterTest/NetfilterNativeTest/jni/libnetfilter_queue/src/libnetfilter_queue.c:35:0:
/home/user/Projects/NetfilterTest/NetfilterNativeTest/jni/libnetfilter_queue/src/internal.h:4:20: fatal error: config.h: No such file or directory
compilation terminated.
make: *** [/home/user/Projects/NetfilterTest/NetfilterNativeTest/obj/local/armeabi/objs/netfilter_queue/libnetfilter_queue/src/libnetfilter_queue.o] Error 1
The config.h file can't be found. After some googling I realize its because the standard C++ libraries aren't available in the prebuilt tool chains.
Everything points to me creating my own tool chain. So I build my own cross compiler using the scripts that the NDK includes.
cd /home/user/android-ndk-r10c/build/tools
./make-standalone-toolchain.sh --platform=android-19 --ndk-dir=/home/user/android-ndk-r10c/ --install-dir=/home/user/android-ndk-r10c/prebuilt/android-arm/android-19
To confirm that config.h is included in my tool chain I searched for it. It's there:
user#ubuntu:~/Projects/NetfilterTest/NetfilterNativeTest/jni$ find /home/user/android-ndk-r10c/prebuilt/android-arm/android-19/ -iname config.h
/home/user/android-ndk-r10c/prebuilt/android-arm/android-19/sysroot/usr/include/linux/config.h
Naturally I need to setup my environment and the Android.mk
JAVA_HOME=/usr/local/java/jdk1.6.0_45
JRE_HOME=$JAVA_HOME/jre
ANDROID_SDK=/home/user/adt-bundle-linux-x86-20140702
ANDROID_NDK=/home/user/android-ndk-r10c
ANDROID_CHAIN=/home/user/android-ndk-r10c/prebuilt/android-arm/android-19
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$ANDROID_SDK/sdk/platform-tools:$ANDROID_SDK/sdk/tools:$ANDROID_NDK:$ANDROID_CHAIN/bin
SYSROOT=$ANDROID_NDK/platforms/android-19/arch-arm
CC=arm-linux-androideabi-gcc
export CC
export ANDROID_SDK
export ANDROID_NDK
export SYSROOT
export JAVA_HOME
export JRE_HOME
export PATH
Here's my Android.mk (based on Roman10's blog:
LOCAL_PATH:=$(call my-dir)
#####################################################################
# build libnflink #
#####################################################################
include $(CLEAR_VARS)
LOCAL_MODULE:=nflink
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libnfnetlink/include
LOCAL_SRC_FILES:=\
libnfnetlink/src/iftable.c \
libnfnetlink/src/rtnl.c \
libnfnetlink/src/libnfnetlink.c
include $(BUILD_STATIC_LIBRARY)
#####################################################################
# build libnetfilter_queue #
#####################################################################
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink/include \
$(LOCAL_PATH)/libnetfilter_queue/include
LOCAL_MODULE:=netfilter_queue
LOCAL_SRC_FILES:=libnetfilter_queue/src/libnetfilter_queue.c
LOCAL_STATIC_LIBRARIES:=libnflink
include $(BUILD_STATIC_LIBRARY)
#####################################################################
# build our code #
#####################################################################
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libnfnetlink/include \
$(LOCAL_PATH)/libnetfilter_queue/include
LOCAL_MODULE:=nfqnltest
#LOCAL_LDLIBS:=-lstdc++
LOCAL_SRC_FILES:=nfqnl_test.c
LOCAL_STATIC_LIBRARIES:=libnetfilter_queue
LOCAL_LDLIBS:=-llog -lm
include $(BUILD_EXECUTABLE)
I still get config.h not found using ndk-build.
I've read that the ndk-build command leverages a config.mk/setup.mk that Google includes in the NDK and has to be modified to point to an alternative toolchain.
I'm completely floored that Google's own tools can't simply point to a custom toolchain that they give you scripts to create. If anyone has any suggestions on how I can use my toolchain to compile Netfilter or just in general it would be a great help.
Thanks in advance!
I can't find any reference to either internal.h or config.h when I search for a version of libnetfilter_queue.c on the web, so I'm not sure what version of the file you're using - can you point to which one you have?
Also, the config.h it looks for isn't the one you found in your toolchain (which should be included as linux/config.h) but most probably is one that you're expected to generate by running a configure script. So unless you've run the configure script (or have a pregenerated config.h from elsewhere) you can't really build it.
Finally, nothing of this has anything to do with libstdc++ since all your source files seem to be pure C, not C++.
I'd like to use GStreamer in my Android application. So far, I can already create GstNetClock and use it successfully.
If I try to create a playbin2 element, the factory always returns NULL. My code:
GstElement* player = gst_element_factory_make("playbin2", NULL);
The relevant lines of jni/Android.mk:
GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) \
$(GSTREAMER_PLUGINS_PLAYBACK) \
$(GSTREAMER_PLUGINS_CODECS) \
$(GSTREAMER_PLUGINS_NET) \
$(GSTREAMER_PLUGINS_SYS)
GSTREAMER_EXTRA_DEPS := gstreamer-net-0.10 \
gstreamer-interfaces-0.10 \
gstreamer-video-0.10 \
gstreamer-plugins-base-0.10
In addition I tried to increase log verbosity of GStreamer to GST_LEVEL_LOG. However no logs are shown at all (as with default settings).
Do I have to load additional plugins or libraries? Or should I configure anything differently?
Please check if you can run at command prompt gst-inspect-0.10 playbin2. You might have an earlier deprecated version which is playbin. Try running that also.
A: Don't think you will require extra plugins as playbin2 is part of gst-plugins-base
I am trying to port libCurl to android with SSL support,
step one would be to port the curl without ssl support I guess so I started doing that. but I run into a problem.
as I read on the dev website and in the Android.mk file, the hard part is configuring the make first. so what I did is :
Download Android Source code (and compile it! since some of the intermediate libs are needed)
Download cURL
unpack curl under : {android_src}/external/curl
make the configure script for curl by creating a sh file in the external/curl folder with this content.
`
export A=/home/user/Development/AOSP/2.3.3
export CC=$A/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc
export NDK=/home/user/Development/Tools/sdk/android/ndk
export NDKLIBS=$NDK/platforms/android-4/arch-arm/usr/include
export SYSROOT=$A/ndk/build/platforms/android-4/arch-arm
export CPPFLAGS="-I $A/system/core/include"
export LDFLAGS="-L$A/out/target/product/generic/obj/lib/ -L$A/out/target/product/generic/system/lib/-L$SYSROOT/usr/lib -Wl,--gc-sections -nostdlib -lc -lm -ldl -llog -lgcc -Wl,--no-undefined,-z,nocopyreloc -Wl,-dynamic-linker,/system/bin/linker -L$NDK/out/target/product/generic/obj/lib/"
export CFLAGS="-fno-exceptions -Wno-multichar -mthumb -mthumb-interwork -nostdlib -lc -ldl -lm -march=armv5te -mtune=xscale -msoft-float -mandroid -fPIC -mthumb-interwork -mthumb -mlong-calls -ffunction-sections -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DOS_ANDROID -D__NEW__ -D__SGI_STL_INTERNAL_PAIR_H -I$SYSROOT/usr/include -I $A/system/core/include -I $NDKLIBS"
./configure --host=arm-eabi --with-ssl=$A/external/openssl
`
And the output summary is this one :
configure: Configured to build curl/libcurl:
curl version: 7.26.0
Host setup: arm-unknown-eabi
Install prefix: /usr/local
Compiler: /home/tanco/Development/AOSP/2.3.3/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc
SSL support: no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls} )
SSH support: no (--with-libssh2)
zlib support: enabled
krb4 support: no (--with-krb4*)
GSSAPI support: no (--with-gssapi)
SPNEGO support: no (--with-spnego)
TLS-SRP support: no (--enable-tls-srp)
resolver: default (--enable-ares / --enable-threaded-resolver)
ipv6 support: no (--enable-ipv6)
IDN support: no (--with-libidn)
Build libcurl: Shared=no, Static=yes
Built-in manual: enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors: enabled (--disable-verbose)
SSPI support: no (--enable-sspi)
ca cert bundle: /etc/ssl/certs/ca-certificates.crt
ca cert path: no
LDAP support: no (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support: no (--enable-ldaps)
RTSP support: enabled
RTMP support: no (--with-librtmp)
Protocols: DICT FILE FTP GOPHER HTTP IMAP POP3 RTSP SMTP TELNET TFTP
SONAME bump: yes - WARNING: this library will be built with the SONAME
number bumped due to (a detected) ABI breakage.
See lib/README.curl_off_t for details on this.
First strange thing that comes to mind is why is SSL not included in the config since the linker shows to the intermediate libs and ssl support flag is called, but after when I use the same curl_config.h file in the jni project which I created for the build (since it has a standalone Android.mk file it can be compiled simply by unzipping in the jni folder of a android project, copying the config file created in the AOSP source and calling ndk-build)
so I compile and I get :
$ ndk-build
Compile thumb : curl <= url.c
In file included from /Projects/temp/testNDK/jni/lib/url.c:32:0:
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h: In function 'getpagesize':
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h:171:3: warning: nested extern declaration of '__page_size' [-Wnested-externs]
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h: In function '__getpageshift':
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h:175:3: warning: nested extern declaration of '__page_shift' [-Wnested-externs]
/Projects/temp/testNDK/jni/lib/url.c: At top level:
/Projects/temp/testNDK/jni/lib/url.c:57:2: error: #error "We can't compile without socket() support!"
make: *** [/Projects/temp/testNDK/obj/local/armeabi/objs/curl/lib/url.o] Error 1
Here is the solution, updated to NDK8c
step zero: download and fix the Android NDK
I don't know how but the ndk has a very interesting flaw, which (in my oppinion) doesn't allow you to compile lot's of stuff, so to be able to compile OpenSSL you need to make a small fix, extract the ndk8c whereever you keep your tools, and then edit the file :
android-ndk-r8c/build/gmsl/__gmsl
line 512 :
change line
int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
with line
int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$(__gmsl_input_int))
And you're good to go!
step one : Download OpenSSL and compile for Android :
either compile a ported version found here
or Download the official 1.0.0c version of OpenSSL and then compile it for android using the manual provided in the github I linked for the Android compatible version
So the next step is to get the libssl.so and libcrypto.so
and put the them in the NDK folder for easy access, so copy them from
openssl-folder/libs/armeabi/
to
android-ndk-r8c/platforms/android-8/arch-arm/usr/lib
this way when compiling you can include the libs using a simple linker switch -lssl -lcrypto
Step two : get Curl's latest source for here
Open the file in Docs/INSTALL and follow the steps needed to make the standalone toolchain and put in your desired folder, and then the tricky part, I needed to have android's source code for the config to continue, even though I have a standalone compiled openssl you can include the header files from there too, in anycase this is the more complicated version so you choose what you do, I did not choose to evade them so you can go to Google AOSP site and go trough the steps to build and initialize the environment.
so it would be something like :
1.download,
go to root of the source code and run :
~: build/envsetup.sh; lunch 1; make;
So finally we need to compile curl with SSL support, so,
Step three
extract curl to the desired folder
(I have a specific desire of disabling everything except http/s to keep the library as small as possible meaning about ~300k, if you want more protocols in your lib, remove the --disable-protocol for the desired protocol)
run the following :
make clean
export PATH=/opt/arm-linux-androideabi-4.4.3/bin:$PATH
export LDFLAGS="\
-lssl \
-lcrypto \
-L/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/lib"
export CFLAGS="\
-I/home/user/Development/AOSP/2.3.7/system/core/include \
-I/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/include"
./configure --host=arm-linux-androideabi \
--with-ssl=/home/user/Development/Projects/portingLibs/openssl-android-master \
--disable-ftp \
--disable-gopher \
--disable-file \
--disable-imap \
--disable-ldap \
--disable-ldaps \
--disable-pop3 \
--disable-proxy \
--disable-rtsp \
--disable-smtp \
--disable-telnet \
--disable-tftp \
--without-gnutls \
--without-libidn \
--without-librtmp \
--disable-dict
make
Note that in the block above, if you don't want to use the AOSP source, you could switch
-I/home/user/Development/AOSP/2.3.7/system/core/include \
with the include folder for your ssl distribution.
So finally you have :
static :
curl-7.28.1/lib/.libs/libcurl.a
and shared :
curl-7.28.1/lib/.libs/libcurl.so.5.3
So that's it.. take the file, and compile away :)
I like the way to use Docker for building such static libs. There is full script here - you just run it and grab the result. Sample: https://gist.github.com/VictorLaskin/1c45245d4cdeab033956
Such script will:
setup compilation tools / utils download sdk/ndk
create custom cross-compilation toolchain download source code for libs (zlib, openssl, curl)
setup environment settings for cross compilation
configure and make libs
gather output at one folder and create the way to get
compiled libs
This specific version is using latest NDK 10e and clang toolchain.
There is post with more details here: http://vitiy.info/dockerfile-example-to-compile-libcurl-for-android-inside-docker-container/
I hope this will help someone to not waste precious time.
Steps for compiling libcurl.so with ssl support for android jni could be found here :
http://ieroot.com/2015/03/29/1728.html
I struggled for a week for figuring out it.
Ask if any questions. I'll reply as soon as possible.
I've been trying for a couple days to compile a native ARM Android binary that will execute on my phone using a terminal application. I want to generate the same type of binary as the standard Posix binaries installed on the phone like ls, mkdir etc. I've downloaded the Android NDK under Mac OS X and have been able to compile simple ELF binaries without errors. However, when I transfer them to the phone, they always segfault. That is, they segfault when compiled with -static in GCC. If I don't use -static, they complain about not being linked, etc. Put simply, they don't work.
My hypothesis is that they are not linking to the Android standard C library properly. Even though I am linking my binaries with the libc provided by the NDK, they still don't work. I read that Android uses the Bionic C library, and tried to download source for it but I'm not sure how to build a library from it (it's all ARM assembly, it seems).
Is it true that the Android C library on the phone is different from the one provided with the Android NDK? Will the one included with the NDK not allow me to compile native binaries I can execute through a terminal? Any guidance here is greatly appreciated!
Update:
I finally got this to work using GCC 4.7.0 on Mac OS X. I downloaded the Bionic headers and then compiled a dynamically linked binary using the C library that comes with the Android NDK. I was able to get a test app to work on the phone using the phone's C lib (the binary was 33K). I also tried to statically link against the NDK's C library, and that also worked.
In order to get this all working I had to pass -nostdlib to GCC and then manually add crtbegin_dynamic.o and crtend_android.o to GCC's command line. It works something like this:
$CC \
$NDK_PATH/usr/lib/crtbegin_dynamic.o \
hello.c -o hello \
$CFLAGS \
$NDK_PATH/usr/lib/crtend_android.o
For static binaries, use "crtbegin_static.o." This is explained in the crtbegin_dynamic.S/crtbegin_static.S source.
For this experiment, I only used plain 'ol GCC 4.7.0 and Binutils 2.22. I also compiled GCC with newlib, but I am not actually linking my ARM binaries with newlib at all. I am forcing GCC/ld to link directly to the libc provided with the Android NDK, or in the case of dynamic binaries, to the libc on the phone.
Just use the android-ndk. And build a Android.mk like so.
include $(BUILD_EXECUTABLE) is what tells it build a executable instead of a JNI .lib
Android.mk
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -Wall
LOCAL_LDLIBS := -L$(LOCAL_PATH)/lib -llog -g
LOCAL_C_INCLUDES := bionic
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_SRC_FILES:= main.cpp
LOCAL_MODULE := mycmd
include $(BUILD_EXECUTABLE)
endif # TARGET_SIMULATOR != true
First, make sure you have the NDK:
http://developer.android.com/tools/sdk/ndk/index.html
Here is the easiest way to compile a C binary for your phone:
http://developer.android.com/tools/sdk/ndk/index.html
http://www.kandroid.org/ndk/docs/STANDALONE-TOOLCHAIN.html
Usually $NDK(may be different) =
Linux:
/home/<user>/android-ndk
Mac OS X:
/Users/<user>/android-ndk
In Terminal:
# create tool-chain - one line
# New method in ndk 12.
$NDK/build/tools/make_standalone_toolchain.py --arch arm --install-dir=/tmp/my-android-toolchain
# Old method.
#$NDK/build/tools/make-standalone-toolchain.sh --platform=android-3 --install-dir=/tmp/my-android-toolchain
# add to terminal PATH variable
export PATH=/tmp/my-android-toolchain/bin:$PATH
# make alias CC be the new gcc binary
export CC=arm-linux-androideabi-gcc
# compile your C code(I tried hello world)
$CC -o foo.o -c foo.c
# push binary to phone
adb push foo.o /data/local/tmp
# execute binary
adb /data/local/tmp/foo.o
Using CMake with the Android NDK is a nice way to compile Android console applications.
Download CMake and android-cmake (set it up like this). If your program is called main.c, then write the following in file CMakeLists.txt:
project(test)
cmake_minimum_required(VERSION 2.8)
add_executable(test ./main.c)
and run cmake -DCMAKE_TOOLCHAIN_FILE=$ANDTOOLCHAIN .
You will then have a Makefile for your program, you can run make to have your test executable.
In CMake, you can cross build using toolchain files.
From google developers:
cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
CMake has its own built-in NDK support. Before CMake 3.21, this workflow is not supported by Android and is often broken with new NDK releases. Starting from CMake 3.21, the implementations are merged.
Starting from cmake 3.21 you can:
mkdir build
cd build
cmake ..
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=23 # API level. optional, recommanded
-DCMAKE_ANDROID_NDK=path/to/ndk
-DCMAKE_ANDROID_ARCH=arm # optional, recommanded
-DCMAKE_ANDROID_ARCH_ABI=armeabi # optional, recommanded
Note: in the command above, line endings (<line feed>) are not escaped, please don't copy-paste this command directly in your shell
See Cross Compiling for Android with the NDK for more information about variables, possible values, and determenation algorithms.
Try if if the agcc wrapper can help you as referenced in the Android-tricks blog. According to the blog post you want to use the bionic library, but the one already installed on the phone, not some separately compiled version.
I'm building some common gnu/linux console utilities for my Android phone but so far I have only been able to build them statically, with quite a size penalty. Can someone walk me through the steps for synamic compiles using shared libraries?
Here's the script(s) I'm using for configuration:
./configure --host=arm-none-linux-gnueabi \
CC="arm-none-linux-gnueabi-gcc" \
CROSS_COMPILE="arm-none-linux-gnueabi-" \
CFLAGS=" -static $_XXFLAGS" \
for shared:
./configure --host=arm-none-linux-gnueabi \
CC="arm-none-linux-gnueabi-gcc" \
CROSS_COMPILE="arm-none-linux-gnueabi-" \
--enable-shared=yes --enable-static=no
Do I need to make the libs on my android phone avaiable
to my cross-compiler? Google isn't helping me here.
You would have to provide the location for the shared libraries that you want to link against. Please post the error that you're getting for a better answer, but take a look at my answer to
install 64-bit glib2 on 32-bit system for cross-compiling
You should just need to add the right -L and -Wl,-rpath-link to the CFLAGS variable when you're running configure.