Re #1716: Initial implementation of new Android app based on pjsua2+SWIG API.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/pjsua2@4691 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
ba10fb5124
commit
3270796782
11
build.mak.in
11
build.mak.in
|
@ -114,6 +114,13 @@ export APP_CFLAGS := -DPJ_AUTOCONF=1\
|
|||
-I$(PJDIR)/pjmedia/include\
|
||||
-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\
|
||||
-L$(PJDIR)/pjnath/lib\
|
||||
|
@ -121,6 +128,7 @@ export APP_LDFLAGS := -L$(PJDIR)/pjlib/lib\
|
|||
-L$(PJDIR)/pjsip/lib\
|
||||
-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
|
||||
#
|
||||
|
@ -144,8 +152,7 @@ export APP_LDLIBS := \
|
|||
$(APP_THIRD_PARTY_LIBS)\
|
||||
$(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
|
||||
#
|
||||
# FIX THIS
|
||||
|
|
|
@ -86,11 +86,11 @@ if test "$1" = "--use-ndk-cflags"; then
|
|||
export CC="${NDK_CC}"
|
||||
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
|
||||
|
||||
|
@ -110,11 +110,11 @@ else
|
|||
export CC="${ANDROID_TC}/bin/${TARGET_HOST}-gcc"
|
||||
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
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ clean depend realclean:
|
|||
$(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $@
|
||||
$(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; \
|
||||
echo '$(PJSYSTEST_EXE): $(APP_LIB_FILES)' >> .pjsystest-$(TARGET_NAME).depend; \
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
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 \
|
||||
-I../../../../pjlib-util/include \
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
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
|
||||
|
||||
|
@ -32,20 +40,20 @@ else
|
|||
else
|
||||
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
|
||||
ifeq ($(OS),android)
|
||||
MY_JNI_CFLAGS := $(MY_JNI_CFLAGS) -D__ANDROID__
|
||||
endif
|
||||
MY_JNI_LIB = $(OUT_DIR)/libpjsua2.so
|
||||
MY_JNI_CFLAGS := -fPIC $(MY_JNI_CFLAGS)
|
||||
endif
|
||||
|
||||
# Env settings, e.g: path to SWIG, JDK, java(.exe), javac(.exe)
|
||||
|
@ -59,40 +67,47 @@ else
|
|||
MY_JAVAC = $(MY_JDK)/javac
|
||||
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
|
||||
|
||||
all: $(LIBPJSUA2_SO) java
|
||||
|
||||
$(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
|
||||
|
||||
test:
|
||||
@# 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:
|
||||
uninstall:
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
|
@ -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 *;
|
||||
#}
|
|
@ -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
|
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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 ==== */
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import org.pjsip.pjsua2.*;
|
||||
|
||||
public class test {
|
||||
static {
|
||||
System.loadLibrary("pjsua2");
|
||||
|
|
|
@ -26,6 +26,27 @@ using namespace pj;
|
|||
}
|
||||
#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
|
||||
%include "symbols.i"
|
||||
|
||||
|
@ -74,7 +95,7 @@ using namespace pj;
|
|||
%template(BuddyVector) std::vector<pj::Buddy*>;
|
||||
%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*>;
|
||||
|
||||
%include "pjsua2/media.hpp"
|
||||
|
|
Loading…
Reference in New Issue