├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── Group-Voice-Call
├── OpenVoiceCall-Android
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── README.zh.md
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── libs
│ │ │ └── PLACEHOLDER
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── io
│ │ │ │ └── agora
│ │ │ │ └── openacall
│ │ │ │ └── ui
│ │ │ │ └── BasicTests.java
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets
│ │ │ └── logback.xml
│ │ │ ├── java
│ │ │ └── io
│ │ │ │ └── agora
│ │ │ │ ├── openacall
│ │ │ │ ├── AGApplication.java
│ │ │ │ ├── model
│ │ │ │ │ ├── AGEventHandler.java
│ │ │ │ │ ├── ConstantApp.java
│ │ │ │ │ ├── CurrentUserSettings.java
│ │ │ │ │ ├── EngineConfig.java
│ │ │ │ │ ├── MyEngineEventHandler.java
│ │ │ │ │ └── WorkerThread.java
│ │ │ │ └── ui
│ │ │ │ │ ├── BaseActivity.java
│ │ │ │ │ ├── ChatActivity.java
│ │ │ │ │ └── MainActivity.java
│ │ │ │ └── propeller
│ │ │ │ ├── Constant.java
│ │ │ │ └── ui
│ │ │ │ ├── AGLinearLayout.java
│ │ │ │ └── ViewUtil.java
│ │ │ ├── jniLibs
│ │ │ ├── armeabi-v7a
│ │ │ │ └── PLACEHOLDER
│ │ │ └── x86
│ │ │ │ └── PLACEHOLDER
│ │ │ └── res
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── btn_endcall.png
│ │ │ ├── btn_mute.png
│ │ │ ├── btn_speaker.png
│ │ │ └── ic_launcher.png
│ │ │ ├── layout
│ │ │ ├── activity_chat.xml
│ │ │ └── activity_main.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── ids.xml
│ │ │ ├── strings.xml
│ │ │ ├── strings_config.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── OpenVoiceCall-iOS-Objective-C
│ ├── .gitignore
│ ├── LICENSE
│ ├── OpenVoiceCall-iOS-Objective-C.xcodeproj
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── OpenVoiceCall-iOS-Objective-C
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── call.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── calling@2x.png
│ │ │ │ └── calling@3x.png
│ │ │ ├── earphone.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── earphone@2x.png
│ │ │ │ └── earphone@3x.png
│ │ │ ├── hungup.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── hungup@2x.png
│ │ │ │ └── hungup@3x.png
│ │ │ ├── mute.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── mute@2x.png
│ │ │ │ └── mute@3x.png
│ │ │ ├── speaker.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── speaker@2x.png
│ │ │ │ └── speaker@3x.png
│ │ │ └── un-mute.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── un-mute@2x.png
│ │ │ │ └── un-mute@3x.png
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── ChannelNameCheck.h
│ │ ├── ChannelNameCheck.m
│ │ ├── ChatButton.h
│ │ ├── ChatButton.m
│ │ ├── Define.h
│ │ ├── Info.plist
│ │ ├── InfoCell.h
│ │ ├── InfoCell.m
│ │ ├── InfoModel.h
│ │ ├── InfoModel.m
│ │ ├── KeyCenter.h
│ │ ├── KeyCenter.m
│ │ ├── MainViewController.h
│ │ ├── MainViewController.m
│ │ ├── OpenVoiceCall.pch
│ │ ├── RoomViewController.h
│ │ ├── RoomViewController.m
│ │ └── main.m
│ ├── README.md
│ └── README.zh.md
└── OpenVoiceCall-iOS
│ ├── .gitignore
│ ├── LICENSE
│ ├── OpenVoiceCall.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── OpenVoiceCall.xcscheme
│ ├── OpenVoiceCall
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── btn_endcall.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_endcall.pdf
│ │ ├── btn_mute.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_mute.pdf
│ │ ├── btn_mute_blue.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_mute_blue.pdf
│ │ ├── btn_speaker.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_speaker.pdf
│ │ └── btn_speaker_blue.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_speaker_blue.pdf
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── KeyCenter.swift
│ ├── LogCell.swift
│ ├── MainViewController.swift
│ ├── MediaCharacter.swift
│ └── RoomViewController.swift
│ ├── OpenVoiceCallUITests
│ ├── Info.plist
│ └── OpenVoiceCallUITests.swift
│ ├── README.md
│ └── README.zh.md
├── LICENSE.md
├── One-to-One-Voice
├── Agora-Android-Voice-Tutorial-1to1
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ ├── README.zh.md
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── libs
│ │ │ └── PLACEHOLDER
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── io
│ │ │ │ └── agora
│ │ │ │ └── tutorials1v1acall
│ │ │ │ └── VoiceChatViewActivity.java
│ │ │ ├── jniLibs
│ │ │ ├── arm64-v8a
│ │ │ │ └── PLACEHOLDER
│ │ │ ├── armeabi-v7a
│ │ │ │ └── PLACEHOLDER
│ │ │ └── x86
│ │ │ │ └── PLACEHOLDER
│ │ │ └── res
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── btn_end_call.png
│ │ │ ├── btn_mute.png
│ │ │ ├── btn_speaker.png
│ │ │ └── ic_launcher.png
│ │ │ ├── layout
│ │ │ └── activity_voice_chat_view.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
└── Agora-iOS-Voice-Tutorial-Swift-1to1
│ ├── .gitignore
│ ├── Agora-iOS-Voice-Tutorial-Tests
│ ├── Agora_iOS_Voice_Tutorial_Tests.swift
│ └── Info.plist
│ ├── Agora-iOS-Voice-Tutorial.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── Agora-iOS-Voice-Tutorial-Tests.xcscheme
│ │ └── Agora-iOS-Voice-Tutorial.xcscheme
│ ├── Agora-iOS-Voice-Tutorial
│ ├── AppDelegate.swift
│ ├── AppID.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── btn_endcall.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_endcall.pdf
│ │ ├── btn_mute.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_mute.pdf
│ │ ├── btn_mute_blue.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_mute_blue.pdf
│ │ ├── btn_speaker.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_speaker.pdf
│ │ └── btn_speaker_blue.imageset
│ │ │ ├── Contents.json
│ │ │ └── btn_speaker_blue.pdf
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── VoiceChatViewController.swift
│ ├── LICENSE
│ ├── README.md
│ └── README.zh.md
├── README.md
└── README.zh.md
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.framework
2 | *.a
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | build/
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # Eclipse project files
20 | .classpath
21 | .project
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Intellij project files
27 | *.iml
28 | *.ipr
29 | *.iws
30 | .idea/
31 |
32 | # Mac OS X
33 | .DS_Store
34 |
35 | # Android Studio
36 | .gradle
37 | /local.properties
38 | /.idea/workspace.xml
39 | obj/
40 |
41 | .externalNativeBuild
42 |
43 | # cscope or ctags files
44 | cscope.in.out
45 | cscope.out
46 | cscope.po.out
47 | tags
48 |
49 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2019 Agora Lab, Inc (http://www.agora.io/)
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
10 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/README.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call for Android
2 |
3 | *其他语言版本: [简体中文](README.zh.md)*
4 |
5 | The Open Voice Call for Android Sample App is an open-source demo that will help you get voice chat integrated directly into your Android applications using the Agora Voice SDK.
6 |
7 | With this sample app, you can:
8 |
9 | - Join / leave channel
10 | - Mute / unmute audio
11 | - Switch speaker
12 |
13 | A tutorial demo can be found here: [Agora-Android-Voice-Tutorial-1to1](https://github.com/AgoraIO/Basic-Audio-Call/tree/master/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1)
14 |
15 | ## Running the App
16 | **First**, create a developer account at [Agora.io](https://dashboard.agora.io/signin/), and obtain an App ID. Update "app/src/main/res/values/strings_config.xml" with your App ID.
17 |
18 | ```
19 | <#YOUR APP ID#>
20 | ```
21 |
22 | **Next**, integrate the Agora Voice SDK and there are two ways to integrate:
23 |
24 | - The recommended way to integrate:
25 |
26 | Add the address which can integrate the Agora Voice SDK automatically through JCenter in the property of the dependence of the "app/build.gradle":
27 | ```
28 | implementation 'io.agora.rtc:voice-sdk:3.0.0'
29 | ```
30 | (This sample program has added this address and do not need to add again. Adding the link address is the most important step if you want to integrate the Agora Voice SDK in your own application.)
31 |
32 | - Alternative way to integrate:
33 |
34 | First, download the **Agora Voice SDK** from [Agora.io SDK](https://www.agora.io/en/download/). Unzip the downloaded SDK package and copy ***.jar** under **libs** to **app/libs**, **arm64-v8a**/**x86**/**armeabi-v7a** under **libs** to **app/src/main/jniLibs**.
35 |
36 | Then, add the fllowing code in the property of the dependence of the "app/build.gradle":
37 |
38 | ```
39 | compile fileTree(dir: 'libs', include: ['*.jar'])
40 | ```
41 |
42 | **Finally**, open project with Android Studio, connect your Android device, build and run.
43 |
44 | Or use `Gradle` to build and run.
45 |
46 | ## Developer Environment Requirements
47 | - Android Studio 3.0 or above
48 | - Real devices (Nexus 5X or other devices)
49 | - Some simulators are function missing or have performance issue, so real device is the best choice
50 |
51 | ## Contact Us
52 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
53 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
54 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
55 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
56 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
57 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
58 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
59 |
60 | ## License
61 | The MIT License (MIT).
62 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/README.zh.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call for Android
2 |
3 | *Read this in other languages: [English](README.md)*
4 |
5 | 这个开源示例项目演示了如何快速集成 Agora 音频 SDK,实现多人音频通话。
6 |
7 | 在这个示例项目中包含了以下功能:
8 |
9 | - 加入通话和离开通话;
10 | - 静音和解除静音;
11 | - 切换扬声器和听筒;
12 |
13 | 你也可以在这里查看入门版的示例项目:[Agora-Android-Voice-Tutorial-1to1](https://github.com/AgoraIO/Basic-Audio-Call/tree/master/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1)
14 |
15 | ## 运行示例程序
16 | **首先**在 [Agora.io 注册](https://dashboard.agora.io/cn/signup/) 注册账号,并创建自己的测试项目,获取到 AppID。将 AppID 填写进 "app/src/main/res/values/strings_config.xml"
17 |
18 | ```
19 | <#YOUR APP ID#>
20 | ```
21 |
22 | **然后**是集成 Agora 音频 SDK,集成方式有以下两种:
23 |
24 | - 首选集成方式:
25 |
26 | 在项目对应的模块的 "app/build.gradle" 文件的依赖属性中加入通过 JCenter 自动集成 Agora 音频 SDK 的地址:
27 |
28 | ```
29 | implementation 'io.agora.rtc:voice-sdk:2.4.0'
30 | ```
31 |
32 | (该示例程序已添加此链接地址,无需再添加,如果要在自己的应用中集成 Agora 音频 SDK,添加链接地址是最重要的一步。)
33 |
34 | - 次选集成方式:
35 |
36 | 第一步: 在 [Agora.io SDK](https://www.agora.io/cn/download/) 下载 **语音通话 + 直播 SDK**,解压后将其中的 **libs** 文件夹下的 ***.jar** 复制到本项目的 **app/libs** 下,其中的 **libs** 文件夹下的 **arm64-v8a**/**x86**/**armeabi-v7a** 复制到本项目的 **app/src/main/jniLibs** 下。
37 |
38 | 第二步: 在本项目的 "app/build.gradle" 文件依赖属性中添加如下依赖关系:
39 |
40 | ```
41 | compile fileTree(dir: 'libs', include: ['*.jar'])
42 | ```
43 |
44 | **最后**用 Android Studio 打开该项目,连上设备,编译并运行。
45 |
46 | 也可以使用 `Gradle` 直接编译运行。
47 |
48 | ## 运行环境
49 | - Android Studio 3.0 +
50 | - 真实 Android 设备 (Nexus 5X 或者其它设备)
51 | - 部分模拟器会存在功能缺失或者性能问题,所以推荐使用真机
52 |
53 | ## 联系我们
54 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
55 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
56 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
57 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
58 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
59 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
60 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
61 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
62 |
63 | ## 代码许可
64 | The MIT License (MIT).
65 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | android {
8 | compileSdkVersion 26
9 |
10 | defaultConfig {
11 | applicationId "io.agora.openacall"
12 | minSdkVersion 16 // ICE_CREAM_SANDWICH
13 | targetSdkVersion 26
14 | versionCode 19
15 | versionName "x.y.z"
16 | }
17 |
18 | compileOptions {
19 | sourceCompatibility JavaVersion.VERSION_1_7
20 | targetCompatibility JavaVersion.VERSION_1_7
21 | }
22 |
23 | buildTypes {
24 | release {
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 | }
30 |
31 | dependencies {
32 | implementation fileTree(dir: 'libs', include: ['*.jar'])
33 |
34 | implementation 'com.android.support:appcompat-v7:26.1.0'
35 | implementation 'com.android.support:support-v4:26.1.0'
36 | implementation 'com.android.support:design:26.1.0'
37 | implementation 'org.slf4j:slf4j-api:1.7.21'
38 | implementation 'com.github.tony19:logback-android-core:1.1.1-4'
39 | implementation('com.github.tony19:logback-android-classic:1.1.1-4') {
40 | // workaround issue #73
41 | exclude group: 'com.google.android', module: 'android'
42 | }
43 |
44 | androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.6.3'
45 | }
46 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/libs/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | agora-rtc-sdk.jar
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/guohai/Dev/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/androidTest/java/io/agora/openacall/ui/BasicTests.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.ui;
2 |
3 | import android.test.ActivityInstrumentationTestCase2;
4 |
5 | import com.robotium.solo.Condition;
6 | import com.robotium.solo.Solo;
7 |
8 | import io.agora.openacall.BuildConfig;
9 | import io.agora.openacall.R;
10 |
11 | public class BasicTests extends ActivityInstrumentationTestCase2 {
12 |
13 | private Solo solo;
14 |
15 | public BasicTests() {
16 | super(MainActivity.class);
17 | }
18 |
19 | @Override
20 | public void setUp() throws Exception {
21 | solo = new Solo(getInstrumentation(), getActivity());
22 | }
23 |
24 | @Override
25 | public void tearDown() throws Exception {
26 | solo.finishOpenedActivities();
27 | }
28 |
29 | public String getString(int resId) {
30 | return solo.getString(resId);
31 | }
32 |
33 | public void testJoinChannel() throws Exception {
34 | String AUTO_TEST_CHANNEL_NAME = "for_auto_test_" + BuildConfig.VERSION_NAME + BuildConfig.VERSION_CODE;
35 |
36 | solo.unlockScreen();
37 |
38 | solo.assertCurrentActivity("Expected MainActivity activity", "MainActivity");
39 | solo.clearEditText(0);
40 | solo.enterText(0, AUTO_TEST_CHANNEL_NAME);
41 | solo.waitForText(AUTO_TEST_CHANNEL_NAME, 1, 2000L);
42 |
43 | solo.clickOnView(solo.getView(R.id.button_join));
44 |
45 | String targetActivity = ChatActivity.class.getSimpleName();
46 |
47 | solo.waitForLogMessage("onJoinChannelSuccess " + AUTO_TEST_CHANNEL_NAME, JOIN_CHANNEL_SUCCESS_THRESHOLD + 1000);
48 |
49 | solo.assertCurrentActivity("Expected " + targetActivity + " activity", targetActivity);
50 |
51 | long firstRemoteAudioTs = System.currentTimeMillis();
52 | solo.waitForLogMessage("volume: ", FIRST_REMOTE_AUDIO_RECEIVED_THRESHOLD + 500);
53 |
54 | assertTrue("first remote audio frame not received", System.currentTimeMillis() - firstRemoteAudioTs <= FIRST_REMOTE_AUDIO_RECEIVED_THRESHOLD);
55 |
56 | solo.waitForCondition(new Condition() { // stay at the channel for some time
57 | @Override
58 | public boolean isSatisfied() {
59 | return false;
60 | }
61 | }, FIRST_REMOTE_AUDIO_RECEIVED_THRESHOLD);
62 | }
63 |
64 | private static final int FIRST_REMOTE_AUDIO_RECEIVED_THRESHOLD = 50 * 1000;
65 | private static final int JOIN_CHANNEL_SUCCESS_THRESHOLD = 5000;
66 | }
67 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/assets/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
13 |
16 |
17 | ${LOG_DIR}/${FILE_PREFIX}${FILE_POSTFIX}
18 |
19 |
20 |
21 |
22 | ${LOG_DIR}/${FILE_PREFIX}.%i${FILE_POSTFIX}
23 |
24 | 1
25 | 7
26 |
27 |
28 | 1MB
29 |
30 |
31 |
32 |
33 | %d{yyyy-MM-dd HH:mm:ss.SSSZ} [%thread] %-5level %logger{0} %msg%n
34 |
35 |
36 |
37 |
38 |
39 |
40 | [%thread] %-5level %logger{0} %msg%n
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/AGApplication.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall;
2 |
3 | import android.app.Application;
4 | import io.agora.openacall.model.CurrentUserSettings;
5 | import io.agora.openacall.model.WorkerThread;
6 |
7 | public class AGApplication extends Application {
8 |
9 | private WorkerThread mWorkerThread;
10 |
11 | public synchronized void initWorkerThread() {
12 | if (mWorkerThread == null) {
13 | mWorkerThread = new WorkerThread(getApplicationContext());
14 | mWorkerThread.start();
15 |
16 | mWorkerThread.waitForReady();
17 | }
18 | }
19 |
20 | public synchronized WorkerThread getWorkerThread() {
21 | return mWorkerThread;
22 | }
23 |
24 | public synchronized void deInitWorkerThread() {
25 | mWorkerThread.exit();
26 | try {
27 | mWorkerThread.join();
28 | } catch (InterruptedException e) {
29 | e.printStackTrace();
30 | }
31 | mWorkerThread = null;
32 | }
33 |
34 | public static final CurrentUserSettings mAudioSettings = new CurrentUserSettings();
35 | }
36 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/model/AGEventHandler.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.model;
2 |
3 | public interface AGEventHandler {
4 | void onJoinChannelSuccess(String channel, int uid, int elapsed);
5 |
6 | void onUserOffline(int uid, int reason);
7 |
8 | void onExtraCallback(int type, Object... data);
9 |
10 | int EVENT_TYPE_ON_USER_AUDIO_MUTED = 7;
11 |
12 | int EVENT_TYPE_ON_SPEAKER_STATS = 8;
13 |
14 | int EVENT_TYPE_ON_AGORA_MEDIA_ERROR = 9;
15 |
16 | int EVENT_TYPE_ON_AUDIO_QUALITY = 10;
17 |
18 | int EVENT_TYPE_ON_APP_ERROR = 13;
19 |
20 | int EVENT_TYPE_ON_AUDIO_ROUTE_CHANGED = 18;
21 | }
22 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/model/ConstantApp.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.model;
2 |
3 | public class ConstantApp {
4 | public static final String APP_BUILD_DATE = "today";
5 |
6 | public static final int BASE_VALUE_PERMISSION = 0X0001;
7 | public static final int PERMISSION_REQ_ID_RECORD_AUDIO = BASE_VALUE_PERMISSION + 1;
8 | public static final int PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE = BASE_VALUE_PERMISSION + 3;
9 |
10 | public static class PrefManager {
11 | public static final String PREF_PROPERTY_UID = "pOCXx_uid";
12 | }
13 |
14 | public static final String ACTION_KEY_CHANNEL_NAME = "ecHANEL";
15 |
16 | public static class AppError {
17 | public static final int NO_NETWORK_CONNECTION = 3;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/model/CurrentUserSettings.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.model;
2 |
3 | public class CurrentUserSettings {
4 | public String mChannelName;
5 |
6 | public CurrentUserSettings() {
7 | reset();
8 | }
9 |
10 | public void reset() {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/model/EngineConfig.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.model;
2 |
3 | public class EngineConfig {
4 | public int mUid;
5 |
6 | public String mChannel;
7 |
8 | public void reset() {
9 | mChannel = null;
10 | }
11 |
12 | EngineConfig() {
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/model/WorkerThread.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.model;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.os.Environment;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.os.Message;
9 | import android.preference.PreferenceManager;
10 | import android.provider.Settings;
11 | import android.text.TextUtils;
12 | import android.util.Log;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.io.File;
18 |
19 | import io.agora.openacall.R;
20 | import io.agora.rtc.Constants;
21 | import io.agora.rtc.RtcEngine;
22 |
23 | public class WorkerThread extends Thread {
24 | private final static Logger log = LoggerFactory.getLogger(WorkerThread.class);
25 |
26 | private final Context mContext;
27 |
28 | private static final int ACTION_WORKER_THREAD_QUIT = 0X1010; // quit this thread
29 |
30 | private static final int ACTION_WORKER_JOIN_CHANNEL = 0X2010;
31 |
32 | private static final int ACTION_WORKER_LEAVE_CHANNEL = 0X2011;
33 |
34 | private static final class WorkerThreadHandler extends Handler {
35 |
36 | private WorkerThread mWorkerThread;
37 |
38 | WorkerThreadHandler(WorkerThread thread) {
39 | this.mWorkerThread = thread;
40 | }
41 |
42 | public void release() {
43 | mWorkerThread = null;
44 | }
45 |
46 | @Override
47 | public void handleMessage(Message msg) {
48 | if (this.mWorkerThread == null) {
49 | log.warn("handler is already released! " + msg.what);
50 | return;
51 | }
52 |
53 | switch (msg.what) {
54 | case ACTION_WORKER_THREAD_QUIT:
55 | mWorkerThread.exit();
56 | break;
57 | case ACTION_WORKER_JOIN_CHANNEL:
58 | String[] data = (String[]) msg.obj;
59 | mWorkerThread.joinChannel(data[0], msg.arg1);
60 | break;
61 | case ACTION_WORKER_LEAVE_CHANNEL:
62 | String channel = (String) msg.obj;
63 | mWorkerThread.leaveChannel(channel);
64 | break;
65 | }
66 | }
67 | }
68 |
69 | private WorkerThreadHandler mWorkerHandler;
70 |
71 | private boolean mReady;
72 |
73 | public final void waitForReady() {
74 | while (!mReady) {
75 | try {
76 | Thread.sleep(20);
77 | } catch (InterruptedException e) {
78 | e.printStackTrace();
79 | }
80 | log.debug("wait for " + WorkerThread.class.getSimpleName());
81 | }
82 | }
83 |
84 | @Override
85 | public void run() {
86 | log.trace("start to run");
87 | Looper.prepare();
88 |
89 | mWorkerHandler = new WorkerThreadHandler(this);
90 |
91 | ensureRtcEngineReadyLock();
92 |
93 | mReady = true;
94 |
95 | // enter thread looper
96 | Looper.loop();
97 | }
98 |
99 | private RtcEngine mRtcEngine;
100 |
101 | public final void joinChannel(final String channel, int uid) {
102 | if (Thread.currentThread() != this) {
103 | log.warn("joinChannel() - worker thread asynchronously " + channel + " " + uid);
104 | Message envelop = new Message();
105 | envelop.what = ACTION_WORKER_JOIN_CHANNEL;
106 | envelop.obj = new String[]{channel};
107 | envelop.arg1 = uid;
108 | mWorkerHandler.sendMessage(envelop);
109 | return;
110 | }
111 |
112 | ensureRtcEngineReadyLock();
113 | mRtcEngine.joinChannel(null, channel, "OpenVCall", uid);
114 |
115 | mEngineConfig.mChannel = channel;
116 |
117 | log.debug("joinChannel " + channel + " " + uid);
118 | }
119 |
120 | public final void leaveChannel(String channel) {
121 | if (Thread.currentThread() != this) {
122 | log.warn("leaveChannel() - worker thread asynchronously " + channel);
123 | Message envelop = new Message();
124 | envelop.what = ACTION_WORKER_LEAVE_CHANNEL;
125 | envelop.obj = channel;
126 | mWorkerHandler.sendMessage(envelop);
127 | return;
128 | }
129 |
130 | if (mRtcEngine != null) {
131 | mRtcEngine.leaveChannel();
132 | }
133 |
134 | mEngineConfig.reset();
135 | log.debug("leaveChannel " + channel);
136 | }
137 |
138 | private EngineConfig mEngineConfig;
139 |
140 | public final EngineConfig getEngineConfig() {
141 | return mEngineConfig;
142 | }
143 |
144 | private final MyEngineEventHandler mEngineEventHandler;
145 |
146 | public static String getDeviceID(Context context) {
147 | // XXX according to the API docs, this value may change after factory reset
148 | // use Android id as device id
149 | return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
150 | }
151 |
152 | private RtcEngine ensureRtcEngineReadyLock() {
153 | if (mRtcEngine == null) {
154 | String appId = mContext.getString(R.string.private_app_id);
155 | if (TextUtils.isEmpty(appId)) {
156 | throw new RuntimeException("NEED TO use your App ID, get your own ID at https://dashboard.agora.io/");
157 | }
158 | try {
159 | // Creates an RtcEngine instance
160 | mRtcEngine = RtcEngine.create(mContext, appId, mEngineEventHandler.mRtcEventHandler);
161 | } catch (Exception e) {
162 | log.error(Log.getStackTraceString(e));
163 | throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
164 | }
165 |
166 | /*
167 | Sets the channel profile of the Agora RtcEngine.
168 | The Agora RtcEngine differentiates channel profiles and applies different optimization
169 | algorithms accordingly. For example, it prioritizes smoothness and low latency for a
170 | video call, and prioritizes video quality for a video broadcast.
171 | */
172 | mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
173 |
174 | /*
175 | Enables the onAudioVolumeIndication callback at a set time interval to report on which
176 | users are speaking and the speakers' volume.
177 | Once this method is enabled, the SDK returns the volume indication in the
178 | onAudioVolumeIndication callback at the set time interval, regardless of whether any user
179 | is speaking in the channel.
180 | */
181 | mRtcEngine.enableAudioVolumeIndication(200, 3, false); // 200 ms
182 | mRtcEngine.setLogFile(Environment.getExternalStorageDirectory()
183 | + File.separator + mContext.getPackageName() + "/log/agora-rtc.log");
184 | }
185 | return mRtcEngine;
186 | }
187 |
188 | public MyEngineEventHandler eventHandler() {
189 | return mEngineEventHandler;
190 | }
191 |
192 | public RtcEngine getRtcEngine() {
193 | return mRtcEngine;
194 | }
195 |
196 | /**
197 | * call this method to exit
198 | * should ONLY call this method when this thread is running
199 | */
200 | public final void exit() {
201 | if (Thread.currentThread() != this) {
202 | log.warn("exit() - exit app thread asynchronously");
203 | mWorkerHandler.sendEmptyMessage(ACTION_WORKER_THREAD_QUIT);
204 | return;
205 | }
206 |
207 | mReady = false;
208 |
209 | // TODO should remove all pending(read) messages
210 |
211 | log.debug("exit() > start");
212 |
213 | // exit thread looper
214 | Looper.myLooper().quit();
215 |
216 | mWorkerHandler.release();
217 |
218 | log.debug("exit() > end");
219 | }
220 |
221 | public WorkerThread(Context context) {
222 | this.mContext = context;
223 |
224 | this.mEngineConfig = new EngineConfig();
225 | SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
226 | this.mEngineConfig.mUid = pref.getInt(ConstantApp.PrefManager.PREF_PROPERTY_UID, 0);
227 |
228 | this.mEngineEventHandler = new MyEngineEventHandler(mContext, this.mEngineConfig);
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/ui/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.ui;
2 |
3 | import android.Manifest;
4 | import android.content.pm.PackageManager;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.support.annotation.NonNull;
9 | import android.support.v4.app.ActivityCompat;
10 | import android.support.v4.content.ContextCompat;
11 | import android.support.v4.view.ViewConfigurationCompat;
12 | import android.support.v7.app.AppCompatActivity;
13 | import android.util.DisplayMetrics;
14 | import android.view.*;
15 | import android.widget.Toast;
16 | import io.agora.openacall.AGApplication;
17 | import io.agora.openacall.BuildConfig;
18 | import io.agora.openacall.model.*;
19 | import io.agora.propeller.Constant;
20 | import io.agora.rtc.RtcEngine;
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 |
24 | import java.util.Arrays;
25 |
26 | public abstract class BaseActivity extends AppCompatActivity {
27 | private final static Logger log = LoggerFactory.getLogger(BaseActivity.class);
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 |
33 | final View layout = findViewById(Window.ID_ANDROID_CONTENT);
34 | ViewTreeObserver vto = layout.getViewTreeObserver();
35 | vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
36 | @Override
37 | public void onGlobalLayout() {
38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
39 | layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
40 | } else {
41 | layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
42 | }
43 | initUIandEvent();
44 | }
45 | });
46 | }
47 |
48 | protected abstract void initUIandEvent();
49 |
50 | protected abstract void deInitUIandEvent();
51 |
52 | @Override
53 | protected void onPostCreate(Bundle savedInstanceState) {
54 | super.onPostCreate(savedInstanceState);
55 |
56 | new Handler().postDelayed(new Runnable() {
57 | @Override
58 | public void run() {
59 | if (isFinishing()) {
60 | return;
61 | }
62 |
63 | boolean checkPermissionResult = checkSelfPermissions();
64 |
65 | if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M)) {
66 | // so far we do not use OnRequestPermissionsResultCallback
67 | }
68 | }
69 | }, 500);
70 | }
71 |
72 | private boolean checkSelfPermissions() {
73 | return checkSelfPermission(Manifest.permission.RECORD_AUDIO, ConstantApp.PERMISSION_REQ_ID_RECORD_AUDIO) &&
74 | checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, ConstantApp.PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE);
75 | }
76 |
77 | @Override
78 | protected void onDestroy() {
79 | deInitUIandEvent();
80 | super.onDestroy();
81 | }
82 |
83 | public boolean checkSelfPermission(String permission, int requestCode) {
84 | log.debug("checkSelfPermission " + permission + " " + requestCode);
85 | if (ContextCompat.checkSelfPermission(this,
86 | permission)
87 | != PackageManager.PERMISSION_GRANTED) {
88 |
89 | ActivityCompat.requestPermissions(this,
90 | new String[]{permission},
91 | requestCode);
92 | return false;
93 | }
94 |
95 | if (Manifest.permission.RECORD_AUDIO.equals(permission)) {
96 | ((AGApplication) getApplication()).initWorkerThread();
97 | }
98 | return true;
99 | }
100 |
101 | protected RtcEngine rtcEngine() {
102 | return ((AGApplication) getApplication()).getWorkerThread().getRtcEngine();
103 | }
104 |
105 | protected final WorkerThread worker() {
106 | return ((AGApplication) getApplication()).getWorkerThread();
107 | }
108 |
109 | protected final EngineConfig config() {
110 | return ((AGApplication) getApplication()).getWorkerThread().getEngineConfig();
111 | }
112 |
113 | protected final MyEngineEventHandler event() {
114 | return ((AGApplication) getApplication()).getWorkerThread().eventHandler();
115 | }
116 |
117 | public final void showLongToast(final String msg) {
118 | this.runOnUiThread(new Runnable() {
119 | @Override
120 | public void run() {
121 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
122 | }
123 | });
124 | }
125 |
126 | @Override
127 | public void onRequestPermissionsResult(int requestCode,
128 | @NonNull String permissions[], @NonNull int[] grantResults) {
129 | log.debug("onRequestPermissionsResult " + requestCode + " " + Arrays.toString(permissions) + " " + Arrays.toString(grantResults));
130 | switch (requestCode) {
131 | case ConstantApp.PERMISSION_REQ_ID_RECORD_AUDIO: {
132 | if (grantResults.length > 0
133 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
134 | checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, ConstantApp.PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE);
135 | ((AGApplication) getApplication()).initWorkerThread();
136 | } else {
137 | finish();
138 | }
139 | break;
140 | }
141 | case ConstantApp.PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE: {
142 | if (grantResults.length > 0
143 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
144 | } else {
145 | finish();
146 | }
147 | break;
148 | }
149 | }
150 | }
151 |
152 | protected CurrentUserSettings vSettings() {
153 | return AGApplication.mAudioSettings;
154 | }
155 |
156 | protected int virtualKeyHeight() {
157 | boolean hasPermanentMenuKey = ViewConfigurationCompat.hasPermanentMenuKey(ViewConfiguration.get(getApplication()));
158 |
159 | DisplayMetrics metrics = new DisplayMetrics();
160 | Display display = getWindowManager().getDefaultDisplay();
161 |
162 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
163 | display.getRealMetrics(metrics);
164 | } else {
165 | display.getMetrics(metrics);
166 | }
167 |
168 | int fullHeight = metrics.heightPixels;
169 |
170 | display.getMetrics(metrics);
171 |
172 | return fullHeight - metrics.heightPixels;
173 | }
174 |
175 | protected void initVersionInfo() {
176 | String version = "V " + BuildConfig.VERSION_NAME + "(Build: " + BuildConfig.VERSION_CODE
177 | + ", " + ConstantApp.APP_BUILD_DATE + ", SDK: " + Constant.MEDIA_SDK_VERSION + ")";
178 | // TextView textVersion = (TextView) findViewById(R.id.app_version);
179 | // textVersion.setText(version);
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/openacall/ui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package io.agora.openacall.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.text.Editable;
6 | import android.text.TextUtils;
7 | import android.text.TextWatcher;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 | import android.widget.EditText;
12 | import io.agora.openacall.R;
13 | import io.agora.openacall.model.ConstantApp;
14 |
15 | public class MainActivity extends BaseActivity {
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_main);
20 | }
21 |
22 | @Override
23 | protected void initUIandEvent() {
24 | EditText v_channel = (EditText) findViewById(R.id.channel_name);
25 | v_channel.addTextChangedListener(new TextWatcher() {
26 | @Override
27 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
28 |
29 | }
30 |
31 | @Override
32 | public void onTextChanged(CharSequence s, int start, int before, int count) {
33 |
34 | }
35 |
36 | @Override
37 | public void afterTextChanged(Editable s) {
38 | boolean isEmpty = TextUtils.isEmpty(s.toString());
39 | findViewById(R.id.button_join).setEnabled(!isEmpty);
40 | }
41 | });
42 |
43 | String lastChannelName = vSettings().mChannelName;
44 | if (!TextUtils.isEmpty(lastChannelName)) {
45 | v_channel.setText(lastChannelName);
46 | v_channel.setSelection(lastChannelName.length());
47 | }
48 | }
49 |
50 | @Override
51 | protected void deInitUIandEvent() {
52 | }
53 |
54 | @Override
55 | public boolean onCreateOptionsMenu(final Menu menu) {
56 | return super.onCreateOptionsMenu(menu);
57 | }
58 |
59 | @Override
60 | public boolean onOptionsItemSelected(MenuItem item) {
61 | return super.onOptionsItemSelected(item);
62 | }
63 |
64 | public void onClickJoin(View view) {
65 | forwardToRoom();
66 | }
67 |
68 | public void forwardToRoom() {
69 | EditText v_channel = (EditText) findViewById(R.id.channel_name);
70 | String channel = v_channel.getText().toString();
71 | vSettings().mChannelName = channel;
72 |
73 | Intent i = new Intent(MainActivity.this, ChatActivity.class);
74 | i.putExtra(ConstantApp.ACTION_KEY_CHANNEL_NAME, channel);
75 |
76 | startActivity(i);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/propeller/Constant.java:
--------------------------------------------------------------------------------
1 | package io.agora.propeller;
2 |
3 | import io.agora.rtc.RtcEngine;
4 |
5 | public class Constant {
6 |
7 | public static final String MEDIA_SDK_VERSION;
8 |
9 | static {
10 | String sdk = "undefined";
11 | try {
12 | sdk = RtcEngine.getSdkVersion();
13 | } catch (Throwable e) {
14 | }
15 | MEDIA_SDK_VERSION = sdk;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/propeller/ui/AGLinearLayout.java:
--------------------------------------------------------------------------------
1 | package io.agora.propeller.ui;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.util.AttributeSet;
6 | import android.view.KeyEvent;
7 | import android.view.MotionEvent;
8 | import android.widget.LinearLayout;
9 |
10 | public class AGLinearLayout extends LinearLayout {
11 | public AGLinearLayout(Context context) {
12 | super(context);
13 | }
14 |
15 | public AGLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
16 | super(context, attrs, defStyleAttr);
17 | }
18 |
19 | public AGLinearLayout(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | }
22 |
23 | @Override
24 | public boolean dispatchTouchEvent(@NonNull MotionEvent event) {
25 | return ViewUtil.checkDoubleTouchEvent(event, this) || super.dispatchTouchEvent(event);
26 | }
27 |
28 | @Override
29 | public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
30 | return ViewUtil.checkDoubleKeyEvent(event, this) || super.dispatchKeyEvent(event);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/java/io/agora/propeller/ui/ViewUtil.java:
--------------------------------------------------------------------------------
1 | package io.agora.propeller.ui;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.os.Build;
5 | import android.os.SystemClock;
6 | import android.view.KeyEvent;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 | public class ViewUtil {
13 | protected static final boolean DEBUG_ENABLED = false;
14 |
15 | private final static Logger log = LoggerFactory.getLogger(ViewUtil.class);
16 |
17 | private static final int DEFAULT_TOUCH_TIMESTAMP = -1; // first time
18 |
19 | private static final int TOUCH_COOL_DOWN_TIME = 500; // ms
20 |
21 | private static long mLastTouchTime = DEFAULT_TOUCH_TIMESTAMP;
22 |
23 | /* package */
24 | static final boolean checkDoubleTouchEvent(MotionEvent event, View view) {
25 | if (DEBUG_ENABLED) {
26 | log.debug("dispatchTouchEvent " + mLastTouchTime + " " + event);
27 | }
28 |
29 | if (event.getAction() == MotionEvent.ACTION_DOWN) { // only check touch down event
30 | if (mLastTouchTime == DEFAULT_TOUCH_TIMESTAMP || (SystemClock.elapsedRealtime() - mLastTouchTime) >= TOUCH_COOL_DOWN_TIME) {
31 | mLastTouchTime = SystemClock.elapsedRealtime();
32 | } else {
33 | log.warn("too many touch events " + view + " " + MotionEvent.ACTION_DOWN);
34 | return true;
35 | }
36 | }
37 | return false;
38 | }
39 |
40 | /* package */
41 | static final boolean checkDoubleKeyEvent(KeyEvent event, View view) {
42 | if (DEBUG_ENABLED) {
43 | log.debug("dispatchKeyEvent " + mLastTouchTime + " " + event);
44 | }
45 |
46 | if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
47 | if (mLastTouchTime != DEFAULT_TOUCH_TIMESTAMP && (SystemClock.elapsedRealtime() - mLastTouchTime) < TOUCH_COOL_DOWN_TIME) {
48 | log.warn("too many key events " + view + " " + KeyEvent.ACTION_DOWN);
49 | return true;
50 | }
51 | mLastTouchTime = SystemClock.elapsedRealtime();
52 | }
53 |
54 | return false;
55 | }
56 |
57 | public static void setBackground(View view, Drawable drawable) {
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
59 | view.setBackground(drawable);
60 | } else {
61 | view.setBackgroundDrawable(drawable);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/jniLibs/armeabi-v7a/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | libagora-rtc-sdk-jni.so
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/jniLibs/x86/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | libagora-rtc-sdk-jni.so
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_endcall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_endcall.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_mute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_mute.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_speaker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/btn_speaker.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/layout/activity_chat.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
23 |
24 |
32 |
33 |
41 |
42 |
48 |
49 |
54 |
55 |
62 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
25 |
26 |
37 |
38 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF00A0EB
4 |
5 | #3F51B5
6 | #303F9F
7 | #FF4081
8 |
9 | #30FF4081
10 |
11 | #CC262626
12 |
13 | #ACFFFFFF
14 |
15 | #FF55585A
16 |
17 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Open Voice Call
5 |
6 | Welcome to Open Voice Call!
7 |
8 | Channel name
9 |
10 | Join
11 |
12 | No network connection, please check the network settings
13 |
14 | // DO NOT TRANSLATE
15 | %d kbps
16 |
17 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/strings_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 | <#YOUR APP ID#>
10 |
11 | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()+,-:;<=.>?@[]^_`{|}~
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
17 |
18 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.4'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | jcenter()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | org.gradle.daemon=true
19 | org.gradle.parallel=true
20 |
21 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-Android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Sep 17 18:00:28 CST 2018
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-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows 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 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-Android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | */.DS_Store
3 | .framework
4 | */.framework
5 | # Xcode
6 | #
7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
8 |
9 | ## Build generated
10 | build/
11 | DerivedData/
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata/
23 |
24 | ## Other
25 | *.moved-aside
26 | *.xccheckout
27 | *.xcscmblueprint
28 |
29 | ## Obj-C/Swift specific
30 | *.hmap
31 | *.ipa
32 | *.dSYM.zip
33 | *.dSYM
34 |
35 | # CocoaPods
36 | #
37 | # We recommend against adding the Pods directory to your .gitignore. However
38 | # you should judge for yourself, the pros and cons are mentioned at:
39 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
40 | #
41 | # Pods/
42 |
43 | # Carthage
44 | #
45 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
46 | # Carthage/Checkouts
47 |
48 | Carthage/Build
49 |
50 | # fastlane
51 | #
52 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
53 | # screenshots whenever they are needed.
54 | # For more information about the recommended setup visit:
55 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
56 |
57 | fastlane/report.xml
58 | fastlane/Preview.html
59 | fastlane/screenshots
60 | fastlane/test_output
61 |
62 | # Code Injection
63 | #
64 | # After new code Injection tools there's a generated folder /iOSInjectionProject
65 | # https://github.com/johnno1962/injectionforxcode
66 |
67 | iOSInjectionProject/
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2017 Agora Lab, Inc (http://www.agora.io/)
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
10 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/call.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "calling@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "calling@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/call.imageset/calling@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/call.imageset/calling@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/call.imageset/calling@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/call.imageset/calling@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/earphone.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "earphone@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "earphone@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/earphone.imageset/earphone@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/earphone.imageset/earphone@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/earphone.imageset/earphone@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/earphone.imageset/earphone@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/hungup.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "hungup@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "hungup@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/hungup.imageset/hungup@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/hungup.imageset/hungup@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/hungup.imageset/hungup@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/hungup.imageset/hungup@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/mute.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "mute@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "mute@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/mute.imageset/mute@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/mute.imageset/mute@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/mute.imageset/mute@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/mute.imageset/mute@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/speaker.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "speaker@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "speaker@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/speaker.imageset/speaker@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/speaker.imageset/speaker@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/speaker.imageset/speaker@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/speaker.imageset/speaker@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/un-mute.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "un-mute@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "un-mute@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/un-mute.imageset/un-mute@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/un-mute.imageset/un-mute@2x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/un-mute.imageset/un-mute@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Assets.xcassets/un-mute.imageset/un-mute@3x.png
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/ChannelNameCheck.h:
--------------------------------------------------------------------------------
1 | //
2 | // ChannelNameCheck.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ChannelNameCheck : NSObject
12 | + (NSString *)channelNameCheckLegal:(NSString *)channelName;
13 | @end
14 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/ChannelNameCheck.m:
--------------------------------------------------------------------------------
1 | //
2 | // ChannelNameCheck.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "ChannelNameCheck.h"
10 |
11 | @implementation ChannelNameCheck
12 | + (NSString *)channelNameCheckLegal:(NSString *)channelName {
13 | NSString *includerChars = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()+,-:;<=.>?@[]^_`{|}~";
14 | NSCharacterSet *invertedSet = [[NSCharacterSet characterSetWithCharactersInString:includerChars] invertedSet];
15 | NSArray *separatedArray = [channelName componentsSeparatedByCharactersInSet:invertedSet];
16 | NSString *fixedChannelName = [separatedArray componentsJoinedByString:@""];
17 | return fixedChannelName;
18 | }
19 | @end
20 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/ChatButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // ChatButton.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/12.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ChatButton : UIButton
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/ChatButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // ChatButton.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/12.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "ChatButton.h"
10 |
11 | @implementation ChatButton
12 |
13 | - (void)layoutSubviews {
14 | [super layoutSubviews];
15 |
16 | CGFloat imageViewWH = 44;
17 | CGFloat imageViewY = (self.frame.size.width - imageViewWH) * 0.5;
18 | CGFloat labelWH = 20;
19 |
20 | self.imageView.frame = CGRectMake(imageViewY, 0, imageViewWH, imageViewWH);
21 | self.titleLabel.frame = CGRectMake(0, imageViewWH, self.frame.size.width, labelWH);
22 | self.titleLabel.textAlignment = NSTextAlignmentCenter;
23 | self.titleLabel.font = [UIFont systemFontOfSize:14];
24 | }
25 |
26 | - (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event {
27 | self.selected = !self.selected;
28 | [super sendAction:action to:target forEvent:event];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Define.h:
--------------------------------------------------------------------------------
1 | //
2 | // Define.h
3 | // OpenVodieCall
4 | //
5 | // Created by CavanSu on 2017/9/5.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #ifndef Define_h
10 | #define Define_h
11 |
12 | #define ThemeColor [UIColor colorWithRed:122.0 / 255.0 green:203.0 / 255.0 blue:253.0 / 255.0 alpha:1]
13 |
14 | #endif /* Define_h */
15 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSMicrophoneUsageDescription
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/InfoCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // InfoCell.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "InfoModel.h"
11 |
12 | @interface InfoCell : UITableViewCell
13 | @property (weak, nonatomic) IBOutlet UILabel *infoLabel;
14 | @property (nonatomic, weak) InfoModel *model;
15 | @end
16 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/InfoCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // InfoCell.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "InfoCell.h"
10 |
11 | @implementation InfoCell
12 |
13 | - (void)awakeFromNib {
14 | [super awakeFromNib];
15 | self.infoLabel.textColor = [UIColor whiteColor];
16 | self.contentView.backgroundColor = [UIColor clearColor];
17 | self.backgroundColor = [UIColor clearColor];
18 | self.infoLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
19 | }
20 |
21 | - (void)setModel:(InfoModel *)model {
22 | self.infoLabel.text = model.infoStr;
23 | [self layoutIfNeeded];
24 | if (!model.height ) {
25 | model.height = CGRectGetMaxY(self.infoLabel.frame);
26 | }
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/InfoModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // InfoModel.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface InfoModel : NSObject
12 | @property (nonatomic, assign) CGFloat height;
13 | @property (nonatomic, copy) NSString *infoStr;
14 | + (instancetype)modelWithInfoStr:(NSString *)infoStr;
15 | @end
16 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/InfoModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // InfoModel.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "InfoModel.h"
10 |
11 | @implementation InfoModel
12 |
13 | + (instancetype)modelWithInfoStr:(NSString *)infoStr {
14 | InfoModel *model = [[ InfoModel alloc] init];
15 | model.infoStr = [[NSString alloc] initWithString:infoStr];
16 | return model;
17 | }
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/KeyCenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // KeyCenter.h
3 | // OpenVideoCall
4 | //
5 | // Created by GongYuhua on 2016/9/12.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface KeyCenter : NSObject
12 | + (NSString *)AppId;
13 | + (NSString *)Token;
14 | @end
15 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/KeyCenter.m:
--------------------------------------------------------------------------------
1 | //
2 | // KeyCenter.m
3 | // OpenVideoCall
4 | //
5 | // Created by GongYuhua on 2016/9/12.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | #import "KeyCenter.h"
10 |
11 | @implementation KeyCenter
12 | + (NSString *)AppId {
13 | return <#Your App Id#>;
14 | }
15 |
16 | // assign token to nil if you have not enabled app certificate
17 | + (NSString *)Token {
18 | return <#Temp Access Token#>;
19 | }
20 | @end
21 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/MainViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MainViewController.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MainViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/MainViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MainViewController.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import "MainViewController.h"
10 | #import "RoomViewController.h"
11 | #import "ChannelNameCheck.h"
12 |
13 | @interface MainViewController ()
14 | @property (weak, nonatomic) IBOutlet UIButton *joinButton;
15 | @property (weak, nonatomic) IBOutlet UILabel *welcomeLabel;
16 | @property (weak, nonatomic) IBOutlet UITextField *channelNameTextField;
17 | @end
18 |
19 | @implementation MainViewController
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | [self updateViews];
24 | }
25 |
26 | - (void)updateViews {
27 | self.view.backgroundColor = ThemeColor;
28 | self.welcomeLabel.adjustsFontSizeToFitWidth = YES;
29 | self.joinButton.backgroundColor = [UIColor whiteColor];
30 | [self.joinButton setTitleColor:ThemeColor forState:UIControlStateNormal];
31 | self.joinButton.layer.cornerRadius = self.joinButton.bounds.size.height * 0.5;
32 | }
33 |
34 | - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender {
35 | BOOL YesOrNo = self.channelNameTextField.text.length > 0 ? YES : NO;
36 | return YesOrNo;
37 | }
38 |
39 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender {
40 | RoomViewController *roomVC = segue.destinationViewController;
41 | roomVC.channelName = self.channelNameTextField.text;
42 | }
43 |
44 | - (IBAction)editingChannelName:(UITextField *)sender {
45 | NSString *legalChannelName = [ChannelNameCheck channelNameCheckLegal:sender.text];
46 | sender.text = legalChannelName;
47 | }
48 |
49 | - (BOOL)textFieldShouldReturn:(UITextField *)textField {
50 | [self.channelNameTextField endEditing:YES];
51 | return YES;
52 | }
53 |
54 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
55 | [self.channelNameTextField endEditing:YES];
56 | }
57 |
58 | - (UIStatusBarStyle)preferredStatusBarStyle {
59 | return UIStatusBarStyleLightContent;
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall.pch:
--------------------------------------------------------------------------------
1 | //
2 | // OpenVoiceCall.pch
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #ifndef OpenVoiceCall_pch
10 | #define OpenVoiceCall_pch
11 |
12 | #import "Define.h"
13 |
14 | #endif /* OpenVoiceCall_pch */
15 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/RoomViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RoomViewController.h
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/18.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RoomViewController : UIViewController
12 | @property (nonatomic, copy) NSString *channelName;
13 | @end
14 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/OpenVoiceCall-iOS-Objective-C/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // OpenVoiceCall-OC
4 | //
5 | // Created by CavanSu on 2017/9/16.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/README.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call iOS for Objective C
2 |
3 | *其他语言版本: [简体中文](README.zh.md)*
4 |
5 | The Open Voice Call iOS for Objective C Sample App is an open-source demo that will help you get voice chat integrated directly into your iOS applications using the Agora Voice SDK.
6 |
7 | With this sample app, you can:
8 |
9 | - Join / leave channel
10 | - Mute / unmute audio
11 | - Switch speaker
12 |
13 | ## Prerequisites
14 | - Xcode 10.0+
15 | - Physical iOS device (iPhone or iPad)
16 | - iOS simulator is NOT supported
17 |
18 | ## Quick Start
19 |
20 | This section shows you how to prepare, build, and run the sample application.
21 |
22 | ### Obtain an App Id
23 |
24 | To build and run the sample application, get an App Id:
25 |
26 | 1. Create a developer account at [agora.io](https://dashboard.agora.io/signin/). Once you finish the signup process, you will be redirected to the Dashboard.
27 | 2. Navigate in the Dashboard tree on the left to **Projects** > **Project List**.
28 | 3. Save the **App Id** from the Dashboard for later use.
29 | 4. Generate a temp **Access Token** (valid for 24 hours) from dashboard page with given channel name, save for later use.
30 |
31 | 5. Open `OpenVoiceCall-iOS-Objective-C.xcodeproj` and edit the `KeyCenter.m` file. Update `<#Your App Id#>` with your App Id, and assign the token variable with the temp Access Token generated from dashboard.
32 |
33 | ```
34 | + (NSString *)AppId {
35 | return <#Your App Id#>;
36 | }
37 |
38 | // assign token to nil if you have not enabled app certificate
39 | + (NSString *)Token {
40 | return <#Temp Access Token#>;
41 | }
42 | ```
43 |
44 | ### Integrate the Agora Audio SDK
45 |
46 | 1. Download the [Agora Voice SDK](https://www.agora.io/en/download/). Unzip the downloaded SDK package and copy the following files from the SDK `libs` folder into the sample application `OpenVoiceCall-iOS-Objective-C` folder.
47 |
48 | - `AograRtcEngineKit.framework`
49 |
50 | 2. Connect your iPhone or iPad device and run the project. Ensure a valid provisioning profile is applied or your project will not run.
51 |
52 | ## Contact Us
53 |
54 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
55 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
56 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
57 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
58 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
59 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
60 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
61 |
62 | ## License
63 |
64 | The MIT License (MIT).
65 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS-Objective-C/README.zh.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call iOS for Objective C
2 |
3 | *Read this in other languages: [English](README.md)*
4 |
5 | 这个开源示例项目演示了如何快速集成Agora音频SDK,实现多人音频通话。
6 |
7 | 在这个示例项目中包含了以下功能:
8 |
9 | - 加入通话和离开通话;
10 | - 静音和解除静音;
11 | - 外放和听筒切换;
12 |
13 | ## 环境准备
14 |
15 | - XCode 10.0 +
16 | - iOS 真机设备
17 | - 不支持模拟器
18 |
19 | ## 运行示例程序
20 |
21 | 这个段落主要讲解了如何编译和运行实例程序。
22 |
23 | ### 创建Agora账号并获取AppId
24 |
25 | 在编译和启动实例程序前,您需要首先获取一个可用的App Id:
26 |
27 | 1. 在[agora.io](https://dashboard.agora.io/signin/)创建一个开发者账号
28 | 2. 前往后台页面,点击左部导航栏的 **项目 > 项目列表** 菜单
29 | 3. 复制后台的 **App Id** 并备注,稍后启动应用时会用到它
30 | 4. 在项目页面生成临时 **Access Token** (24小时内有效)并备注,注意生成的Token只能适用于对应的频道名。
31 |
32 | 5. 将 AppID 和 Token 填写进 KeyCenter.swift
33 |
34 | ```
35 | + (NSString *)AppId {
36 | return <#Your App Id#>;
37 | }
38 |
39 | // 如果你没有打开Token功能,token可以直接给nil
40 | + (NSString *)Token {
41 | return <#Temp Access Token#>;
42 | }
43 | ```
44 |
45 | ### 集成 Agora 音频 SDK
46 |
47 | 1. 在 [Agora.io SDK](https://www.agora.io/cn/blog/download/) 下载 **语音通话 + 直播 SDK**,解压后将其中**libs**文件夹中的下列文件拷贝到本项目的 OpenVoiceCall-iOS-Objective-C 文件夹下。
48 |
49 | - AgoraRtcEngineKit.framework
50 |
51 | 2. 最后使用 Xcode 打开 OpenVoiceCall-iOS-Objective-C.xcodeproj,连接 iPhone/iPad 测试设备,设置有效的开发者签名后即可运行。
52 |
53 | ## 联系我们
54 |
55 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
56 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
57 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
58 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
59 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
60 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
61 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
62 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
63 |
64 | ## 代码许可
65 |
66 | The MIT License (MIT).
67 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/.gitignore:
--------------------------------------------------------------------------------
1 | xcuserdata
2 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2017 Agora Lab, Inc (http://www.agora.io/)
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
10 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall.xcodeproj/xcshareddata/xcschemes/OpenVoiceCall.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // OpenVoiceCall
4 | //
5 | // Created by GongYuhua on 16/9/7.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_endcall.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_endcall.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_endcall.imageset/btn_endcall.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_endcall.imageset/btn_endcall.pdf
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_mute.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute.imageset/btn_mute.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute.imageset/btn_mute.pdf
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute_blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_mute_blue.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute_blue.imageset/btn_mute_blue.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_mute_blue.imageset/btn_mute_blue.pdf
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_speaker.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker.imageset/btn_speaker.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker.imageset/btn_speaker.pdf
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker_blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_speaker_blue.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker_blue.imageset/btn_speaker_blue.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Assets.xcassets/btn_speaker_blue.imageset/btn_speaker_blue.pdf
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSMicrophoneUsageDescription
26 | use microphone to start video call
27 | UIBackgroundModes
28 |
29 | audio
30 |
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | UIMainStoryboardFile
34 | Main
35 | UIRequiredDeviceCapabilities
36 |
37 | armv7
38 |
39 | UISupportedInterfaceOrientations
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationLandscapeLeft
43 | UIInterfaceOrientationLandscapeRight
44 |
45 | UISupportedInterfaceOrientations~ipad
46 |
47 | UIInterfaceOrientationPortrait
48 | UIInterfaceOrientationPortraitUpsideDown
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/KeyCenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyCenter.swift
3 | // LargeGroupVideoChat
4 | //
5 | // Created by ZhangJi on 30/09/2017.
6 | // Copyright © 2017 Agora. All rights reserved.
7 | //
8 |
9 | struct KeyCenter {
10 | static let AppId: String = <#Your App Id#>
11 |
12 | // assign token to nil if you have not enabled app certificate
13 | static var Token: String? = <#Temp Access Token#>
14 | }
15 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/LogCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LogCell.swift
3 | // OpenVoiceCall
4 | //
5 | // Created by GongYuhua on 16/9/7.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LogCell: UITableViewCell {
12 |
13 | @IBOutlet weak var logLabel: UILabel!
14 |
15 | func set(log: String) {
16 | logLabel.text = log
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/MainViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainViewController.swift
3 | // OpenVoiceCall
4 | //
5 | // Created by GongYuhua on 16/8/17.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MainViewController: UIViewController {
12 |
13 | @IBOutlet weak var roomNameTextField: UITextField!
14 |
15 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
16 | guard let segueId = segue.identifier , segueId == "mainToRoom",
17 | let roomName = sender as? String else {
18 | return
19 | }
20 |
21 | let roomVC = segue.destination as! RoomViewController
22 | roomVC.roomName = roomName
23 | roomVC.delegate = self
24 | }
25 |
26 | @IBAction func doRoomNameTextFieldEditing(_ sender: UITextField) {
27 | if let text = sender.text , !text.isEmpty {
28 | let legalString = MediaCharacter.updateToLegalMediaString(from: text)
29 | sender.text = legalString
30 | }
31 | }
32 |
33 | @IBAction func doJoinPressed(_ sender: UIButton) {
34 | enter(roomName: roomNameTextField.text)
35 | }
36 | }
37 |
38 | private extension MainViewController {
39 | func enter(roomName: String?) {
40 | guard let roomName = roomName , !roomName.isEmpty else {
41 | return
42 | }
43 | performSegue(withIdentifier: "mainToRoom", sender: roomName)
44 | }
45 | }
46 |
47 | extension MainViewController: RoomVCDelegate {
48 | func roomVCNeedClose(_ roomVC: RoomViewController) {
49 | dismiss(animated: true, completion: nil)
50 | }
51 | }
52 |
53 | extension MainViewController: UITextFieldDelegate {
54 | func textFieldShouldReturn(_ textField: UITextField) -> Bool {
55 | enter(roomName: textField.text)
56 | return true
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCall/MediaCharacter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MediaCharacter.swift
3 | // OpenVoiceCall
4 | //
5 | // Created by GongYuhua on 16/8/1.
6 | // Copyright © 2016年 Agora. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct MediaCharacter {
12 |
13 | fileprivate static let legalMediaCharacterSet: NSCharacterSet = {
14 | return NSCharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()+,-:;<=.>?@[]^_`{|}~")
15 | }()
16 |
17 | static func updateToLegalMediaString(from string: String) -> String {
18 | let legalSet = MediaCharacter.legalMediaCharacterSet
19 | let separatedArray = string.components(separatedBy: legalSet.inverted)
20 | let legalString = separatedArray.joined(separator: "")
21 | return legalString
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCallUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/OpenVoiceCallUITests/OpenVoiceCallUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpenVoiceCallUITests.swift
3 | // OpenVoiceCallUITests
4 | //
5 | // Created by GongYuhua on 2017/1/13.
6 | // Copyright © 2017年 Agora. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class OpenVoiceCallUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | continueAfterFailure = false
17 | XCUIApplication().launch()
18 | }
19 |
20 | override func tearDown() {
21 | super.tearDown()
22 | }
23 |
24 | func testJoinAndLeaveChannel() {
25 |
26 | let app = XCUIApplication()
27 | let channelNameTextField = app.textFields["Channel name"]
28 | channelNameTextField.tap()
29 | channelNameTextField.typeText("uiTestChannel")
30 |
31 | app.buttons["JoinChannel"].tap()
32 |
33 | let closeButton = app.buttons["btn endcall"]
34 | expectation(for: NSPredicate(format: "exists == 1"), evaluatedWith: closeButton, handler: nil)
35 | waitForExpectations(timeout: 5, handler: nil)
36 |
37 | closeButton.tap()
38 |
39 | let textField = app.textFields["Channel name"]
40 | expectation(for: NSPredicate(format: "exists == 1"), evaluatedWith: textField, handler: nil)
41 | waitForExpectations(timeout: 5, handler: nil)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/README.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call iOS for Swift
2 |
3 | *其他语言版本: [简体中文](README.zh.md)*
4 |
5 | The Open Voice Call iOS for Swift Sample App is an open-source demo that will help you get voice chat integrated directly into your iOS applications using the Agora Voice SDK.
6 |
7 | With this sample app, you can:
8 |
9 | - Join / leave channel
10 | - Mute / unmute audio
11 | - Switch speaker
12 |
13 | ## Prerequisites
14 | - Xcode 10.0+
15 | - Physical iOS device (iPhone or iPad)
16 | - iOS simulator is NOT supported
17 |
18 | ## Quick Start
19 |
20 | This section shows you how to prepare, build, and run the sample application.
21 |
22 | ### Obtain an App Id
23 |
24 | To build and run the sample application, get an App Id:
25 |
26 | 1. Create a developer account at [agora.io](https://dashboard.agora.io/signin/). Once you finish the signup process, you will be redirected to the Dashboard.
27 | 2. Navigate in the Dashboard tree on the left to **Projects** > **Project List**.
28 | 3. Save the **App Id** from the Dashboard for later use.
29 | 4. Generate a temp **Access Token** (valid for 24 hours) from dashboard page with given channel name, save for later use.
30 |
31 | 5. Open `OpenVoiceCall.xcodeproj` and edit the `KeyCenter.swift` file. Update `<#Your App Id#>` with your App Id, and assign the token variable with the temp Access Token generated from dashboard.
32 |
33 | ``` Swift
34 | static let AppId: String = <#Your App Id#>
35 |
36 | // assign token to nil if you have not enabled app certificate
37 | static var Token: String? = <#Temp Access Token#>
38 | ```
39 |
40 | ### Integrate the Agora Audio SDK
41 |
42 | 1. Download the [Agora Voice SDK](https://www.agora.io/en/download/). Unzip the downloaded SDK package and copy the following files from the SDK `libs` folder into the sample application `OpenVoiceCall ` folder.
43 |
44 | - `AograRtcKit.framework`
45 |
46 | 2. Connect your iPhone or iPad device and run the project. Ensure a valid provisioning profile is applied or your project will not run.
47 |
48 | ## Contact Us
49 |
50 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
51 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
52 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
53 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
54 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
55 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
56 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
57 |
58 | ## License
59 |
60 | The MIT License (MIT).
61 |
--------------------------------------------------------------------------------
/Group-Voice-Call/OpenVoiceCall-iOS/README.zh.md:
--------------------------------------------------------------------------------
1 | # Open Voice Call iOS for Swift
2 |
3 | *Read this in other languages: [English](README.md)*
4 |
5 | 这个开源示例项目演示了如何快速集成Agora音频SDK,实现多人音频通话。
6 |
7 | 在这个示例项目中包含了以下功能:
8 |
9 | - 加入通话和离开通话;
10 | - 静音和解除静音;
11 | - 外放和听筒切换;
12 |
13 | ## 环境准备
14 |
15 | - XCode 10.0 +
16 | - iOS 真机设备
17 | - 不支持模拟器
18 |
19 | ## 运行示例程序
20 |
21 | 这个段落主要讲解了如何编译和运行实例程序。
22 |
23 | ### 创建Agora账号并获取AppId
24 |
25 | 在编译和启动实例程序前,您需要首先获取一个可用的App Id:
26 |
27 | 1. 在 [agora.io](https://dashboard.agora.io/signin/) 创建一个开发者账号
28 | 2. 前往后台页面,点击左部导航栏的 **项目 > 项目列表** 菜单
29 | 3. 复制后台的 **App Id** 并备注,稍后启动应用时会用到它
30 | 4. 在项目页面生成临时 **Access Token** (24小时内有效)并备注,注意生成的Token只能适用于对应的频道名。
31 |
32 | 5. 将 AppID 和 Token 填写进 KeyCenter.swift
33 |
34 | ```
35 | static let AppId: String = <#Your App Id#>
36 |
37 | // 如果你没有打开Token功能,token可以直接给nil
38 | static var Token: String? = <#Temp Access Token#>
39 | ```
40 |
41 | ### 集成 Agora 音频 SDK
42 |
43 | 1. 在 [Agora.io SDK](https://www.agora.io/cn/blog/download/) 下载 **语音通话 + 直播 SDK**,解压后将其中**libs**文件夹中的下列文件拷贝到本项目的 OpenVoiceCall 文件夹下。
44 |
45 | - AgoraRtcKit.framework
46 |
47 | 2. 最后使用 Xcode 打开 OpenVoiceCall.xcodeproj,连接 iPhone/iPad 测试设备,设置有效的开发者签名后即可运行。
48 |
49 | ## 联系我们
50 |
51 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
52 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
53 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
54 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
55 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
56 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
57 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
58 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
59 |
60 | ## 代码许可
61 |
62 | The MIT License (MIT).
63 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Agora Lab, Inc (http://www.agora.io/)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | build/
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # Eclipse project files
20 | .classpath
21 | .project
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Intellij project files
27 | *.iml
28 | *.ipr
29 | *.iws
30 | .idea/
31 |
32 | # Mac OS X
33 | .DS_Store
34 |
35 | # Android Studio
36 | .gradle
37 | /local.properties
38 | /.idea/workspace.xml
39 | obj/
40 |
41 | .externalNativeBuild
42 |
43 | # cscope or ctags files
44 | cscope.in.out
45 | cscope.out
46 | cscope.po.out
47 | tags
48 |
49 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Agora.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/README.md:
--------------------------------------------------------------------------------
1 | # Agora Android Voice Tutorial - 1to1
2 |
3 | *其他语言版本: [简体中文](README.zh.md)*
4 |
5 | The Agora Android Voice Tutorial for Swift 1to1 Sample App is an open-source demo that will help you get voice chat integrated directly into your Android applications using the Agora Voice SDK.
6 |
7 | With this sample app, you can:
8 |
9 | - Join / leave channel
10 | - Mute / unmute audio
11 | - Switch speaker
12 |
13 | A full-fledged demo can be found here: [OpenVoiceCall-Android](https://github.com/AgoraIO/Basic-Audio-Call/tree/master/Group-Voice-Call/OpenVoiceCall-Android)
14 |
15 | ## Running the App
16 | **First**, create a developer account at [Agora.io](https://dashboard.agora.io/signin/), and obtain an App ID. Note you can get a temp token from dashboard project page (Can be used to join given channel only). Update "app/src/main/res/values/strings.xml" with your App ID and Token.
17 |
18 | ```
19 |
20 |
21 |
22 |
24 | <#YOUR APP ID#>
25 |
26 |
27 | #YOUR ACCESS TOKEN#
28 | ```
29 |
30 | **Next**, integrate the Agora Voice SDK and there are two ways to integrate:
31 |
32 | - The recommended way to integrate:
33 |
34 | Add the address which can integrate the Agora Voice SDK automatically through JCenter in the property of the dependence of the "app/build.gradle":
35 |
36 | ```
37 | implementation 'io.agora.rtc:voice-sdk:3.0.0'
38 | ```
39 | (Adding the link address is the most important step if you want to integrate the Agora Video SDK in your own application.)
40 | - Alternative way to integrate:
41 |
42 | First, download the **Agora Voice SDK** from [Agora.io SDK](https://www.agora.io/en/download/). Unzip the downloaded SDK package and copy ***.jar** under **libs** to **app/libs**, **arm64-v8a**/**x86**/**armeabi-v7a** under **libs** to **app/src/main/jniLibs**.
43 |
44 | Then, add the fllowing code in the property of the dependence of the "app/build.gradle":
45 |
46 | ```
47 | compile fileTree(dir: 'libs', include: ['*.jar'])
48 | ```
49 |
50 | **Finally**, open project with Android Studio, connect your Android device, build and run.
51 |
52 | Or use `Gradle` to build and run.
53 |
54 | ## Developer Environment Requirements
55 | - Android Studio 3.0 or above
56 | - Real devices (Nexus 5X or other devices)
57 | - Some simulators are function missing or have performance issue, so real device is the best choice
58 |
59 | ## Contact Us
60 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
61 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
62 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
63 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
64 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
65 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
66 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
67 |
68 | ## License
69 | The MIT License (MIT).
70 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/README.zh.md:
--------------------------------------------------------------------------------
1 | # Agora Android Voice Tutorial - 1to1
2 |
3 | *Read this in other languages: [English](README.md)*
4 |
5 | 这个开源示例项目演示了如何快速集成 Agora 音频 SDK,实现1对1音频通话。
6 |
7 | 在这个示例项目中包含了以下功能:
8 |
9 | - 加入通话和离开通话;
10 | - 静音和解除静音;
11 | - 切换扬声器和听筒;
12 |
13 | 你可以在这里查看进阶版的示例项目:[OpenVoiceCall-Android](https://github.com/AgoraIO/Basic-Audio-Call/tree/master/Group-Voice-Call/OpenVoiceCall-Android)
14 |
15 | ## 运行示例程序
16 | **首先**在 [Agora.io 注册](https://dashboard.agora.io/cn/signup/) 注册账号,并创建自己的测试项目,获取到 AppID。你可以在你的项目页面生成一个临时的Token (生成的Token只能用于加入指定的频道),将 AppID 和 Token 填写进 "app/src/main/res/values/strings.xml"
17 |
18 | ```
19 |
20 |
21 |
22 |
24 | <#YOUR APP ID#>
25 |
26 |
27 | #YOUR ACCESS TOKEN#
28 | ```
29 |
30 | **然后**是集成 Agora 音频 SDK ,集成方式有以下两种:
31 |
32 | - 首选集成方式:
33 |
34 | 在项目对应的模块的 "app/build.gradle" 文件的依赖属性中加入通过 JCenter 自动集成 Agora 音频 SDK 的地址:
35 |
36 | ```
37 | implementation 'io.agora.rtc:voice-sdk:2.4.1'
38 | ```
39 |
40 | ( 如果要在自己的应用中集成 Agora 音频 SDK,添加链接地址是最重要的一步。)
41 |
42 | - 次选集成方式:
43 |
44 | 第一步: 在 [Agora.io SDK](https://www.agora.io/cn/download/) 下载 **语音通话 + 直播 SDK**,解压后将其中的 **libs** 文件夹下的 ***.jar** 复制到本项目的 **app/libs** 下,其中的 **libs** 文件夹下的 **arm64-v8a**/**x86**/**armeabi-v7a** 复制到本项目的 **app/src/main/jniLibs** 下。
45 |
46 | 第二步: 在本项目的 "app/build.gradle" 文件依赖属性中添加如下依赖关系:
47 |
48 | ```
49 | compile fileTree(dir: 'libs', include: ['*.jar'])
50 | ```
51 |
52 | **最后**用 Android Studio 打开该项目,连上设备,编译并运行。
53 |
54 | 也可以使用 `Gradle` 直接编译运行。
55 |
56 | ## 运行环境
57 | - Android Studio 3.0 +
58 | - 真实 Android 设备 (Nexus 5X 或者其它设备)
59 | - 部分模拟器会存在功能缺失或者性能问题,所以推荐使用真机
60 |
61 | ## 联系我们
62 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
63 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
64 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
65 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
66 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
67 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
68 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
69 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
70 |
71 | ## 代码许可
72 | The MIT License (MIT).
73 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 |
6 | defaultConfig {
7 | applicationId "io.agora.tutorials1v1acall"
8 | minSdkVersion 16 // JELLY_BEAN
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | }
15 |
16 | compileOptions {
17 | sourceCompatibility JavaVersion.VERSION_1_8
18 | targetCompatibility JavaVersion.VERSION_1_8
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 |
28 | lintOptions {
29 | warning 'InvalidPackage'
30 | }
31 | }
32 |
33 | dependencies {
34 | implementation fileTree(dir: 'libs', include: ['*.jar']) // DO NOT CHANGE, CI may needs it when packaging
35 | implementation 'com.android.support:appcompat-v7:28.0.0'
36 | }
37 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/libs/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | agora-rtc-sdk.jar
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/guohai/Dev/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/jniLibs/arm64-v8a/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | libagora-rtc-sdk-jni.so
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/jniLibs/armeabi-v7a/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | libagora-rtc-sdk-jni.so
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/jniLibs/x86/PLACEHOLDER:
--------------------------------------------------------------------------------
1 | libagora-rtc-sdk-jni.so
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_end_call.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_end_call.png
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_mute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_mute.png
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_speaker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/btn_speaker.png
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/layout/activity_voice_chat_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
25 |
26 |
30 |
31 |
38 |
39 |
46 |
47 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Agora-Android-Voice-Tutorial
3 |
4 |
5 |
6 |
7 |
9 | <#YOUR APP ID#>
10 |
11 |
12 | #YOUR ACCESS TOKEN#
13 |
14 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.4.2'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | jcenter()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 30 20:13:38 CST 2019
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-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows 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 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/.gitignore:
--------------------------------------------------------------------------------
1 | xcuserdata
2 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial-Tests/Agora_iOS_Voice_Tutorial_Tests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Agora_iOS_Voice_Tutorial_Tests.swift
3 | // Agora-iOS-Voice-Tutorial-Tests
4 | //
5 | // Created by CavanSu on 2020/7/3.
6 | // Copyright © 2020 Agora. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Agora_iOS_Voice_Tutorial
11 | import AgoraRtcKit
12 |
13 | class Agora_iOS_Voice_Tutorial_Tests: XCTestCase {
14 |
15 | override func setUpWithError() throws {
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDownWithError() throws {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | }
22 |
23 | func testExample() throws {
24 | _ = AgoraRtcEngineKit.sharedEngine(withAppId: "", delegate: nil)
25 | }
26 |
27 | func testPerformanceExample() throws {
28 | // This is an example of a performance test case.
29 | measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial-Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial.xcodeproj/xcshareddata/xcschemes/Agora-iOS-Voice-Tutorial-Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
14 |
15 |
17 |
23 |
24 |
25 |
26 |
27 |
37 |
39 |
45 |
46 |
47 |
48 |
54 |
55 |
61 |
62 |
63 |
64 |
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial.xcodeproj/xcshareddata/xcschemes/Agora-iOS-Voice-Tutorial.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Agora-iOS-Voice-Tutorial
4 | //
5 | // Created by GongYuhua on 2017/4/10.
6 | // Copyright © 2017年 Agora. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/AppID.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppID.swift
3 | // Agora iOS Voice Tutorial
4 | //
5 | // Created by GongYuhua on 2017/4/10.
6 | // Copyright © 2017年 Agora. All rights reserved.
7 | //
8 |
9 | let AppID: String = <#Your App Id#>
10 | // assign Token to nil if you have not enabled app certificate
11 | let Token: String? = <#Temp Access Token#>
12 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_endcall.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_endcall.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_endcall.imageset/btn_endcall.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_endcall.imageset/btn_endcall.pdf
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_mute.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute.imageset/btn_mute.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute.imageset/btn_mute.pdf
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute_blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_mute_blue.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute_blue.imageset/btn_mute_blue.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_mute_blue.imageset/btn_mute_blue.pdf
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_speaker.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker.imageset/btn_speaker.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker.imageset/btn_speaker.pdf
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker_blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "btn_speaker_blue.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker_blue.imageset/btn_speaker_blue.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO/Basic-Audio-Call/da10f89abf4677cdb52b9236d656bb954d791471/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Assets.xcassets/btn_speaker_blue.imageset/btn_speaker_blue.pdf
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
40 |
51 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSMicrophoneUsageDescription
24 |
25 | UIBackgroundModes
26 |
27 | audio
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | UISupportedInterfaceOrientations~ipad
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationPortraitUpsideDown
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/Agora-iOS-Voice-Tutorial/VoiceChatViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VoiceChatViewController.swift
3 | // Agora-iOS-Voice-Tutorial
4 | //
5 | // Created by GongYuhua on 2017/4/10.
6 | // Copyright © 2017年 Agora. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AgoraRtcKit
11 |
12 | class VoiceChatViewController: UIViewController {
13 |
14 | @IBOutlet weak var controlButtonsView: UIView!
15 |
16 | var agoraKit: AgoraRtcEngineKit!
17 |
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 |
21 | initializeAgoraEngine()
22 | joinChannel()
23 | }
24 |
25 | func initializeAgoraEngine() {
26 | // Initializes the Agora engine with your app ID.
27 | agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: AppID, delegate: nil)
28 | }
29 |
30 | func joinChannel() {
31 | // Allows a user to join a channel.
32 | agoraKit.joinChannel(byToken: Token, channelId: "demoChannel", info:nil, uid:0) {[unowned self] (sid, uid, elapsed) -> Void in
33 | // Joined channel "demoChannel"
34 | self.agoraKit.setEnableSpeakerphone(true)
35 | UIApplication.shared.isIdleTimerDisabled = true
36 | }
37 | }
38 |
39 | @IBAction func didClickHangUpButton(_ sender: UIButton) {
40 | leaveChannel()
41 | }
42 |
43 | func leaveChannel() {
44 | agoraKit.leaveChannel(nil)
45 | hideControlButtons()
46 |
47 | UIApplication.shared.isIdleTimerDisabled = false
48 | }
49 |
50 | func hideControlButtons() {
51 | controlButtonsView.isHidden = true
52 | }
53 |
54 | @IBAction func didClickMuteButton(_ sender: UIButton) {
55 | sender.isSelected = !sender.isSelected
56 | // Stops/Resumes sending the local audio stream.
57 | agoraKit.muteLocalAudioStream(sender.isSelected)
58 | }
59 |
60 | @IBAction func didClickSwitchSpeakerButton(_ sender: UIButton) {
61 | sender.isSelected = !sender.isSelected
62 | // Enables/Disables the audio playback route to the speakerphone.
63 | //
64 | // This method sets whether the audio is routed to the speakerphone or earpiece. After calling this method, the SDK returns the onAudioRouteChanged callback to indicate the changes.
65 | agoraKit.setEnableSpeakerphone(sender.isSelected)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Agora.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/README.md:
--------------------------------------------------------------------------------
1 | # Agora iOS Voice Tutorial for Swift - 1to1
2 |
3 | *其他语言版本: [简体中文](README.zh.md)*
4 |
5 | The Agora iOS Voice Tutorial for Swift 1to1 Sample App is an open-source demo that will help you get voice chat integrated directly into your iOS applications using the Agora Voice SDK.
6 |
7 | With this sample app, you can:
8 |
9 | - Join / leave channel
10 | - Mute / unmute audio
11 | - Switch speaker
12 |
13 | ## Prerequisites
14 | - Xcode 10.0+
15 | - Physical iOS device (iPhone or iPad)
16 | - iOS simulator is NOT supported
17 |
18 | ## Quick Start
19 |
20 | This section shows you how to prepare, build, and run the sample application.
21 |
22 | ### Obtain an App Id
23 |
24 | To build and run the sample application, get an App Id:
25 |
26 | 1. Create a developer account at [agora.io](https://dashboard.agora.io/signin/). Once you finish the signup process, you will be redirected to the Dashboard.
27 | 2. Navigate in the Dashboard tree on the left to **Projects** > **Project List**.
28 | 3. Save the **App Id** from the Dashboard for later use.
29 | 4. Generate a temp **Access Token** (valid for 24 hours) from dashboard page with given channel name, save for later use.
30 |
31 | 5. Open `Agora iOS Voice Tutorial.xcodeproj` and edit the `AppID.swift` file. Update `<#Your App Id#>` with your App Id, and assign the token variable with the temp Access Token generated from dashboard.
32 |
33 | ``` Swift
34 | let AppID: String = <#Your App Id#>
35 | // assign Token to nil if you have not enabled app certificate
36 | let Token: String? = <#Temp Token#>
37 | ```
38 |
39 | ### Integrate the Agora Audio SDK
40 |
41 | 1. Download the [Agora Voice SDK](https://www.agora.io/en/download/). Unzip the downloaded SDK package and copy the following files from the SDK `libs` folder into the sample application `Agora iOS Voice Tutorial` folder.
42 |
43 | - `AograRtcKit.framework`
44 |
45 | 2. Connect your iPhone or iPad device and run the project. Ensure a valid provisioning profile is applied or your project will not run.
46 |
47 | ## Contact Us
48 |
49 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
50 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
51 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
52 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
53 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
54 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
55 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
56 |
57 | ## License
58 |
59 | The MIT License (MIT).
60 |
--------------------------------------------------------------------------------
/One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1/README.zh.md:
--------------------------------------------------------------------------------
1 | # Agora iOS Voice Tutorial for Swift - 1to1
2 |
3 | *Read this in other languages: [English](README.md)*
4 |
5 | 这个开源示例项目演示了如何快速集成Agora音频SDK,实现1对1音频通话。
6 |
7 | 在这个示例项目中包含了以下功能:
8 |
9 | - 加入通话和离开通话;
10 | - 静音和解除静音;
11 | - 切换扬声器和听筒;
12 |
13 | ## 环境准备
14 |
15 | - XCode 10.0 +
16 | - iOS 真机设备
17 | - 不支持模拟器
18 |
19 | ## 运行示例程序
20 |
21 | 这个段落主要讲解了如何编译和运行实例程序。
22 |
23 | ### 创建Agora账号并获取AppId
24 |
25 | 在编译和启动实例程序前,您需要首先获取一个可用的App Id:
26 |
27 | 1. 在 [agora.io](https://dashboard.agora.io/signin/) 创建一个开发者账号
28 | 2. 前往后台页面,点击左部导航栏的 **项目 > 项目列表** 菜单
29 | 3. 复制后台的 **App Id** 并备注,稍后启动应用时会用到它
30 | 4. 在项目页面生成临时 **Access Token** (24小时内有效)并备注,注意生成的Token只能适用于对应的频道名。
31 |
32 | 5. 将 AppID 和 Token 填写进 AppID.swift
33 |
34 | ```
35 | let AppID: String = <#Your App Id#>
36 | // 如果你没有打开Token功能,token可以直接给nil
37 | let Token: String? = <#Temp Token#>
38 | ```
39 |
40 | ### 集成 Agora 音频 SDK
41 |
42 | 1. 在 [Agora.io SDK](https://www.agora.io/cn/blog/download/) 下载 **语音通话 + 直播 SDK**,解压后将其中**libs**文件夹中的下列文件拷贝到本项目的 Agora iOS Voice Tutorial 文件夹下。
43 |
44 | - AgoraRtcKit.framework
45 |
46 | 2. 最后使用 Xcode 打开 Agora iOS Voice Tutorial.xcodeproj,连接 iPhone/iPad 测试设备,设置有效的开发者签名后即可运行。
47 |
48 | ## 联系我们
49 |
50 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
51 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
52 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
53 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
54 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
55 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
56 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
57 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
58 |
59 | ## 代码许可
60 |
61 | The MIT License (MIT).
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic Audio Call
2 |
3 | _Other Languages: [简体中文](README.zh.md)_
4 |
5 | Agora provides a set of sample applications demonstrating how to integrate the Agora Audio SDK for:
6 |
7 | - [1-to-1 voice calls](#1-to-1-voice-calls)
8 | - [Group vocie calls](#group-voice-calls)
9 |
10 | ## Platforms Supported
11 |
12 | ### 1-to-1 Voice Calls
13 |
14 | Sample applications for 1-to-1 voice calls are provided for Android, iOS.
15 |
16 | The 1-to-1 voice call sample applications, demonstrate how to:
17 |
18 | - Join / leave a channel
19 | - Mute / unmute audio
20 | - Switch speaker
21 |
22 |
23 | Project Folder Name|Platform|Description
24 | ---|---|---
25 | [Agora Android Voice Tutorial - 1 to 1](./One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1)|Android|Agora Android Voice Tutorial 1 to 1
26 | [Agora iOS Voice Tutorial for Swift - 1 to 1](./One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1)|iOS|Agora iOS Voice Tutorial 1 to 1 using Swift
27 |
28 |
29 |
30 | ### Group Voice Calls
31 |
32 | Sample applications for group voice calls are provided for Android, iOS.
33 |
34 |
35 | The group voice call sample applications, demonstrate how to:
36 |
37 | - Join / leave a channel
38 | - Mute / unmute audio
39 | - Switch speaker
40 |
41 | Project Folder Name|Platform|Description
42 | ---|---|---
43 | [Open Voice Call for Android](./Group-Voice-Call/OpenVoiceCall-Android)|Android|Open Voice Call for Android
44 | [Open Voice Call iOS for Objective C](./Group-Voice-Call/OpenVoiceCall-iOS-Objective-C)|iOS|Open Voice Call for iOS using Objective C
45 | [Open Voice Call iOS for Swift](./Group-Voice-Call/OpenVoiceCall-iOS)|iOS|Open Voice Call for iOS using Swift
46 |
47 | ## Contact Us
48 |
49 | - For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
50 | - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
51 | - Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
52 | - Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
53 | - You can find full API documentation at [Document Center](https://docs.agora.io/en/)
54 | - If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
55 | - You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
56 |
57 |
58 | ## License
59 |
60 | All sample applications are licensed under the MIT License (MIT). [View the license](LICENSE.md).
61 |
--------------------------------------------------------------------------------
/README.zh.md:
--------------------------------------------------------------------------------
1 | # 音频通话
2 |
3 | _其他语言:[English](README.md)_
4 |
5 | Agora 提供一系列的示例应用,展示如何集成 Agora 音频 SDK。
6 |
7 | - [一对一音频通话](#一对一音频通话)
8 | - [多人音频通话](#多人音频通话)
9 |
10 | ## 支持的平台
11 |
12 | ### 一对一音频通话
13 |
14 | 一对一音频通话的示例应用包含 Android, iOS平台。
15 |
16 | 一对一音频通话的示例应用,展示了:
17 |
18 | - 加入通话和离开通话
19 | - 静音和解除静音
20 | - 外放和听筒切换
21 |
22 | 项目文件夹名称|平台|描述
23 | ---|---|---
24 | [Agora Android Voice Tutorial - 1 to 1](./One-to-One-Voice/Agora-Android-Voice-Tutorial-1to1)|Android|Agora Android 一对一音频通话指南
25 | [Agora iOS Voice Tutorial for Swift - 1 to 1](./One-to-One-Voice/Agora-iOS-Voice-Tutorial-Swift-1to1)|iOS|Agora iOS 一对一音频通话指南(Swift)
26 |
27 | ### 多人音频通话
28 |
29 | 多人音频通话的示例应用包含 Web, Android, iOS, MacOS, Windows 以及 Linux 平台。
30 |
31 |
32 | 多人音频通话的示例应用,展示了:
33 |
34 | - 加入通话和离开通话
35 | - 静音和解除静音
36 | - 外放和听筒切换
37 |
38 | 项目文件夹名称|平台|描述
39 | ---|---|---
40 | [Open Voice Call for Android](./Group-Voice-Call/OpenVoiceCall-Android)|Android|Android 多人音频通话指南
41 | [Open Voice Call iOS for Objective C](./Group-Voice-Call/OpenVoiceCall-iOS-Objective-C)|iOS|iOS 多人音频通话指南(Objective C)
42 | [Open Voice Call iOS for Swift](./Group-Voice-Call/OpenVoiceCall-iOS)|iOS|iOS 多人音频通话指南(Swift)
43 |
44 |
45 | ## 联系我们
46 |
47 | - 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
48 | - 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
49 | - 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
50 | - 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
51 | - 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
52 | - 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
53 | - 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
54 | - 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Audio-Call/issues)
55 |
56 | ## 代码许可
57 |
58 | MIT许可证 [查看许可](LICENSE.md)。
59 |
--------------------------------------------------------------------------------