Closed tommi97 closed 10 months ago
@tommi97 any update ? i have the same issue on android devices
@KhaledOuartsi The problem was that the zoom SDK used form the package is too old, so I decide to use this guide: https://stefan-majiros.com/blog/integrating-zoom-sdk-into-react-native/ to implement my custom bridge from React and Zoom SDK to be free to update the zoom SDK.
After following this guide I found some difficulty because the code doesn't work correctly but after some modifications now it works.
When it finally worked, I changed the startMeeting function to accept ZAK authentication instead of JWT because it will be deprecated.
Finally I copied from this package (react-native-zoom-us) some pieces of code to implement some parameters that I used before like: disableShowVideoPreviewWhenJoinMeeting, language and so on...
I hope I was helpful, Good luck! :muscle:
@tommi97 thank you so much for your reply, Me too i decided to implement my custum bridge, and it's working now
You follow my guide or you find another one?
I followed the same link yeah, because i just saw your reply
Ok, I am happy to be helpful to you!!
Can you link me your JAVA files so can I check the difference with my code?
You create only android bridge or also IOS?
Ios it was working, i had issues only with android, so i created bridge only for android version,
I will past it here tomorrow.
Hello, This is the bridge working with ZoomSDK 5.10.3 `public class ZoomManager extends ReactContextBaseJavaModule implements ZoomSDKInitializeListener, MeetingServiceListener {
private final ReactApplicationContext reactContext;
private Promise initPromise;
private Promise meetingPromise;
ZoomManager(ReactApplicationContext context) {
super(context);
this.reactContext = context;
}
@NonNull
@Override
public String getName() {
// this defines name of how we will import this module in JS
return "FDZoomSDKAndroid";
}
@ReactMethod
public void initZoom(String publicKey, String privateKey, String domain, Promise promise) {
try {
initPromise = promise;
this.getReactApplicationContext().getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ZoomSDK zoomSDK = ZoomSDK.getInstance();
ZoomSDKInitParams initParams = new ZoomSDKInitParams();
initParams.appKey = publicKey;
initParams.appSecret = privateKey;
// initParams.domain = domain;
zoomSDK.initialize(Objects.requireNonNull(reactContext.getCurrentActivity()),ZoomManager.this, initParams);
}
});
} catch (Exception e) {
Log.e("ERR_UNEXPECTED_EXCEPTIO", e.getMessage());
promise.reject("ERR_UNEXPECTED_EXCEPTIO", e);
}
}
@Override
public void onZoomSDKInitializeResult(int errorCode, int internalErrorCode) {
Log.d(this.getName(), "Init Zoom Result with : errorCode " + errorCode
+ " and internalErrorCode: " + internalErrorCode);
if(errorCode == ZoomError.ZOOM_ERROR_SUCCESS) {
Log.d(this.getName(), "Initializing meeting service SUCCESSFUL");
ZoomSDK zoomSDK = ZoomSDK.getInstance();
MeetingService meetingService = zoomSDK.getMeetingService();
if(meetingService != null) {
Log.d(this.getName(), "Adding listener for meeting service ");
meetingService.addListener(this);
}
//here we should notify JS
initPromise.resolve("Zoom initialized");
}
}
@Override
public void onZoomAuthIdentityExpired() {
}
@Override
public void onMeetingStatusChanged(MeetingStatus meetingStatus, int errorCode, int internalErrorCode) {
Log.d(this.getName(), "Meeting Status Changed meetingStatus : " + meetingStatus
+ " errorCode: " + errorCode + " and internalErrorCode: " + internalErrorCode);
switch(meetingStatus) {
case MEETING_STATUS_FAILED: {
Log.d(this.getName(), "onMeetingStatusChanged: MEETING_STATUS_FAILED");
break;
}
case MEETING_STATUS_DISCONNECTING: {
Log.d(this.getName(), "onMeetingStatusChanged: MEETING_STATUS_DISCONNECTING");
break;
}
case MEETING_STATUS_INMEETING: {
Log.d(this.getName(), "onMeetingStatusChanged: MEETING_STATUS_INMEETING");
break;
}
case MEETING_STATUS_IN_WAITING_ROOM: {
Log.d(this.getName(), "onMeetingStatusChanged: MEETING_STATUS_IN_WAITING_ROOM");
break;
}
}
}
@Override
public void onMeetingParameterNotification(MeetingParameter meetingParameter) {
}
@ReactMethod
public void joinMeeting(String displayName, String meetingNumber, Promise promise) {
Log.d("ou shit", "Join meeting called : displayName " + displayName
+ " and meetingNumber: " + meetingNumber);
this.getReactApplicationContext().getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ZoomSDK zoomSDK = ZoomSDK.getInstance();
if(!zoomSDK.isInitialized()) {
promise.reject("ERR_ZOOM_START", "ZoomSDK has not been initialized successfully");
Log.d(getName(), "ZoomSDK has not been initialized successfully");
return;
}
MeetingService meetingService = zoomSDK.getMeetingService();
if(meetingService == null) {
promise.reject("ERR_ZOOM_START", "Zoom MeetingService has not been initialized successfully");
Log.d(getName(), "Zoom MeetingService has not been initialized successfully");
return;
}
JoinMeetingOptions opts = new JoinMeetingOptions();
JoinMeetingParams params = new JoinMeetingParams();
params.displayName = displayName;
params.meetingNo = meetingNumber;
// params.password = "password";
try {
int joinMeetingResult = meetingService.joinMeetingWithParams(reactContext, params,opts);
Log.i(getName(), "joinMeeting, joinMeetingResult=" + joinMeetingResult);
if (joinMeetingResult != MeetingError.MEETING_ERROR_SUCCESS) {
promise.reject("ERR_ZOOM_JOIN", "joinMeeting, errorCode=" + joinMeetingResult);
Log.i(getName(), "joinMeeting, errorCode=" + joinMeetingResult);
}
meetingPromise = promise;
} catch (Exception e) {
promise.reject("JoinMeetingException", e);
}
}
});
}
// put in into something like ZakUtils class to make it clean ??
private String getZak(String userId, String jwtApiKey, String jwtApiSecret){
String jwtAccessToken = this.createJWTAccessToken(jwtApiKey, jwtApiSecret);
String zak = this.getZoomAccessToken(userId, jwtAccessToken);
return zak;
}
public String getZoomAccessToken(String userId, String jwtAccessToken) {
// String jwtAccessToken = createJWTAccessToken();
if(jwtAccessToken == null || jwtAccessToken.isEmpty())
return null;
// Create connection
try {
URL zoomTokenEndpoint = new URL("https://api.zoom.us/v2/users/" + userId + "/token?type=zak&access_token=" + jwtAccessToken);
HttpsURLConnection connection = (HttpsURLConnection) zoomTokenEndpoint.openConnection();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream responseBody = connection.getInputStream();
InputStreamReader responseBodyReader = new InputStreamReader(responseBody, "UTF-8");
BufferedReader streamReader = new BufferedReader(responseBodyReader);
StringBuilder responseStrBuilder = new StringBuilder();
//get JSON String
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
connection.disconnect();
JSONObject jsonObject = new JSONObject(responseStrBuilder.toString());
return jsonObject.getString("token");
} else {
Log.d(this.getName(), "error in connection");
return null;
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e){
e.printStackTrace();
}
return null;
}
public String createJWTAccessToken(final String API_KEY, final String API_SECRET) {
long EXPIRED_TIME= 3600 * 2;
long time=System.currentTimeMillis()/1000 + EXPIRED_TIME;
String header = "{\"alg\": \"HS256\", \"typ\": \"JWT\"}";
String payload = "{\"iss\": \"" + API_KEY + "\"" + ", \"exp\": " + String.valueOf(time) + "}";
try {
String headerBase64Str = Base64.encodeToString(header.getBytes("utf-8"), Base64.NO_WRAP| Base64.NO_PADDING | Base64.URL_SAFE);
String payloadBase64Str = Base64.encodeToString(payload.getBytes("utf-8"), Base64.NO_WRAP| Base64.NO_PADDING | Base64.URL_SAFE);
final Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(API_SECRET.getBytes(), "HmacSHA256");
mac.init(secretKeySpec);
byte[] digest = mac.doFinal((headerBase64Str + "." + payloadBase64Str).getBytes());
return headerBase64Str + "." + payloadBase64Str + "." + Base64.encodeToString(digest, Base64.NO_WRAP| Base64.NO_PADDING | Base64.URL_SAFE);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
}`
Pls upgrade your react-native version to ^0.71.3 It worked on my case
I created issue to upgrade Android SDK (https://github.com/mieszko4/react-native-zoom-us/issues/280)
@KhaledOuartsi @tommi97 I am not sure why you used older 5.10.3
. based on minimum version policy version 5.12.2
is the minimum supported version from August 5 2023.
In any case idea of react-native-zoom-us
and react-native-zoom-us-test
is to make it easy to integrate Zoom SDK for others. So I think it would be great if you could make a PR if you managed to resolve some issues that others are experiencing with the bridge :)
I created issue to upgrade Android SDK (mieszko4/react-native-zoom-us#280)
Closing because it is now done in react-native-zoom-us@6.20.0
In some Android devices I have the same error when i try to join or start a meeting, with both version 6.15.1 and 6.16.5. IOS work fine.
When i try to join a meeting I recive following event before the "error 4": {"event": "meetingClientIncompatible", "status": "MEETING_STATUS_FAILED"}
How can i resolve this issue in Android?