๊ธฐ๋ณธ ์ค์
๋ฐฉ์ก์ ํ๊ธฐ ์ ์ ๊ฐ ํ๋ ํผ ๋ณ ํ๋ก์ ํธ ์ค์ ์ ์งํ ํฉ๋๋ค.
๊ฐ๋ฐ
RemonCast
ํด๋์ค๋ ๋ฐฉ์ก ์์ฑ ๋ฐ ์์ฒญ์ ์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. RemonCast
ํด๋์ค์ create()
ํจ์์ join()
ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ฐฉ์ก ๊ธฐ๋ฅ์ ์ด์ฉ ํ ์ ์์ต๋๋ค.
์ ์ฒด์ ์ธ ๊ตฌ์ฑ๊ณผ ํ๋ฆ์ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
View ๋ฑ๋ก
๋ฐฉ์ก ์ก์ถ์๊ฐ ์ค์ค๋ก์ ๋ชจ์ต์ ํ์ธํ๊ฑฐ๋, ์์ฒญ์๊ฐ ๋ฐฉ์ก์ ๋ณด๊ธฐ ์ํด์ ์ค์ ๋น๋์ค๊ฐ ๊ทธ๋ ค์ง๋ View๋ฅผ ์ ํ๊ณ ์ฐ๊ฒฐํด์ผ ๋ฉ๋๋ค. ๋ฐฉ์ก ์ก์ถ์์๊ฒ๋ ์ค์ค๋ก๊ฐ ๋ณด์ด๋๋ก Local View๋ฅผ ๋ฑ๋ก ํ๊ณ , ์์ฒญ์์๊ฒ๋ ์ก์ถ์๊ฐ ๋ณด์ด๋๋ก Remote View๋ฅผ ๋ฑ๋กํฉ๋๋ค.
Copy <!-- Caster : local view -->
<video id="localVideo" autoplay muted></video>
Copy <!-- Viewer : remote view -->
<video id="remoteVideo" autoplay></video>
Copy <!-- Caster : local view -->
<com.remotemonster.sdk.PercentFrameLayout
android:id="@+id/perFrameLocal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.webrtc.SurfaceViewRenderer
android:id="@+id/surfRendererLocal"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.remotemonster.sdk.PercentFrameLayout>
Copy <!-- Viewer : remote view -->
<com.remotemonster.sdk.PercentFrameLayout
android:id="@+id/perFrameRemote"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.webrtc.SurfaceViewRenderer
android:id="@+id/surfRendererRemote"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.remotemonster.sdk.PercentFrameLayout>
ConstraintLayout ๊ณผ ๊ฐ์ด ์๋๋ก์ด๋์์ ์ ๊ณตํ๋ ๋ ์ด์์์ผ๋ก ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
Copy <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- Remote -->
<RelativeLayout
android:id="@+id/layoutRemote"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
app:layout_constraintDimensionRatio="H,1:1.33"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
>
<org.webrtc.SurfaceViewRenderer
android:id="@+id/surfRendererRemote"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<!-- Local -->
<RelativeLayout
android:id="@+id/layoutLocal"
android:layout_width="80dp"
android:layout_height="0dp"
android:layout_margin="18dp"
app:layout_constraintDimensionRatio="H,1:1.33"
app:layout_constraintVertical_bias="0.1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
>
<org.webrtc.SurfaceViewRenderer
android:id="@+id/surfRendererLocal"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/remon_identity"
android:scaleType="fitCenter"
android:visibility="visible"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Interface Builder๋ฅผ ํตํด ์ง์ ํ๊ฒ ๋๋ฉฐ iOS - Getting Start์ ๋ฐ๋ผ ํ๊ฒฝ์ค์ ์ ํ๋ค๋ฉด ์ด๋ฏธ View๋ฑ๋ก์ด ์๋ฃ๋ ์ํ ์
๋๋ค. ํน, ์์ง ์๋ฃ๊ฐ ์๋ ์ํ๋ผ๋ฉด ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
Interface Builder๋ฅผ ํตํด ์ง์ ํ๊ฒ ๋๋ฉฐ iOS - Getting Start์ ๋ฐ๋ผ ํ๊ฒฝ์ค์ ์ ํ๋ค๋ฉด ์ด๋ฏธ View๋ฑ๋ก์ด ์๋ฃ๋ ์ํ ์
๋๋ค. ํน, ์์ง ์๋ฃ๊ฐ ์๋ ์ํ๋ผ๋ฉด ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ณด๋ค ๋ ์์ธํ ๋ด์ฉ์ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ฐฉ์ก์์ฑ
RemonCast
์ create()
ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ฐฉ์ก ๋ง๋ค ์ ์์ต๋๋ค. create()
ํจ์๊ฐ ํธ์ถ ๋๋ฉด Remon
์ ๋ฏธ๋์ด ์๋ฒ์๋ค๋ฅธ ์ฌ์ฉ์๋ค์ด ์ ์ ํ ์ ์๋ ๋ฐฉ์ก์ด ์ฑ๋๋ก์จ ๋ง๋ค์ด ์ง๊ฒ ๋ฉ๋๋ค. ์ด๋ ์ฑ๋์ด ๋ง๋ค์ด ์ง๋ฉด์ channelId
๋ฅผ ๋ฐํํ๊ฒ ๋๊ณ , ์ด๋ฅผ ํตํด ์์ฒญ์๊ฐ ์ ๊ทผํ ์ ์์ต๋๋ค.
Copy // <video id="localVideo" autoplay muted></video>
let myChannelId
const config = {
credential: {
serviceId: 'MY_SERVICE_ID',
key: 'MY_SERVICE_KEY'
},
view: {
local: '#localVideo'
},
media: {
sendonly: true
}
}
const listener = {
onCreate(channelId) {
myChannelId = channelId
}
}
โ
const caster = new Remon({ listener, config })
caster.createCast()
Copy caster = RemonCast.builder()
.serviceId("MY_SERVICE_ID")
.key("MY_SERVICE_KEY")
.context(CastActivity.this)
.localView(surfRendererlocal) // local Video Renderer
.build();
caster.onCreate((channelId) -> {
myChannelId = channelId;
});
caster.create();
Copy caster = RemonCast.builder()
.serviceId("MY_SERVICE_ID")
.key("MY_SERVICE_KEY")
.context(CastActivity.this)
.localView(surfRendererlocal) // local Video Renderer
.build()
caster.onCreate { channelId ->
myChannelId = channelId;
}
caster.create()
Copy remonCast.create("MY_CHANNEL_ID")
ํน์ ์๋์ ๊ฐ์ด Interface Builder ์์ด ์์ฑ ๊ฐ๋ฅํฉ๋๋ค.
Copy let caster = RemonCast()
caster.serviceId = "MY_SERVICE_ID"
caster.serviceKey = "MY_SERVICE_KEY"
caster.localView = localView
remonCast.onCreate { (channelId) in
let myChannelId = caster.channelId
}
caster.create("MY_CHANNEL_ID")
Copy [remonCast create:@"MY_CHANNEL_ID"];
Or you can create it without Interface Builder as follows.
Copy RemonCast *caster = [[RemonCast alloc]init];
caster.serviceId = @"MY_SERVICE_ID";
caster.serviceKey = @"MY_SERVICE_KEY";
caster.localView = localView;
[self.remonCast onCreateWithBlock:^(NSString * _Nullable chId) {
[self.channelIdLabel setText:chId];
}];
[caster create:@"MY_CHANNEL_ID"];
๋ฐฉ์ก์์ฒญ
RemonCast
์ joinRoom(channelId)
ํจ์๋ฅผ ์ด์ฉํ๋ฉด ๋ฐฉ์ก์ ์ฐธ์ฌ ํ ์ ์์ต๋๋ค. ์ด๋ ์ํ๋ channelId
๋ฅผ ์๋ ค์ค์ผ ํ๋๋ฐ ๋ณดํต ์๋์ Channel์ ์ฐธ๊ณ ํ์ฌ ์ ์ฒด ๋ชฉ๋ก์ ํตํด ์ฌ์ฉ์๊ฐ ์ ํํ๋ ๋ฐฉ์์ด ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
Copy // <video id="remoteVideo" autoplay></video>
let myChannelId
const config = {
credential: {
serviceId: 'MY_SERVICE_ID',
key: 'MY_SERVICE_KEY'
},
view: {
local: '#remoteVideo'
},
media: {
recvonly: true
}
}
const listener = {
onJoin() {
// Do something
}
}
โ
const viewer = new Remon({ listener, config })
viewer.joinCast('MY_CHANNEL_ID') // myChnnelId from caster
Copy viewer = RemonCast.builder()
.serviceId("MY_SERVICE_ID")
.key("MY_SERVICE_KEY")
.context(ViewerActivity.this)
.remoteView(surfRendererRemote) // remote video renderer
.build();
โ
viewer.onJoin(() -> {});
viewer.join("MY_CHANNEL_ID"); // myChid from caster
Copy viewer = RemonCast.builder()
.serviceId("MY_SERVICE_ID")
.key("MY_SERVICE_KEY")
.context(ViewerActivity.this)
.remoteView(surfRendererRemote) // remote video renderer
.build()
โ
viewer.onJoin{
}
viewer.join("MY_CHANNEL_ID") // myChid from caster
Copy remonCast.join("MY_CHANNEL_ID")
ํน์ ์๋์ ๊ฐ์ด Interface Builder ์์ด ์์ฑ ๊ฐ๋ฅํฉ๋๋ค.
Copy let viewer = RemonCast()
viewer.serviceId = "MY_SERVICE_ID"
viewer.key = "MY_SERVICE_KEY"
viewer.remoteView = remoteView
viewer.onJoin {
// Do something
}
viewer.join("MY_CHANNEL_ID")
Copy [remonCast join:@"MY_CHANNEL_ID"]
Or you can create it without Interface Builder as follows.
Copy RemonCast *caster = [[RemonCast alloc]init];
caster.serviceId = @"MY_SERVICE_ID";
caster.serviceKey = @"MY_SERVICE_KEY";
caster.localView = localView;
[self.remonCast onJoinWithBlock:^() {
}];
[caster join:@"MY_CHANNEL_ID"];
Callbacks
๊ฐ๋ฐ์ค ๋ค์ํ ์ํ ์ถ์ ์ ๋๊ธฐ ์ํ Callback์ ์ ๊ณต ํฉ๋๋ค.
์๋๋ก์ด๋ 2.4.13, iOS 2.6.9 ๋ฒ์ ๋ถํฐ ์ฝ๋ฐฑ์ ๋ชจ๋ UI Thread ์์ ํธ์ถ๋ฉ๋๋ค.
Copy const listener = {
onInit(token) {
// UI ์ฒ๋ฆฌ๋ฑ remon์ด ์ด๊ธฐํ ๋์์ ๋ ์ฒ๋ฆฌํ์ฌ์ผ ํ ์์
},
โ
onConnect(channelId) {
// ํตํ ์์ฑ ํ ๋๊ธฐ ํน์ ์๋ต
},
โ
onComplete() {
// Caller, Callee๊ฐ ํตํ ์์
},
โ
onClose() {
// ์ข
๋ฃ
}
}
Copy remonCast = RemonCast.builder().build();
// UI ์ฒ๋ฆฌ๋ฑ remon์ด ์ด๊ธฐํ ๋์์ ๋ ์ฒ๋ฆฌํ์ฌ์ผ ํ ์์
remonCast.onInit(() -> {
});
โ
// ๋ฐฉ์ก ์์ฑ
remonCast.onCreate((channelId) -> {
});
โ
// ๋ฐฉ์ก ์ฐธ
remonCast.onJoin ( () -> {
});
// Caller, Callee๊ฐ ํตํ ์์
remonCast.onComplete(() -> {
});
โ
// ์ข
๋ฃ
remonCast.onClose(() -> {
});
Copy remonCast = RemonCast.builder().build()
// UI ์ฒ๋ฆฌ๋ฑ remon์ด ์ด๊ธฐํ ๋์์ ๋ ์ฒ๋ฆฌํ์ฌ์ผ ํ ์์
remonCast.onInit {
}
โ
// ๋ฐฉ์ก ์์ฑ
remonCast.onCreate { channelId -> {
}
โ
// ๋ฐฉ์ก ์ฐธ
remonCast.onJoin {
}
// Caller, Callee๊ฐ ํตํ ์์
remonCast.onComplete {
}
โ
// ์ข
๋ฃ
remonCast.onClose {
}
Copy let remonCast = RemonCast()
remonCast.onInit { [weak self] in
// UI ์ฒ๋ฆฌ๋ฑ remon์ด ์ด๊ธฐํ ๋์์ ๋ ์ฒ๋ฆฌํ์ฌ์ผ ํ ์์
}
โ
remonCast.onCreate { [weak self](channelId) in
// ํด๋น 'chid'๋ก ๋ฏธ๋ฆฌ ์์ฑ๋ ์ฑ๋์ด ์๋ค๋ฉด ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ํด๋น 'chid'๋ก ์ฐ๊ฒฐ์ ์๋ ํ ๋ ๊น์ง ๋๊ธฐ ์ํ๊ฐ ๋ฉ๋๋ค.
}
โ
remonCast.onJoin { [weak self] in
}
remonCast.onComplete { [weak self] in
// Caller, Callee๊ฐ ํตํ ์์
}
โ
remonCast.onClose { [weak self](closeType) in
// ์ข
๋ฃ
}
Copy RemonCast *remonCast = [[RemonCast alloc] init];
[remonCast onInitWithBlock:^{
// Things to do when remon is initialized, such as UI processing, etc.
}];
[remonCast onConnectWithBlock:^(NSString * _Nullable chId) {
// Make a call then wait the callee
}];
[remonCast onJoinWithBlock:^{
}];
[remonCast onCompleteWithBlock:^{
// Start between Caller and Callee
}];
[remonCast onCloseWithBlock:^{
// End calling
}];
๋ ๋ง์ ๋ด์ฉ์ ์๋๋ฅผ ์ฐธ์กฐ ํ์ธ์.โ
Channel ๋ชฉ๋ก ์กฐํ
๋ฐฉ์ก์ ๋ง๋ค๋ฉด ์ฑ๋์ด ์์ฑ๋๊ณ ๊ณ ์ ํ channelId
๊ฐ ์์ฑ ๋ฉ๋๋ค. ์ด channelId
๋ฅผ ํตํด ์์ฒญ์๊ฐ ์์ฑ๋ ๋ฐฉ์ก์ ์ ๊ทผ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ ๋ฐฉ์ก์ค์ธ ์ ์ฒด ์ฑ๋ ๋ชฉ๋ก์ ์๋์ ๊ฐ์ด ์กฐํ ๊ฐ๋ฅํฉ๋๋ค.
Copy const remonCast = new Remon()
const casts = await remonCast.fetchCasts()
Copy remonCast = RemonCast.builder().build();
remonCast.onFetch((casts) -> {
// Do something
});
remonCast.featchCasts();
Copy remonCast = RemonCast.builder().build()
remonCast.onFetch { casts ->
// Do something
}
remonCast.featchCasts()
Copy let remonCast = RemonCast()
remonCast.fetchCasts { (error, results) in
// Do something
}
Copy RemonCast *remonCast = [[RemonCast alloc]init];
[remonCast fetchCastsWithIsTest:YES
complete:^(NSArray<RemonSearchResult *> * _Nullable chs) {
// Do something
}];
๋ ์์ธํ ๋ด์ฉ์ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ข
๋ฃ
๋ฐฉ์ก์ ์ก์ถ, ์์ฒญ์ด ๋๋ฌ์ ๊ฒฝ์ฐ ๊ผญ RemonCast
๊ฐ์ฒด๋ฅผ close()
ํด์ฃผ์ด์ผ ํฉ๋๋ค. close๋ฅผ ํตํด์ ๋ชจ๋ ๋ฐฉ์ก ์์๊ณผ ๋ฏธ๋์ด ์คํธ๋ฆผ ์์์ด ํด์ ๋ฉ๋๋ค.
Copy const remonCast = new Remon()
remonCast.close()
Copy remonCast = RemonCast.builder().build();
remonCast.close();
Copy remonCast = RemonCast.builder().build()
remonCast.close()
Copy let remonCast = RemonCast()
remonCast.closeRemon()
Copy RemonCast *remonCast = [[RemonCast alloc]init];
[remonCast closeRemon];
๊ธฐํ
์๋๋ฅผ ํตํด ๋ณด๋ค ์์ธํ ์ค์ , ์ค ์๋น์ค๋ฅผ ์ํ ํ๋ ํฐ์ค๋ฑ ๋ค์ํ ๋ด์ฉ์ ํ์ธํด ๋ณด์ธ์.