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 @@ + + + + + + + + + + + \ 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() } }