├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable │ │ │ ├── icon.png │ │ │ ├── btn_speak_normal.png │ │ │ ├── btn_speak_pressed.png │ │ │ ├── btn_speak_selected.png │ │ │ └── btn_record.xml │ │ ├── values │ │ │ └── strings.xml │ │ ├── xml │ │ │ └── preferences.xml │ │ └── layout │ │ │ ├── call_address_dialog.xml │ │ │ └── walkietalkie.xml │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── android │ │ │ └── sip │ │ │ ├── SipSettings.java │ │ │ ├── IncomingCallReceiver.java │ │ │ └── WalkieTalkieActivity.java │ │ └── AndroidManifest.xml └── build.gradle ├── settings.gradle ├── .idea ├── copyright │ └── profiles_settings.xml ├── markdown-navigator │ └── profiles_settings.xml ├── vcs.xml ├── modules.xml ├── runConfigurations.xml ├── compiler.xml └── misc.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── import-summary.txt ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/SipDemo/HEAD/app/src/main/res/drawable/icon.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/SipDemo/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_speak_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/SipDemo/HEAD/app/src/main/res/drawable/btn_speak_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_speak_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/SipDemo/HEAD/app/src/main/res/drawable/btn_speak_pressed.png -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_speak_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/SipDemo/HEAD/app/src/main/res/drawable/btn_speak_selected.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu May 11 10:54:50 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.example.android.sip" 9 | minSdkVersion 9 10 | targetSdkVersion 9 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | SIP Demo 20 | SIP Address to contact 21 | Talk 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_record.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | # Uncomment the following line if you do not want to check your keystore files in. 45 | #*.jks 46 | 47 | # External native build folder generated in Android Studio 2.2 and later 48 | .externalNativeBuild 49 | 50 | # Google Services (e.g. APIs or Firebase) 51 | google-services.json 52 | 53 | # Freeline 54 | freeline.py 55 | freeline/ 56 | freeline_project_description.json -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/sip/SipSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.sip; 18 | 19 | import android.os.Bundle; 20 | import android.preference.PreferenceActivity; 21 | 22 | /** 23 | * Handles SIP authentication settings for the Walkie Talkie app. 24 | */ 25 | public class SipSettings extends PreferenceActivity { 26 | 27 | @Override 28 | public void onCreate(Bundle savedInstanceState) { 29 | // Note that none of the preferences are actually defined here. 30 | // They're all in the XML file res/xml/preferences.xml. 31 | super.onCreate(savedInstanceState); 32 | addPreferencesFromResource(R.xml.preferences); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /import-summary.txt: -------------------------------------------------------------------------------- 1 | ECLIPSE ANDROID PROJECT IMPORT SUMMARY 2 | ====================================== 3 | 4 | Ignored Files: 5 | -------------- 6 | The following files were *not* copied into the new Gradle project; you 7 | should evaluate whether these are still needed in your project and if 8 | so manually move them: 9 | 10 | * .DS_Store 11 | 12 | Moved Files: 13 | ------------ 14 | Android Gradle projects use a different directory structure than ADT 15 | Eclipse projects. Here's how the projects were restructured: 16 | 17 | * AndroidManifest.xml => app/src/main/AndroidManifest.xml 18 | * res/ => app/src/main/res/ 19 | * src/ => app/src/main/java/ 20 | * src/.DS_Store => app/src/main/resources/.DS_Store 21 | * src/com/.DS_Store => app/src/main/resources/com/.DS_Store 22 | * src/com/example/.DS_Store => app/src/main/resources/com/example/.DS_Store 23 | * src/com/example/android/.DS_Store => app/src/main/resources/com/example/android/.DS_Store 24 | 25 | Next Steps: 26 | ----------- 27 | You can now build the project. The Gradle project needs network 28 | connectivity to download dependencies. 29 | 30 | Bugs: 31 | ----- 32 | If for some reason your project does not build, and you determine that 33 | it is due to a bug or limitation of the Eclipse to Gradle importer, 34 | please file a bug at http://b.android.com with category 35 | Component-Tools. 36 | 37 | (This import summary is for your information only, and can be deleted 38 | after import once you are satisfied with the results.) 39 | -------------------------------------------------------------------------------- /app/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 25 | 31 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/call_address_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 22 | 23 | 32 | 33 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/walkietalkie.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 26 | 27 | 34 | 35 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/sip/IncomingCallReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.sip; 18 | 19 | import android.content.BroadcastReceiver; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.net.sip.*; 23 | import android.util.Log; 24 | 25 | /** 26 | * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity. 27 | */ 28 | public class IncomingCallReceiver extends BroadcastReceiver { 29 | /** 30 | * Processes the incoming call, answers it, and hands it over to the 31 | * WalkieTalkieActivity. 32 | * @param context The context under which the receiver is running. 33 | * @param intent The intent being received. 34 | */ 35 | @Override 36 | public void onReceive(Context context, Intent intent) { 37 | SipAudioCall incomingCall = null; 38 | try { 39 | 40 | SipAudioCall.Listener listener = new SipAudioCall.Listener() { 41 | @Override 42 | public void onRinging(SipAudioCall call, SipProfile caller) { 43 | try { 44 | call.answerCall(30); 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | }; 50 | 51 | WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context; 52 | 53 | incomingCall = wtActivity.manager.takeAudioCall(intent, listener); 54 | incomingCall.answerCall(30); 55 | incomingCall.startAudio(); 56 | incomingCall.setSpeakerMode(true); 57 | if(incomingCall.isMuted()) { 58 | incomingCall.toggleMute(); 59 | } 60 | 61 | // wtActivity.call = incomingCall; 62 | 63 | wtActivity.updateStatus(incomingCall); 64 | 65 | } catch (Exception e) { 66 | if (incomingCall != null) { 67 | incomingCall.close(); 68 | } 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 38 | 39 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 87 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Android 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 120 | 121 | $USER_HOME$/.subversion 122 | 123 | 124 | 125 | 126 | 127 | 128 | 133 | 134 | 135 | 136 | 137 | 138 | 1.8 139 | 140 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/sip/WalkieTalkieActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.sip; 18 | 19 | import android.app.Activity; 20 | import android.app.AlertDialog; 21 | import android.app.Dialog; 22 | import android.app.PendingIntent; 23 | import android.content.DialogInterface; 24 | import android.content.Intent; 25 | import android.content.IntentFilter; 26 | import android.content.SharedPreferences; 27 | import android.os.Bundle; 28 | import android.preference.PreferenceManager; 29 | import android.util.Log; 30 | import android.view.*; 31 | import android.net.sip.*; 32 | import android.widget.Button; 33 | import android.widget.EditText; 34 | import android.widget.TextView; 35 | import android.widget.ToggleButton; 36 | 37 | import java.text.ParseException; 38 | 39 | /** 40 | * Handles all calling, receiving calls, and UI interaction in the WalkieTalkie app. 41 | */ 42 | public class WalkieTalkieActivity extends Activity implements View.OnTouchListener { 43 | 44 | public String sipAddress = null; 45 | 46 | public SipManager manager = null; 47 | public SipProfile me = null; 48 | public SipAudioCall call = null; 49 | public IncomingCallReceiver callReceiver; 50 | 51 | private static final int CALL_ADDRESS = 1; 52 | private static final int SET_AUTH_INFO = 2; 53 | private static final int UPDATE_SETTINGS_DIALOG = 3; 54 | private static final int HANG_UP = 4; 55 | 56 | 57 | @Override 58 | public void onCreate(Bundle savedInstanceState) { 59 | 60 | super.onCreate(savedInstanceState); 61 | setContentView(R.layout.walkietalkie); 62 | 63 | ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk); 64 | // Button button = (Button) findViewById(R.id.ben); 65 | // button.setOnClickListener(this); 66 | pushToTalkButton.setOnTouchListener(this); 67 | 68 | // Set up the intent filter. This will be used to fire an 69 | // IncomingCallReceiver when someone calls the SIP address used by this 70 | // application. 71 | IntentFilter filter = new IntentFilter(); 72 | filter.addAction("android.SipDemo.INCOMING_CALL"); 73 | callReceiver = new IncomingCallReceiver(); 74 | this.registerReceiver(callReceiver, filter); 75 | 76 | // "Push to talk" can be a serious pain when the screen keeps turning off. 77 | // Let's prevent that. 78 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 79 | 80 | initializeManager(); 81 | } 82 | 83 | @Override 84 | public void onStart() { 85 | super.onStart(); 86 | // When we get back from the preference setting Activity, assume 87 | // settings have changed, and re-login with new auth info. 88 | initializeManager(); 89 | } 90 | 91 | @Override 92 | public void onDestroy() { 93 | super.onDestroy(); 94 | if (call != null) { 95 | call.close(); 96 | } 97 | 98 | closeLocalProfile(); 99 | 100 | if (callReceiver != null) { 101 | this.unregisterReceiver(callReceiver); 102 | } 103 | } 104 | 105 | public void initializeManager() { 106 | if(manager == null) { 107 | manager = SipManager.newInstance(this); 108 | } 109 | 110 | initializeLocalProfile(); 111 | } 112 | 113 | /** 114 | * Logs you into your SIP provider, registering this device as the location to 115 | * send SIP calls to for your SIP address. 116 | */ 117 | public void initializeLocalProfile() { 118 | if (manager == null) { 119 | return; 120 | } 121 | 122 | if (me != null) { 123 | closeLocalProfile(); 124 | } 125 | 126 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); 127 | String username = prefs.getString("namePref", ""); 128 | String domain = prefs.getString("domainPref", ""); 129 | String password = prefs.getString("passPref", ""); 130 | 131 | if (username.length() == 0 || domain.length() == 0 || password.length() == 0) { 132 | showDialog(UPDATE_SETTINGS_DIALOG); 133 | return; 134 | } 135 | 136 | try { 137 | SipProfile.Builder builder = new SipProfile.Builder(username, domain); 138 | builder.setPassword(password); 139 | me = builder.build(); 140 | 141 | Intent i = new Intent(); 142 | i.setAction("android.SipDemo.INCOMING_CALL"); 143 | PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA); 144 | manager.open(me, pi, null); 145 | 146 | 147 | // This listener must be added AFTER manager.open is called, 148 | // Otherwise the methods aren't guaranteed to fire. 149 | 150 | manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() { 151 | public void onRegistering(String localProfileUri) { 152 | updateStatus("Registering with SIP Server..."); 153 | } 154 | 155 | public void onRegistrationDone(String localProfileUri, long expiryTime) { 156 | updateStatus("Ready"); 157 | } 158 | 159 | public void onRegistrationFailed(String localProfileUri, int errorCode, 160 | String errorMessage) { 161 | updateStatus("Registration failed. Please check settings."); 162 | } 163 | }); 164 | } catch (ParseException pe) { 165 | updateStatus("Connection Error."); 166 | } catch (SipException se) { 167 | updateStatus("Connection error."); 168 | } 169 | } 170 | 171 | /** 172 | * Closes out your local profile, freeing associated objects into memory 173 | * and unregistering your device from the server. 174 | */ 175 | public void closeLocalProfile() { 176 | if (manager == null) { 177 | return; 178 | } 179 | try { 180 | if (me != null) { 181 | manager.close(me.getUriString()); 182 | } 183 | } catch (Exception ee) { 184 | // Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee); 185 | } 186 | } 187 | 188 | /** 189 | * Make an outgoing call. 190 | */ 191 | public void initiateCall() { 192 | 193 | updateStatus(sipAddress); 194 | 195 | try { 196 | SipAudioCall.Listener listener = new SipAudioCall.Listener() { 197 | // Much of the client's interaction with the SIP Stack will 198 | // happen via listeners. Even making an outgoing call, don't 199 | // forget to set up a listener to set things up once the call is established. 200 | @Override 201 | public void onCallEstablished(SipAudioCall call) { 202 | call.startAudio(); 203 | call.setSpeakerMode(true); 204 | call.toggleMute(); 205 | updateStatus(call); 206 | } 207 | 208 | @Override 209 | public void onCallEnded(SipAudioCall call) { 210 | updateStatus("Ready."); 211 | } 212 | }; 213 | 214 | call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30); 215 | 216 | } 217 | catch (Exception e) { 218 | // Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e); 219 | if (me != null) { 220 | try { 221 | manager.close(me.getUriString()); 222 | } catch (Exception ee) { 223 | // Log.i("WalkieTalkieActivity/InitiateCall", 224 | // "Error when trying to close manager.", ee); 225 | ee.printStackTrace(); 226 | } 227 | } 228 | if (call != null) { 229 | call.close(); 230 | } 231 | } 232 | } 233 | 234 | /** 235 | * Updates the status box at the top of the UI with a messege of your choice. 236 | * @param status The String to display in the status box. 237 | */ 238 | public void updateStatus(final String status) { 239 | // Be a good citizen. Make sure UI changes fire on the UI thread. 240 | this.runOnUiThread(new Runnable() { 241 | public void run() { 242 | Log.i("allenssip",status); 243 | TextView labelView = (TextView) findViewById(R.id.sipLabel); 244 | labelView.setText(status); 245 | } 246 | }); 247 | } 248 | 249 | /** 250 | * Updates the status box with the SIP address of the current call. 251 | * @param call The current, active call. 252 | */ 253 | public void updateStatus(SipAudioCall call) { 254 | String useName = call.getPeerProfile().getDisplayName(); 255 | if(useName == null) { 256 | useName = call.getPeerProfile().getUserName(); 257 | } 258 | updateStatus(useName + "@" + call.getPeerProfile().getSipDomain()); 259 | } 260 | 261 | /** 262 | * Updates whether or not the user's voice is muted, depending on whether the button is pressed. 263 | * @param v The View where the touch event is being fired. 264 | * @param event The motion to act on. 265 | * @return boolean Returns false to indicate that the parent view should handle the touch event 266 | * as it normally would. 267 | */ 268 | public boolean onTouch(View v, MotionEvent event) { 269 | if (call == null) { 270 | return false; 271 | } else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) { 272 | call.toggleMute(); 273 | } else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) { 274 | call.toggleMute(); 275 | } 276 | return false; 277 | } 278 | 279 | public boolean onCreateOptionsMenu(Menu menu) { 280 | menu.add(0, CALL_ADDRESS, 0, "Call someone"); 281 | menu.add(0, SET_AUTH_INFO, 0, "Edit your SIP Info."); 282 | menu.add(0, HANG_UP, 0, "End Current Call."); 283 | 284 | return true; 285 | } 286 | 287 | public boolean onOptionsItemSelected(MenuItem item) { 288 | switch (item.getItemId()) { 289 | case CALL_ADDRESS: 290 | showDialog(CALL_ADDRESS); 291 | break; 292 | case SET_AUTH_INFO: 293 | updatePreferences(); 294 | break; 295 | case HANG_UP: 296 | if(call != null) { 297 | try { 298 | call.endCall(); 299 | } catch (SipException se) { 300 | // Log.d("WalkieTalkieActivity/onOptionsItemSelected", 301 | // "Error ending call.", se); 302 | } 303 | call.close(); 304 | } 305 | break; 306 | } 307 | return true; 308 | } 309 | 310 | @Override 311 | protected Dialog onCreateDialog(int id) { 312 | switch (id) { 313 | case CALL_ADDRESS: 314 | 315 | LayoutInflater factory = LayoutInflater.from(this); 316 | final View textBoxView = factory.inflate(R.layout.call_address_dialog, null); 317 | return new AlertDialog.Builder(this) 318 | .setTitle("Call Someone.") 319 | .setView(textBoxView) 320 | .setPositiveButton( 321 | android.R.string.ok, new DialogInterface.OnClickListener() { 322 | public void onClick(DialogInterface dialog, int whichButton) { 323 | EditText textField = (EditText) 324 | (textBoxView.findViewById(R.id.calladdress_edit)); 325 | sipAddress = textField.getText().toString(); 326 | initiateCall(); 327 | 328 | } 329 | }) 330 | .setNegativeButton( 331 | android.R.string.cancel, new DialogInterface.OnClickListener() { 332 | public void onClick(DialogInterface dialog, int whichButton) { 333 | // Noop. 334 | } 335 | }) 336 | .create(); 337 | 338 | case UPDATE_SETTINGS_DIALOG: 339 | return new AlertDialog.Builder(this) 340 | .setMessage("Please update your SIP Account Settings.") 341 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 342 | public void onClick(DialogInterface dialog, int whichButton) { 343 | updatePreferences(); 344 | } 345 | }) 346 | .setNegativeButton( 347 | android.R.string.cancel, new DialogInterface.OnClickListener() { 348 | public void onClick(DialogInterface dialog, int whichButton) { 349 | // Noop. 350 | } 351 | }) 352 | .create(); 353 | } 354 | return null; 355 | } 356 | 357 | public void updatePreferences() { 358 | Intent settingsActivity = new Intent(getBaseContext(), 359 | SipSettings.class); 360 | startActivity(settingsActivity); 361 | } 362 | 363 | // @Override 364 | // public void onClick(View v) { 365 | // initiateCall(); 366 | // } 367 | } 368 | --------------------------------------------------------------------------------