{"id":862,"date":"2015-06-10T17:46:50","date_gmt":"2015-06-10T08:46:50","guid":{"rendered":"https:\/\/eguchi.jp\/blog\/?p=862"},"modified":"2015-06-10T17:46:50","modified_gmt":"2015-06-10T08:46:50","slug":"webrtc-data-channel-sample-for-android-%e3%82%92%e4%bd%9c%e3%81%a3%e3%81%a6%e3%81%bf%e3%81%9f","status":"publish","type":"post","link":"https:\/\/eguchi.jp\/blog\/?p=862","title":{"rendered":"WebRTC Data Channel Sample for Android \u3092\u4f5c\u3063\u3066\u307f\u305f"},"content":{"rendered":"<p>\u3053\u3053\u3093\u3068\u3053\u308d\u3001WebRTC\u306e\u30a2\u30d7\u30ea\u3092\u4f5c\u308d\u3046\u3068\u3057\u3066\u3001\u56db\u82e6\u516b\u82e6\u3057\u3066\u3044\u307e\u3057\u305f\u3002<\/p>\n<p>\u3084\u3063\u3068\u3001\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30cd\u30eb\u3067\u9001\u53d7\u4fe1\u3059\u308b\u30a2\u30d7\u30ea\u304c\u3067\u304d\u305f\u306e\u3067\u3001\u3053\u3053\u306b\u516c\u958b\u3057\u307e\u3059\u3002<\/p>\n<p>\u958b\u767a\u74b0\u5883\u3067\u3059\u304c<br \/>\nAndroid Studio 1.2.1.1 build 141.19032520<br \/>\n\u3092\u4f7f\u3063\u3066\u958b\u767a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>\u666e\u901a\u306b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<p>\u307e\u305a\u3001WebRTC\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3059\u308b\u70ba\u306e\u8a2d\u5b9a\u3092\u884c\u3044\u307e\u3059\u3002<\/p>\n<p>app\u914d\u4e0b\u306b\u3042\u308bbuild.gradle\u306edependencies\u306b\u4e0b\u8a18\u306e\u4e00\u884c\u3092\u5165\u308c\u308b\u3060\u3051<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ncompile 'io.pristine:libjingle:9357@aar'\r\n<\/pre>\n<p>\u3053\u308c\u3067\u306a\u3093\u3068\u3001\u30cd\u30a4\u30c6\u30a3\u30d6\u306eso\u30e9\u30a4\u30d6\u30e9\u30ea\u307e\u3067\u6301\u3063\u3066\u304d\u3066\u304f\u308c\u307e\u3059\uff08\u306a\u3093\u3068\u4fbf\u5229\u306a\uff01\uff09<\/p>\n<p><a href=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0006.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0006-300x126.png\" alt=\"150610-0006\" width=\"300\" height=\"126\" class=\"alignnone size-medium wp-image-866\" srcset=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0006-300x126.png 300w, https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0006-1024x429.png 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>\u6b21\u306b\u3001AndroidManifest.xml\u306b\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3\u3092\u8ffd\u52a0\u3057\u307e\u3059<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;uses-feature android:name=&quot;android.hardware.camera&quot; \/&gt;\r\n&lt;uses-feature android:name=&quot;android.hardware.camera.autofocus&quot; \/&gt;\r\n&lt;uses-feature android:glEsVersion=&quot;0x00020000&quot; android:required=&quot;true&quot; \/&gt;\r\n\r\n&lt;uses-permission android:name=&quot;android.permission.CAMERA&quot; \/&gt;\r\n&lt;uses-permission android:name=&quot;android.permission.RECORD_AUDIO&quot; \/&gt;\r\n&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; \/&gt;\r\n&lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; \/&gt;\r\n&lt;uses-permission android:name=&quot;android.permission.MODIFY_AUDIO_SETTINGS&quot; \/&gt;\r\n<\/pre>\n<p><a href=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0003.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0003-300x236.png\" alt=\"150610-0003\" width=\"300\" height=\"236\" class=\"alignnone size-medium wp-image-864\" srcset=\"https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0003-300x236.png 300w, https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0003-1024x807.png 1024w, https:\/\/eguchi.jp\/blog\/wp-content\/uploads\/2015\/06\/150610-0003.png 1256w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>\u3053\u308c\u3067\u3001\u6e96\u5099OK\u3001\u3053\u3053\u304b\u3089\u306f\u3001MainActivity.java\u306e\u30bd\u30fc\u30b9\u3092\u305d\u306e\u307e\u307e\u63b2\u8f09\u3057\u3061\u3083\u3044\u307e\u3059\u3002<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage jp.eguchi.android.datachannelsample;\r\n\r\n\/\/ WebRTC Data Channel Sample Program\r\n\/\/ Programed by Kazuyuki Eguchi\r\n\r\nimport android.app.Activity;\r\nimport android.os.Bundle;\r\nimport android.util.Log;\r\n\r\nimport org.json.JSONObject;\r\nimport org.webrtc.DataChannel;\r\nimport org.webrtc.IceCandidate;\r\nimport org.webrtc.MediaConstraints;\r\nimport org.webrtc.MediaStream;\r\nimport org.webrtc.PeerConnection;\r\nimport org.webrtc.PeerConnectionFactory;\r\nimport org.webrtc.SdpObserver;\r\nimport org.webrtc.SessionDescription;\r\n\r\nimport java.nio.ByteBuffer;\r\nimport java.util.LinkedList;\r\nimport java.util.List;\r\n\r\n\r\npublic class MainActivity extends Activity {\r\n\r\n    final private String TAG = &quot;sample&quot;;\r\n\r\n    PeerConnectionFactory factory = null;\r\n\r\n    PeerConnection pc1 = null;\r\n    PeerConnection pc2 = null;\r\n\r\n    DataChannel dc1 = null;\r\n    DataChannel dc2 = null;\r\n\r\n    \/\/ pc1\u7528\u306eObserver\r\n    PeerConnection.Observer pcob1 = new PeerConnection.Observer() {\r\n        @Override\r\n        public void onSignalingChange(PeerConnection.SignalingState signalingState) {\r\n            Log.d(TAG, &quot;pcob1 onSignalingChange() &quot; + signalingState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {\r\n            Log.d(TAG, &quot;pcob1 onIceConnectionChange() &quot; + iceConnectionState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {\r\n            Log.d(TAG, &quot;pcob1 onIceGatheringChange() &quot; + iceGatheringState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceCandidate(IceCandidate iceCandidate) {\r\n            Log.d(TAG, &quot;pcob1 onIceCandidate()&quot;);\r\n\r\n            JSONObject json = new JSONObject();\r\n\r\n            String mes = null;\r\n\r\n            try {\r\n                json.put(&quot;type&quot;, &quot;candidate&quot;);\r\n                json.put(&quot;sdpMLineIndex&quot;, iceCandidate.sdpMLineIndex);\r\n                json.put(&quot;sdpMid&quot;, iceCandidate.sdpMid);\r\n                json.put(&quot;candidate&quot;, iceCandidate.sdp);\r\n\r\n                mes = json.toString();\r\n\r\n                Log.d(TAG, mes);\r\n\r\n                \/\/ \u3053\u3053\u3067\u3001 WebSocket\u7b49\u3067\u76f8\u624b\u5074\u306b mes\u3092\u9001\u308b\r\n                \/\/ \u53d7\u4fe1\u5074\u3067\u306f\r\n\r\n                JSONObject json2 = new JSONObject(mes);\r\n                IceCandidate candidate = new IceCandidate(json2.getString(&quot;sdpMid&quot;), json2.getInt(&quot;sdpMLineIndex&quot;), json2.getString(&quot;candidate&quot;));\r\n                pc2.addIceCandidate(candidate);\r\n\r\n            } catch (org.json.JSONException ex) {\r\n                Log.d(TAG, ex.toString());\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void onAddStream(MediaStream mediaStream) {\r\n            Log.d(TAG, &quot;pcob1 onAddStream()&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onRemoveStream(MediaStream mediaStream) {\r\n            Log.d(TAG, &quot;pcob1 onRemoveStream&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onDataChannel(DataChannel dataChannel) {\r\n            Log.d(TAG, &quot;pcob1 onDataChannel()&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onRenegotiationNeeded() {\r\n            Log.d(TAG, &quot;pcob1 onRenegotiationNeeded()&quot;);\r\n        }\r\n    };\r\n\r\n    \/\/ pc2\u7528\u306eObserver\r\n    PeerConnection.Observer pcob2 = new PeerConnection.Observer() {\r\n        @Override\r\n        public void onSignalingChange(PeerConnection.SignalingState signalingState) {\r\n            Log.d(TAG, &quot;pcob2 onSignalingChange() &quot; + signalingState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {\r\n            Log.d(TAG, &quot;pcob2 onIceConnectionChange() &quot; + iceConnectionState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {\r\n            Log.d(TAG, &quot;pcob2 onIceGatheringChange() &quot; + iceGatheringState.name());\r\n        }\r\n\r\n        @Override\r\n        public void onIceCandidate(IceCandidate iceCandidate) {\r\n            Log.d(TAG, &quot;pcob2 onIceCandidate()&quot;);\r\n\r\n            JSONObject json = new JSONObject();\r\n\r\n            String mes = null;\r\n\r\n            try {\r\n                json.put(&quot;type&quot;, &quot;candidate&quot;);\r\n                json.put(&quot;sdpMLineIndex&quot;, iceCandidate.sdpMLineIndex);\r\n                json.put(&quot;sdpMid&quot;, iceCandidate.sdpMid);\r\n                json.put(&quot;candidate&quot;, iceCandidate.sdp);\r\n\r\n                mes = json.toString();\r\n\r\n                Log.d(TAG, mes);\r\n\r\n                \/\/ \u3053\u3053\u3067\u3001 WebSocket\u7b49\u3067\u76f8\u624b\u5074\u306b mes\u3092\u9001\u308b\r\n                \/\/ \u53d7\u4fe1\u5074\u3067\u306f\r\n\r\n                JSONObject json2 = new JSONObject(mes);\r\n                IceCandidate candidate = new IceCandidate(json2.getString(&quot;sdpMid&quot;), json2.getInt(&quot;sdpMLineIndex&quot;), json2.getString(&quot;candidate&quot;));\r\n                pc1.addIceCandidate(candidate);\r\n\r\n            } catch (org.json.JSONException ex) {\r\n                Log.d(TAG, ex.toString());\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void onAddStream(MediaStream mediaStream) {\r\n            Log.d(TAG, &quot;pcob2 onAddStream()&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onRemoveStream(MediaStream mediaStream) {\r\n            Log.d(TAG, &quot;pcob2 onRemoveStream&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onDataChannel(DataChannel dataChannel) {\r\n            Log.d(TAG, &quot;pcob2 onDataChannel()&quot;);\r\n            dc2 = dataChannel;\r\n            dc2.registerObserver(dc2o);\r\n        }\r\n\r\n        @Override\r\n        public void onRenegotiationNeeded() {\r\n            Log.d(TAG, &quot;pcob2 onRenegotiationNeeded()&quot;);\r\n        }\r\n    };\r\n\r\n    SdpObserver so1 = new SdpObserver() {\r\n        @Override\r\n        public void onCreateSuccess(SessionDescription sessionDescription) {\r\n            Log.d(TAG, &quot;so1 onCreateSuccess()&quot;);\r\n\r\n            pc1.setLocalDescription(so1, sessionDescription);\r\n\r\n            JSONObject json = new JSONObject();\r\n\r\n            String mes = null;\r\n\r\n            try {\r\n                json.put(&quot;type&quot;, sessionDescription.type.toString().toLowerCase());\r\n                json.put(&quot;sdp&quot;, sessionDescription.description);\r\n\r\n                mes = json.toString();\r\n\r\n                Log.d(TAG, mes);\r\n\r\n                \/\/ \u3053\u3053\u3067\u3001 WebSocket\u7b49\u3067\u76f8\u624b\u5074\u306b mes\u3092\u9001\u308b\r\n                \/\/ \u53d7\u4fe1\u5074\u3067\u306f\r\n\r\n                JSONObject json2 = new JSONObject(mes);\r\n                String type = json2.getString(&quot;type&quot;);\r\n                String sdp = json2.getString(&quot;sdp&quot;);\r\n\r\n                SessionDescription sdp2 = new SessionDescription(SessionDescription.Type.fromCanonicalForm(type), sdp);\r\n\r\n                pc2.setRemoteDescription(so2, sdp2);\r\n                MediaConstraints constraints = new MediaConstraints();\r\n                pc2.createAnswer(so2, constraints);\r\n\r\n            } catch (org.json.JSONException ex) {\r\n                Log.d(TAG, ex.toString());\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void onSetSuccess() {\r\n            Log.d(TAG, &quot;so1 onCreateSuccess()&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onCreateFailure(String s) {\r\n            Log.d(TAG, &quot;so1 onCreateFailure() &quot; + s);\r\n        }\r\n\r\n        @Override\r\n        public void onSetFailure(String s) {\r\n            Log.d(TAG, &quot;so1 onSetFailure() &quot; + s);\r\n        }\r\n    };\r\n\r\n    SdpObserver so2 = new SdpObserver() {\r\n        @Override\r\n        public void onCreateSuccess(SessionDescription sessionDescription) {\r\n            Log.d(TAG, &quot;so2 onCreateSuccess()&quot;);\r\n            pc2.setLocalDescription(so2, sessionDescription);\r\n\r\n            JSONObject json = new JSONObject();\r\n\r\n            String mes = null;\r\n\r\n            try {\r\n                json.put(&quot;type&quot;, sessionDescription.type.toString().toLowerCase());\r\n                json.put(&quot;sdp&quot;, sessionDescription.description);\r\n\r\n                mes = json.toString();\r\n\r\n                Log.d(TAG, mes);\r\n\r\n                \/\/ \u3053\u3053\u3067\u3001 WebSocket\u7b49\u3067\u76f8\u624b\u5074\u306b mes\u3092\u9001\u308b\r\n                \/\/ \u53d7\u4fe1\u5074\u3067\u306f\r\n\r\n                JSONObject json2 = new JSONObject(mes);\r\n                String type = json2.getString(&quot;type&quot;);\r\n                String sdp = json2.getString(&quot;sdp&quot;);\r\n\r\n                SessionDescription sdp2 = new SessionDescription(SessionDescription.Type.fromCanonicalForm(type), sdp);\r\n\r\n                pc1.setRemoteDescription(so1, sdp2);\r\n\r\n            } catch (org.json.JSONException ex) {\r\n                Log.d(TAG, ex.toString());\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void onSetSuccess() {\r\n            Log.d(TAG, &quot;so2 onCreateSuccess()&quot;);\r\n        }\r\n\r\n        @Override\r\n        public void onCreateFailure(String s) {\r\n            Log.d(TAG, &quot;so2 onCreateFailure() &quot; + s);\r\n        }\r\n\r\n        @Override\r\n        public void onSetFailure(String s) {\r\n            Log.d(TAG, &quot;so2 onSetFailure() &quot; + s);\r\n        }\r\n    };\r\n\r\n    DataChannel.Observer dc1o = new DataChannel.Observer() {\r\n        @Override\r\n        public void onStateChange() {\r\n            Log.d(TAG, &quot;da1o onStateChange() &quot; + dc1.state().name());\r\n\r\n            if (dc1.state() == DataChannel.State.OPEN) {\r\n                String data = &quot;from dc1&quot;;\r\n                ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());\r\n                dc1.send(new DataChannel.Buffer(buffer, false));\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void onMessage(DataChannel.Buffer buffer) {\r\n            Log.d(TAG, &quot;da1o onMessage()&quot;);\r\n\r\n            if (buffer.binary == false) {\r\n                int limit = buffer.data.limit();\r\n                byte&#x5B;] datas = new byte&#x5B;limit];\r\n                buffer.data.get(datas);\r\n                String tmp = new String(datas);\r\n                Log.d(TAG, tmp);\r\n            }\r\n        }\r\n    };\r\n\r\n    DataChannel.Observer dc2o = new DataChannel.Observer() {\r\n        @Override\r\n        public void onStateChange() {\r\n            Log.d(TAG, &quot;da2o onStateChange() &quot; + dc2.state().name());\r\n\r\n            if (dc2.state() == DataChannel.State.OPEN) {\r\n                String data = &quot;from dc2&quot;;\r\n                ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());\r\n                dc2.send(new DataChannel.Buffer(buffer, false));\r\n            }\r\n\r\n        }\r\n\r\n        @Override\r\n        public void onMessage(DataChannel.Buffer buffer) {\r\n            Log.d(TAG, &quot;da2o onMessage()&quot;);\r\n\r\n            if (buffer.binary == false) {\r\n                int limit = buffer.data.limit();\r\n                byte&#x5B;] datas = new byte&#x5B;limit];\r\n                buffer.data.get(datas);\r\n                String tmp = new String(datas);\r\n                Log.d(TAG, tmp);\r\n            }\r\n        }\r\n    };\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n\r\n        Log.d(TAG, &quot;onCreate()&quot;);\r\n\r\n        PeerConnectionFactory.initializeAndroidGlobals(getApplicationContext(), true, false, false, null);\r\n        factory = new PeerConnectionFactory();\r\n    }\r\n\r\n    @Override\r\n    protected void onResume() {\r\n        super.onResume();\r\n\r\n        Log.d(TAG, &quot;onResume()&quot;);\r\n\r\n        \/\/ STRN\u30b5\u30fc\u30d0\u306f Google\u69d8\u306e\u3092\u4f7f\u308f\u305b\u3066\u3082\u3089\u3046\u3002\r\n        List&lt;PeerConnection.IceServer&gt; iceServers = new LinkedList&lt;PeerConnection.IceServer&gt;();\r\n        iceServers.add(new PeerConnection.IceServer(&quot;stun:stun.l.google.com:19302&quot;));\r\n\r\n        MediaConstraints constraints = new MediaConstraints();\r\n\r\n        pc1 = factory.createPeerConnection(iceServers, constraints, pcob1);\r\n        pc2 = factory.createPeerConnection(iceServers, constraints, pcob2);\r\n\r\n        \/\/ offer\u3059\u308b\u524d\u306b\u30c7\u30fc\u30bf\u30c1\u30e3\u30cd\u30eb\u3092\u4f5c\u6210\u3059\u308b\r\n        dc1 = pc1.createDataChannel(&quot;RTCDataChannel&quot;, new DataChannel.Init());\r\n        dc1.registerObserver(dc1o);\r\n\r\n        \/\/ Offer\u3059\u308b\r\n        pc1.createOffer(so1, constraints);\r\n    }\r\n\r\n    @Override\r\n    protected void onPause() {\r\n        super.onPause();\r\n\r\n        Log.d(TAG, &quot;onPause()&quot;);\r\n\r\n        if (dc1 != null) {\r\n            dc1.close();\r\n            dc1.unregisterObserver();\r\n        }\r\n\r\n        if (dc2 != null) {\r\n            dc2.close();\r\n            dc2.unregisterObserver();\r\n        }\r\n\r\n        if (pc1 != null) {\r\n            pc1.close();\r\n        }\r\n\r\n        if (pc2 != null) {\r\n            pc2.close();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>\u5b9f\u884c\u3057\u305f\u969b\u306eLogcat\u306e\u30ed\u30b0<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n06-10 17:44:58.719    4149-4149\/jp.eguchi.android.datachannelsample D\/sample\ufe55 onCreate()\r\n06-10 17:44:58.723   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 AttachCurrentThreadIfNeeded::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.723   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 Attaching thread to JVM\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JVM::environment@&#x5B;tid=11577]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::RegisterNatives(org\/webrtc\/voiceengine\/WebRtcAudioManager)\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::NewObject@&#x5B;tid=11577]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioManager\ufe55 ctor@&#x5B;name=Thread-1038, id=1038]\r\n06-10 17:44:58.724   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioManager\ufe55 Nexus 5 is blacklisted for HW AEC usage!\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 OnCacheAudioParameters@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 hardware_aec: 0\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 low_latency_output: 1\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 sample_rate: 48000\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 channels: 1\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 output_buffer_size: 240\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 input_buffer_size: 1920\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 GlobalRef::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 JavaAudioManager::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 IsLowLatencyPlayoutSupported()\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample W\/AudioManager\ufe55 NOTE: OpenSL ES output is currently disabled!\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 AttachCurrentThreadIfNeeded::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JVM::environment@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioTrackJni\ufe55 ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::RegisterNatives(org\/webrtc\/voiceengine\/WebRtcAudioTrack)\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::NewObject@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioTrack\ufe55 ctor@&#x5B;name=Thread-1038, id=1038]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioTrack\ufe55 Android SDK: 22, Release: M, Brand: google, Device: hammerhead, Id: MPZ44Q, Hardware: hammerhead, Manufacturer: LGE, Model: Nexus 5, Product: hammerhead\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 GlobalRef::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 AttachCurrentThreadIfNeeded::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JVM::environment@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioRecordJni\ufe55 ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 JNIEnvironment::RegisterNatives(org\/webrtc\/voiceengine\/WebRtcAudioRecord)\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 NativeRegistration::NewObject@&#x5B;tid=11577]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioRecord\ufe55 ctor@&#x5B;name=Thread-1038, id=1038]\r\n06-10 17:44:58.726   4149-11577\/jp.eguchi.android.datachannelsample D\/JVM\ufe55 GlobalRef::ctor@&#x5B;tid=11577]\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 SetActiveAudioLayer(5)@&#x5B;tid=11577]\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 delay_estimate_in_milliseconds: 150\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioTrackJni\ufe55 AttachAudioBuffer@&#x5B;tid=11577]\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioTrackJni\ufe55 SetPlayoutSampleRate(48000)\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioTrackJni\ufe55 SetPlayoutChannels(1)\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioRecordJni\ufe55 AttachAudioBuffer\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioRecordJni\ufe55 SetRecordingSampleRate(48000)\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioRecordJni\ufe55 SetRecordingChannels(1)\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioRecordJni\ufe55 total_delay_in_milliseconds: 150\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/AudioManager\ufe55 Init@&#x5B;tid=11577]\r\n06-10 17:44:58.727   4149-11577\/jp.eguchi.android.datachannelsample D\/WebRtcAudioManager\ufe55 init@&#x5B;name=Thread-1038, id=1038]\r\n06-10 17:44:58.731    4149-4149\/jp.eguchi.android.datachannelsample D\/sample\ufe55 onResume()\r\n06-10 17:44:59.157   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onRenegotiationNeeded()\r\n06-10 17:44:59.158   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so1 onCreateSuccess()\r\n06-10 17:44:59.395   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onSignalingChange() HAVE_LOCAL_OFFER\r\n06-10 17:44:59.396   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 {&quot;type&quot;:&quot;offer&quot;,&quot;sdp&quot;:&quot;v=0\\r\\no=- 113918549713234061 2 IN IP4 127.0.0.1\\r\\ns=-\\r\\nt=0 0\\r\\na=msid-semantic: WMS\\r\\nm=application 9 DTLS\\\/SCTP 5000\\r\\nc=IN IP4 0.0.0.0\\r\\na=ice-ufrag:lw3\\\/LpT+Giz61KGg\\r\\na=ice-pwd:QxRiyQgLEFnfWEsJ0p5+6G3s\\r\\na=fingerprint:sha-256 B8:AB:2D:09:BB:01:23:04:44:64:81:1E:F6:65:24:25:74:A5:6C:F0:62:8B:96:3E:86:83:E2:ED:A9:33:E6:FA\\r\\na=setup:actpass\\r\\na=mid:data\\r\\na=sctpmap:5000 webrtc-datachannel 1024\\r\\n&quot;}\r\n06-10 17:44:59.398   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onSignalingChange() HAVE_REMOTE_OFFER\r\n06-10 17:44:59.398   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceGatheringChange() GATHERING\r\n06-10 17:44:59.398   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so1 onCreateSuccess()\r\n06-10 17:44:59.398   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so2 onCreateSuccess()\r\n06-10 17:44:59.399   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so2 onCreateSuccess()\r\n06-10 17:44:59.404   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onSignalingChange() STABLE\r\n06-10 17:44:59.406   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 {&quot;type&quot;:&quot;answer&quot;,&quot;sdp&quot;:&quot;v=0\\r\\no=- 3088308566766388678 2 IN IP4 127.0.0.1\\r\\ns=-\\r\\nt=0 0\\r\\na=msid-semantic: WMS\\r\\nm=application 9 DTLS\\\/SCTP 5000\\r\\nc=IN IP4 0.0.0.0\\r\\nb=AS:30\\r\\na=ice-ufrag:4gco7NuR3wheyF6s\\r\\na=ice-pwd:Fv95\\\/TF5FvTbGMCcISNSKNf3\\r\\na=fingerprint:sha-256 31:EE:E9:19:85:5B:02:5F:CC:80:A3:FC:F7:64:EC:71:B6:01:4E:D0:35:1B:74:8E:D1:30:05:43:49:0D:52:55\\r\\na=setup:active\\r\\na=mid:data\\r\\na=sctpmap:5000 webrtc-datachannel 1024\\r\\n&quot;}\r\n06-10 17:44:59.410   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onSignalingChange() STABLE\r\n06-10 17:44:59.412   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceConnectionChange() CHECKING\r\n06-10 17:44:59.412   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceCandidate()\r\n06-10 17:44:59.412   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 {&quot;type&quot;:&quot;candidate&quot;,&quot;sdpMLineIndex&quot;:0,&quot;sdpMid&quot;:&quot;data&quot;,&quot;candidate&quot;:&quot;candidate:3209757399 1 udp 2122260223 10.49.120.146 39965 typ host generation 0&quot;}\r\n06-10 17:44:59.415   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceConnectionChange() CHECKING\r\n06-10 17:44:59.415   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceGatheringChange() GATHERING\r\n06-10 17:44:59.415   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so2 onCreateSuccess()\r\n06-10 17:44:59.415   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 so1 onCreateSuccess()\r\n06-10 17:44:59.416   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceCandidate()\r\n06-10 17:44:59.416   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 {&quot;type&quot;:&quot;candidate&quot;,&quot;sdpMLineIndex&quot;:0,&quot;sdpMid&quot;:&quot;data&quot;,&quot;candidate&quot;:&quot;candidate:3209757399 1 udp 2122260223 10.49.120.146 41101 typ host generation 0&quot;}\r\n06-10 17:44:59.444   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceGatheringChange() COMPLETE\r\n06-10 17:44:59.453   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceGatheringChange() COMPLETE\r\n06-10 17:44:59.486   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceConnectionChange() CONNECTED\r\n06-10 17:44:59.487   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceConnectionChange() COMPLETED\r\n06-10 17:44:59.488   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da1o onStateChange() OPEN\r\n06-10 17:44:59.489   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceConnectionChange() CONNECTED\r\n06-10 17:44:59.493   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onDataChannel()\r\n06-10 17:44:59.494   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da2o onStateChange() OPEN\r\n06-10 17:44:59.495   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da2o onMessage()\r\n06-10 17:44:59.495   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 from dc1\r\n06-10 17:44:59.496   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da1o onMessage()\r\n06-10 17:44:59.496   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 from dc2\r\n06-10 17:45:03.231    4149-4149\/jp.eguchi.android.datachannelsample D\/sample\ufe55 onPause()\r\n06-10 17:45:03.231   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da1o onStateChange() CLOSING\r\n06-10 17:45:03.233   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da1o onStateChange() CLOSED\r\n06-10 17:45:03.233   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da2o onStateChange() CLOSING\r\n06-10 17:45:03.234   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 da2o onStateChange() CLOSED\r\n06-10 17:45:03.236   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onIceConnectionChange() CLOSED\r\n06-10 17:45:03.236   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob1 onSignalingChange() CLOSED\r\n06-10 17:45:03.239   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onIceConnectionChange() CLOSED\r\n06-10 17:45:03.240   4149-11578\/jp.eguchi.android.datachannelsample D\/sample\ufe55 pcob2 onSignalingChange() CLOSED\r\n<\/pre>\n<p>\u4ee5\u4e0a\u3001\u3054\u53c2\u8003\u307e\u3067\u306b<\/p>\n<p>\u3053\u308c\u3067\u3001WebRTC\u306e\u30a2\u30d7\u30ea\u304c\u5897\u3048\u308b\u3068\u3044\u3044\u306a\u3042\u301c<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u3053\u3053\u3093\u3068\u3053\u308d\u3001WebRTC\u306e\u30a2\u30d7\u30ea\u3092\u4f5c\u308d\u3046\u3068\u3057\u3066\u3001\u56db\u82e6\u516b\u82e6\u3057\u3066\u3044\u307e\u3057\u305f\u3002 \u3084\u3063\u3068\u3001\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30cd\u30eb\u3067\u9001\u53d7\u4fe1\u3059\u308b\u30a2\u30d7\u30ea\u304c\u3067\u304d\u305f\u306e\u3067\u3001\u3053\u3053\u306b\u516c\u958b\u3057\u307e\u3059\u3002 \u958b\u767a\u74b0\u5883\u3067\u3059\u304c Android Studio 1.2.1.1 buil &hellip; <a href=\"https:\/\/eguchi.jp\/blog\/?p=862\" class=\"more-link\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">WebRTC Data Channel Sample for Android \u3092\u4f5c\u3063\u3066\u307f\u305f<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,18,2],"tags":[],"class_list":["post-862","post","type-post","status-publish","format-standard","hentry","category-android","category-webrtc","category-2"],"_links":{"self":[{"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=862"}],"version-history":[{"count":7,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/862\/revisions"}],"predecessor-version":[{"id":871,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=\/wp\/v2\/posts\/862\/revisions\/871"}],"wp:attachment":[{"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eguchi.jp\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}