use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MXMediaDownloadWorkerTask method doInBackground.
/**
* Download and decode media in background.
*
* @param params
* @return JsonElement if an error occurs
*/
@Override
protected JsonElement doInBackground(Void... params) {
JsonElement jsonElementResult = null;
MatrixError defaultError = new MatrixError();
defaultError.errcode = MatrixError.UNKNOWN;
try {
URL url = new URL(mUrl);
Log.d(LOG_TAG, "MXMediaDownloadWorkerTask " + this + " starts");
mDownloadStats = new IMXMediaDownloadListener.DownloadStats();
// don't known yet
mDownloadStats.mEstimatedRemainingTime = -1;
InputStream stream = null;
int filelen = -1;
HttpURLConnection connection = null;
try {
Proxy proxyConfig = mHsConfig.getProxyConfig();
if (proxyConfig == null) {
proxyConfig = Proxy.NO_PROXY;
}
connection = (HttpURLConnection) url.openConnection(proxyConfig);
if (RestClient.getUserAgent() != null) {
connection.setRequestProperty("User-Agent", RestClient.getUserAgent());
}
if (mHsConfig != null && connection instanceof HttpsURLConnection) {
// Add SSL Socket factory.
HttpsURLConnection sslConn = (HttpsURLConnection) connection;
try {
Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mHsConfig);
sslConn.setSSLSocketFactory(pair.first);
sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mHsConfig));
} catch (Exception e) {
Log.e(LOG_TAG, "doInBackground SSL exception " + e.getMessage(), e);
}
}
// add a timeout to avoid infinite loading display.
float scale = (null != mNetworkConnectivityReceiver) ? mNetworkConnectivityReceiver.getTimeoutScale() : 1.0f;
connection.setReadTimeout((int) (DOWNLOAD_TIME_OUT * scale));
if (mIsAvScannerEnabled && null != mEncryptedFileInfo) {
// POST the encryption info to let the av scanner decrypt and scan the content.
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setDoOutput(true);
connection.setUseCaches(false);
EncryptedMediaScanBody encryptedMediaScanBody = new EncryptedMediaScanBody();
encryptedMediaScanBody.encryptedFileInfo = mEncryptedFileInfo;
String data = JsonUtility.getCanonicalizedJsonString(encryptedMediaScanBody);
// Encrypt the data, if antivirus server supports it
String publicServerKey = getAntivirusServerPublicKey();
if (publicServerKey == null) {
// Error
throw new Exception("Unable to get public key");
} else if (!TextUtils.isEmpty(publicServerKey)) {
OlmPkEncryption olmPkEncryption = new OlmPkEncryption();
olmPkEncryption.setRecipientKey(publicServerKey);
OlmPkMessage message = olmPkEncryption.encrypt(data);
EncryptedMediaScanEncryptedBody encryptedMediaScanEncryptedBody = new EncryptedMediaScanEncryptedBody();
encryptedMediaScanEncryptedBody.encryptedBodyFileInfo = new EncryptedBodyFileInfo(message);
data = JsonUtility.getCanonicalizedJsonString(encryptedMediaScanEncryptedBody);
}
// Else: no public key on this server, do not encrypt data
OutputStream outputStream = connection.getOutputStream();
try {
outputStream.write(data.getBytes("UTF-8"));
} catch (Exception e) {
Log.e(LOG_TAG, "doInBackground Failed to serialize encryption info " + e.getMessage(), e);
} finally {
outputStream.close();
}
}
filelen = connection.getContentLength();
stream = connection.getInputStream();
} catch (Exception e) {
Log.e(LOG_TAG, "bitmapForURL : fail to open the connection " + e.getMessage(), e);
defaultError.error = e.getLocalizedMessage();
// In case of 403, revert the key
if (connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN && mMediaScanRestClient != null) {
mMediaScanRestClient.resetServerPublicKey();
}
InputStream errorStream = connection.getErrorStream();
if (null != errorStream) {
try {
BufferedReader streamReader = new BufferedReader(new InputStreamReader(errorStream, "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null) {
responseStrBuilder.append(inputStr);
}
jsonElementResult = new JsonParser().parse(responseStrBuilder.toString());
} catch (Exception ee) {
Log.e(LOG_TAG, "bitmapForURL : Error parsing error " + ee.getMessage(), ee);
}
}
// privacy
// Log.d(LOG_TAG, "MediaWorkerTask " + mUrl + " does not exist");
Log.d(LOG_TAG, "MediaWorkerTask an url does not exist");
// (because the same url is used for all encrypted media when the av scanner is enabled).
if (!mIsAvScannerEnabled || null == mEncryptedFileInfo) {
synchronized (sUnreachableUrls) {
sUnreachableUrls.add(mUrl);
}
}
}
dispatchDownloadStart();
// failed to open the remote stream without having exception
if ((null == stream) && (null == jsonElementResult)) {
jsonElementResult = new JsonParser().parse("Cannot open " + mUrl);
// (because the same url is used for all encrypted media when the av scanner is enabled).
if (!mIsAvScannerEnabled || null == mEncryptedFileInfo) {
synchronized (sUnreachableUrls) {
sUnreachableUrls.add(mUrl);
}
}
}
// test if the download has not been cancelled
if (!isDownloadCancelled() && (null == jsonElementResult)) {
final long startDownloadTime = System.currentTimeMillis();
String filename = buildFileName(mDownloadId, mMimeType) + ".tmp";
FileOutputStream fos = new FileOutputStream(new File(mDirectoryFile, filename));
mDownloadStats.mDownloadId = mDownloadId;
mDownloadStats.mProgress = 0;
mDownloadStats.mDownloadedSize = 0;
mDownloadStats.mFileSize = filelen;
mDownloadStats.mElapsedTime = 0;
mDownloadStats.mEstimatedRemainingTime = -1;
mDownloadStats.mBitRate = 0;
// Publish progress every 100ms
final Timer refreshTimer = new Timer();
refreshTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!mIsDone) {
updateAndPublishProgress(startDownloadTime);
}
}
}, new Date(), 100);
try {
byte[] buf = new byte[DOWNLOAD_BUFFER_READ_SIZE];
int len;
while (!isDownloadCancelled() && (len = stream.read(buf)) != -1) {
fos.write(buf, 0, len);
mDownloadStats.mDownloadedSize += len;
}
if (!isDownloadCancelled()) {
mDownloadStats.mProgress = 100;
}
} catch (OutOfMemoryError outOfMemoryError) {
Log.e(LOG_TAG, "doInBackground: out of memory", outOfMemoryError);
defaultError.error = outOfMemoryError.getLocalizedMessage();
} catch (Exception e) {
Log.e(LOG_TAG, "doInBackground fail to read image " + e.getMessage(), e);
defaultError.error = e.getLocalizedMessage();
}
mIsDone = true;
close(stream);
fos.flush();
fos.close();
refreshTimer.cancel();
if ((null != connection) && (connection instanceof HttpsURLConnection)) {
connection.disconnect();
}
// the file has been successfully downloaded
if (mDownloadStats.mProgress == 100) {
try {
File originalFile = new File(mDirectoryFile, filename);
String newFileName = buildFileName(mDownloadId, mMimeType);
File newFile = new File(mDirectoryFile, newFileName);
if (newFile.exists()) {
// Or you could throw here.
mApplicationContext.deleteFile(newFileName);
}
originalFile.renameTo(newFile);
} catch (Exception e) {
Log.e(LOG_TAG, "doInBackground : renaming error " + e.getMessage(), e);
defaultError.error = e.getLocalizedMessage();
}
}
}
if (mDownloadStats.mProgress == 100) {
Log.d(LOG_TAG, "The download " + this + " is done.");
} else {
if (null != jsonElementResult) {
Log.d(LOG_TAG, "The download " + this + " failed : mErrorAsJsonElement " + jsonElementResult.toString());
} else {
Log.d(LOG_TAG, "The download " + this + " failed.");
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "Unable to download media " + this, e);
defaultError.error = e.getMessage();
}
// build a JSON from the error
if (!TextUtils.isEmpty(defaultError.error)) {
jsonElementResult = JsonUtils.getGson(false).toJsonTree(defaultError);
}
// remove the task from the loading one
synchronized (sPendingDownloadById) {
sPendingDownloadById.remove(mDownloadId);
}
return jsonElementResult;
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MatrixMessageListFragment method add.
/**
* Add a media item in the room.
*/
private void add(final RoomMediaMessage roomMediaMessage) {
MessageRow messageRow = addMessageRow(roomMediaMessage);
// add sanity check
if (null == messageRow) {
return;
}
final Event event = messageRow.getEvent();
if (!event.isUndelivered()) {
ApiCallback<Void> callback = new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
getUiHandler().post(new Runnable() {
@Override
public void run() {
onMessageSendingSucceeded(event);
}
});
}
private void commonFailure(final Event event) {
getUiHandler().post(new Runnable() {
@Override
public void run() {
Activity activity = getActivity();
if (null != activity) {
// display the error message only if the message cannot be resent
if ((null != event.unsentException) && (event.isUndelivered())) {
if (event.unsentException instanceof IOException) {
Toast.makeText(activity, activity.getString(R.string.unable_to_send_message) + " : " + activity.getString(R.string.network_error), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, activity.getString(R.string.unable_to_send_message) + " : " + event.unsentException.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
} else if (null != event.unsentMatrixError) {
String localised = (event.unsentMatrixError instanceof MXCryptoError) ? ((MXCryptoError) event.unsentMatrixError).getDetailedErrorDescription() : event.unsentMatrixError.getLocalizedMessage();
Toast.makeText(activity, activity.getString(R.string.unable_to_send_message) + " : " + localised, Toast.LENGTH_LONG).show();
}
mAdapter.notifyDataSetChanged();
onMessageSendingFailed(event);
}
}
});
}
@Override
public void onNetworkError(final Exception e) {
commonFailure(event);
}
@Override
public void onMatrixError(final MatrixError e) {
// do not display toast if the sending failed because of unknown device (e2e issue)
if (event.mSentState == Event.SentState.FAILED_UNKNOWN_DEVICES) {
getUiHandler().post(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
onUnknownDevices(event, (MXCryptoError) e);
}
});
} else if (MatrixError.M_CONSENT_NOT_GIVEN.equals(e.errcode)) {
getUiHandler().post(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
onConsentNotGiven(event, e);
}
});
} else {
commonFailure(event);
}
}
@Override
public void onUnexpectedError(final Exception e) {
commonFailure(event);
}
};
roomMediaMessage.setEventSendingCallback(callback);
}
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MatrixMessageListFragment method requestSearchHistory.
/**
* Search the pattern on a pagination server side.
*/
public void requestSearchHistory() {
// there is no more server message
if (TextUtils.isEmpty(mNextBatch)) {
mIsBackPaginating = false;
return;
}
mIsBackPaginating = true;
final int firstPos = mMessageListView.getFirstVisiblePosition();
final String fPattern = mPattern;
final int countBeforeUpdate = mAdapter.getCount();
showLoadingBackProgress();
List<String> roomIds = null;
if (null != mRoom) {
roomIds = Arrays.asList(mRoom.getRoomId());
}
ApiCallback<SearchResponse> callback = new ApiCallback<SearchResponse>() {
@Override
public void onSuccess(final SearchResponse searchResponse) {
// check that the pattern was not modified before the end of the search
if (TextUtils.equals(mPattern, fPattern)) {
List<SearchResult> searchResults = searchResponse.searchCategories.roomEvents.results;
// is there any result to display
if (0 != searchResults.size()) {
mAdapter.setNotifyOnChange(false);
for (SearchResult searchResult : searchResults) {
MessageRow row = new MessageRow(searchResult.result, (null == mRoom) ? null : mRoom.getState());
mAdapter.insert(row, 0);
}
mNextBatch = searchResponse.searchCategories.roomEvents.nextBatch;
// Scroll the list down to where it was before adding rows to the top
getUiHandler().post(new Runnable() {
@Override
public void run() {
final int expectedFirstPos = firstPos + (mAdapter.getCount() - countBeforeUpdate);
// trick to avoid that the list jump to the latest item.
mMessageListView.lockSelectionOnResize();
mAdapter.notifyDataSetChanged();
// do not use count because some messages are not displayed
// so we compute the new pos
mMessageListView.setSelection(expectedFirstPos);
mMessageListView.post(new Runnable() {
@Override
public void run() {
mIsBackPaginating = false;
// fill the history
if (mMessageListView.getFirstVisiblePosition() <= 2) {
requestSearchHistory();
}
}
});
}
});
} else {
mIsBackPaginating = false;
}
hideLoadingBackProgress();
}
}
private void onError() {
mIsBackPaginating = false;
hideLoadingBackProgress();
}
// the request will be auto restarted when a valid network will be found
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "Network error: " + e.getMessage(), e);
onError();
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "Matrix error" + " : " + e.errcode + " - " + e.getMessage());
onError();
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "onUnexpectedError error" + e.getMessage(), e);
onError();
}
};
if (mIsMediaSearch) {
mSession.searchMediaByName(mPattern, roomIds, mNextBatch, callback);
} else {
mSession.searchMessagesByText(mPattern, roomIds, mNextBatch, callback);
}
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MatrixMessageListFragment method onPaginateRequestError.
// ==============================================================================================================
// pagination methods
// ==============================================================================================================
/**
* Manage the request history error cases.
*
* @param error the error object.
*/
private void onPaginateRequestError(final Object error) {
Activity activity = getActivity();
if (null != activity) {
if (error instanceof Exception) {
Log.e(LOG_TAG, "Network error: " + ((Exception) error).getMessage(), (Exception) error);
Toast.makeText(activity, activity.getString(R.string.network_error), Toast.LENGTH_SHORT).show();
} else if (error instanceof MatrixError) {
final MatrixError matrixError = (MatrixError) error;
Log.e(LOG_TAG, "Matrix error" + " : " + matrixError.errcode + " - " + matrixError.getMessage());
Toast.makeText(activity, activity.getString(R.string.matrix_error) + " : " + matrixError.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
hideLoadingBackProgress();
hideLoadingForwardProgress();
Log.d(LOG_TAG, "requestHistory failed " + error);
mIsBackPaginating = false;
}
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class GroupsManager method onJoinGroup.
/**
* Manage the group joining.
*
* @param groupId the group id
* @param notify true to notify
*/
public void onJoinGroup(final String groupId, final boolean notify) {
Group group = getGroup(groupId);
if (null == group) {
group = new Group(groupId);
}
if (TextUtils.equals(RoomMember.MEMBERSHIP_JOIN, group.getMembership())) {
Log.d(LOG_TAG, "## onJoinGroup() : the group " + groupId + " was already joined");
return;
}
group.setMembership(RoomMember.MEMBERSHIP_JOIN);
mStore.storeGroup(group);
// try retrieve the summary
mGroupsRestClient.getGroupSummary(groupId, new ApiCallback<GroupSummary>() {
/**
* Common method
*/
private void onDone() {
if (notify) {
mDataHandler.onJoinGroup(groupId);
}
}
@Override
public void onSuccess(GroupSummary groupSummary) {
Group group = getGroup(groupId);
if (null != group) {
group.setGroupSummary(groupSummary);
mStore.flushGroup(group);
onDone();
if (null != mPendingJoinGroups.get(groupId)) {
mPendingJoinGroups.get(groupId).onSuccess(null);
mPendingJoinGroups.remove(groupId);
}
}
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## onJoinGroup() : failed " + e.getMessage(), e);
onDone();
if (null != mPendingJoinGroups.get(groupId)) {
mPendingJoinGroups.get(groupId).onNetworkError(e);
mPendingJoinGroups.remove(groupId);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## onMatrixError() : failed " + e.getMessage());
onDone();
if (null != mPendingJoinGroups.get(groupId)) {
mPendingJoinGroups.get(groupId).onMatrixError(e);
mPendingJoinGroups.remove(groupId);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## onUnexpectedError() : failed " + e.getMessage(), e);
onDone();
if (null != mPendingJoinGroups.get(groupId)) {
mPendingJoinGroups.get(groupId).onUnexpectedError(e);
mPendingJoinGroups.remove(groupId);
}
}
});
}
Aggregations