mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-25 01:07:47 +00:00
Make UI responsive to UniversalTransport upgrades.
This commit is contained in:
parent
07b7696937
commit
dadabdfaa8
@ -146,7 +146,7 @@ public class KeyExchangeProcessor {
|
|||||||
.saveIdentity(masterSecret, recipient, remoteIdentity);
|
.saveIdentity(masterSecret, recipient, remoteIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processKeyExchangeMessage(PreKeyEntity message) {
|
public void processKeyExchangeMessage(PreKeyEntity message, long threadId) {
|
||||||
PublicKey remoteKey = new PublicKey(message.getKeyId(), message.getPublicKey());
|
PublicKey remoteKey = new PublicKey(message.getKeyId(), message.getPublicKey());
|
||||||
remoteKeyRecord.setCurrentRemoteKey(remoteKey);
|
remoteKeyRecord.setCurrentRemoteKey(remoteKey);
|
||||||
remoteKeyRecord.setLastRemoteKey(remoteKey);
|
remoteKeyRecord.setLastRemoteKey(remoteKey);
|
||||||
@ -166,6 +166,8 @@ public class KeyExchangeProcessor {
|
|||||||
|
|
||||||
DatabaseFactory.getIdentityDatabase(context)
|
DatabaseFactory.getIdentityDatabase(context)
|
||||||
.saveIdentity(masterSecret, recipient, message.getIdentityKey());
|
.saveIdentity(masterSecret, recipient, message.getIdentityKey());
|
||||||
|
|
||||||
|
broadcastSecurityUpdateEvent(context, threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processKeyExchangeMessage(KeyExchangeMessage message, long threadId) {
|
public void processKeyExchangeMessage(KeyExchangeMessage message, long threadId) {
|
||||||
@ -202,6 +204,10 @@ public class KeyExchangeProcessor {
|
|||||||
|
|
||||||
DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
|
DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
|
||||||
|
|
||||||
|
broadcastSecurityUpdateEvent(context, threadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void broadcastSecurityUpdateEvent(Context context, long threadId) {
|
||||||
Intent intent = new Intent(SECURITY_UPDATE_EVENT);
|
Intent intent = new Intent(SECURITY_UPDATE_EVENT);
|
||||||
intent.putExtra("thread_id", threadId);
|
intent.putExtra("thread_id", threadId);
|
||||||
intent.setPackage(context.getPackageName());
|
intent.setPackage(context.getPackageName());
|
||||||
|
@ -166,6 +166,10 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
|||||||
updateTypeBitmask(id, 0, Types.KEY_EXCHANGE_CORRUPTED_BIT);
|
updateTypeBitmask(id, 0, Types.KEY_EXCHANGE_CORRUPTED_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markAsSecure(long id) {
|
||||||
|
updateTypeBitmask(id, 0, Types.SECURE_MESSAGE_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
public void markAsDecryptFailed(long id) {
|
public void markAsDecryptFailed(long id) {
|
||||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT);
|
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import android.content.Intent;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
@ -30,6 +29,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
|||||||
import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler;
|
import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler;
|
||||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||||
import org.thoughtcrime.securesms.transport.UniversalTransport;
|
import org.thoughtcrime.securesms.transport.UniversalTransport;
|
||||||
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
|
|
||||||
import ws.com.google.android.mms.MmsException;
|
import ws.com.google.android.mms.MmsException;
|
||||||
import ws.com.google.android.mms.pdu.SendReq;
|
import ws.com.google.android.mms.pdu.SendReq;
|
||||||
@ -37,16 +37,14 @@ import ws.com.google.android.mms.pdu.SendReq;
|
|||||||
public class MmsSender {
|
public class MmsSender {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final ToastHandler toastHandler;
|
|
||||||
|
|
||||||
public MmsSender(Context context, ToastHandler toastHandler) {
|
public MmsSender(Context context, ToastHandler toastHandler) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.toastHandler = toastHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(MasterSecret masterSecret, Intent intent) {
|
public void process(MasterSecret masterSecret, Intent intent) {
|
||||||
Log.w("MmsSender", "Got intent action: " + intent.getAction());
|
Log.w("MmsSender", "Got intent action: " + intent.getAction());
|
||||||
if (intent.getAction().equals(SendReceiveService.SEND_MMS_ACTION)) {
|
if (SendReceiveService.SEND_MMS_ACTION.equals(intent.getAction())) {
|
||||||
handleSendMms(masterSecret, intent);
|
handleSendMms(masterSecret, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,15 +59,16 @@ public class MmsSender {
|
|||||||
SendReq[] messages = database.getOutgoingMessages(masterSecret, messageId);
|
SendReq[] messages = database.getOutgoingMessages(masterSecret, messageId);
|
||||||
|
|
||||||
for (SendReq message : messages) {
|
for (SendReq message : messages) {
|
||||||
|
long threadId = database.getThreadIdForMessage(message.getDatabaseMessageId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.w("MmsSender", "Passing to MMS transport: " + message.getDatabaseMessageId());
|
Log.w("MmsSender", "Passing to MMS transport: " + message.getDatabaseMessageId());
|
||||||
database.markAsSending(message.getDatabaseMessageId());
|
database.markAsSending(message.getDatabaseMessageId());
|
||||||
Pair<byte[], Integer> result = transport.deliver(message);
|
Pair<byte[], Integer> result = transport.deliver(message, threadId);
|
||||||
database.markAsSent(message.getDatabaseMessageId(), result.first, result.second);
|
database.markAsSent(message.getDatabaseMessageId(), result.first, result.second);
|
||||||
} catch (UndeliverableMessageException e) {
|
} catch (UndeliverableMessageException e) {
|
||||||
Log.w("MmsSender", e);
|
Log.w("MmsSender", e);
|
||||||
database.markAsSentFailed(message.getDatabaseMessageId());
|
database.markAsSentFailed(message.getDatabaseMessageId());
|
||||||
long threadId = database.getThreadIdForMessage(messageId);
|
|
||||||
Recipients recipients = threads.getRecipientsForThreadId(threadId);
|
Recipients recipients = threads.getRecipientsForThreadId(threadId);
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,18 @@ public class SmsSender {
|
|||||||
private void handleSentMessage(Intent intent) {
|
private void handleSentMessage(Intent intent) {
|
||||||
long messageId = intent.getLongExtra("message_id", -1);
|
long messageId = intent.getLongExtra("message_id", -1);
|
||||||
int result = intent.getIntExtra("ResultCode", -31337);
|
int result = intent.getIntExtra("ResultCode", -31337);
|
||||||
|
boolean upgraded = intent.getBooleanExtra("upgraded", false);
|
||||||
|
|
||||||
Log.w("SMSReceiverService", "Intent resultcode: " + result);
|
Log.w("SMSReceiverService", "Intent resultcode: " + result);
|
||||||
Log.w("SMSReceiverService", "Running sent callback: " + messageId);
|
Log.w("SMSReceiverService", "Running sent callback: " + messageId);
|
||||||
|
|
||||||
if (result == Activity.RESULT_OK) {
|
if (result == Activity.RESULT_OK) {
|
||||||
DatabaseFactory.getSmsDatabase(context).markAsSent(messageId);
|
DatabaseFactory.getSmsDatabase(context).markAsSent(messageId);
|
||||||
|
|
||||||
|
if (upgraded) {
|
||||||
|
DatabaseFactory.getSmsDatabase(context).markAsSecure(messageId);
|
||||||
|
}
|
||||||
|
|
||||||
unregisterForRadioChanges();
|
unregisterForRadioChanges();
|
||||||
} else if (result == SmsManager.RESULT_ERROR_NO_SERVICE || result == SmsManager.RESULT_ERROR_RADIO_OFF) {
|
} else if (result == SmsManager.RESULT_ERROR_NO_SERVICE || result == SmsManager.RESULT_ERROR_RADIO_OFF) {
|
||||||
DatabaseFactory.getSmsDatabase(context).markAsOutbox(messageId);
|
DatabaseFactory.getSmsDatabase(context).markAsOutbox(messageId);
|
||||||
|
@ -133,6 +133,7 @@ public class MessageSender {
|
|||||||
Intent intent = new Intent(SendReceiveService.SEND_MMS_ACTION, null,
|
Intent intent = new Intent(SendReceiveService.SEND_MMS_ACTION, null,
|
||||||
context, SendReceiveService.class);
|
context, SendReceiveService.class);
|
||||||
intent.putExtra("message_id", messageId);
|
intent.putExtra("message_id", messageId);
|
||||||
|
intent.putExtra("thread_id", threadId);
|
||||||
|
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,14 @@ import org.thoughtcrime.securesms.service.SmsListener;
|
|||||||
|
|
||||||
public abstract class BaseTransport {
|
public abstract class BaseTransport {
|
||||||
|
|
||||||
protected Intent constructSentIntent(Context context, long messageId, long type) {
|
protected Intent constructSentIntent(Context context, long messageId, long type, boolean upgraded) {
|
||||||
Intent pending = new Intent(SendReceiveService.SENT_SMS_ACTION,
|
Intent pending = new Intent(SendReceiveService.SENT_SMS_ACTION,
|
||||||
Uri.parse("custom://" + messageId + System.currentTimeMillis()),
|
Uri.parse("custom://" + messageId + System.currentTimeMillis()),
|
||||||
context, SmsListener.class);
|
context, SmsListener.class);
|
||||||
|
|
||||||
pending.putExtra("type", type);
|
pending.putExtra("type", type);
|
||||||
pending.putExtra("message_id", messageId);
|
pending.putExtra("message_id", messageId);
|
||||||
|
pending.putExtra("upgraded", upgraded);
|
||||||
|
|
||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
@ -73,24 +73,27 @@ public class PushTransport extends BaseTransport {
|
|||||||
try {
|
try {
|
||||||
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||||
Recipient recipient = message.getIndividualRecipient();
|
Recipient recipient = message.getIndividualRecipient();
|
||||||
|
long threadId = message.getThreadId();
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
||||||
PushDestination destination = PushDestination.create(context, credentials,
|
PushDestination destination = PushDestination.create(context, credentials,
|
||||||
recipient.getNumber());
|
recipient.getNumber());
|
||||||
|
|
||||||
String plaintextBody = message.getBody().getBody();
|
String plaintextBody = message.getBody().getBody();
|
||||||
byte[] plaintext = PushMessageContent.newBuilder().setBody(plaintextBody).build().toByteArray();
|
byte[] plaintext = PushMessageContent.newBuilder().setBody(plaintextBody).build().toByteArray();
|
||||||
PushBody pushBody = getEncryptedMessage(socket, recipient, destination, plaintext);
|
PushBody pushBody = getEncryptedMessage(socket, threadId, recipient, destination, plaintext);
|
||||||
|
|
||||||
socket.sendMessage(destination, pushBody);
|
socket.sendMessage(destination, pushBody);
|
||||||
|
|
||||||
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType()));
|
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType(), true));
|
||||||
} catch (RateLimitException e) {
|
} catch (RateLimitException e) {
|
||||||
Log.w("PushTransport", e);
|
Log.w("PushTransport", e);
|
||||||
throw new IOException("Rate limit exceeded.");
|
throw new IOException("Rate limit exceeded.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deliver(SendReq message, List<PushDestination> destinations) throws IOException {
|
public void deliver(SendReq message, List<PushDestination> destinations, long threadId)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
||||||
@ -118,7 +121,7 @@ public class PushTransport extends BaseTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] plaintext = builder.build().toByteArray();
|
byte[] plaintext = builder.build().toByteArray();
|
||||||
PushBody pushBody = getEncryptedMessage(socket, recipients.getPrimaryRecipient(), destination, plaintext);
|
PushBody pushBody = getEncryptedMessage(socket, threadId, recipients.getPrimaryRecipient(), destination, plaintext);
|
||||||
|
|
||||||
pushBodies.add(pushBody);
|
pushBodies.add(pushBody);
|
||||||
}
|
}
|
||||||
@ -158,7 +161,7 @@ public class PushTransport extends BaseTransport {
|
|||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PushBody getEncryptedMessage(PushServiceSocket socket, Recipient recipient,
|
private PushBody getEncryptedMessage(PushServiceSocket socket, long threadId, Recipient recipient,
|
||||||
PushDestination pushDestination, byte[] plaintext)
|
PushDestination pushDestination, byte[] plaintext)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
@ -172,7 +175,7 @@ public class PushTransport extends BaseTransport {
|
|||||||
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||||
} else {
|
} else {
|
||||||
Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session...");
|
Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session...");
|
||||||
byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, pushDestination, plaintext);
|
byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, threadId, recipient, pushDestination, plaintext);
|
||||||
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,6 +193,7 @@ public class PushTransport extends BaseTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getEncryptedPrekeyBundleMessageForNewSession(PushServiceSocket socket,
|
private byte[] getEncryptedPrekeyBundleMessageForNewSession(PushServiceSocket socket,
|
||||||
|
long threadId,
|
||||||
Recipient recipient,
|
Recipient recipient,
|
||||||
PushDestination pushDestination,
|
PushDestination pushDestination,
|
||||||
byte[] plaintext)
|
byte[] plaintext)
|
||||||
@ -200,7 +204,7 @@ public class PushTransport extends BaseTransport {
|
|||||||
PreKeyEntity preKey = socket.getPreKey(pushDestination);
|
PreKeyEntity preKey = socket.getPreKey(pushDestination);
|
||||||
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
||||||
|
|
||||||
processor.processKeyExchangeMessage(preKey);
|
processor.processKeyExchangeMessage(preKey, threadId);
|
||||||
|
|
||||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair);
|
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair);
|
||||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, plaintext);
|
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, plaintext);
|
||||||
|
@ -37,7 +37,6 @@ import org.whispersystems.textsecure.crypto.KeyUtil;
|
|||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||||
import org.whispersystems.textsecure.crypto.ecc.Curve;
|
import org.whispersystems.textsecure.crypto.ecc.Curve;
|
||||||
import org.whispersystems.textsecure.crypto.ecc.ECPublicKey;
|
|
||||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ public class SmsTransport extends BaseTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<String> messages = multipartMessageHandler.divideMessage(transportMessage);
|
ArrayList<String> messages = multipartMessageHandler.divideMessage(transportMessage);
|
||||||
ArrayList<PendingIntent> sentIntents = constructSentIntents(message.getId(), message.getType(), messages);
|
ArrayList<PendingIntent> sentIntents = constructSentIntents(message.getId(), message.getType(), messages, true);
|
||||||
ArrayList<PendingIntent> deliveredIntents = constructDeliveredIntents(message.getId(), message.getType(), messages);
|
ArrayList<PendingIntent> deliveredIntents = constructDeliveredIntents(message.getId(), message.getType(), messages);
|
||||||
|
|
||||||
Log.w("SmsTransport", "Secure divide into message parts: " + messages.size());
|
Log.w("SmsTransport", "Secure divide into message parts: " + messages.size());
|
||||||
@ -103,7 +102,7 @@ public class SmsTransport extends BaseTransport {
|
|||||||
throws UndeliverableMessageException
|
throws UndeliverableMessageException
|
||||||
{
|
{
|
||||||
ArrayList<String> messages = SmsManager.getDefault().divideMessage(message.getBody().getBody());
|
ArrayList<String> messages = SmsManager.getDefault().divideMessage(message.getBody().getBody());
|
||||||
ArrayList<PendingIntent> sentIntents = constructSentIntents(message.getId(), message.getType(), messages);
|
ArrayList<PendingIntent> sentIntents = constructSentIntents(message.getId(), message.getType(), messages, false);
|
||||||
ArrayList<PendingIntent> deliveredIntents = constructDeliveredIntents(message.getId(), message.getType(), messages);
|
ArrayList<PendingIntent> deliveredIntents = constructDeliveredIntents(message.getId(), message.getType(), messages);
|
||||||
String recipient = message.getIndividualRecipient().getNumber();
|
String recipient = message.getIndividualRecipient().getNumber();
|
||||||
|
|
||||||
@ -132,12 +131,14 @@ public class SmsTransport extends BaseTransport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<PendingIntent> constructSentIntents(long messageId, long type, ArrayList<String> messages) {
|
private ArrayList<PendingIntent> constructSentIntents(long messageId, long type,
|
||||||
|
ArrayList<String> messages, boolean secure)
|
||||||
|
{
|
||||||
ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messages.size());
|
ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messages.size());
|
||||||
|
|
||||||
for (String ignored : messages) {
|
for (String ignored : messages) {
|
||||||
sentIntents.add(PendingIntent.getBroadcast(context, 0,
|
sentIntents.add(PendingIntent.getBroadcast(context, 0,
|
||||||
constructSentIntent(context, messageId, type),
|
constructSentIntent(context, messageId, type, secure),
|
||||||
0));
|
0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,9 @@ public class UniversalTransport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<byte[], Integer> deliver(SendReq mediaMessage) throws UndeliverableMessageException {
|
public Pair<byte[], Integer> deliver(SendReq mediaMessage, long threadId)
|
||||||
|
throws UndeliverableMessageException
|
||||||
|
{
|
||||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||||
return mmsTransport.deliver(mediaMessage);
|
return mmsTransport.deliver(mediaMessage);
|
||||||
}
|
}
|
||||||
@ -86,7 +88,7 @@ public class UniversalTransport {
|
|||||||
if (isPushTransport(destinations)) {
|
if (isPushTransport(destinations)) {
|
||||||
try {
|
try {
|
||||||
Log.w("UniversalTransport", "Delivering media message with GCM...");
|
Log.w("UniversalTransport", "Delivering media message with GCM...");
|
||||||
pushTransport.deliver(mediaMessage, destinations);
|
pushTransport.deliver(mediaMessage, destinations, threadId);
|
||||||
return new Pair<byte[], Integer>("push".getBytes("UTF-8"), 0);
|
return new Pair<byte[], Integer>("push".getBytes("UTF-8"), 0);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
Log.w("UniversalTransport", ioe);
|
Log.w("UniversalTransport", ioe);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user