= Getting Started: Building for Android = [[TracNav(Getting-Started/TOC)]] [[PageOutline(2-3,,inline)]] Android target is available since 2.2. == Requirements == * Besides the [http://developer.android.com/sdk/index.html Android SDK], you will also need the [http://developer.android.com/tools/sdk/ndk/index.html Android NDK] (minimum version r8b). * Optional if you want to build and and run the sample application PJSUA: * [http://www.swig.org/download.html SWIG] (minimum version 2.0.5) * Eclipse with [http://developer.android.com/tools/sdk/eclipse-adt.html ADT Plugin]. * Telnet application to interact with PJSUA command line. If you are not familiar with telnet, please find a tutorial suitable for your development platform. == Build Preparation == 1. [wiki:Getting-Started/Download-Source#GettingfromSubversiontrunk Get the source code from repository], if you haven't already. This tutorial applies to PJSIP version 2.2 and above (or the 2.1 from SVN trunk dated 2013/04/24 or later). 2. Set your [wiki:Getting-Started/Build-Preparation config_site.h] to the following: {{{ #define PJ_CONFIG_ANDROID 1 #include }}} This will activate Android specific settings in the {{{config_site_sample.h}}}. == Building PJSIP == Just run: {{{ $ cd /path/to/your/pjsip/dir $ export ANDROID_NDK_ROOT=/path_to_android_ndk_dir $ ./configure-android $ make dep && make clean && make }}} Notes: * to build for other targets, e.g: arm64 (arm64-v8a), x86, or armv7, instead of just '{{{./configure-android}}}', specify the target arch in TARGET_ABI and run it, for example: {{{ TARGET_ABI=armeabi-v7a ./configure-android --use-ndk-cflags }}} * for some targets, there may be error like {{{ error: undefined reference to '__stack_chk_fail_local' }}} this can be fixed by adding {{{-fno-stack-protector}}} into CFLAGS, e.g: via {{{user.mak}}} file. * the {{{./configure-android}}} is a wrapper that calls the standard {{{./configure}}} script with settings suitable for Android target. * you may pass standard {{{./configure}}} options to this script too. * for more info, run {{{./configure-android --help}}} * other customizations are similar to what is explained in [wiki:Getting-Started/Autoconf Building with GNU] page. == Setting up the target device == To run or debug application (such as the sample applications below), first we need to setup the target device: - using virtual device: http://developer.android.com/tools/devices/index.html - using real device: http://developer.android.com/tools/device.html == Building and running pjsua sample application == #pjsua We have pjsua sample application located under {{{pjsip-apps/src/pjsua/android}}}. It is not built by default, and you need [http://www.swig.org/download.html SWIG] to build it. Follow these steps to build pjsua: 1. Make sure SWIG is in the build environment PATH. - Alternatively, update SWIG path in {{{$PJDIR/pjsip-apps/src/pjsua/android/jni/Android.mk}}} file. 1. Run {{{ndk-build}}} from directory {{{$PJDIR/pjsip-apps/src/pjsua/android}}} (note that the Android NDK root should be in the PATH), e.g: {{{ $ cd /path/to/your/pjsip/dir $ cd pjsip-apps/src/pjsua/android $ ndk-build }}} 1. Create Android project from pjsua. In Eclipse: a. From menu: '''File''' --> '''New''' --> '''Project''' a. Select '''Android Project from Existing Code''', press '''Next''' a. In ''Root Directory'', put the location of '''pjsua''' source code (i.e. {{{$PJDIR/pjsip-apps/src/pjsua/android}}}) and press '''Finish''' 1. You may need to select different Android SDK than what is configured in pjsua. You can do this from the project's '''Properties'''. 1. Run it. 1. You will see telnet instructions on the device's screen. Telnet to this address to operate the application. See [wiki:PJSUA-CLI PJSUA CLI Manual] for command reference. == Building and running pjsua2 sample application == #pjsua2 Another sample application, which is based on [https://trac.pjsip.org/repos/ticket/1519 pjsua2 high-level API] with SWIG binding, is located under {{{pjsip-apps/src/swig/java/android}}}. It is not built by default, and you need [http://www.swig.org/download.html SWIG] to build it. Follow these steps to build pjsua2 sample application: 1. Make sure SWIG is in the build environment PATH. 1. Run {{{make}}} from directory {{{$PJDIR/pjsip-apps/src/swig}}} (note that the Android NDK root should be in the PATH), e.g: {{{ $ cd /path/to/your/pjsip/dir $ cd pjsip-apps/src/swig $ make }}} 1. Create Android project from pjsua. In Eclipse: a. From menu: '''File''' --> '''New''' --> '''Project''' a. Select '''Android Project from Existing Code''', press '''Next''' a. In ''Root Directory'', put the location of '''pjsua2''' source code (i.e. {{{$PJDIR/pjsip-apps/src/swig/java/android}}}) and press '''Finish''' 1. You may need to select different Android SDK than what is configured in pjsua2. You can do this from the project's '''Properties'''. 1. Run it. === Log output === The pjsua2 sample application will write log messages to '''!LogCat''' window (to show !LogCat window, from Eclipse menu: '''Window''' --> '''Show View''' --> '''Other''' --> type ''!LogCat'') == Debugging native code with Eclipse == #debug-native Here are the steps for debugging PJSIP native code using Eclipse: 1. Build PJSIP with debugging enabled, e.g: insert {{{CFLAGS += -g}}} into {{{user.mak}}} in PJSIP root directory. 1. Make sure that the JNI part of the application is built using {{{ndk-build}}}. For reference, check pjsua's {{{Android.mk}}} build config in {{{pjsip-apps/src/pjsua/android/jni}}}, it contains sample of how to import PJSIP build settings (build search paths, build flags, etc) and SWIG invocation. 1. Enable NDK plugin for Eclipse, check [http://tools.android.com/recent/usingthendkplugin this] and follow the instructions. - CDT can also be fetched from [http://www.eclipse.org/cdt/downloads.php CDT download page], normally Eclipse for C/C++ will have CDT installed, just make sure that the CDT version is 7.0.2 or newer. 1. It is recommended to introduce delay (about 5 seconds) in the application code between loading the native code library and calling any native functions (to be debugged), e.g: {{{ try { System.loadLibrary("some_native_lib.so"); } catch (UnsatisfiedLinkError e) { return -1; } // Wait for GDB init if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { try { Thread.sleep(5000); } catch (InterruptedException e) { } } // Start calling native functions here // ... }}} 1. Load the PJSIP project to Eclipse (if not yet), and try put breakpoint anywhere in the PJSIP code before launching the Android application debug configuration in Eclipse. == Important Issue(s) when Developing Android Apps == #issues === Unable to Make or Receive Call (Problem with sending and receiving large (INVITE) requests over TCP) === #invite The issue is documented in #1488. The solution is to try using port other than 5060 in *both* client and server, and/or reducing the SIP message size by following our [https://trac.pjsip.org/repos/wiki/FAQ#sip-msg-size FAQ here]. === Garbage Collector May Crash Your App (Pjsua2 API) === #gc There are two problems with Java garbage collector (gc): - it delays the destruction of Java objects (including pjsua2 objects), causing the code in object's destructor to be executed out of order - the gc operation may be run on different thread, not previously registered to PJLIB Due to problems above, '''application MUST immediately destroy pjsua2 objects using object's delete() method''', instead of relying on the gc to clean up the object. For example, to delete an Account: {{{ acc.delete(); }}} === OpenSLES audio device deadlock upon shutdown === #opensl As reported in [https://groups.google.com/forum/#!topic/android-ndk/G7dLKAGGL28 Android NDK forum], when shutting down OpenSLES sound device backend, it may block forever: {{{ W/libOpenSLES(6434): frameworks/wilhelm/src/itf/IBufferQueue.c:57: pthread 0x5fce71c0 (tid 6670) sees object 0x5fcd0080 was locked by pthread 0x5f3a2cb0 (tid 6497) at frameworks/wilhelm/src/itf/IObject.c:411 }}} Currently, the only workaround is to use PJSIP's Android JNI sound device instead (one way to do this is by defining PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI to 1 and PJMEDIA_AUDIO_DEV_HAS_OPENSL to 0). === Bad audio recording quality on some devices === #badrecord Reported that audio quality recorded on the microphone is bad and the speed is twice what it should be, it only happens on some devices. It could be fixed by setting audio mode via {{{AudioManager}}} to {{{MODE_IN_COMMUNICATION}}} in the application, e.g: {{{ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int original_mode = am.getMode(); /* Set audio mode before using audio device, for example before making/answering a SIP call */ am.setMode(AudioManager.MODE_IN_COMMUNICATION); ... /* Restore back to the original mode after finished with audio device */ am.setMode(original_mode); }}} == Other Android projects == Also have a look at the following PJSIP Android project: * [http://code.google.com/p/csipsimple/ csipsimple] project, an Android port of pjsip.