Index: /pjproject/branches/projects/pjsua2/build.mak.in
===================================================================
--- /pjproject/branches/projects/pjsua2/build.mak.in	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/build.mak.in	(revision 4691)
@@ -115,4 +115,11 @@
 	-I$(PJDIR)/pjsip/include
 export APP_CXXFLAGS := $(APP_CFLAGS)
+#  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x
+#
+# FIX THIS
+#
+# pjsua2 is c++ library hence maybe needs to be put in separate
+# variables. it will also require -lstdc++ or -static-libstdc++
+#  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x
 export APP_LDFLAGS := -L$(PJDIR)/pjlib/lib\
 	-L$(PJDIR)/pjlib-util/lib\
@@ -122,4 +129,5 @@
 	-L$(PJDIR)/third_party/lib\
 	$(PJ_VIDEO_LDFLAGS) \
+	-static-libstdc++ \
 	@LDFLAGS@
 #  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x
@@ -145,6 +153,5 @@
 	$(APP_THIRD_PARTY_EXT)\
 	-lpj-$(TARGET_NAME)\
-	@LIBS@ \
-	-lstdc++
+	@LIBS@
 #  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x  x   x  x  x  x  x
 #
Index: /pjproject/branches/projects/pjsua2/configure-android
===================================================================
--- /pjproject/branches/projects/pjsua2/configure-android	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/configure-android	(revision 4691)
@@ -87,9 +87,9 @@
   export CXX="${NDK_CXX}"
 
-  export LDFLAGS="${LDFLAGS} -nostdlib -L${ANDROID_SYSROOT}/usr/lib/"
-  export LIBS="${LIBS} -lc -lgcc"
-  export CFLAGS="${CFLAGS} ${NDK_CFLAGS}"
-  export CPPFLAGS="${CFLAGS}"
-  export CXXFLAGS="${NDK_CXXFLAGS}"
+  export LDFLAGS="${LDFLAGS} -nostdlib -L${ANDROID_SYSROOT}/usr/lib/ -L${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi"
+  export LIBS="${LIBS} -lgnustl_static -lc -lgcc ${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o"
+  export CFLAGS="${CFLAGS} ${NDK_CFLAGS} -I${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/include -I${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi/include"
+  export CPPFLAGS="${CFLAGS} -fexceptions -frtti"
+  export CXXFLAGS="${NDK_CXXFLAGS} -fexceptions -frtti"
 
 else
@@ -111,9 +111,9 @@
   export CXX="${ANDROID_TC}/bin/${TARGET_HOST}-g++"
 
-  export LDFLAGS="${LDFLAGS} -nostdlib -L${ANDROID_SYSROOT}/usr/lib/"
-  export LIBS="${LIBS} -lc -lgcc"
-  export CFLAGS="${CFLAGS} -I${ANDROID_SYSROOT}/usr/include"
-  export CPPFLAGS="${CFLAGS}"
-  export CXXFLAGS="${CXXFLAGS} -shared --sysroot=${ANDROID_SYSROOT}"
+  export LDFLAGS="${LDFLAGS} -nostdlib -L${ANDROID_SYSROOT}/usr/lib/ -L${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi"
+  export LIBS="${LIBS} -lgnustl_static -lc -lgcc ${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o"
+  export CFLAGS="${CFLAGS} -I${ANDROID_SYSROOT}/usr/include -I${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/include -I${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi/include"
+  export CPPFLAGS="${CFLAGS} -fexceptions -frtti"
+  export CXXFLAGS="${CXXFLAGS} -shared --sysroot=${ANDROID_SYSROOT} -fexceptions -frtti"
 
 fi
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/build/Makefile
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/build/Makefile	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/build/Makefile	(revision 4691)
@@ -97,4 +97,5 @@
 	$(MAKE) -f $(RULES_MAK) APP=PJSYSTEST app=pjsystest $@
 	$(MAKE) -f Samples.mak $@
+	$(MAKE) -C ../src/swig $@
 	@if test "$@" = "depend"; then \
 	  echo '$(PJSUA_EXE): $(APP_LIB_FILES)' >> .pjsua-$(TARGET_NAME).depend; \
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/Makefile
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/Makefile	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/Makefile	(revision 4691)
@@ -1,3 +1,10 @@
-DIRS = python java
+include ../../../build.mak
+
+ifneq ($(findstring android,$(TARGET_NAME)),)
+  # no python for android
+  DIRS = java
+else
+  DIRS = python java
+endif
 
 export SWIG_FLAGS=-I../../../../pjlib/include \
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/Makefile
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/Makefile	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/Makefile	(revision 4691)
@@ -1,16 +1,24 @@
 include ../../../../build.mak
 
-ifneq ($(findstring "$(TARGET_NAME)","darwin"),"")
+ifneq ($(findstring android,$(TARGET_NAME)),)
+ OS=android
+else
+ ifneq ($(findstring darwin,$(TARGET_NAME)),)
   OS=darwin
+ endif
 endif
 
 OUT_DIR=output
 ifeq ($(OS),Windows_NT)
-LIBPJSUA2_SO=$(OUT_DIR)/pjsua2.dll
+  LIBPJSUA2_SO=$(OUT_DIR)/pjsua2.dll
 else
   ifeq ($(OS),darwin)
     LIBPJSUA2_SO=$(OUT_DIR)/libpjsua2.jnilib
   else
-    LIBPJSUA2_SO=$(OUT_DIR)/libpjsua2.so
+    ifeq ($(OS),android)
+      LIBPJSUA2_SO=android/libs/armeabi/libpjsua2.so
+    else
+      LIBPJSUA2_SO=$(OUT_DIR)/libpjsua2.so
+    endif
   endif
 endif
@@ -33,18 +41,18 @@
     JAVA_BIN := $(JAVA_HOME)
   endif
-  #$(error $(JAVA_BIN))
 endif
 
 # OS specific
 ifeq ($(OS),Windows_NT)
-  MY_JNI_LDFLAGS	 = -L$(MY_JDK)/lib -Wl,--kill-at
-  MY_JNI_LIB       = $(OUT_DIR)/pjsua2.dll
+  MY_JNI_LDFLAGS	= -L$(MY_JDK)/lib -Wl,--kill-at
 else
-  MY_JNI_LDFLAGS	 = -L$(MY_JDK)/lib
-  ifneq ($(OS),darwin)
-    MY_JNI_LDFLAGS := $(MY_JNI_LDFLAGS) -Wl,-soname,pjsua2.so
+  MY_JNI_CFLAGS	 	= -fPIC
+  MY_JNI_LDFLAGS	= -L$(MY_JDK)/lib
+  ifeq ($(OS),darwin)
+    MY_JNI_LDFLAGS 	:= $(MY_JNI_LDFLAGS) -Wl,-soname,pjsua2.so
   endif
-  MY_JNI_LIB       = $(OUT_DIR)/libpjsua2.so
-  MY_JNI_CFLAGS	 := -fPIC $(MY_JNI_CFLAGS)
+  ifeq ($(OS),android)
+    MY_JNI_CFLAGS	:= $(MY_JNI_CFLAGS) -D__ANDROID__
+  endif
 endif
 
@@ -60,9 +68,15 @@
 endif
 MY_JNI_CFLAGS	 := $(MY_JNI_CFLAGS) -I$(MY_JDK)/include -I$(MY_JDK)/include/win32 \
-		   -I$(MY_JDK)/include/linux -I.
+		    -I$(MY_JDK)/include/linux -I.
 
 # Build settings
 MY_CFLAGS	 = $(PJ_CFLAGS) $(MY_JNI_CFLAGS)
-MY_LDFLAGS	 = $(PJ_LDFLAGS) -lpjsua2-$(TARGET_NAME) $(PJ_LDLIBS) $(MY_JNI_LDFLAGS) -static-libstdc++
+MY_LDFLAGS	 = $(PJ_LDFLAGS) -lpjsua2-$(TARGET_NAME) $(PJ_LDLIBS) $(MY_JNI_LDFLAGS)
+MY_PACKAGE_NAME	 = org.pjsip.pjsua2
+ifeq ($(OS),android)
+  MY_PACKAGE_PATH  = android/src/$(subst .,/,$(MY_PACKAGE_NAME))
+else
+  MY_PACKAGE_PATH  = $(OUT_DIR)/$(subst .,/,$(MY_PACKAGE_NAME))
+endif
 
 .PHONY: all java install uninstall
@@ -71,21 +85,22 @@
 
 $(LIBPJSUA2_SO): $(OUT_DIR)/pjsua2_wrap.o
-	g++ -shared -o $(LIBPJSUA2_SO) $(OUT_DIR)/pjsua2_wrap.o $(MY_CFLAGS) $(MY_LDFLAGS)
+	$(PJ_CXX) -shared -o $(LIBPJSUA2_SO) $(OUT_DIR)/pjsua2_wrap.o $(MY_CFLAGS) $(MY_LDFLAGS)
 
 $(OUT_DIR)/pjsua2_wrap.o: $(OUT_DIR)/pjsua2_wrap.cpp Makefile
-	g++ -c $(OUT_DIR)/pjsua2_wrap.cpp -o $(OUT_DIR)/pjsua2_wrap.o $(MY_CFLAGS) $(MY_LDFLAGS)
+	$(PJ_CXX) -c $(OUT_DIR)/pjsua2_wrap.cpp -o $(OUT_DIR)/pjsua2_wrap.o $(MY_CFLAGS) $(MY_LDFLAGS)
 
 $(OUT_DIR)/pjsua2_wrap.cpp: ../pjsua2.i ../symbols.i $(SRCS)
-	swig $(SWIG_FLAGS) -java  -o $(OUT_DIR)/pjsua2_wrap.cpp ../pjsua2.i
+	mkdir -p $(MY_PACKAGE_PATH)
+	swig $(SWIG_FLAGS) -java  -package $(MY_PACKAGE_NAME) -outdir $(MY_PACKAGE_PATH) -o $(OUT_DIR)/pjsua2_wrap.cpp ../pjsua2.i
 
 clean distclean realclean:
-	rm -rf $(OUT_DIR)/pjsua2_wrap.cpp $(OUT_DIR)/pjsua2_wrap.o $(LIBPJSUA2_SO) $(OUT_DIR)/*.java $(OUT_DIR)/*.class
+	rm -rf $(LIBPJSUA2_SO) $(OUT_DIR)/* $(MY_PACKAGE_PATH)/*.java $(MY_PACKAGE_PATH)/*.class
 
-java: output/Error.class output/test.class
+java: $(MY_PACKAGE_PATH)/Error.class $(MY_PACKAGE_PATH)/test.class
 
-output/Error.class: output/Error.java
-	$(MY_JAVAC) -d $(OUT_DIR) $(OUT_DIR)/*.java
+$(MY_PACKAGE_PATH)/Error.class: $(MY_PACKAGE_PATH)/Error.java
+	$(MY_JAVAC) -d $(OUT_DIR) $(MY_PACKAGE_PATH)/*.java
 
-output/test.class: test.java
+$(MY_PACKAGE_PATH)/test.class: test.java
 	$(MY_JAVAC) -d $(OUT_DIR) -classpath "$(OUT_DIR)" test.java
 
@@ -93,5 +108,5 @@
 	@# Need to specify classpath and library path, alternatively, they can be set via
 	@# CLASSPATH and java.library.path env settings
-	$(MY_JAVA) -cp $(OUT_DIR) -Djava.library.path="$(OUT_DIR)" test
+	$(MY_JAVA) -cp "$(OUT_DIR);$(MY_PACKAGE_PATH)" -Djava.library.path="$(OUT_DIR)" test
 
 install:
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.classpath
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.classpath	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.classpath	(revision 4691)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.project
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.project	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.project	(revision 4691)
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Pjsua2</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.settings/org.eclipse.jdt.core.prefs	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/.settings/org.eclipse.jdt.core.prefs	(revision 4691)
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/AndroidManifest.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/AndroidManifest.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/AndroidManifest.xml	(revision 4691)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.pjsip.pjsua2.app"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="11"
+        android:targetSdkVersion="15" />
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="org.pjsip.pjsua2.app.MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.pjsip.pjsua2.app.CallActivity"
+            android:label="@string/title_activity_call" >
+        </activity>
+    </application>
+
+</manifest>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/proguard-project.txt
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/proguard-project.txt	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/proguard-project.txt	(revision 4691)
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/project.properties
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/project.properties	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/project.properties	(revision 4691)
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-15
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/drawable/bkg.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/drawable/bkg.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/drawable/bkg.xml	(revision 4691)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@color/pressed_color" />
+    <item android:drawable="@color/default_color" />
+</selector>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_call.xml	(revision 4691)
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/textViewPeer"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:text="Peer URI"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <TextView
+        android:id="@+id/textViewCallState"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:text="Call state" />
+
+    <Button
+        android:id="@+id/buttonAccept"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:onClick="acceptCall"
+        android:text="Accept" />
+
+    <Button
+        android:id="@+id/buttonHangup"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:onClick="hangupCall"
+        android:text="Reject" />
+
+</LinearLayout>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_main.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_main.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/activity_main.xml	(revision 4691)
@@ -0,0 +1,65 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".MainActivity" >
+
+    <ListView
+        android:id="@+id/listViewBuddy"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+    	android:listSelector="@drawable/bkg" >
+    </ListView>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <ImageButton
+            android:id="@+id/buttonCall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:onClick="makeCall"
+            android:src="@android:drawable/ic_menu_call" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+			android:text="   "/>
+
+        <ImageButton
+            android:id="@+id/buttonAddBuddy"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:onClick="addBuddy"
+            android:src="@android:drawable/ic_menu_add" />
+        
+        <ImageButton
+            android:id="@+id/buttonEditBuddy"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:onClick="editBuddy"
+            android:src="@android:drawable/ic_menu_edit" />
+        
+        <ImageButton
+            android:id="@+id/buttonDelBuddy"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:onClick="delBuddy"
+            android:src="@android:drawable/ic_menu_delete" />
+
+        </LinearLayout>
+
+</LinearLayout>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_account_config.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_account_config.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_account_config.xml	(revision 4691)
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TableLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:padding = "20dp"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/textViewInfo"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+    	android:paddingBottom="20dp"
+        android:textColor="#b0b0b0" >
+    </TextView>
+    
+	<TableRow>
+        <TextView android:text="ID">
+        </TextView>  
+
+	    <EditText
+	        android:id="@+id/editTextId"
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_weight="1"
+	        android:inputType="textUri" >
+
+	        <requestFocus />
+	    </EditText>
+    </TableRow>
+	<TableRow>
+        <TextView android:text="Registrar">
+        </TextView>  
+	    <EditText
+	        android:id="@+id/editTextRegistrar"
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_weight="1"
+	        android:inputType="textUri" >
+	    </EditText>
+    </TableRow>
+	<TableRow>
+        <TextView android:text="Proxy">
+        </TextView>  
+	    <EditText
+	        android:id="@+id/editTextProxy"
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_weight="1"
+	        android:inputType="textUri" >
+	    </EditText>
+    </TableRow>
+	<TableRow>
+        <TextView android:text="Username">
+        </TextView>  
+
+	    <EditText
+	        android:id="@+id/editTextUsername"
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_weight="1"
+	        android:inputType="text" >
+
+	    </EditText>
+    </TableRow>
+	<TableRow>
+        <TextView android:text="Password">
+        </TextView>  
+
+	    <EditText
+	        android:id="@+id/editTextPassword"
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_weight="1"
+	        android:inputType="textPassword" >
+
+	    </EditText>
+    </TableRow>
+</TableLayout>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_add_buddy.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_add_buddy.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/layout/dlg_add_buddy.xml	(revision 4691)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TableLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:padding = "20dp"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+	<TableRow>
+        <TextView android:text="Buddy URI">
+        </TextView>  
+
+	    <EditText
+	        android:id="@+id/editTextUri"
+	        android:layout_weight="1"
+	        android:inputType="textUri" >
+	        <requestFocus />
+	    </EditText>
+    </TableRow>
+	<TableRow>
+        <CheckBox
+            android:id="@+id/checkBoxSubscribe"
+            android:layout_column="1"
+            android:text="Subscribe presence" />
+    </TableRow>
+</TableLayout>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/call.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/call.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/call.xml	(revision 4691)
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/main.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/main.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/menu/main.xml	(revision 4691)
@@ -0,0 +1,14 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_acc_config"
+        android:icon="@android:drawable/ic_menu_manage"
+        android:showAsAction="ifRoom"
+        android:title="Account Config"/>
+    <item
+        android:id="@+id/action_quit"
+        android:icon="@android:drawable/ic_menu_close_clear_cancel"
+        android:showAsAction="ifRoom"
+        android:title="Quit"/>
+    
+</menu>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw600dp/dimens.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw600dp/dimens.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw600dp/dimens.xml	(revision 4691)
@@ -0,0 +1,8 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw600dp devices (e.g. 7" tablets) here.
+    -->
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw720dp-land/dimens.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw720dp-land/dimens.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-sw720dp-land/dimens.xml	(revision 4691)
@@ -0,0 +1,9 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
+    -->
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v11/styles.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v11/styles.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v11/styles.xml	(revision 4691)
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v14/styles.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v14/styles.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values-v14/styles.xml	(revision 4691)
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/colors.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/colors.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/colors.xml	(revision 4691)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="pressed_color">#B8F2F5</color>
+    <color name="default_color">#E8FEFF</color>
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/dimens.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/dimens.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/dimens.xml	(revision 4691)
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/strings.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/strings.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/strings.xml	(revision 4691)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">Pjsua2</string>
+    <string name="action_settings">Settings</string>
+    <string name="title_activity_call">Call</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/styles.xml
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/styles.xml	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/res/values/styles.xml	(revision 4691)
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/CallActivity.java	(revision 4691)
@@ -0,0 +1,147 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package org.pjsip.pjsua2.app;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+
+import org.pjsip.pjsua2.*;
+
+public class CallActivity extends Activity implements Handler.Callback {
+	
+	public final Handler handler = new Handler(this);
+	public static Handler handler_;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_call);
+		
+		handler_ = handler;
+		MyCall call = MainActivity.currentCall;
+		
+		final TextView tvPeer  = (TextView) findViewById(R.id.textViewPeer);
+		final TextView tvState = (TextView) findViewById(R.id.textViewCallState);
+		final Button buttonAccept = (Button) findViewById(R.id.buttonAccept);
+		final Button buttonHangup = (Button) findViewById(R.id.buttonHangup);
+
+		String remote_uri = "Somebody";
+		String call_state = "";
+		try {
+			CallInfo ci = call.getInfo();
+			remote_uri = ci.getRemoteUri();
+			if (ci.getRole() == pjsip_role_e.PJSIP_ROLE_UAS) {
+				call_state = "Incoming call..";
+			} else {
+				buttonAccept.setVisibility(View.GONE);
+				buttonHangup.setText("Cancel");
+				call_state = ci.getStateText();
+			}
+		} catch (Exception e) {
+			System.out.println(e);
+		}
+		
+		tvPeer.setText(remote_uri);
+		tvState.setText(call_state);		
+	}
+
+    @Override
+    protected void onDestroy() {
+    	super.onDestroy();
+    	handler_ = null;
+    }
+	
+	public void acceptCall(View view) {
+		CallOpParam prm = new CallOpParam();
+		prm.setStatusCode(pjsip_status_code.PJSIP_SC_OK);
+		try {
+			MainActivity.currentCall.answer(prm);
+		} catch (Exception e) {
+			System.out.println(e);
+		}
+		
+		view.setVisibility(View.GONE);
+	}
+
+	public void hangupCall(View view) {
+		handler_ = null;
+		finish();
+		
+		if (MainActivity.currentCall != null) {
+			CallOpParam prm = new CallOpParam();
+			prm.setStatusCode(pjsip_status_code.PJSIP_SC_DECLINE);
+			try {
+				MainActivity.currentCall.hangup(prm);
+			} catch (Exception e) {
+				System.out.println(e);
+			}
+
+			MainActivity.currentCall = null;
+		}
+	}
+	
+	@Override
+	public boolean handleMessage(Message m) {
+		
+		if (m.what == MainActivity.MSG_TYPE.CALL_STATE) {
+			
+			TextView tvState = (TextView) findViewById(R.id.textViewCallState);
+			Button buttonHangup = (Button) findViewById(R.id.buttonHangup);
+			Button buttonAccept = (Button) findViewById(R.id.buttonAccept);
+			
+			CallInfo ci = (CallInfo) m.obj;
+			String call_state = "";
+			if (ci.getRole() == pjsip_role_e.PJSIP_ROLE_UAC ||
+				ci.getState().swigValue() >= pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED.swigValue())
+			{
+				call_state = ci.getStateText();
+				tvState.setText(call_state);
+			}
+			
+			if (ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED) {
+				buttonHangup.setText("Hangup");
+			}
+			
+			if (ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED) {
+				buttonHangup.setText("OK");
+				buttonAccept.setVisibility(View.GONE);
+				tvState.setText("Call disconnected: " + ci.getLastReason());
+				MainActivity.currentCall = null;
+			}
+			
+		} else {
+			
+			/* Message not handled */
+			return false;
+			
+		}
+			
+		return true;
+	}
+	
+	
+}
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MainActivity.java	(revision 4691)
@@ -0,0 +1,483 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package org.pjsip.pjsua2.app;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.pjsip.pjsua2.*;
+
+public class MainActivity extends Activity implements Handler.Callback, MyAppObserver {
+	public static MyApp app = new MyApp();
+	public static MyCall currentCall = null;
+	public static MyAccount account = null;
+	public static AccountConfig accCfg = null;
+	
+	private ListView buddyListView;
+	private SimpleAdapter buddyListAdapter;
+	private int buddyListSelectedIdx = -1;
+    ArrayList<Map<String, String>> buddyList;
+    private String lastRegStatus = "";
+
+	private final Handler handler = new Handler(this);
+	public class MSG_TYPE {
+		public final static int INCOMING_CALL = 1;
+		public final static int CALL_STATE = 2;
+		public final static int REG_STATE = 3;
+		public final static int BUDDY_STATE = 4;
+	}
+
+	private HashMap<String, String> putData(String uri, String status) {
+		HashMap<String, String> item = new HashMap<String, String>();
+		item.put("uri", uri);
+		item.put("status", status);
+		return item;
+	}
+	
+	private void showCallActivity() {
+        Intent intent = new Intent(this, CallActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        startActivity(intent);
+	}
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+	    app.init(this, getFilesDir().getAbsolutePath());
+	    if (app.accList.size() == 0) {
+	    	accCfg = new AccountConfig();
+	    	accCfg.setIdUri("sip:localhost");
+	    	account = app.addAcc(accCfg);
+	    } else {
+	    	account = app.accList.get(0);
+	    	accCfg = account.cfg;
+	    }
+	    
+		buddyList = new ArrayList<Map<String, String>>();
+		for (int i = 0; i < account.buddyList.size(); i++) {
+			buddyList.add(putData(account.buddyList.get(i).cfg.getUri(),
+								  account.buddyList.get(i).getStatusText()));
+		}
+
+		String[] from = { "uri", "status" };
+	    int[] to = { android.R.id.text1, android.R.id.text2 };
+	    buddyListAdapter = new SimpleAdapter(this, buddyList, android.R.layout.simple_list_item_2, from, to);
+	    
+		buddyListView = (ListView) findViewById(R.id.listViewBuddy);;
+	    buddyListView.setAdapter(buddyListAdapter);
+	    buddyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+	    	@Override
+	    	public void onItemClick(AdapterView<?> parent, final View view,
+	    			int position, long id) 
+	    	{
+	    		view.setSelected(true);
+	    		buddyListSelectedIdx = position;
+	    	}
+	    });
+	    
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+		// Inflate the menu; this adds items to the action bar if it is present.
+		getMenuInflater().inflate(R.menu.main, menu);
+		return true;
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		CharSequence str = item.getTitle();
+		switch (item.getItemId()) {
+		case R.id.action_acc_config:
+			dlgAccountSetting();
+			break;
+
+		case R.id.action_quit:
+			Message m = Message.obtain(handler, 0);
+			m.sendToTarget();
+			break;
+			
+		default:
+			break;
+		}
+
+		return true;
+	} 	
+
+	@Override
+	public boolean handleMessage(Message m) {
+		
+		if (m.what == 0) {
+			
+			app.deinit();
+			finish();
+			System.gc();
+			android.os.Process.killProcess(android.os.Process.myPid());
+			
+		} else if (m.what == MSG_TYPE.CALL_STATE) {
+			
+			CallInfo ci = (CallInfo) m.obj;
+			
+			/* Forward the message to CallActivity */
+			if (CallActivity.handler_ != null) {
+				Message m2 = Message.obtain(CallActivity.handler_, MSG_TYPE.CALL_STATE, ci);
+				m2.sendToTarget();
+			}
+			
+			if (ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED)
+				currentCall = null;
+			
+		} else if (m.what == MSG_TYPE.BUDDY_STATE) {
+			
+			MyBuddy buddy = (MyBuddy) m.obj;
+			int idx = account.buddyList.indexOf(buddy);
+			if (idx >= 0) {
+				buddyList.get(idx).put("status", buddy.getStatusText());
+				buddyListAdapter.notifyDataSetChanged();
+				// TODO: selection color/mark is gone after this,
+				//       dont know how to return it back.
+				//buddyListView.setSelection(buddyListSelectedIdx);
+				//buddyListView.performItemClick(buddyListView, buddyListSelectedIdx,
+				//							   buddyListView.getItemIdAtPosition(buddyListSelectedIdx));
+			}
+			
+		} else if (m.what == MSG_TYPE.REG_STATE) {
+			
+			String msg_str = (String) m.obj;
+			lastRegStatus = msg_str;
+			
+		} else if (m.what == MSG_TYPE.INCOMING_CALL) {
+			
+			/* Incoming call */
+			final MyCall call = (MyCall) m.obj;
+			CallOpParam prm = new CallOpParam();
+			
+			/* Only one call at anytime */
+			if (currentCall != null) {
+				prm.setStatusCode(pjsip_status_code.PJSIP_SC_BUSY_HERE);
+				try {
+					call.hangup(prm);
+				} catch (Exception e) {}
+				return true;
+			}
+
+			/* Answer with ringing */
+			prm.setStatusCode(pjsip_status_code.PJSIP_SC_RINGING);
+			try {
+				call.answer(prm);
+			} catch (Exception e) {}
+			
+			currentCall = call;
+			showCallActivity();
+
+		} else {
+			
+			/* Message not handled */
+			return false;
+			
+		}
+			
+		return true;
+	}
+	
+
+	private void dlgAccountSetting() {
+		
+		LayoutInflater li = LayoutInflater.from(this);
+		View view = li.inflate(R.layout.dlg_account_config, null);
+		
+		if (!lastRegStatus.isEmpty()) {
+			TextView tvInfo = (TextView)view.findViewById(R.id.textViewInfo);
+			tvInfo.setText("Last status: " + lastRegStatus);
+		}
+
+		AlertDialog.Builder adb = new AlertDialog.Builder(this);
+		adb.setView(view);
+		adb.setTitle("Account Settings");
+
+		final EditText etId    = (EditText)view.findViewById(R.id.editTextId);
+		final EditText etReg   = (EditText)view.findViewById(R.id.editTextRegistrar);
+		final EditText etProxy = (EditText)view.findViewById(R.id.editTextProxy);
+		final EditText etUser  = (EditText)view.findViewById(R.id.editTextUsername);
+		final EditText etPass  = (EditText)view.findViewById(R.id.editTextPassword);
+		
+		etId.   setText(accCfg.getIdUri());
+		etReg.  setText(accCfg.getRegConfig().getRegistrarUri());
+		StringVector proxies = accCfg.getSipConfig().getProxies();
+		if (proxies.size() > 0)
+			etProxy.setText(proxies.get(0));
+		else
+			etProxy.setText("");
+		AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
+		if (creds.size() > 0) {
+			etUser. setText(creds.get(0).getUsername());
+			etPass. setText(creds.get(0).getData());
+		} else {
+			etUser. setText("");
+			etPass. setText("");
+		}
+		
+		adb.setCancelable(false);
+		adb.setPositiveButton("OK",
+			  new DialogInterface.OnClickListener() {
+			    public void onClick(DialogInterface dialog,int id) {
+			    	String acc_id 	 = etId.getText().toString();
+			    	String registrar = etReg.getText().toString();
+			    	String proxy 	 = etProxy.getText().toString();
+			    	String username  = etUser.getText().toString();
+			    	String password  = etPass.getText().toString();
+			    	
+			    	accCfg.setIdUri(acc_id);
+			    	accCfg.getRegConfig().setRegistrarUri(registrar);
+					AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
+					creds.clear();
+					if (!username.isEmpty()) {
+						creds.add(new AuthCredInfo("Digest", "*", username, 0, password));
+					}
+					StringVector proxies = accCfg.getSipConfig().getProxies();
+					proxies.clear();
+					if (!proxy.isEmpty()) {
+						proxies.add(proxy);
+					}
+					
+					/* Finally */
+					lastRegStatus = "";
+					try {
+						account.modify(accCfg);
+					} catch (Exception e) {}
+			    }
+			  });
+		adb.setNegativeButton("Cancel",
+			  new DialogInterface.OnClickListener() {
+			    public void onClick(DialogInterface dialog,int id) {
+				dialog.cancel();
+			    }
+			  });
+
+		AlertDialog ad = adb.create();
+		ad.show();
+	}
+	
+	
+	public void makeCall(View view) {
+		if (buddyListSelectedIdx == -1)
+			return;
+		
+		/* Only one call at anytime */
+		if (currentCall != null) {
+			return;
+		}
+		
+		HashMap<String, String> item = (HashMap<String, String>) buddyListView.getItemAtPosition(buddyListSelectedIdx);
+		String buddy_uri = item.get("uri");
+		
+		MyCall call = new MyCall(account, -1);
+		CallOpParam prm = new CallOpParam();
+		CallSetting opt = prm.getOpt();
+		opt.setAudioCount(1);
+		opt.setVideoCount(0);
+
+		try {
+			call.makeCall(buddy_uri, prm);
+		} catch (Exception e) {
+			currentCall = null;
+			return;
+		}
+		
+		currentCall = call;
+		showCallActivity();
+	}
+
+	private void dlgAddEditBuddy(BuddyConfig initial) {
+		final BuddyConfig cfg = new BuddyConfig();
+		final BuddyConfig old_cfg = initial;
+		final boolean is_add = initial == null;
+		
+		LayoutInflater li = LayoutInflater.from(this);
+		View view = li.inflate(R.layout.dlg_add_buddy, null);
+
+		AlertDialog.Builder adb = new AlertDialog.Builder(this);
+		adb.setView(view);
+
+		final EditText etUri    = (EditText)view.findViewById(R.id.editTextUri);
+		final CheckBox cbSubs  = (CheckBox)view.findViewById(R.id.checkBoxSubscribe);
+
+		if (is_add) {
+			adb.setTitle("Add Buddy");
+		} else {
+			adb.setTitle("Edit Buddy");
+			etUri. setText(initial.getUri());
+			cbSubs.setChecked(initial.getSubscribe());
+		}
+
+		adb.setCancelable(false);
+		adb.setPositiveButton("OK",
+			  new DialogInterface.OnClickListener() {
+			    public void onClick(DialogInterface dialog,int id) {
+			    	cfg.setUri(etUri.getText().toString());
+			    	cfg.setSubscribe(cbSubs.isChecked());
+			    	
+			    	if (is_add) {
+			    		account.addBuddy(cfg);
+						buddyList.add(putData(cfg.getUri(), ""));
+						buddyListAdapter.notifyDataSetChanged();
+						buddyListSelectedIdx = -1;
+			    	} else {
+			    		if (old_cfg.getUri() != cfg.getUri()) {
+			    			account.delBuddy(buddyListSelectedIdx);
+			    			account.addBuddy(cfg);
+							buddyList.remove(buddyListSelectedIdx);
+							buddyList.add(putData(cfg.getUri(), ""));
+			    			buddyListAdapter.notifyDataSetChanged();
+			    			buddyListSelectedIdx = -1;
+			    		} else if (old_cfg.getSubscribe() != cfg.getSubscribe()) {
+			    			MyBuddy bud = account.buddyList.get(buddyListSelectedIdx);
+							try {
+				    			bud.subscribePresence(cfg.getSubscribe());
+							} catch (Exception e) {}
+			    		}
+			    	}
+			    }
+			  });
+		adb.setNegativeButton("Cancel",
+			  new DialogInterface.OnClickListener() {
+			    public void onClick(DialogInterface dialog,int id) {
+				dialog.cancel();
+			    }
+			  });
+
+		AlertDialog ad = adb.create();
+		ad.show();
+	}
+	
+	public void addBuddy(View view) {
+		dlgAddEditBuddy(null);
+	}
+
+	public void editBuddy(View view) {
+		if (buddyListSelectedIdx == -1)
+			return;
+		
+		BuddyConfig old_cfg = account.buddyList.get(buddyListSelectedIdx).cfg;
+		dlgAddEditBuddy(old_cfg);
+	}
+	
+	public void delBuddy(View view) {
+		if (buddyListSelectedIdx == -1)
+			return;
+		
+		final HashMap<String, String> item = (HashMap<String, String>) buddyListView.getItemAtPosition(buddyListSelectedIdx);
+		String buddy_uri = item.get("uri");
+		
+		DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
+		    @Override
+		    public void onClick(DialogInterface dialog, int which) {
+		        switch (which) {
+		        case DialogInterface.BUTTON_POSITIVE:
+		        	account.delBuddy(buddyListSelectedIdx);
+		    		buddyList.remove(item);
+		    		buddyListAdapter.notifyDataSetChanged();
+		    		buddyListSelectedIdx = -1;
+		            break;
+		        case DialogInterface.BUTTON_NEGATIVE:
+		            break;
+		        }
+		    }
+		};
+
+		AlertDialog.Builder adb = new AlertDialog.Builder(this);
+		adb.setTitle(buddy_uri);
+		adb.setMessage("\nDelete this buddy?\n");
+		adb.setPositiveButton("Yes", ocl);
+		adb.setNegativeButton("No", ocl);
+		adb.show();
+	}
+	
+	
+	/*
+	 * === MyAppObserver ===
+	 * 
+	 * As we cannot do UI from worker thread, the callbacks mostly just send
+	 * a message to UI/main thread.
+	 */
+	
+	public void notifyIncomingCall(MyCall call) {
+		Message m = Message.obtain(handler, MSG_TYPE.INCOMING_CALL, call);
+		m.sendToTarget();
+	}
+
+	public void notifyRegState(pjsip_status_code code, String reason, int expiration) {
+		String msg_str = "";
+		if (expiration == 0)
+			msg_str += "Unregistration";
+		else
+			msg_str += "Registration";
+		
+		if (code.swigValue()/100 == 2)
+			msg_str += " successful";
+		else
+			msg_str += " failed: " + reason;
+		
+		Message m = Message.obtain(handler, MSG_TYPE.REG_STATE, msg_str);
+		m.sendToTarget();
+	}
+	
+	public void notifyCallState(MyCall call) {
+		if (currentCall == null || call.getId() != currentCall.getId())
+			return;
+		
+		CallInfo ci;
+		try {
+			ci = call.getInfo();
+		} catch (Exception e) {
+			ci = null;
+		}
+		Message m = Message.obtain(handler, MSG_TYPE.CALL_STATE, ci);
+		m.sendToTarget();
+	}
+	
+	public void notifyBuddyState(MyBuddy buddy) {
+		Message m = Message.obtain(handler, MSG_TYPE.BUDDY_STATE, buddy);
+		m.sendToTarget();
+	}
+
+	/* === end of MyAppObserver ==== */
+
+}
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java	(revision 4691)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/android/src/org/pjsip/pjsua2/app/MyApp.java	(revision 4691)
@@ -0,0 +1,414 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package org.pjsip.pjsua2.app;
+
+import java.io.File;
+import java.util.ArrayList;
+import org.pjsip.pjsua2.*;
+
+
+/* Interface to separate UI & engine a bit better */
+interface MyAppObserver {
+	abstract void notifyRegState(pjsip_status_code code, String reason, int expiration);
+	abstract void notifyIncomingCall(MyCall call);
+	abstract void notifyCallState(MyCall call);
+	abstract void notifyBuddyState(MyBuddy buddy);
+}
+
+
+class MyLogWriter extends LogWriter {
+	@Override
+	public void write(LogEntry entry) {
+		System.out.println(entry.getMsg());
+	}
+}
+
+
+class MyCall extends Call {
+	MyCall(MyAccount acc, int call_id) {
+		super(acc, call_id);
+	}
+
+	@Override
+	public void onCallState(OnCallStateParam prm) {
+		MyApp.observer.notifyCallState(this);
+	}
+	
+	@Override
+	public void onCallMediaState(OnCallMediaStateParam prm) {
+		CallInfo ci;
+		try {
+			ci = getInfo();
+		} catch (Exception e) {
+			return;
+		}
+		
+		CallMediaInfoVector cmiv = ci.getMedia();
+		
+		for (int i = 0; i < cmiv.size(); i++) {
+			CallMediaInfo cmi = cmiv.get(i);
+			if (cmi.getType() == pjmedia_type.PJMEDIA_TYPE_AUDIO &&
+			    (cmi.getStatus() == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE ||
+			     cmi.getStatus() == pjsua_call_media_status.PJSUA_CALL_MEDIA_REMOTE_HOLD))
+			{
+				// unfortunately, on Java too, the returned Media cannot be downcasted to AudioMedia 
+				Media m = getMedia(i);
+				AudioMedia am = AudioMedia.typecastFromMedia(m);
+				
+				// connect ports
+				try {
+					MyApp.ep.audDevManager().getCaptureDevMedia().startTransmit(am);
+					am.startTransmit(MyApp.ep.audDevManager().getPlaybackDevMedia());
+				} catch (Exception e) {
+					continue;
+				}
+			}
+		}
+	}
+}
+
+
+class MyAccount extends Account {
+	public ArrayList<MyBuddy> buddyList = new ArrayList<MyBuddy>();
+	public AccountConfig cfg;
+	
+	MyAccount(AccountConfig config) {
+		super();
+		cfg = config;
+	}
+	
+	public MyBuddy addBuddy(BuddyConfig bud_cfg)
+	{
+		/* Create Buddy */
+		MyBuddy bud = new MyBuddy(bud_cfg);
+		try {
+			bud.create(this, bud_cfg);
+		} catch (Exception e) {
+			bud = null;
+		}
+		
+		if (bud != null) {
+			buddyList.add(bud);
+			if (bud_cfg.getSubscribe())
+				try {
+					bud.subscribePresence(true);
+				} catch (Exception e) {}
+		}
+		
+		return bud;
+	}
+	
+	public void delBuddy(MyBuddy buddy) {
+		buddyList.remove(buddy);
+	}
+	
+	public void delBuddy(int index) {
+		buddyList.remove(index);
+	}
+	
+	@Override
+	public void onRegState(OnRegStateParam prm) {
+		MyApp.observer.notifyRegState(prm.getCode(), prm.getReason(), prm.getExpiration());
+	}
+
+	@Override
+	public void onIncomingCall(OnIncomingCallParam prm) {
+		System.out.println("======== Incoming call ======== ");
+		MyCall call = new MyCall(this, prm.getCallId());
+		MyApp.observer.notifyIncomingCall(call);
+	}
+	
+	@Override
+	public void onInstantMessage(OnInstantMessageParam prm) {
+		System.out.println("======== Incoming pager ======== ");
+		System.out.println("From 		: " + prm.getFromUri());
+		System.out.println("To			: " + prm.getToUri());
+		System.out.println("Contact		: " + prm.getContactUri());
+		System.out.println("Mimetype	: " + prm.getContentType());
+		System.out.println("Body		: " + prm.getMsgBody());
+	}
+}
+
+
+class MyBuddy extends Buddy {
+	public BuddyConfig cfg;
+	
+	MyBuddy(BuddyConfig config) {
+		super();
+		cfg = config;
+	}
+	
+	String getStatusText() {
+		BuddyInfo bi;
+		
+		try {
+			bi = getInfo();
+		} catch (Exception e) {
+			return "?";
+		}
+		
+		String status = "";
+		if (bi.getSubState() == pjsip_evsub_state.PJSIP_EVSUB_STATE_ACTIVE) {
+			if (bi.getPresStatus().getStatus() == pjsua_buddy_status.PJSUA_BUDDY_STATUS_ONLINE) {
+				status = bi.getPresStatus().getStatusText();
+				if (status == null || status == "") {
+					status = "Online";
+				}
+			} else if (bi.getPresStatus().getStatus() == pjsua_buddy_status.PJSUA_BUDDY_STATUS_OFFLINE) {
+				status = "Offline";
+			} else {
+				status = "Unknown";
+			}
+		}
+		return status;
+	}
+
+	@Override
+	public void onBuddyState() {
+		MyApp.observer.notifyBuddyState(this);
+	}
+	
+}
+
+
+class MyAccountConfig {
+	public AccountConfig accCfg = new AccountConfig();
+	public ArrayList<BuddyConfig> buddyCfgs = new ArrayList<BuddyConfig>();
+	
+	public void readObject(ContainerNode node) {
+		try {
+			ContainerNode acc_node = node.readContainer("Account");
+			accCfg.readObject(acc_node);
+			ContainerNode buddies_node = acc_node.readArray("buddies");
+			buddyCfgs.clear();
+			while (buddies_node.hasUnread()) {
+				BuddyConfig bud_cfg = new BuddyConfig(); 
+				bud_cfg.readObject(buddies_node);
+				buddyCfgs.add(bud_cfg);
+			}
+		} catch (Exception e) {}
+	}
+	
+	public void writeObject(ContainerNode node) {
+		try {
+			ContainerNode acc_node = node.writeNewContainer("Account");
+			accCfg.writeObject(acc_node);
+			ContainerNode buddies_node = acc_node.writeNewArray("buddies");
+			for (int j = 0; j < buddyCfgs.size(); j++) {
+				buddyCfgs.get(j).writeObject(buddies_node);
+			}
+		} catch (Exception e) {}
+	}
+}
+
+
+class MyApp {
+	static {
+		System.loadLibrary("pjsua2");
+		System.out.println("Library loaded");
+	}
+	
+	public static Endpoint ep = new Endpoint();
+	public static MyAppObserver observer;
+	public ArrayList<MyAccount> accList = new ArrayList<MyAccount>();
+
+	private ArrayList<MyAccountConfig> accCfgs = new ArrayList<MyAccountConfig>();
+	private EpConfig epConfig = new EpConfig();
+	private TransportConfig sipTpConfig = new TransportConfig();
+	private String appDir;
+
+	private final String configName = "pjsua2.json";
+	private final int SIP_PORT  = 6000;
+	private final int LOG_LEVEL = 4;
+	
+	public void init(MyAppObserver obs, String app_dir) {
+		observer = obs;
+		appDir = app_dir;
+		
+		/* Create endpoint */
+		try {
+			ep.libCreate();
+		} catch (Exception e) {
+			return;
+		}
+			
+		
+		/* Load config */
+		String configPath = appDir + "/" + configName;
+		File f = new File(configPath);
+		if (f.exists()) {
+			loadConfig(configPath);
+		} else {
+			/* Set 'default' values */
+			sipTpConfig.setPort(SIP_PORT);
+		}
+		
+		/* Override log level setting */
+		epConfig.getLogConfig().setLevel(LOG_LEVEL);
+		epConfig.getLogConfig().setConsoleLevel(LOG_LEVEL);
+		
+		/* Set log config. */
+		LogConfig log_cfg = epConfig.getLogConfig();
+		log_cfg.setWriter(new MyLogWriter());
+		log_cfg.setDecor(log_cfg.getDecor() & 
+						 ~(pj_log_decoration.PJ_LOG_HAS_CR.swigValue() | 
+						   pj_log_decoration.PJ_LOG_HAS_NEWLINE.swigValue()));
+		
+		/* Set ua config. */
+		UaConfig ua_cfg = epConfig.getUaConfig();
+		ua_cfg.setUserAgent("Pjsua2And" + ep.libVersion().getFull());
+		
+		/* Init endpoint */
+		try {
+			ep.libInit(epConfig);
+		} catch (Exception e) {
+			return;
+		}
+		
+		/* Create transports. */
+		try {
+			ep.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, sipTpConfig);
+		} catch (Exception e) {
+			System.out.println(e);
+		}
+
+		try {
+			ep.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_TCP, sipTpConfig);
+		} catch (Exception e) {
+			System.out.println(e);
+		}
+		
+		/* Create accounts. */
+		for (int i = 0; i < accCfgs.size(); i++) {
+			MyAccountConfig my_cfg = accCfgs.get(i);
+			MyAccount acc = addAcc(my_cfg.accCfg);
+			if (acc == null)
+				continue;
+			
+			/* Add Buddies */
+			for (int j = 0; j < my_cfg.buddyCfgs.size(); j++) {
+				BuddyConfig bud_cfg = my_cfg.buddyCfgs.get(j);
+				acc.addBuddy(bud_cfg);
+			}
+		}
+
+		/* Start. */
+		try {
+			ep.libStart();
+		} catch (Exception e) {
+			return;
+		}
+	}
+	
+	public MyAccount addAcc(AccountConfig cfg) {
+		MyAccount acc = new MyAccount(cfg);
+		try {
+			acc.create(cfg);
+		} catch (Exception e) {
+			acc = null;
+			return null;
+		}
+		
+		accList.add(acc);
+		return acc;
+	}
+	
+	public void delAcc(MyAccount acc) {
+		accList.remove(acc);
+		/* GC will delete the acc soon? */
+	}
+	
+	private void loadConfig(String filename) {
+		JsonDocument json = new JsonDocument();
+		
+		try {
+			/* Load file */
+			json.loadFile(filename);
+			ContainerNode root = json.getRootContainer();
+			
+			/* Read endpoint config */
+			epConfig.readObject(root);
+			
+			/* Read transport config */
+			ContainerNode tp_node = root.readContainer("SipTransport");
+			sipTpConfig.readObject(tp_node);
+			
+			/* Read account configs */
+			accCfgs.clear();
+			ContainerNode accs_node = root.readArray("accounts");
+			while (accs_node.hasUnread()) {
+				MyAccountConfig acc_cfg = new MyAccountConfig();
+				acc_cfg.readObject(accs_node);
+				accCfgs.add(acc_cfg);
+			}
+		} catch (Exception e) {
+			System.out.println(e);
+		}
+	}
+
+	private void buildAccConfigs() {
+		/* Sync accCfgs from accList */
+		accCfgs.clear();
+		for (int i = 0; i < accList.size(); i++) {
+			MyAccount acc = accList.get(i);
+			MyAccountConfig my_acc_cfg = new MyAccountConfig();
+			my_acc_cfg.accCfg = acc.cfg;
+			
+			my_acc_cfg.buddyCfgs.clear();
+			for (int j = 0; j < acc.buddyList.size(); j++) {
+				MyBuddy bud = acc.buddyList.get(j);
+				my_acc_cfg.buddyCfgs.add(bud.cfg);
+			}
+			
+			accCfgs.add(my_acc_cfg);
+		}
+	}
+	
+	private void saveConfig(String filename) {
+		JsonDocument json = new JsonDocument();
+		
+		try {
+			/* Write endpoint config */
+			json.writeObject(epConfig);
+			
+			/* Write transport config */
+			ContainerNode tp_node = json.writeNewContainer("SipTransport");
+			sipTpConfig.writeObject(tp_node);
+			
+			/* Write account configs */
+			buildAccConfigs();
+			ContainerNode accs_node = json.writeNewArray("accounts");
+			for (int i = 0; i < accCfgs.size(); i++) {
+				accCfgs.get(i).writeObject(accs_node);
+			}
+			
+			/* Save file */
+			json.saveFile(filename);
+		} catch (Exception e) {}
+	}
+	
+	public void deinit() {
+		String configPath = appDir + "/" + configName;
+		saveConfig(configPath);
+		try {
+			ep.libDestroy();
+		} catch (Exception e) {}
+		ep = null;
+	} 
+}
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/test.java
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/test.java	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/java/test.java	(revision 4691)
@@ -1,2 +1,4 @@
+import org.pjsip.pjsua2.*;
+
 public class test {
   static {
Index: /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i
===================================================================
--- /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i	(revision 4690)
+++ /pjproject/branches/projects/pjsua2/pjsip-apps/src/swig/pjsua2.i	(revision 4691)
@@ -26,4 +26,25 @@
   }
 #endif
+
+// Allow C++ exceptions to be handled in Java
+#ifdef SWIGJAVA
+  %typemap(throws, throws="java.lang.Exception") pj::Error {
+  jclass excep = jenv->FindClass("java/lang/Exception");
+  if (excep)
+    jenv->ThrowNew(excep, $1.info(true).c_str());
+  return $null;
+}
+
+  // Force the Error Java class to extend java.lang.Exception
+  %typemap(javabase) pj::Error "java.lang.Exception";
+
+  // Override getMessage()
+  %typemap(javacode) pj::Error %{
+  public String getMessage() {
+    return getTitle();
+  }
+%}
+#endif
+
 
 // Constants from PJSIP libraries
@@ -75,5 +96,5 @@
 %template(AudioMediaVector)		std::vector<pj::AudioMedia*>;
 %template(MediaFormatVector)		std::vector<pj::MediaFormat*>;
-%template(AudioDevInfoVector)		std::vector<AudioDevInfo*>;
+%template(AudioDevInfoVector)		std::vector<pj::AudioDevInfo*>;
 %template(CodecInfoVector)		std::vector<pj::CodecInfo*>;
 
