LoginSignup
5

More than 5 years have passed since last update.

kotlinで最低限の実装でandroidでskywayを動かすよ

Posted at

もくもく会の結果

とりあえず30分くらいで映像通信はできたのでシェアします。

準備

AndroidManifest.xmlをいじる

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="santapj.co.jp.santa">

    <!-- ここから  -->
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <!-- ここまでを追加  -->

    <application
       ....
    </application>

</manifest>

skyway.arrを設定

スクリーンショット 2017-12-08 14.13.05.png

ここに置いてModuleのgradleを



apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"

    defaultConfig {
        applicationId "santapj.co.jp.santa"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
    compile (name:'skyway',ext:'aar')
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
repositories{
    flatDir{
        dirs 'libs'
    }
    mavenCentral()
}

こうじゃ。graldeでリポジトリ指定してimportできなかったけど、きっと何か事情あるんだろう。

実装

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="santapj.co.jp.santa.MainActivity">

    <view
        android:layout_width="140dp"
        android:layout_height="140dp"
        class="io.skyway.Peer.Browser.Canvas"
        android:id="@+id/remoteStreamView" />

    <view
        android:layout_width="140dp"
        android:layout_height="140dp"
        class="io.skyway.Peer.Browser.Canvas"
        android:id="@+id/localStreamView" />
</LinearLayout>

MainActivity.kt
package santapj.co.jp.santa

import android.content.pm.PackageManager
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import io.skyway.Peer.Browser.Canvas
import io.skyway.Peer.Peer

class MainActivity : AppCompatActivity() {

    lateinit var viewModel:ViewModel
    lateinit var localStreamView:Canvas
    lateinit var remoteStreamView:Canvas

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        localStreamView = findViewById(R.id.localStreamView) as Canvas
        remoteStreamView = findViewById(R.id.remoteStreamView) as Canvas

        viewModel = ViewModel(this, localStreamView, remoteStreamView)
        viewModel.setup()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            0 -> {
                if (grantResults.count() > 0 && grantResults[0] === PackageManager.PERMISSION_GRANTED) {
                    viewModel.setupPeer()
                } else {
                    print("Error")
                }
            }
        }
    }
}

viewModel.kt
package santapj.co.jp.santa

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.util.Log
import io.skyway.Peer.Browser.Canvas
import io.skyway.Peer.Browser.MediaConstraints
import io.skyway.Peer.Browser.MediaStream
import io.skyway.Peer.Browser.Navigator
import io.skyway.Peer.MediaConnection
import io.skyway.Peer.OnCallback
import io.skyway.Peer.Peer
import io.skyway.Peer.PeerOption

/**
 * Created by kentaro.haneda on 2017/12/06.
 */
class ViewModel (val activity: MainActivity, val localStreamView:Canvas, val remoteStreamView:Canvas){
    companion object {
        val API_KEY = "XXXXXX"
        val DOMAIN  = "XXXXXX"
    }

    var peer:Peer? = null
    var remoteStream:MediaStream? = null
    var localStream:MediaStream? = null
    var mediaConnection:MediaConnection? = null

    fun setup(){
        checkPermission()
    }


    fun setupPeer(){
        val option = PeerOption()
        option.key = API_KEY
        option.domain = DOMAIN
        option.debug = Peer.DebugLevelEnum.ALL_LOGS
        this.peer = Peer(activity, option)

        this.setupPeerCallBack()
    }

    private fun setupPeerCallBack(){
        this.peer?.on(Peer.PeerEventEnum.OPEN, object : OnCallback {
            override fun onCallback(p0: Any?) {
                (p0 as? String)?.let{
                    peerID ->
                    Log.d("debug", "peerID: ${peerID}")
                    startLocalStream()
                }
            }
        })
        this.peer?.on(Peer.PeerEventEnum.ERROR, object : OnCallback {
            override fun onCallback(p0: Any?) {
                Log.d("debug", "peer error ${p0}")
            }
        })
        this.peer?.on(Peer.PeerEventEnum.CALL, object : OnCallback {
            override fun onCallback(p0: Any?) {
                (p0 as? MediaConnection)?.let{
                    this@ViewModel.mediaConnection = it
                    this@ViewModel.setupMediaCallBack()
                    this@ViewModel.mediaConnection?.answer(localStream)
                }
            }
        })

    }

    private fun checkPermission(){
        if (ContextCompat.checkSelfPermission(activity,
                Manifest.permission.CAMERA) !== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(activity,
                Manifest.permission.RECORD_AUDIO) !== PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, arrayOf<String>(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO), 0)
        } else {
            this.setupPeer()
        }
    }

    private fun startLocalStream(){
        val constraints = MediaConstraints()
        constraints.maxWidth = 960
        constraints.maxHeight = 540
        constraints.cameraPosition = MediaConstraints.CameraPositionEnum.FRONT
        Navigator.initialize(peer)
        localStream = Navigator.getUserMedia(constraints)
        localStream?.addVideoRenderer(localStreamView, 0)
    }

    fun setupMediaCallBack(){
        mediaConnection?.on(MediaConnection.MediaEventEnum.STREAM, object : OnCallback {
            override fun onCallback(p0: Any?) {
                (p0 as? MediaStream)?.let{
                    this@ViewModel.remoteStream = it
                    this@ViewModel.remoteStream?.addVideoRenderer(remoteStreamView, 0)
                }
            }
        })
    }
}

でとりあえず動く。イカしたサンプルは後日こちらへプルリク投げナス :meat_on_bone:

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5