티스토리 뷰

0. getWindow()

getWindow().addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD | LayoutParams.FLAG_SHOW_WHEN_LOCKED
| LayoutParams.FLAG_TURN_SCREEN_ON); 

 

- LayoutParams.FLAG_DISMISS_KEYGUARD // phone이 lock 상태면 보여주지 않음 

- LayoutParams.FLAG_SHOW_WHEN_LOCKED // 잠금화면 위에 app  보여주기 

- LayoutParams.FLAG_TURN_SCREEN_ON //꺼진 화면을 on 

 

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //네비바 숨김 

- View.SYSTEM_UI_FLAG_FULLSCREEN // 풀스크린 모드 

- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY // 

 

 

1. import android.databinding.DataBindingUtil;

- gradle app module에 dataBinding { enabled true} 추가

- xml 위아래에 <layout> 추가

 

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"

dataBinding {
enabled = true
}....

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

 

- binding 세팅 후 build -> Rebuild Project를 꼭 해주어야 함 , 컴파일러가 자동으로 바인딩 클래스를 생성해주기 때문이다. 자동으로 생성된 Binding 클래스는 다음과 같은 규칙을 따른다. 

1. Binding 클래스는 파일 이름을 파스칼 형식으로 바꾸고 그 뒤에 Binding을 접미사로 붙임

2. 컴포넌트 id는 카멜 표기법으로 변환 

ex) activity_main (xml)  -> ActivityMainBinding

ex) tv_sample (id) -> tvSample 

 

 

 

 

2. 안드로이드 권한 정리

- 안드로이드 권한에는 "위험한 권한" & "일반권한" 이 존재

- "위험 권한"에는 반드시 권한을 요청해야하는데 이는 Runtime Permission이라는 권한 요청으로 구현 가능

- EasyPermission 라이브러리 구현

 

import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;

 

* @AfterPermissionGranted() 

- build.gradle dependencies에

implementation 'pub.devrel:easypermissions:1.1.3'  

허가 추가

 

 

 

* Manifest.xml -> Manifest에 요청할 Permission 선언 

<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.CAMERA" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />

 

 

 

3. JAVA IO.socket 

 

//gradle dependencies 

implementation('io.socket:socket.io-client:1.0.0') {
exclude group: 'org.json', module: 'json'
}

 

 

 

 

import io.socket.client.IO;
import io.socket.client.Socket;

import static io.socket.client.Socket.EVENT_CONNECT;
import static io.socket.client.Socket.EVENT_DISCONNECT;

 

 

private Socket socker = IO.socket(url) 

 

 

# 이벤트 전달 연결

1. Socket.on(String event, Listener listener)

- 첫번째 인자 -> 서버로부터 전달을 기다리는 이벤트명

- 두번째 인자 -> 해당이벤트로

 

2. Socket.emit(String event, Object args) 

- 첫번재 인자 -> 서버로 전송할 이벤트 명 

- 두번째 인자 -> 추가적으로 전송할 데이터 , 대부분의 서버-클라이언트 통신은 JSON을 이용한 통신이기 때문에 JSON Object로 데이터 생성 필요 

 

 

* 중요한점 peer2peer로 연결될 때 똑같은 event 이름으로 설정 되어 있어야 한다. 

 

socket= IO.socket("http://10.0.2.2:8080")

socket.on(EVENT_CONNECT, args->{

   socket.emit("create or join", "foo");

}).on("ipaddr", args -> {

 

}).on("created", args -> {

 

}).on("full", args -> {

 

}).on("join", args -> {

 

}).on("log", args -> {

 

}) .... 

 

 

 

 

4. PeerConnection 

import org.webrtc.PeerConnection;

 

 

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
JSONObject message = (JSONObject) args[0];
Log.d(TAG, "connectToSignallingServer: got message " + message);
 
if (message.getString("type").equals("offer")) {
 Log.d(TAG, "connectToSignallingServer: received an offer " + isInitiator + " " + isStarted);
 
 
    if (!isInitiator && !isStarted) {
       maybeStart();
    }
 
    peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(OFFER, message.getString("sdp")));
    doAnswer();
 
 
    } else if (message.getString("type").equals("answer"&& isStarted) {
    peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(ANSWER, message.getString("sdp")));
    } else if (message.getString("type").equals("candidate"&& isStarted) {


    Log.d(TAG, "connectToSignallingServer: receiving candidates");
    IceCandidate candidate = new IceCandidate(message.getString("id"), message.getInt("label"), message.getString("candidate"));
    peerConnection.addIceCandidate(candidate);
    }
 
}
 
cs

private PeerConnection peerConnection

 

 

(1) setRemoteDescription

- peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(OFFER, message.getString("sdp")));

 

 

- peerConnection.setRemoteDescription(new SimpleSdpObserver(), new SessionDescription(ANSWER, message.getString("sdp")));

 

 

(2) setLocalDescription

- peerConnection.setLocalDescription(new SimpleSdpObserver(), sessionDescription);

 

 

 

 

(3) IceServer 구성하기

 

 

1
2
3
4
ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));
 
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
cs

 

 

 

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
PeerConnection.Observer pcObserver = new PeerConnection.Observer() {
 
    @Override
    public void onSignalingChange(PeerConnection.SignalingState signalingState) {
        Log.d(TAG, "onSignalingChange: ");
    }
 
    @Override
    public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
        Log.d(TAG, "onIceConnectionChange: ");
    }
 
    @Override
    public void onIceConnectionReceivingChange(boolean b) {
        Log.d(TAG, "onIceConnectionReceivingChange: ");
    }
 
    @Override
    public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
        Log.d(TAG, "onIceGatheringChange: ");
    }
 
    @Override
    public void onIceCandidate(IceCandidate iceCandidate) {
        Log.d(TAG, "onIceCandidate: ");
        JSONObject message = new JSONObject();
 
        try {
            message.put("type""candidate");
            message.put("label", iceCandidate.sdpMLineIndex);
            message.put("id", iceCandidate.sdpMid);
            message.put("candidate", iceCandidate.sdp);
 
            Log.d(TAG, "onIceCandidate: sending candidate " + message);
            sendMessage(message);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {
        Log.d(TAG, "onIceCandidatesRemoved: ");
    }
 
    @Override
    public void onAddStream(MediaStream mediaStream) {
        Log.d(TAG, "onAddStream: " + mediaStream.videoTracks.size());
        VideoTrack remoteVideoTrack = mediaStream.videoTracks.get(0);
        remoteVideoTrack.setEnabled(true);
        remoteVideoTrack.addRenderer(new VideoRenderer(binding.surfaceView2));
 
    }
 
    @Override
    public void onRemoveStream(MediaStream mediaStream) {
        Log.d(TAG, "onRemoveStream: ");
    }
 
    @Override
    public void onDataChannel(DataChannel dataChannel) {
        Log.d(TAG, "onDataChannel: ");
    }
 
    @Override
    public void onRenegotiationNeeded() {
        Log.d(TAG, "onRenegotiationNeeded: ");
    }
};
 
cs

 

 

 

 

5. IceCandidate 

import org.webrtc.IceCandidate;

 

 

IceCandidate candidate = new IceCandidate(message.getString("id"), message.getInt("label"), message.getString("candidate"));

 

 

 

6. EglBase

- Video renderers을 생성하는 것

 

import org.webrtc.EglBase;

private EglBase rootEglBase;

 

 

rootEglBase = EglBase.create();

 

 

 

#1 예시

binding.localVideoView.init(rootEglBase.getEglBaseContext(), null); // 기본
binding.remoteVideoView.init(rootEglBase.getEglBaseContext(), null); // 기본 

binding.localVideoView.setZOrderMediaOverlay(true);
binding.localVideoView.setEnableHardwareScaler(true);
binding.remoteVideoView.setEnableHardwareScaler(true);
binding.remoteVideoLayout.setPosition(REMOTE_X, REMOTE_Y, REMOTE_WIDTH, REMOTE_HEIGHT);
binding.remoteVideoView.setScalingType(SCALE_ASPECT_FILL);
binding.remoteVideoView.setMirror(false);

 

 

if (iceConnected) {
binding.localVideoLayout.setPosition(
LOCAL_X_CONNECTED, LOCAL_Y_CONNECTED, LOCAL_WIDTH_CONNECTED, LOCAL_HEIGHT_CONNECTED);
binding.localVideoView.setScalingType(SCALE_ASPECT_FIT);
} else {
binding.localVideoLayout.setPosition(
LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING, LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING);
binding.localVideoView.setScalingType(SCALE_ASPECT_FILL);
}
binding.localVideoView.setMirror(true);

binding.localVideoView.requestLayout();
binding.remoteVideoView.requestLayout();

 

 

 

 

#2 예시 

binding.surfaceView.init(rootEglBase.getEglBaseContext(), null);
binding.surfaceView.setEnableHardwareScaler(true);
binding.surfaceView.setMirror(true);

binding.surfaceView2.init(rootEglBase.getEglBaseContext(), null);
binding.surfaceView2.setEnableHardwareScaler(true);
binding.surfaceView2.setMirror(true);

 

 

7. 카메라 찾기

 

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
    private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
        final String[] deviceNames = enumerator.getDeviceNames();
 
        for (String deviceName : deviceNames) {
            if (enumerator.isFrontFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
 
                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }
 
        for (String deviceName : deviceNames) {
            if (!enumerator.isFrontFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
 
                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }
 
        return null;
    }
 
cs

 

 

 

 

 

 

 

 

<관련 Socket.io 출처 글>

1. 공식 socket.io 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/02   »
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
글 보관함