diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..9a5f7f9
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,31 @@
+name: Build
+
+on:
+ push:
+ paths-ignore:
+ - 'README.md'
+ - 'CHANGES.md'
+ - 'LICENSE'
+ - 'THANKS'
+ schedule:
+ - cron: "0 0 * * *"
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'adopt'
+ java-version: '11'
+ cache: 'gradle'
+ - name: Copy gradle.properties
+ run: cp gradle.properties.example gradle.properties
+ - name: Build with Gradle
+ run: ./gradlew build
+ - name: Lint Check
+ run: ./gradlew ktlintCheck
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..f663132
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index de37077..921b70c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -9,8 +9,23 @@
- FIX
- バグ修正
+## develop
+
+## sora-andoroid-sdk-2022.2.0
+
+- [UPDATE] システム条件を更新する
+ - Android Studio 2022.1.1 以降
+ - Sora Android SDK 2022.2.0 以降
+ - @miosakuma
+- [UPDATE] Kotlin Android Extensions の非推奨化に伴い、ビュー バインディングに移行する
+ - @miosakuma
+
## sora-andoroid-sdk-2022.1.0
+- [UPDATE] システム条件を更新する
+ - Android Studio 2020.3.1 以降
+ - Sora Android SDK 2022.1.0 以降
+ - @miosakuma
- [ADD] シグナリング接続時に送信するメタデータを外部ファイルから設定できるようにする
- @miosakuma
diff --git a/README.md b/README.md
index d3781df..5ae7d9c 100644
--- a/README.md
+++ b/README.md
@@ -26,9 +26,9 @@ Sora Android SDK の使い方は
## システム条件
- Android 5.0 以降 (エミュレーターでの動作は保証しません)
-- Android Studio 2020.3.1 以降
-- WebRTC SFU Sora 2021.1 以降
-- Sora Android SDK 2021.3 以降
+- Android Studio 2022.1.1 以降
+- WebRTC SFU Sora 2021.2 以降
+- Sora Android SDK 2022.2.0 以降
## 参考リンク
diff --git a/build.gradle b/build.gradle
index c283913..319418f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,8 +1,8 @@
apply plugin: "com.github.ben-manes.versions"
buildscript {
- ext.kotlin_version = '1.4.31'
- ext.sora_android_sdk_version = '2022.1.0'
+ ext.kotlin_version = '1.6.10'
+ ext.sora_android_sdk_version = '2022.2.0'
repositories {
google()
@@ -10,11 +10,12 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
+ classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
- classpath "com.github.ben-manes:gradle-versions-plugin:0.38.0"
+ classpath "com.github.ben-manes:gradle-versions-plugin:0.41.0"
+ classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.1"
}
// デバッグ用: true に設定すると wss ではなく ws で接続できる
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 442d913..0f80bbf 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/quickstart/build.gradle b/quickstart/build.gradle
index 74683b5..b6c44bd 100644
--- a/quickstart/build.gradle
+++ b/quickstart/build.gradle
@@ -1,8 +1,7 @@
apply plugin: 'com.android.application'
-apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
+apply plugin: 'org.jlleitschuh.gradle.ktlint'
android {
compileSdkVersion 30
@@ -39,20 +38,32 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+
+ viewBinding {
+ enabled = true
+ }
}
+ktlint {
+ version = "0.43.2"
+ android = false
+ outputToConsole = true
+ reporters {
+ reporter "checkstyle"
+ }
+ ignoreFailures = false
+}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlin_version}"
- implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}"
- implementation 'com.google.code.gson:gson:2.8.6'
+ implementation 'com.google.code.gson:gson:2.8.9'
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "com.google.android.material:material:1.3.0"
- implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.8.0"
- kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.8.0"
+ implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.9.1"
+ kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.9.1"
// Sora Android SDK
if (findProject(':sora-android-sdk') != null) {
@@ -74,6 +85,7 @@ configurations.all {
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
+ finalizedBy("ktlintFormat")
kotlinOptions {
jvmTarget = "1.8"
}
diff --git a/quickstart/src/main/kotlin/jp/shiguredo/sora/quickstart/MainActivity.kt b/quickstart/src/main/kotlin/jp/shiguredo/sora/quickstart/MainActivity.kt
index 34263d3..ef03b69 100644
--- a/quickstart/src/main/kotlin/jp/shiguredo/sora/quickstart/MainActivity.kt
+++ b/quickstart/src/main/kotlin/jp/shiguredo/sora/quickstart/MainActivity.kt
@@ -1,6 +1,7 @@
package jp.shiguredo.sora.quickstart
import android.Manifest
+import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.media.AudioManager
@@ -9,16 +10,22 @@ import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
-import com.google.gson.*
+import com.google.gson.Gson
+import jp.shiguredo.sora.quickstart.databinding.ActivityMainBinding
import jp.shiguredo.sora.sdk.camera.CameraCapturerFactory
import jp.shiguredo.sora.sdk.channel.SoraMediaChannel
import jp.shiguredo.sora.sdk.channel.option.SoraMediaOption
import jp.shiguredo.sora.sdk.channel.signaling.message.PushMessage
import jp.shiguredo.sora.sdk.error.SoraErrorReason
import jp.shiguredo.sora.sdk.util.SoraLogger
-import kotlinx.android.synthetic.main.activity_main.*
-import org.webrtc.*
-import permissions.dispatcher.*
+import org.webrtc.CameraVideoCapturer
+import org.webrtc.EglBase
+import org.webrtc.MediaStream
+import permissions.dispatcher.NeedsPermission
+import permissions.dispatcher.OnPermissionDenied
+import permissions.dispatcher.OnShowRationale
+import permissions.dispatcher.PermissionRequest
+import permissions.dispatcher.RuntimePermissions
@RuntimePermissions
class MainActivity : AppCompatActivity() {
@@ -32,25 +39,28 @@ class MainActivity : AppCompatActivity() {
private var audioManager: AudioManager? = null
+ private lateinit var binding: ActivityMainBinding
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
SoraLogger.enabled = true
- setContentView(R.layout.activity_main)
- startButton.setOnClickListener {
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ binding.startButton.setOnClickListener {
disableStartButton()
startWithPermissionCheck()
}
- stopButton.setOnClickListener {
+ binding.stopButton.setOnClickListener {
close()
disableStopButton()
}
egl = EglBase.create()
val eglContext = egl!!.eglBaseContext
- localRenderer?.init(eglContext, null)
- remoteRenderer?.init(eglContext, null)
+ binding.localRenderer?.init(eglContext, null)
+ binding.remoteRenderer?.init(eglContext, null)
disableStopButton()
audioManager = applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
@@ -64,6 +74,8 @@ class MainActivity : AppCompatActivity() {
this.volumeControlStream = AudioManager.STREAM_VOICE_CALL
}
+ // AudioManager.MODE_INVALID が使われているため lint でエラーが出るので一時的に抑制しておく
+ @SuppressLint("WrongConstant")
override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
@@ -104,7 +116,7 @@ class MainActivity : AppCompatActivity() {
if (ms.videoTracks.size > 0) {
val track = ms.videoTracks[0]
track.setEnabled(true)
- track.addSink(this@MainActivity.remoteRenderer)
+ track.addSink(this@MainActivity.binding.remoteRenderer)
}
}
}
@@ -115,18 +127,18 @@ class MainActivity : AppCompatActivity() {
if (ms.videoTracks.size > 0) {
val track = ms.videoTracks[0]
track.setEnabled(true)
- track.addSink(this@MainActivity.localRenderer)
+ track.addSink(this@MainActivity.binding.localRenderer)
capturer?.startCapture(400, 400, 30)
}
}
}
override fun onPushMessage(mediaChannel: SoraMediaChannel, push: PushMessage) {
- Log.d(TAG, "onPushMessage: push=${push}")
+ Log.d(TAG, "onPushMessage: push=$push")
val data = push.data
- if(data is Map<*, *>) {
+ if (data is Map<*, *>) {
data.forEach { (key, value) ->
- Log.d(TAG, "received push data: ${key}=${value}")
+ Log.d(TAG, "received push data: $key=$value")
}
}
}
@@ -150,12 +162,13 @@ class MainActivity : AppCompatActivity() {
}
mediaChannel = SoraMediaChannel(
- context = this,
- signalingEndpoint = BuildConfig.SIGNALING_ENDPOINT,
- channelId = BuildConfig.CHANNEL_ID,
- signalingMetadata = Gson().fromJson(BuildConfig.SIGNALING_METADATA, Map::class.java),
- mediaOption = option,
- listener = channelListener)
+ context = this,
+ signalingEndpoint = BuildConfig.SIGNALING_ENDPOINT,
+ channelId = BuildConfig.CHANNEL_ID,
+ signalingMetadata = Gson().fromJson(BuildConfig.SIGNALING_METADATA, Map::class.java),
+ mediaOption = option,
+ listener = channelListener
+ )
mediaChannel!!.connect()
}
@@ -169,25 +182,25 @@ class MainActivity : AppCompatActivity() {
capturer?.stopCapture()
capturer = null
- localRenderer?.release()
- remoteRenderer?.release()
+ binding.localRenderer?.release()
+ binding.remoteRenderer?.release()
egl?.release()
egl = null
}
private fun disableStartButton() {
- stopButton.isEnabled = true
- stopButton.setBackgroundColor(Color.parseColor("#F06292"))
- startButton.isEnabled = false
- startButton.setBackgroundColor(Color.parseColor("#CCCCCC"))
+ binding.stopButton.isEnabled = true
+ binding.stopButton.setBackgroundColor(Color.parseColor("#F06292"))
+ binding.startButton.isEnabled = false
+ binding.startButton.setBackgroundColor(Color.parseColor("#CCCCCC"))
}
private fun disableStopButton() {
- stopButton.isEnabled = false
- stopButton.setBackgroundColor(Color.parseColor("#CCCCCC"))
- startButton.isEnabled = true
- startButton.setBackgroundColor(Color.parseColor("#F06292"))
+ binding.stopButton.isEnabled = false
+ binding.stopButton.setBackgroundColor(Color.parseColor("#CCCCCC"))
+ binding.startButton.isEnabled = true
+ binding.startButton.setBackgroundColor(Color.parseColor("#F06292"))
}
// -- PermissionDispatcher --
@@ -201,25 +214,28 @@ class MainActivity : AppCompatActivity() {
fun showRationaleForCameraAndAudio(request: PermissionRequest) {
Log.d(TAG, "showRationaleForCameraAndAudio")
showRationaleDialog(
- "ビデオチャットを利用するには、カメラとマイクの使用許可が必要です", request)
+ "ビデオチャットを利用するには、カメラとマイクの使用許可が必要です", request
+ )
}
@OnPermissionDenied(value = [Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO])
fun onCameraAndAudioDenied() {
Log.d(TAG, "onCameraAndAudioDenied")
- Snackbar.make(rootLayout,
- "ビデオチャットを利用するには、カメラとマイクの使用を許可してください",
- Snackbar.LENGTH_LONG)
- .setAction("OK") { }
- .show()
+ Snackbar.make(
+ binding.rootLayout,
+ "ビデオチャットを利用するには、カメラとマイクの使用を許可してください",
+ Snackbar.LENGTH_LONG
+ )
+ .setAction("OK") { }
+ .show()
}
private fun showRationaleDialog(message: String, request: PermissionRequest) {
AlertDialog.Builder(this)
- .setPositiveButton(getString(R.string.permission_button_positive)) { _, _ -> request.proceed() }
- .setNegativeButton(getString(R.string.permission_button_negative)) { _, _ -> request.cancel() }
- .setCancelable(false)
- .setMessage(message)
- .show()
+ .setPositiveButton(getString(R.string.permission_button_positive)) { _, _ -> request.proceed() }
+ .setNegativeButton(getString(R.string.permission_button_negative)) { _, _ -> request.cancel() }
+ .setCancelable(false)
+ .setMessage(message)
+ .show()
}
}