Skip to content

Commit 7b7bf69

Browse files
Release v1.3.0 (#125)
* Dual-Stack Endpoint Support (#112) * Add the dual-stack checkbox * Change checkbox to switch, improve margins * Move KVS client creation to separate class * Update app/src/main/java/com/amazonaws/kinesisvideo/demoapp/util/KvsClientFactory.java Co-authored-by: sirknightj <jggunawa@amazon.com> * Address comments * Add dual-stack STUN url * Update UI component * Fix rebase * Actually fix rebase * Add back custom endpoint capabilities * Add missing import --------- Co-authored-by: sirknightj <jggunawa@amazon.com> * Update versionName to 1.3.0 (#124) --------- Co-authored-by: sirknightj <jggunawa@amazon.com>
1 parent 6898ee8 commit 7b7bf69

5 files changed

Lines changed: 119 additions & 25 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ android {
1313
minSdk 29
1414
targetSdk 33
1515
versionCode 1
16-
versionName "1.2.0"
16+
versionName "1.3.0"
1717

1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919

@@ -122,4 +122,4 @@ tasks.register('checkForLibWebRTC') {
122122
}
123123
}
124124

125-
preBuild.dependsOn checkForLibWebRTC
125+
preBuild.dependsOn checkForLibWebRTC

app/src/main/java/com/amazonaws/kinesisvideo/demoapp/activity/WebRtcActivity.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import static com.amazonaws.kinesisvideo.demoapp.fragment.StreamWebRtcConfigurationFragment.KEY_STREAM_ARN;
1414
import static com.amazonaws.kinesisvideo.demoapp.fragment.StreamWebRtcConfigurationFragment.KEY_WEBRTC_ENDPOINT;
1515
import static com.amazonaws.kinesisvideo.demoapp.fragment.StreamWebRtcConfigurationFragment.KEY_WSS_ENDPOINT;
16+
import static com.amazonaws.kinesisvideo.demoapp.fragment.StreamWebRtcConfigurationFragment.KEY_USE_DUAL_STACK_ENDPOINTS;
1617

1718
import android.Manifest;
1819
import android.annotation.SuppressLint;
@@ -157,6 +158,7 @@ public class WebRtcActivity extends AppCompatActivity {
157158
private String mClientId;
158159

159160
private String webrtcEndpoint;
161+
private boolean useDualStackEndpoints;
160162
private String mStreamArn;
161163

162164
private String mWssEndpoint;
@@ -575,6 +577,7 @@ protected void onCreate(final Bundle savedInstanceState) {
575577
mStreamArn = intent.getStringExtra(KEY_STREAM_ARN);
576578
mWssEndpoint = intent.getStringExtra(KEY_WSS_ENDPOINT);
577579
webrtcEndpoint = intent.getStringExtra(KEY_WEBRTC_ENDPOINT);
580+
useDualStackEndpoints = intent.getBooleanExtra(KEY_USE_DUAL_STACK_ENDPOINTS, false);
578581

579582
mClientId = intent.getStringExtra(KEY_CLIENT_ID);
580583
// If no client identifier is present, a random one will be created.
@@ -595,8 +598,16 @@ protected void onCreate(final Bundle savedInstanceState) {
595598

596599
//TODO: add ui to control TURN only option
597600

601+
String stunDomain = useDualStackEndpoints
602+
? "api.aws"
603+
: "amazonaws.com";
604+
String stunUrl = String.format(
605+
"stun:stun.kinesisvideo.%s.%s:443",
606+
mRegion,
607+
stunDomain
608+
);
598609
final IceServer stun = IceServer
599-
.builder(String.format("stun:stun.kinesisvideo.%s.amazonaws.com:443", mRegion))
610+
.builder(stunUrl)
600611
.createIceServer();
601612

602613
peerIceServers.add(stun);

app/src/main/java/com/amazonaws/kinesisvideo/demoapp/fragment/StreamWebRtcConfigurationFragment.java

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.widget.ArrayAdapter;
1515
import android.widget.Button;
1616
import android.widget.CheckBox;
17+
import android.widget.Switch;
1718
import android.widget.CheckedTextView;
1819
import android.widget.EditText;
1920
import android.widget.ListView;
@@ -49,6 +50,7 @@
4950
import com.amazonaws.services.kinesisvideosignaling.model.GetIceServerConfigRequest;
5051
import com.amazonaws.services.kinesisvideosignaling.model.GetIceServerConfigResult;
5152
import com.amazonaws.services.kinesisvideosignaling.model.IceServer;
53+
import com.amazonaws.kinesisvideo.demoapp.util.KvsClientFactory;
5254

5355

5456
import java.lang.ref.WeakReference;
@@ -72,6 +74,7 @@ public class StreamWebRtcConfigurationFragment extends Fragment {
7274
public static final String KEY_ICE_SERVER_TTL = "iceServerTTL";
7375
public static final String KEY_ICE_SERVER_URI = "iceServerUri";
7476
public static final String KEY_CAMERA_FRONT_FACING = "cameraFrontFacing";
77+
public static final String KEY_USE_DUAL_STACK_ENDPOINTS = "useDualStackEndpoints";
7578

7679
public static final String KEY_SEND_VIDEO = "sendVideo";
7780
public static final String KEY_SEND_AUDIO = "sendAudio";
@@ -86,11 +89,15 @@ public class StreamWebRtcConfigurationFragment extends Fragment {
8689
KEY_SEND_AUDIO,
8790
};
8891

92+
public static final String DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT = "kinesisvideo.%s.api.aws";
93+
public static final String DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT_CN = "kinesisvideo.%s.api.amazonwebservices.com.cn";
94+
8995

9096
private EditText mChannelName;
9197
private EditText mClientId;
9298
private EditText mRegion;
9399
private Spinner mCameras;
100+
private Switch mUseDualStackEndpoints;
94101
private CheckBox mIngestMedia;
95102
private final List<ResourceEndpointListItem> mEndpointList = new ArrayList<>();
96103
private final List<IceServer> mIceServerList = new ArrayList<>();
@@ -132,6 +139,7 @@ public void onViewCreated(final View view, Bundle savedInstanceState) {
132139
mChannelName = view.findViewById(R.id.channel_name);
133140
mClientId = view.findViewById(R.id.client_id);
134141
mRegion = view.findViewById(R.id.region);
142+
mUseDualStackEndpoints = view.findViewById(R.id.use_dual_stack_endpoints);
135143
mIngestMedia = view.findViewById(R.id.ingest_media);
136144
setRegionFromCognito();
137145

@@ -175,8 +183,6 @@ private void setRegionFromCognito() {
175183
}
176184
}
177185

178-
179-
180186
private View.OnClickListener startMasterActivityWhenClicked() {
181187
return new View.OnClickListener() {
182188
@Override
@@ -267,6 +273,7 @@ private Bundle setExtras(boolean isMaster) {
267273
extras.putString(KEY_CHANNEL_ARN, mChannelArn);
268274
extras.putString(KEY_STREAM_ARN, mStreamArn);
269275
extras.putBoolean(KEY_IS_MASTER, isMaster);
276+
extras.putBoolean(KEY_USE_DUAL_STACK_ENDPOINTS, mUseDualStackEndpoints.isChecked());
270277

271278
if (!mIceServerList.isEmpty()) {
272279
ArrayList<String> userNames = new ArrayList<>(mIceServerList.size());
@@ -308,24 +315,6 @@ private Bundle setExtras(boolean isMaster) {
308315
return extras;
309316
}
310317

311-
private AWSKinesisVideoClient getAwsKinesisVideoClient(final String region) {
312-
final AWSKinesisVideoClient awsKinesisVideoClient = new AWSKinesisVideoClient(
313-
KinesisVideoWebRtcDemoApp.getCredentialsProvider().getCredentials());
314-
awsKinesisVideoClient.setRegion(Region.getRegion(region));
315-
awsKinesisVideoClient.setSignerRegionOverride(region);
316-
awsKinesisVideoClient.setServiceNameIntern("kinesisvideo");
317-
try {
318-
String customEndpoint = BuildConfig.CONTROL_PLANE_URI;
319-
if (customEndpoint != null && !customEndpoint.isEmpty() && !"null".equals(customEndpoint)) {
320-
awsKinesisVideoClient.setEndpoint(customEndpoint);
321-
}
322-
} catch (Exception e) {
323-
// CONTROL_PLANE_URI not defined in .env
324-
}
325-
326-
return awsKinesisVideoClient;
327-
}
328-
329318
private AWSKinesisVideoSignalingClient getAwsKinesisVideoSignalingClient(final String region, final String endpoint) {
330319
final AWSKinesisVideoSignalingClient client = new AWSKinesisVideoSignalingClient(
331320
KinesisVideoWebRtcDemoApp.getCredentialsProvider().getCredentials());
@@ -395,7 +384,8 @@ protected String doInBackground(final Object... objects) {
395384
// Step 1. Create Kinesis Video Client
396385
final AWSKinesisVideoClient awsKinesisVideoClient;
397386
try {
398-
awsKinesisVideoClient = mFragment.get().getAwsKinesisVideoClient(region);
387+
final boolean useDualStack = mFragment.get().mUseDualStackEndpoints.isChecked();
388+
awsKinesisVideoClient = KvsClientFactory.getAwsKinesisVideoClient(region, useDualStack);
399389
} catch (Exception e) {
400390
return "Create client failed with " + e.getLocalizedMessage();
401391
}
@@ -488,6 +478,7 @@ protected String doInBackground(final Object... objects) {
488478
// client is just used for getting ICE servers, not for actual signaling.
489479
// Step 6. Call GetIceServerConfig in order to obtain TURN ICE server info.
490480
// Note: the STUN endpoint will be `stun:stun.kinesisvideo.${region}.amazonaws.com:443`
481+
// for legacy mode and `stun:stun.kinesisvideo.${region}.api.aws:443` for dual-stack mode.
491482
try {
492483
final AWSKinesisVideoSignalingClient awsKinesisVideoSignalingClient = mFragment.get().getAwsKinesisVideoSignalingClient(region, dataEndpoint);
493484
GetIceServerConfigResult getIceServerConfigResult = awsKinesisVideoSignalingClient.getIceServerConfig(
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.amazonaws.kinesisvideo.demoapp.util;
2+
3+
import com.amazonaws.kinesisvideo.demoapp.KinesisVideoWebRtcDemoApp;
4+
import com.amazonaws.services.kinesisvideo.AWSKinesisVideoClient;
5+
import com.amazonaws.regions.Region;
6+
import com.amazonaws.kinesisvideo.demoapp.BuildConfig;
7+
8+
import android.util.Log;
9+
10+
11+
public class KvsClientFactory {
12+
private static final String TAG = KvsClientFactory.class.getSimpleName();
13+
14+
private static final String DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT = "kinesisvideo.%s.api.aws";
15+
private static final String DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT_CN = "kinesisvideo.%s.api.amazonwebservices.com.cn";
16+
private static final String KVS_SERVICE_NAME = "kinesisvideo";
17+
18+
private static String generateDualStackEndpoint(final String region) {
19+
if (region == null || region.isEmpty()) {
20+
Log.w(TAG, "AWS region is null or empty, will use legacy control-plane endpoint.");
21+
return null;
22+
}
23+
24+
if (region.startsWith("cn-")) {
25+
return String.format(DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT_CN, region);
26+
}
27+
28+
return String.format(DUAL_STACK_CONTROL_PLANE_ENDPOINT_FORMAT, region);
29+
}
30+
31+
public static AWSKinesisVideoClient getAwsKinesisVideoClient(final String region, final boolean useDualStack) {
32+
final AWSKinesisVideoClient awsKinesisVideoClient = new AWSKinesisVideoClient(
33+
KinesisVideoWebRtcDemoApp.getCredentialsProvider().getCredentials());
34+
awsKinesisVideoClient.setRegion(Region.getRegion(region));
35+
awsKinesisVideoClient.setSignerRegionOverride(region);
36+
awsKinesisVideoClient.setServiceNameIntern(KVS_SERVICE_NAME);
37+
38+
boolean isCustomEndpointSet = false;
39+
try {
40+
String customEndpoint = BuildConfig.CONTROL_PLANE_URI;
41+
if (customEndpoint != null && !customEndpoint.isEmpty() && !"null".equals(customEndpoint)) {
42+
awsKinesisVideoClient.setEndpoint(customEndpoint);
43+
isCustomEndpointSet = true;
44+
}
45+
} catch (Exception e) {
46+
}
47+
48+
if (!isCustomEndpointSet) {
49+
if (useDualStack) {
50+
awsKinesisVideoClient.setEndpoint(generateDualStackEndpoint(region));
51+
}
52+
}
53+
54+
return awsKinesisVideoClient;
55+
}
56+
57+
}

app/src/main/res/layout/fragment_stream_webrtc_configuration.xml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,40 @@
7070
tools:ignore="Autofill,HardcodedText"
7171
android:inputType="text" />
7272

73+
<Space
74+
android:layout_width="match_parent"
75+
android:layout_height="20dp" />
76+
77+
<TextView
78+
android:layout_width="wrap_content"
79+
android:layout_height="wrap_content"
80+
android:text="KVS Endpoint Type"
81+
tools:ignore="HardcodedText" />
82+
83+
<LinearLayout
84+
android:layout_width="match_parent"
85+
android:layout_height="wrap_content"
86+
android:orientation="horizontal"
87+
android:gravity="center_vertical"
88+
android:layout_marginStart="20dp">
89+
90+
<TextView
91+
android:id="@+id/label_dual_stack"
92+
android:layout_width="wrap_content"
93+
android:layout_height="wrap_content"
94+
android:text="Dual-stack"
95+
android:textSize="16sp"
96+
android:layout_marginStart="0dp" />
97+
98+
<Switch
99+
android:id="@+id/use_dual_stack_endpoints"
100+
android:layout_width="wrap_content"
101+
android:layout_height="wrap_content"
102+
android:layout_marginStart="16dp" />
103+
104+
</LinearLayout>
105+
106+
73107
<Space
74108
android:layout_width="match_parent"
75109
android:layout_height="20dp" />
@@ -83,7 +117,8 @@
83117
<Spinner
84118
android:layout_width="match_parent"
85119
android:layout_height="20dp"
86-
android:id="@+id/camera_spinner" />
120+
android:id="@+id/camera_spinner"
121+
android:layout_marginStart="10dp" />
87122

88123
<Space
89124
android:layout_width="match_parent"

0 commit comments

Comments
 (0)