use of org.matrix.androidsdk.core.callback.ApiCallback in project matrix-android-sdk by matrix-org.
the class MXCallsManager method refreshTurnServer.
/**
* Refresh the turn servers.
*/
private void refreshTurnServer() {
if (mSuspendTurnServerRefresh) {
return;
}
Log.d(LOG_TAG, "## refreshTurnServer () starts");
mUIThreadHandler.post(() -> mCallResClient.getTurnServer(new ApiCallback<JsonObject>() {
private void restartAfter(int msDelay) {
// "ttl" seems invalid
if (msDelay <= 0) {
Log.e(LOG_TAG, "## refreshTurnServer() : invalid delay " + msDelay);
} else {
if (null != mTurnServerTimer) {
mTurnServerTimer.cancel();
}
try {
mTurnServerTimer = new Timer();
mTurnServerTimer.schedule(new TimerTask() {
@Override
public void run() {
if (mTurnServerTimer != null) {
mTurnServerTimer.cancel();
mTurnServerTimer = null;
}
refreshTurnServer();
}
}, msDelay);
} catch (Throwable e) {
Log.e(LOG_TAG, "## refreshTurnServer() failed to start the timer", e);
if (null != mTurnServerTimer) {
mTurnServerTimer.cancel();
mTurnServerTimer = null;
}
refreshTurnServer();
}
}
}
@Override
public void onSuccess(JsonObject info) {
// privacy
Log.d(LOG_TAG, "## refreshTurnServer () : onSuccess");
if (null != info) {
if (info.has("uris")) {
synchronized (LOG_TAG) {
mTurnServer = info;
}
}
if (info.has("ttl")) {
int ttl = 60000;
try {
ttl = info.get("ttl").getAsInt();
// restart a 90 % before ttl expires
ttl = ttl * 9 / 10;
} catch (Exception e) {
Log.e(LOG_TAG, "Fail to retrieve ttl " + e.getMessage(), e);
}
Log.d(LOG_TAG, "## refreshTurnServer () : onSuccess : retry after " + ttl + " seconds");
restartAfter(ttl * 1000);
}
}
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## refreshTurnServer () : onNetworkError", e);
restartAfter(60000);
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## refreshTurnServer () : onMatrixError() : " + e.errcode);
if (TextUtils.equals(e.errcode, MatrixError.LIMIT_EXCEEDED) && (null != e.retry_after_ms)) {
Log.e(LOG_TAG, "## refreshTurnServer () : onMatrixError() : retry after " + e.retry_after_ms + " ms");
restartAfter(e.retry_after_ms);
}
}
@Override
public void onUnexpectedError(Exception e) {
// should never happen
Log.e(LOG_TAG, "## refreshTurnServer () : onUnexpectedError()", e);
}
}));
}
use of org.matrix.androidsdk.core.callback.ApiCallback in project matrix-android-sdk by matrix-org.
the class EventsRestClient method searchUsers.
/**
* Search users with a patter,
*
* @param text the text to search for.
* @param limit the maximum nbr of users in the response
* @param userIdsFilter the userIds to exclude from the result
* @param callback the request callback
*/
public void searchUsers(final String text, final Integer limit, final Set<String> userIdsFilter, final ApiCallback<SearchUsersResponse> callback) {
SearchUsersParams searchParams = new SearchUsersParams();
searchParams.search_term = text;
searchParams.limit = limit + ((null != userIdsFilter) ? userIdsFilter.size() : 0);
final String uid = mSearchUsersPatternIdentifier = System.currentTimeMillis() + " " + text + " " + limit;
final String description = "searchUsers";
// don't retry to send the request
// if the search fails, stop it
mApi.searchUsers(searchParams).enqueue(new RestAdapterCallback<SearchUsersRequestResponse>(description, null, new ApiCallback<SearchUsersRequestResponse>() {
/**
* Tells if the current response for the latest request.
*
* @return true if it is the response of the latest request.
*/
private boolean isActiveRequest() {
return TextUtils.equals(mSearchUsersPatternIdentifier, uid);
}
@Override
public void onSuccess(SearchUsersRequestResponse aResponse) {
if (isActiveRequest()) {
SearchUsersResponse response = new SearchUsersResponse();
response.limited = aResponse.limited;
response.results = new ArrayList<>();
Set<String> filter = (null != userIdsFilter) ? userIdsFilter : new HashSet<String>();
if (null != aResponse.results) {
for (SearchUsersRequestResponse.User user : aResponse.results) {
if ((null != user.user_id) && !filter.contains(user.user_id)) {
User addedUser = new User();
addedUser.user_id = user.user_id;
addedUser.avatar_url = user.avatar_url;
addedUser.displayname = user.display_name;
response.results.add(addedUser);
}
}
}
callback.onSuccess(response);
mSearchUsersPatternIdentifier = null;
}
}
@Override
public void onNetworkError(Exception e) {
if (isActiveRequest()) {
callback.onNetworkError(e);
mSearchUsersPatternIdentifier = null;
}
}
@Override
public void onMatrixError(MatrixError e) {
if (isActiveRequest()) {
callback.onMatrixError(e);
mSearchUsersPatternIdentifier = null;
}
}
@Override
public void onUnexpectedError(Exception e) {
if (isActiveRequest()) {
callback.onUnexpectedError(e);
mSearchUsersPatternIdentifier = null;
}
}
}, new RestAdapterCallback.RequestRetryCallBack() {
@Override
public void onRetry() {
searchUsers(text, limit, userIdsFilter, callback);
}
}));
}
use of org.matrix.androidsdk.core.callback.ApiCallback in project matrix-android-sdk by matrix-org.
the class EventsRestClient method searchMessagesByText.
/**
* Search a text in room messages.
*
* @param text the text to search for.
* @param rooms a list of rooms to search in. nil means all rooms the user is in.
* @param beforeLimit the number of events to get before the matching results.
* @param afterLimit the number of events to get after the matching results.
* @param nextBatch the token to pass for doing pagination from a previous response.
* @param callback the request callback
*/
public void searchMessagesByText(final String text, final List<String> rooms, final int beforeLimit, final int afterLimit, final String nextBatch, final ApiCallback<SearchResponse> callback) {
SearchParams searchParams = new SearchParams();
SearchRoomEventCategoryParams searchEventParams = new SearchRoomEventCategoryParams();
searchEventParams.search_term = text;
searchEventParams.order_by = "recent";
searchEventParams.event_context = new HashMap<>();
searchEventParams.event_context.put("before_limit", beforeLimit);
searchEventParams.event_context.put("after_limit", afterLimit);
searchEventParams.event_context.put("include_profile", true);
if (null != rooms) {
searchEventParams.filter = new HashMap<>();
searchEventParams.filter.put("rooms", rooms);
}
searchParams.search_categories = new HashMap<>();
searchParams.search_categories.put("room_events", searchEventParams);
final String description = "searchMessageText";
final String uid = System.currentTimeMillis() + "";
mSearchEventsPatternIdentifier = uid + text;
// don't retry to send the request
// if the search fails, stop it
mApi.searchEvents(searchParams, nextBatch).enqueue(new RestAdapterCallback<SearchResponse>(description, null, new ApiCallback<SearchResponse>() {
/**
* Tells if the current response for the latest request.
*
* @return true if it is the response of the latest request.
*/
private boolean isActiveRequest() {
return TextUtils.equals(mSearchEventsPatternIdentifier, uid + text);
}
@Override
public void onSuccess(SearchResponse response) {
if (isActiveRequest()) {
if (null != callback) {
callback.onSuccess(response);
}
mSearchEventsPatternIdentifier = null;
}
}
@Override
public void onNetworkError(Exception e) {
if (isActiveRequest()) {
if (null != callback) {
callback.onNetworkError(e);
}
mSearchEventsPatternIdentifier = null;
}
}
@Override
public void onMatrixError(MatrixError e) {
if (isActiveRequest()) {
if (null != callback) {
callback.onMatrixError(e);
}
mSearchEventsPatternIdentifier = null;
}
}
@Override
public void onUnexpectedError(Exception e) {
if (isActiveRequest()) {
if (null != callback) {
callback.onUnexpectedError(e);
}
mSearchEventsPatternIdentifier = null;
}
}
}, new RestAdapterCallback.RequestRetryCallBack() {
@Override
public void onRetry() {
searchMessagesByText(text, rooms, beforeLimit, afterLimit, nextBatch, callback);
}
}));
}
use of org.matrix.androidsdk.core.callback.ApiCallback in project matrix-android-sdk by matrix-org.
the class Room method sendEvent.
// ==============================================================================================================
// Send methods
// ==============================================================================================================
/**
* Send an event content to the room.
* The event is updated with the data provided by the server
* The provided event contains the error description.
*
* @param event the message
* @param callback the callback with the created event
*/
public void sendEvent(final Event event, final ApiCallback<Void> callback) {
// wait that the room is synced before sending messages
if (!mIsReady || !isJoined()) {
mDataHandler.updateEventState(event, Event.SentState.WAITING_RETRY);
try {
callback.onNetworkError(null);
} catch (Exception e) {
Log.e(LOG_TAG, "sendEvent exception " + e.getMessage(), e);
}
return;
}
final String prevEventId = event.eventId;
final ApiCallback<CreatedEvent> localCB = new ApiCallback<CreatedEvent>() {
@Override
public void onSuccess(final CreatedEvent createdEvent) {
if (null != getStore()) {
// remove the tmp event
getStore().deleteEvent(event);
}
// replace the tmp event id by the final one
boolean isReadMarkerUpdated = TextUtils.equals(getReadMarkerEventId(), event.eventId);
// update the event with the server response
event.eventId = createdEvent.eventId;
event.originServerTs = System.currentTimeMillis();
mDataHandler.updateEventState(event, Event.SentState.SENT);
// the message echo is not yet echoed
if (null != getStore() && !getStore().doesEventExist(createdEvent.eventId, getRoomId())) {
getStore().storeLiveRoomEvent(event);
}
// send the dedicated read receipt asap
markAllAsRead(isReadMarkerUpdated, null);
if (null != getStore()) {
getStore().commit();
}
mDataHandler.onEventSent(event, prevEventId);
try {
callback.onSuccess(null);
} catch (Exception e) {
Log.e(LOG_TAG, "sendEvent exception " + e.getMessage(), e);
}
}
@Override
public void onNetworkError(Exception e) {
event.unsentException = e;
mDataHandler.updateEventState(event, Event.SentState.UNDELIVERED);
try {
callback.onNetworkError(e);
} catch (Exception anException) {
Log.e(LOG_TAG, "sendEvent exception " + anException.getMessage(), anException);
}
}
@Override
public void onMatrixError(MatrixError e) {
event.unsentMatrixError = e;
mDataHandler.updateEventState(event, Event.SentState.UNDELIVERED);
if (MatrixError.isConfigurationErrorCode(e.errcode)) {
mDataHandler.onConfigurationError(e.errcode);
} else {
try {
callback.onMatrixError(e);
} catch (Exception anException) {
Log.e(LOG_TAG, "sendEvent exception " + anException.getMessage(), anException);
}
}
}
@Override
public void onUnexpectedError(Exception e) {
event.unsentException = e;
mDataHandler.updateEventState(event, Event.SentState.UNDELIVERED);
try {
callback.onUnexpectedError(e);
} catch (Exception anException) {
Log.e(LOG_TAG, "sendEvent exception " + anException.getMessage(), anException);
}
}
};
if (isEncrypted() && (null != mDataHandler.getCrypto())) {
mDataHandler.updateEventState(event, Event.SentState.ENCRYPTING);
// Store the "m.relates_to" data and remove them from event content before encrypting the event content
final JsonElement relatesTo;
JsonObject contentAsJsonObject = event.getContentAsJsonObject();
if (contentAsJsonObject != null && contentAsJsonObject.has("m.relates_to")) {
// Get a copy of "m.relates_to" data...
relatesTo = contentAsJsonObject.get("m.relates_to");
// ... and remove "m.relates_to" data from the content before encrypting it
contentAsJsonObject.remove("m.relates_to");
} else {
relatesTo = null;
}
// Encrypt the content before sending
mDataHandler.getCrypto().encryptEventContent(contentAsJsonObject, event.getType(), this, new ApiCallback<MXEncryptEventContentResult>() {
@Override
public void onSuccess(MXEncryptEventContentResult encryptEventContentResult) {
// update the event content with the encrypted data
event.type = encryptEventContentResult.mEventType;
// Add the "m.relates_to" data to the encrypted event here
JsonObject encryptedContent = encryptEventContentResult.mEventContent.getAsJsonObject();
if (relatesTo != null) {
encryptedContent.add("m.relates_to", relatesTo);
}
event.updateContent(encryptedContent);
mDataHandler.decryptEvent(event, null);
// sending in progress
mDataHandler.updateEventState(event, Event.SentState.SENDING);
mDataHandler.getDataRetriever().getRoomsRestClient().sendEventToRoom(event.eventId, getRoomId(), encryptEventContentResult.mEventType, encryptEventContentResult.mEventContent.getAsJsonObject(), localCB);
}
@Override
public void onNetworkError(Exception e) {
event.unsentException = e;
mDataHandler.updateEventState(event, Event.SentState.UNDELIVERED);
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
// update the sent state if the message encryption failed because there are unknown devices.
if ((e instanceof MXCryptoError) && TextUtils.equals(((MXCryptoError) e).errcode, MXCryptoError.UNKNOWN_DEVICES_CODE)) {
event.mSentState = Event.SentState.FAILED_UNKNOWN_DEVICES;
} else {
event.mSentState = Event.SentState.UNDELIVERED;
}
event.unsentMatrixError = e;
mDataHandler.onEventSentStateUpdated(event);
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
event.unsentException = e;
mDataHandler.updateEventState(event, Event.SentState.UNDELIVERED);
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
} else {
mDataHandler.updateEventState(event, Event.SentState.SENDING);
if (Event.EVENT_TYPE_MESSAGE.equals(event.getType())) {
mDataHandler.getDataRetriever().getRoomsRestClient().sendMessage(event.eventId, getRoomId(), event.getContentAsJsonObject(), localCB);
} else {
mDataHandler.getDataRetriever().getRoomsRestClient().sendEventToRoom(event.eventId, getRoomId(), event.getType(), event.getContentAsJsonObject(), localCB);
}
}
}
use of org.matrix.androidsdk.core.callback.ApiCallback in project matrix-android-sdk by matrix-org.
the class MXCallsManager method createCallInRoom.
/**
* Create an IMXCall in the room defines by its room Id.
* -> for a 1:1 call, it is a standard call.
* -> for a conference call,
* ----> the conference user is invited to the room (if it was not yet invited)
* ----> the call signaling room is created (or retrieved) with the conference
* ----> and the call is started
*
* @param roomId the room roomId
* @param isVideo true to start a video call
* @param callback the async callback
*/
public void createCallInRoom(final String roomId, final boolean isVideo, final ApiCallback<IMXCall> callback) {
Log.d(LOG_TAG, "createCallInRoom in " + roomId);
final Room room = mSession.getDataHandler().getRoom(roomId);
// sanity check
if (null != room) {
if (isSupported()) {
int joinedMembers = room.getNumberOfJoinedMembers();
Log.d(LOG_TAG, "createCallInRoom : the room has " + joinedMembers + " joined members");
if (joinedMembers > 1) {
if (joinedMembers == 2) {
// So it seems safer to reject the call creation it it will fail.
if (room.isEncrypted() && mSession.getCrypto() != null && mSession.getCrypto().warnOnUnknownDevices()) {
room.getJoinedMembersAsync(new SimpleApiCallback<List<RoomMember>>(callback) {
@Override
public void onSuccess(List<RoomMember> members) {
if (members.size() != 2) {
// Safety check
callback.onUnexpectedError(new Exception("Wrong number of members"));
return;
}
String userId1 = members.get(0).getUserId();
String userId2 = members.get(1).getUserId();
// force the refresh to ensure that the devices list is up-to-date
mSession.getCrypto().checkUnknownDevices(Arrays.asList(userId1, userId2), new SimpleApiCallback<Void>(callback) {
@Override
public void onSuccess(Void anything) {
final IMXCall call = getCallWithCallId(null, true);
call.setRooms(room, room);
call.setIsVideo(isVideo);
dispatchOnOutgoingCall(call);
if (null != callback) {
mUIThreadHandler.post(() -> callback.onSuccess(call));
}
}
});
}
});
} else {
final IMXCall call = getCallWithCallId(null, true);
call.setIsVideo(isVideo);
dispatchOnOutgoingCall(call);
call.setRooms(room, room);
if (null != callback) {
mUIThreadHandler.post(() -> callback.onSuccess(call));
}
}
} else {
Log.d(LOG_TAG, "createCallInRoom : inviteConferenceUser");
inviteConferenceUser(room, new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
Log.d(LOG_TAG, "createCallInRoom : inviteConferenceUser succeeds");
getConferenceUserRoom(room.getRoomId(), new ApiCallback<Room>() {
@Override
public void onSuccess(Room conferenceRoom) {
Log.d(LOG_TAG, "createCallInRoom : getConferenceUserRoom succeeds");
final IMXCall call = getCallWithCallId(null, true);
call.setRooms(room, conferenceRoom);
call.setIsConference(true);
call.setIsVideo(isVideo);
dispatchOnOutgoingCall(call);
if (null != callback) {
mUIThreadHandler.post(() -> callback.onSuccess(call));
}
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "createCallInRoom : getConferenceUserRoom failed " + e.getMessage(), e);
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "createCallInRoom : getConferenceUserRoom failed " + e.getMessage());
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "createCallInRoom : getConferenceUserRoom failed " + e.getMessage(), e);
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "createCallInRoom : inviteConferenceUser fails " + e.getMessage(), e);
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "createCallInRoom : inviteConferenceUser fails " + e.getMessage());
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "createCallInRoom : inviteConferenceUser fails " + e.getMessage(), e);
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
}
} else {
if (null != callback) {
callback.onMatrixError(new MatrixError(MatrixError.NOT_SUPPORTED, "too few users"));
}
}
} else {
if (null != callback) {
callback.onMatrixError(new MatrixError(MatrixError.NOT_SUPPORTED, "VOIP is not supported"));
}
}
} else {
if (null != callback) {
callback.onMatrixError(new MatrixError(MatrixError.NOT_FOUND, "room not found"));
}
}
}
Aggregations