use of org.matrix.androidsdk.rest.model.MatrixError in project matrix-android-sdk by matrix-org.
the class RestAdapterCallback method failure.
/**
* Default failure implementation that calls the right error handler
*
* @param error the retrofit error
*/
@Override
public void failure(RetrofitError error) {
if (null != mEventDescription) {
Log.d(LOG_TAG, "## failure(): [" + mEventDescription + "]" + " with error " + error.getMessage());
}
boolean retry = true;
if (null != error.getResponse()) {
retry = (error.getResponse().getStatus() < 400) || (error.getResponse().getStatus() > 500);
}
// do not retry if the response format is not the expected one.
retry &= (null == error.getCause()) || !(error.getCause() instanceof ConversionException);
if (retry && (null != mUnsentEventsManager)) {
Log.d(LOG_TAG, "Add it to the UnsentEventsManager");
mUnsentEventsManager.onEventSendingFailed(mEventDescription, mIgnoreEventTimeLifeInOffline, error, mApiCallback, mRequestRetryCallBack);
} else {
if (error.isNetworkError()) {
try {
if (null != mApiCallback) {
try {
mApiCallback.onNetworkError(error);
} catch (Exception e) {
Log.e(LOG_TAG, "## failure(): onNetworkError " + error.getMessage());
}
}
} catch (Exception e) {
// privacy
// Log.e(LOG_TAG, "Exception NetworkError " + e.getMessage() + " while managing " + error.getUrl());
Log.e(LOG_TAG, "## failure(): NetworkError " + e.getMessage());
}
} else {
// Try to convert this into a Matrix error
MatrixError mxError;
try {
mxError = (MatrixError) error.getBodyAs(MatrixError.class);
mxError.mStatus = error.getResponse().getStatus();
mxError.mReason = error.getResponse().getReason();
TypedInput body = error.getResponse().getBody();
if (null != body) {
mxError.mErrorBodyMimeType = body.mimeType();
mxError.mErrorBody = body;
try {
if (body instanceof TypedByteArray) {
mxError.mErrorBodyAsString = new String(((TypedByteArray) body).getBytes());
} else {
mxError.mErrorBodyAsString = (String) error.getBodyAs(String.class);
}
} catch (Exception castException) {
Log.e(LOG_TAG, "## failure(): MatrixError cannot cast the response body" + castException.getMessage());
}
}
} catch (Exception e) {
mxError = null;
}
if (mxError != null) {
if (MatrixError.LIMIT_EXCEEDED.equals(mxError.errcode) && (null != mUnsentEventsManager)) {
mUnsentEventsManager.onEventSendingFailed(mEventDescription, mIgnoreEventTimeLifeInOffline, error, mApiCallback, mRequestRetryCallBack);
} else if (MatrixError.isConfigurationErrorCode(mxError.errcode) && (null != mUnsentEventsManager)) {
mUnsentEventsManager.onConfigurationErrorCode(mxError.errcode, mEventDescription);
} else {
try {
if (null != mApiCallback) {
mApiCallback.onMatrixError(mxError);
}
} catch (Exception e) {
// privacy
// Log.e(LOG_TAG, "Exception MatrixError " + e.getMessage() + " while managing " + error.getUrl());
Log.e(LOG_TAG, "## failure(): MatrixError " + e.getMessage());
}
}
} else {
try {
if (null != mApiCallback) {
mApiCallback.onUnexpectedError(error);
}
} catch (Exception e) {
// privacy
// Log.e(LOG_TAG, "Exception UnexpectedError " + e.getMessage() + " while managing " + error.getUrl());
Log.e(LOG_TAG, "## failure(): UnexpectedError " + e.getMessage());
}
}
}
}
}
use of org.matrix.androidsdk.rest.model.MatrixError in project matrix-android-sdk by matrix-org.
the class EventsThread method startSync.
/**
* Start the events sync
*/
@SuppressLint("NewApi")
private void startSync() {
if (null != mCurrentToken) {
Log.d(LOG_TAG, "Resuming initial sync from " + mCurrentToken);
} else {
Log.d(LOG_TAG, "Requesting initial sync...");
}
int serverTimeout;
mPaused = false;
//
mInitialSyncDone = null != mCurrentToken;
if (mInitialSyncDone) {
// get the latest events asap
serverTimeout = 0;
// dummy initial sync
// to hide the splash screen
SyncResponse dummySyncResponse = new SyncResponse();
dummySyncResponse.nextBatch = mCurrentToken;
mListener.onSyncResponse(dummySyncResponse, null, true);
} else {
// Start with initial sync
while (!mInitialSyncDone) {
final CountDownLatch latch = new CountDownLatch(1);
mEventsRestClient.syncFromToken(null, 0, DEFAULT_CLIENT_TIMEOUT_MS, mIsOnline ? null : "offline", DATA_SAVE_MODE_FILTER, new SimpleApiCallback<SyncResponse>(mFailureCallback) {
@Override
public void onSuccess(SyncResponse syncResponse) {
Log.d(LOG_TAG, "Received initial sync response.");
mNextServerTimeoutms = hasDevicesChanged(syncResponse) ? 0 : mDefaultServerTimeoutms;
mListener.onSyncResponse(syncResponse, null, (0 == mNextServerTimeoutms));
mCurrentToken = syncResponse.nextBatch;
mInitialSyncDone = true;
// unblock the events thread
latch.countDown();
}
private void sleepAndUnblock() {
Log.i(LOG_TAG, "Waiting a bit before retrying");
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
public void run() {
latch.countDown();
}
}, RETRY_WAIT_TIME_MS);
}
@Override
public void onNetworkError(Exception e) {
if (null != mCurrentToken) {
onSuccess(null);
} else {
Log.e(LOG_TAG, "Sync V2 onNetworkError " + e.getMessage());
super.onNetworkError(e);
sleepAndUnblock();
}
}
@Override
public void onMatrixError(MatrixError e) {
super.onMatrixError(e);
if (MatrixError.isConfigurationErrorCode(e.errcode)) {
mListener.onConfigurationError(e.errcode);
} else {
sleepAndUnblock();
}
}
@Override
public void onUnexpectedError(Exception e) {
super.onUnexpectedError(e);
Log.e(LOG_TAG, "Sync V2 onUnexpectedError " + e.getMessage());
sleepAndUnblock();
}
});
// block until the initial sync callback is invoked.
try {
latch.await();
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Interrupted whilst performing initial sync.");
} catch (Exception e) {
Log.e(LOG_TAG, "## startSync() failed " + e.getMessage());
}
}
serverTimeout = mNextServerTimeoutms;
}
Log.d(LOG_TAG, "Starting event stream from token " + mCurrentToken);
// sanity check
if (null != mNetworkConnectivityReceiver) {
mNetworkConnectivityReceiver.addEventListener(mNetworkListener);
//
mbIsConnected = mNetworkConnectivityReceiver.isConnected();
mIsNetworkSuspended = !mbIsConnected;
}
// Then repeatedly long-poll for events
while (!mKilling) {
// test if a delay between two syncs
if ((!mPaused && !mIsNetworkSuspended) && (0 != mRequestDelayMs)) {
Log.d(LOG_TAG, "startSync : start a delay timer ");
Intent intent = new Intent(mContext, SyncDelayReceiver.class);
intent.putExtra(SyncDelayReceiver.EXTRA_INSTANCE_ID, this.toString());
mPendingDelayedIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long futureInMillis = SystemClock.elapsedRealtime() + mRequestDelayMs;
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) && mPowerManager.isIgnoringBatteryOptimizations(mContext.getPackageName())) {
mAlarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, mPendingDelayedIntent);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, mPendingDelayedIntent);
}
}
if (mPaused || mIsNetworkSuspended || (null != mPendingDelayedIntent)) {
if (null != mPendingDelayedIntent) {
Log.d(LOG_TAG, "Event stream is paused because there is a timer delay.");
} else if (mIsNetworkSuspended) {
Log.d(LOG_TAG, "Event stream is paused because there is no available network.");
} else {
Log.d(LOG_TAG, "Event stream is paused. Waiting.");
}
try {
Log.d(LOG_TAG, "startSync : wait ...");
synchronized (mSyncObject) {
mSyncObject.wait();
}
if (null != mPendingDelayedIntent) {
Log.d(LOG_TAG, "startSync : cancel mSyncDelayTimer");
mAlarmManager.cancel(mPendingDelayedIntent);
mPendingDelayedIntent.cancel();
mPendingDelayedIntent = null;
}
Log.d(LOG_TAG, "Event stream woken from pause.");
// perform a catchup asap
serverTimeout = 0;
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Unexpected interruption while paused: " + e.getMessage());
}
}
// the service could have been killed while being paused.
if (!mKilling) {
// "{\"room\":{\"timeline\":{\"limit\":250}}}";
String inlineFilter = mIsInDataSaveMode ? DATA_SAVE_MODE_FILTER : null;
final CountDownLatch latch = new CountDownLatch(1);
if (mIsInDataSaveMode) {
Log.d(LOG_TAG, "[Data save mode] Get events from token " + mCurrentToken);
} else {
Log.d(LOG_TAG, "Get events from token " + mCurrentToken);
}
final int fServerTimeout = serverTimeout;
mNextServerTimeoutms = mDefaultServerTimeoutms;
mEventsRestClient.syncFromToken(mCurrentToken, serverTimeout, DEFAULT_CLIENT_TIMEOUT_MS, mIsOnline ? null : "offline", inlineFilter, new SimpleApiCallback<SyncResponse>(mFailureCallback) {
@Override
public void onSuccess(SyncResponse syncResponse) {
if (!mKilling) {
// we get no to_device messages back.
if (0 == fServerTimeout) {
if (hasDevicesChanged(syncResponse)) {
if (mIsCatchingUp) {
Log.d(LOG_TAG, "Some devices have changed but do not set mNextServerTimeoutms to 0 to avoid infinite loops");
} else {
Log.d(LOG_TAG, "mNextServerTimeoutms is set to 0 because of hasDevicesChanged " + syncResponse.deviceLists.changed);
mNextServerTimeoutms = 0;
}
}
}
// to loop again
if (mIsCatchingUp && (0 != mNextServerTimeoutms)) {
// the catchup triggers sync requests until there are some useful events
int eventCounts = 0;
if (null != syncResponse.rooms) {
RoomsSyncResponse roomsSyncResponse = syncResponse.rooms;
if (null != roomsSyncResponse.join) {
eventCounts += roomsSyncResponse.join.size();
}
if (null != roomsSyncResponse.invite) {
eventCounts += roomsSyncResponse.invite.size();
}
}
// stop any catch up
mIsCatchingUp = false;
mPaused = (0 == mRequestDelayMs);
Log.d(LOG_TAG, "Got " + eventCounts + " useful events while catching up : mPaused is set to " + mPaused);
}
Log.d(LOG_TAG, "Got event response");
mListener.onSyncResponse(syncResponse, mCurrentToken, (0 == mNextServerTimeoutms));
mCurrentToken = syncResponse.nextBatch;
Log.d(LOG_TAG, "mCurrentToken is now set to " + mCurrentToken);
}
// unblock the events thread
latch.countDown();
}
private void onError(String description) {
boolean isConnected;
Log.d(LOG_TAG, "Got an error while polling events " + description);
synchronized (mSyncObject) {
isConnected = mbIsConnected;
}
// detected if the device is connected before trying again
if (isConnected) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
public void run() {
latch.countDown();
}
}, RETRY_WAIT_TIME_MS);
} else {
// no network -> wait that a network connection comes back.
mIsNetworkSuspended = true;
latch.countDown();
}
}
@Override
public void onNetworkError(Exception e) {
onError(e.getLocalizedMessage());
}
@Override
public void onMatrixError(MatrixError e) {
if (MatrixError.isConfigurationErrorCode(e.errcode)) {
mListener.onConfigurationError(e.errcode);
} else {
onError(e.getLocalizedMessage());
}
}
@Override
public void onUnexpectedError(Exception e) {
onError(e.getLocalizedMessage());
}
});
// block until the sync callback is invoked.
try {
latch.await();
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Interrupted whilst polling message");
} catch (Exception e) {
// reported by GA
// The thread might have been killed.
Log.e(LOG_TAG, "latch.await() failed " + e.getMessage());
}
}
serverTimeout = mNextServerTimeoutms;
}
if (null != mNetworkConnectivityReceiver) {
mNetworkConnectivityReceiver.removeEventListener(mNetworkListener);
}
Log.d(LOG_TAG, "Event stream terminating.");
}
use of org.matrix.androidsdk.rest.model.MatrixError in project matrix-android-sdk by matrix-org.
the class TestsHelper method createAccountAndSync.
/**
* Create an account and a dedicated session
* @param context the context
* @param userName the account username
* @param password the password
* @param startSession true to perform an initial sync
* @param callback the callback
* @throws Exception an exception if the account cannot be created
*/
public static void createAccountAndSync(Context context, String userName, String password, boolean startSession, ApiCallback<MXSession> callback) throws Exception {
RestClient.mUseMXExececutor = true;
Uri uri = Uri.parse(TESTS_HOME_SERVER_URL);
HomeServerConnectionConfig hs = new HomeServerConnectionConfig(uri);
LoginRestClient loginRestClient = new LoginRestClient(hs);
final HashMap<String, Object> params = new HashMap<>();
RegistrationParams registrationParams = new RegistrationParams();
mLock = new CountDownLatch(1);
// get the registration session id
loginRestClient.register(registrationParams, new ApiCallback<Credentials>() {
@Override
public void onSuccess(Credentials credentials) {
mLock.countDown();
}
@Override
public void onNetworkError(Exception e) {
mLock.countDown();
}
@Override
public void onMatrixError(MatrixError e) {
// detect if a parameter is expected
RegistrationFlowResponse registrationFlowResponse = null;
// when a response is not completed the server returns an error message
if ((null != e.mStatus) && (e.mStatus == 401)) {
try {
registrationFlowResponse = JsonUtils.toRegistrationFlowResponse(e.mErrorBodyAsString);
} catch (Exception castExcept) {
}
}
// check if the server response can be casted
if (null != registrationFlowResponse) {
params.put("session", registrationFlowResponse.session);
}
mLock.countDown();
}
@Override
public void onUnexpectedError(Exception e) {
mLock.countDown();
}
});
mLock.await(1000, TimeUnit.MILLISECONDS);
String session = (String) params.get("session");
if (null == session) {
callback.onUnexpectedError(null);
}
registrationParams.username = userName;
registrationParams.password = password;
HashMap<String, Object> authParams = new HashMap<>();
authParams.put("session", session);
authParams.put("type", LoginRestClient.LOGIN_FLOW_TYPE_DUMMY);
registrationParams.auth = authParams;
mLock = new CountDownLatch(1);
loginRestClient.register(registrationParams, new ApiCallback<Credentials>() {
@Override
public void onSuccess(Credentials credentials) {
params.put("credentials", credentials);
mLock.countDown();
}
@Override
public void onNetworkError(Exception e) {
mLock.countDown();
}
@Override
public void onMatrixError(MatrixError e) {
mLock.countDown();
}
@Override
public void onUnexpectedError(Exception e) {
mLock.countDown();
}
});
mLock.await(1000, TimeUnit.MILLISECONDS);
Credentials credentials = (Credentials) params.get("credentials");
if (null == credentials) {
callback.onMatrixError(null);
return;
}
hs.setCredentials(credentials);
IMXStore store = new MXFileStore(hs, context);
MXSession mxSession = new MXSession(hs, new MXDataHandler(store, credentials), context);
if (!startSession) {
callback.onSuccess(mxSession);
return;
}
mxSession.getDataHandler().getStore().open();
mxSession.startEventStream(null);
mLock = new CountDownLatch(1);
mxSession.getDataHandler().addListener(new MXEventListener() {
@Override
public void onInitialSyncComplete(String toToken) {
params.put("isInit", true);
mLock.countDown();
}
});
mLock.await(10000, TimeUnit.MILLISECONDS);
if (params.containsKey("isInit")) {
callback.onSuccess(mxSession);
} else {
callback.onMatrixError(null);
}
}
Aggregations