mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 09:49:30 +01:00
Move all files to natural position.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingEncryptedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingEncryptedMessage(IncomingTextMessage base, String newBody) {
|
||||
super(base, newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingTextMessage withMessageBody(String body) {
|
||||
return new IncomingEncryptedMessage(this, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecureMessage() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingEndSessionMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingEndSessionMessage(IncomingTextMessage base) {
|
||||
this(base, base.getMessageBody());
|
||||
}
|
||||
|
||||
public IncomingEndSessionMessage(IncomingTextMessage base, String newBody) {
|
||||
super(base, newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingEndSessionMessage withMessageBody(String messageBody) {
|
||||
return new IncomingEndSessionMessage(this, messageBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEndSession() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
public class IncomingGroupMessage extends IncomingTextMessage {
|
||||
|
||||
private final GroupContext groupContext;
|
||||
|
||||
public IncomingGroupMessage(IncomingTextMessage base, GroupContext groupContext, String body) {
|
||||
super(base, body);
|
||||
this.groupContext = groupContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingGroupMessage withMessageBody(String body) {
|
||||
return new IncomingGroupMessage(this, groupContext, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGroup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isUpdate() {
|
||||
return groupContext.getType().getNumber() == GroupContext.Type.UPDATE_VALUE;
|
||||
}
|
||||
|
||||
public boolean isQuit() {
|
||||
return groupContext.getType().getNumber() == GroupContext.Type.QUIT_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
public class IncomingIdentityDefaultMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityDefaultMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingIdentityUpdateMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityUpdateMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
public class IncomingIdentityVerifiedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityVerifiedMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityVerified() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
public class IncomingJoinedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingJoinedMessage(RecipientId sender) {
|
||||
super(sender, 1, System.currentTimeMillis(), null, Optional.absent(), 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJoined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecureMessage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingPreKeyBundleMessage extends IncomingTextMessage {
|
||||
|
||||
private final boolean legacy;
|
||||
|
||||
public IncomingPreKeyBundleMessage(IncomingTextMessage base, String newBody, boolean legacy) {
|
||||
super(base, newBody);
|
||||
this.legacy = legacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingPreKeyBundleMessage withMessageBody(String messageBody) {
|
||||
return new IncomingPreKeyBundleMessage(this, messageBody, legacy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacyPreKeyBundle() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContentPreKeyBundle() {
|
||||
return !legacy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telephony.SmsMessage;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class IncomingTextMessage implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<IncomingTextMessage> CREATOR = new Parcelable.Creator<IncomingTextMessage>() {
|
||||
@Override
|
||||
public IncomingTextMessage createFromParcel(Parcel in) {
|
||||
return new IncomingTextMessage(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingTextMessage[] newArray(int size) {
|
||||
return new IncomingTextMessage[size];
|
||||
}
|
||||
};
|
||||
private static final String TAG = IncomingTextMessage.class.getSimpleName();
|
||||
|
||||
private final String message;
|
||||
private RecipientId sender;
|
||||
private final int senderDeviceId;
|
||||
private final int protocol;
|
||||
private final String serviceCenterAddress;
|
||||
private final boolean replyPathPresent;
|
||||
private final String pseudoSubject;
|
||||
private final long sentTimestampMillis;
|
||||
private final String groupId;
|
||||
private final boolean push;
|
||||
private final int subscriptionId;
|
||||
private final long expiresInMillis;
|
||||
private final boolean unidentified;
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender, @NonNull SmsMessage message, int subscriptionId) {
|
||||
this.message = message.getDisplayMessageBody();
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = message.getProtocolIdentifier();
|
||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||
this.replyPathPresent = message.isReplyPathPresent();
|
||||
this.pseudoSubject = message.getPseudoSubject();
|
||||
this.sentTimestampMillis = message.getTimestampMillis();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresInMillis = 0;
|
||||
this.groupId = null;
|
||||
this.push = false;
|
||||
this.unidentified = false;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender, int senderDeviceId, long sentTimestampMillis,
|
||||
String encodedBody, Optional<String> groupId,
|
||||
long expiresInMillis, boolean unidentified)
|
||||
{
|
||||
this.message = encodedBody;
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = senderDeviceId;
|
||||
this.protocol = 31337;
|
||||
this.serviceCenterAddress = "GCM";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = sentTimestampMillis;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = expiresInMillis;
|
||||
this.unidentified = unidentified;
|
||||
this.groupId = groupId.orNull();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(Parcel in) {
|
||||
this.message = in.readString();
|
||||
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.senderDeviceId = in.readInt();
|
||||
this.protocol = in.readInt();
|
||||
this.serviceCenterAddress = in.readString();
|
||||
this.replyPathPresent = (in.readInt() == 1);
|
||||
this.pseudoSubject = in.readString();
|
||||
this.sentTimestampMillis = in.readLong();
|
||||
this.groupId = in.readString();
|
||||
this.push = (in.readInt() == 1);
|
||||
this.subscriptionId = in.readInt();
|
||||
this.expiresInMillis = in.readLong();
|
||||
this.unidentified = in.readInt() == 1;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
||||
this.message = newBody;
|
||||
this.sender = base.getSender();
|
||||
this.senderDeviceId = base.getSenderDeviceId();
|
||||
this.protocol = base.getProtocol();
|
||||
this.serviceCenterAddress = base.getServiceCenterAddress();
|
||||
this.replyPathPresent = base.isReplyPathPresent();
|
||||
this.pseudoSubject = base.getPseudoSubject();
|
||||
this.sentTimestampMillis = base.getSentTimestampMillis();
|
||||
this.groupId = base.getGroupId();
|
||||
this.push = base.isPush();
|
||||
this.subscriptionId = base.getSubscriptionId();
|
||||
this.expiresInMillis = base.getExpiresIn();
|
||||
this.unidentified = base.isUnidentified();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
||||
for (IncomingTextMessage message : fragments) {
|
||||
body.append(message.getMessageBody());
|
||||
}
|
||||
|
||||
this.message = body.toString();
|
||||
this.sender = fragments.get(0).getSender();
|
||||
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
|
||||
this.protocol = fragments.get(0).getProtocol();
|
||||
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
|
||||
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
|
||||
this.pseudoSubject = fragments.get(0).getPseudoSubject();
|
||||
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
||||
this.groupId = fragments.get(0).getGroupId();
|
||||
this.push = fragments.get(0).isPush();
|
||||
this.subscriptionId = fragments.get(0).getSubscriptionId();
|
||||
this.expiresInMillis = fragments.get(0).getExpiresIn();
|
||||
this.unidentified = fragments.get(0).isUnidentified();
|
||||
}
|
||||
|
||||
protected IncomingTextMessage(@NonNull RecipientId sender, @Nullable String groupId)
|
||||
{
|
||||
this.message = "";
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = 31338;
|
||||
this.serviceCenterAddress = "Outgoing";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = System.currentTimeMillis();
|
||||
this.groupId = groupId;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = 0;
|
||||
this.unidentified = false;
|
||||
}
|
||||
|
||||
public int getSubscriptionId() {
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
public long getExpiresIn() {
|
||||
return expiresInMillis;
|
||||
}
|
||||
|
||||
public long getSentTimestampMillis() {
|
||||
return sentTimestampMillis;
|
||||
}
|
||||
|
||||
public String getPseudoSubject() {
|
||||
return pseudoSubject;
|
||||
}
|
||||
|
||||
public String getMessageBody() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public IncomingTextMessage withMessageBody(String message) {
|
||||
return new IncomingTextMessage(this, message);
|
||||
}
|
||||
|
||||
public RecipientId getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public int getSenderDeviceId() {
|
||||
return senderDeviceId;
|
||||
}
|
||||
|
||||
public int getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public String getServiceCenterAddress() {
|
||||
return serviceCenterAddress;
|
||||
}
|
||||
|
||||
public boolean isReplyPathPresent() {
|
||||
return replyPathPresent;
|
||||
}
|
||||
|
||||
public boolean isSecureMessage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPreKeyBundle() {
|
||||
return isLegacyPreKeyBundle() || isContentPreKeyBundle();
|
||||
}
|
||||
|
||||
public boolean isLegacyPreKeyBundle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isContentPreKeyBundle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEndSession() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPush() {
|
||||
return push;
|
||||
}
|
||||
|
||||
public @Nullable String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isJoined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityVerified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUnidentified() {
|
||||
return unidentified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(message);
|
||||
out.writeParcelable(sender, flags);
|
||||
out.writeInt(senderDeviceId);
|
||||
out.writeInt(protocol);
|
||||
out.writeString(serviceCenterAddress);
|
||||
out.writeInt(replyPathPresent ? 1 : 0);
|
||||
out.writeString(pseudoSubject);
|
||||
out.writeLong(sentTimestampMillis);
|
||||
out.writeString(groupId);
|
||||
out.writeInt(push ? 1 : 0);
|
||||
out.writeInt(subscriptionId);
|
||||
out.writeLong(expiresInMillis);
|
||||
out.writeInt(unidentified ? 1 : 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId;
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentCopyJob;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentCompressionJob;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob;
|
||||
import org.thoughtcrime.securesms.jobs.MmsSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushMediaSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushTextSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.ReactionSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MessageSender {
|
||||
|
||||
private static final String TAG = MessageSender.class.getSimpleName();
|
||||
|
||||
public static long send(final Context context,
|
||||
final OutgoingTextMessage message,
|
||||
final long threadId,
|
||||
final boolean forceSms,
|
||||
final SmsDatabase.InsertListener insertListener)
|
||||
{
|
||||
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
Recipient recipient = message.getRecipient();
|
||||
boolean keyExchange = message.isKeyExchange();
|
||||
|
||||
long allocatedThreadId;
|
||||
|
||||
if (threadId == -1) {
|
||||
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
} else {
|
||||
allocatedThreadId = threadId;
|
||||
}
|
||||
|
||||
long messageId = database.insertMessageOutbox(allocatedThreadId, message, forceSms, System.currentTimeMillis(), insertListener);
|
||||
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
|
||||
|
||||
return allocatedThreadId;
|
||||
}
|
||||
|
||||
public static long send(final Context context,
|
||||
final OutgoingMediaMessage message,
|
||||
final long threadId,
|
||||
final boolean forceSms,
|
||||
final SmsDatabase.InsertListener insertListener)
|
||||
{
|
||||
try {
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
|
||||
long allocatedThreadId;
|
||||
|
||||
if (threadId == -1) {
|
||||
allocatedThreadId = threadDatabase.getThreadIdFor(message.getRecipient(), message.getDistributionType());
|
||||
} else {
|
||||
allocatedThreadId = threadId;
|
||||
}
|
||||
|
||||
Recipient recipient = message.getRecipient();
|
||||
long messageId = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener);
|
||||
|
||||
sendMediaMessage(context, recipient, forceSms, messageId, message.getExpiresIn());
|
||||
|
||||
return allocatedThreadId;
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, e);
|
||||
return threadId;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendMediaBroadcast(@NonNull Context context, @NonNull List<OutgoingSecureMediaMessage> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
Log.w(TAG, "sendMediaBroadcast() - No messages!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidBroadcastList(messages)) {
|
||||
Log.w(TAG, "sendMediaBroadcast() - Invalid message list!");
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||
List<List<DatabaseAttachment>> databaseAttachments = new ArrayList<>(messages.get(0).getAttachments().size());
|
||||
List<Long> messageIds = new ArrayList<>(messages.size());
|
||||
|
||||
for (int i = 0; i < messages.get(0).getAttachments().size(); i++) {
|
||||
databaseAttachments.add(new ArrayList<>(messages.size()));
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
mmsDatabase.beginTransaction();
|
||||
|
||||
for (OutgoingSecureMediaMessage message : messages) {
|
||||
long allocatedThreadId = threadDatabase.getThreadIdFor(message.getRecipient(), message.getDistributionType());
|
||||
long messageId = mmsDatabase.insertMessageOutbox(message, allocatedThreadId, false, null);
|
||||
List<DatabaseAttachment> attachments = attachmentDatabase.getAttachmentsForMessage(messageId);
|
||||
|
||||
if (attachments.size() != databaseAttachments.size()) {
|
||||
Log.w(TAG, "Got back an attachment list that was a different size than expected. Expected: " + databaseAttachments.size() + " Actual: "+ attachments.size());
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < attachments.size(); i++) {
|
||||
databaseAttachments.get(i).add(attachments.get(i));
|
||||
}
|
||||
|
||||
messageIds.add(messageId);
|
||||
}
|
||||
|
||||
mmsDatabase.setTransactionSuccessful();
|
||||
} finally {
|
||||
mmsDatabase.endTransaction();
|
||||
}
|
||||
|
||||
List<Job> compressionJobs = new ArrayList<>(databaseAttachments.size());
|
||||
List<Job> uploadJobs = new ArrayList<>(databaseAttachments.size());
|
||||
List<Job> copyJobs = new ArrayList<>(databaseAttachments.size());
|
||||
List<Job> messageJobs = new ArrayList<>(databaseAttachments.get(0).size());
|
||||
|
||||
for (List<DatabaseAttachment> attachmentList : databaseAttachments) {
|
||||
DatabaseAttachment source = attachmentList.get(0);
|
||||
|
||||
compressionJobs.add(AttachmentCompressionJob.fromAttachment(source, false, -1));
|
||||
|
||||
uploadJobs.add(new AttachmentUploadJob(source.getAttachmentId()));
|
||||
|
||||
if (attachmentList.size() > 1) {
|
||||
AttachmentId sourceId = source.getAttachmentId();
|
||||
List<AttachmentId> destinationIds = Stream.of(attachmentList.subList(1, attachmentList.size()))
|
||||
.map(DatabaseAttachment::getAttachmentId)
|
||||
.toList();
|
||||
|
||||
copyJobs.add(new AttachmentCopyJob(sourceId, destinationIds));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < messageIds.size(); i++) {
|
||||
long messageId = messageIds.get(i);
|
||||
OutgoingSecureMediaMessage message = messages.get(i);
|
||||
Recipient recipient = message.getRecipient();
|
||||
|
||||
if (isLocalSelfSend(context, recipient, false)) {
|
||||
sendLocalMediaSelf(context, messageId);
|
||||
} else if (isGroupPushSend(recipient)) {
|
||||
messageJobs.add(new PushGroupSendJob(messageId, recipient.getId(), null));
|
||||
} else {
|
||||
messageJobs.add(new PushMediaSendJob(messageId, recipient));
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, String.format(Locale.ENGLISH, "sendMediaBroadcast() - Uploading %d attachment(s), copying %d of them, then sending %d messages.",
|
||||
uploadJobs.size(),
|
||||
copyJobs.size(),
|
||||
messageJobs.size()));
|
||||
|
||||
JobManager.Chain chain = ApplicationDependencies.getJobManager()
|
||||
.startChain(compressionJobs)
|
||||
.then(uploadJobs);
|
||||
|
||||
if (copyJobs.size() > 0) {
|
||||
chain = chain.then(copyJobs);
|
||||
}
|
||||
|
||||
chain = chain.then(messageJobs);
|
||||
chain.enqueue();
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, "sendMediaBroadcast() - Failed to send messages!", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void sendNewReaction(@NonNull Context context, long messageId, boolean isMms, @NonNull String emoji) {
|
||||
MessagingDatabase db = isMms ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
||||
ReactionRecord reaction = new ReactionRecord(emoji, Recipient.self().getId(), System.currentTimeMillis(), System.currentTimeMillis());
|
||||
|
||||
db.addReaction(messageId, reaction);
|
||||
|
||||
try {
|
||||
ApplicationDependencies.getJobManager().add(ReactionSendJob.create(context, messageId, isMms, reaction, false));
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, "[sendNewReaction] Could not find message! Ignoring.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendReactionRemoval(@NonNull Context context, long messageId, boolean isMms, @NonNull ReactionRecord reaction) {
|
||||
MessagingDatabase db = isMms ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
||||
|
||||
db.deleteReaction(messageId, reaction.getAuthor());
|
||||
|
||||
try {
|
||||
ApplicationDependencies.getJobManager().add(ReactionSendJob.create(context, messageId, isMms, reaction, true));
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, "[sendReactionRemoval] Could not find message! Ignoring.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void resendGroupMessage(Context context, MessageRecord messageRecord, RecipientId filterRecipientId) {
|
||||
if (!messageRecord.isMms()) throw new AssertionError("Not Group");
|
||||
sendGroupPush(context, messageRecord.getRecipient(), messageRecord.getId(), filterRecipientId);
|
||||
}
|
||||
|
||||
public static void resend(Context context, MessageRecord messageRecord) {
|
||||
long messageId = messageRecord.getId();
|
||||
boolean forceSms = messageRecord.isForcedSms();
|
||||
boolean keyExchange = messageRecord.isKeyExchange();
|
||||
long expiresIn = messageRecord.getExpiresIn();
|
||||
Recipient recipient = messageRecord.getRecipient();
|
||||
|
||||
if (messageRecord.isMms()) {
|
||||
sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
|
||||
} else {
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendMediaMessage(Context context, Recipient recipient, boolean forceSms, long messageId, long expiresIn)
|
||||
{
|
||||
if (isLocalSelfSend(context, recipient, forceSms)) {
|
||||
sendLocalMediaSelf(context, messageId);
|
||||
} else if (isGroupPushSend(recipient)) {
|
||||
sendGroupPush(context, recipient, messageId, null);
|
||||
} else if (!forceSms && isPushMediaSend(context, recipient)) {
|
||||
sendMediaPush(context, recipient, messageId);
|
||||
} else {
|
||||
sendMms(context, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendTextMessage(Context context, Recipient recipient,
|
||||
boolean forceSms, boolean keyExchange,
|
||||
long messageId)
|
||||
{
|
||||
if (isLocalSelfSend(context, recipient, forceSms)) {
|
||||
sendLocalTextSelf(context, messageId);
|
||||
} else if (!forceSms && isPushTextSend(context, recipient, keyExchange)) {
|
||||
sendTextPush(context, recipient, messageId);
|
||||
} else {
|
||||
sendSms(context, recipient, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
jobManager.add(new PushTextSendJob(messageId, recipient));
|
||||
}
|
||||
|
||||
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, recipient);
|
||||
}
|
||||
|
||||
private static void sendGroupPush(Context context, Recipient recipient, long messageId, RecipientId filterRecipientId) {
|
||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
PushGroupSendJob.enqueue(context, jobManager, messageId, recipient.getId(), filterRecipientId);
|
||||
}
|
||||
|
||||
private static void sendSms(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
jobManager.add(new SmsSendJob(context, messageId, recipient));
|
||||
}
|
||||
|
||||
private static void sendMms(Context context, long messageId) {
|
||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
MmsSendJob.enqueue(context, jobManager, messageId);
|
||||
}
|
||||
|
||||
private static boolean isPushTextSend(Context context, Recipient recipient, boolean keyExchange) {
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyExchange) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipient);
|
||||
}
|
||||
|
||||
private static boolean isPushMediaSend(Context context, Recipient recipient) {
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipient.isGroup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipient);
|
||||
}
|
||||
|
||||
private static boolean isGroupPushSend(Recipient recipient) {
|
||||
return recipient.isGroup() && !recipient.isMmsGroup();
|
||||
}
|
||||
|
||||
private static boolean isPushDestination(Context context, Recipient destination) {
|
||||
if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
||||
return true;
|
||||
} else if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
RecipientDatabase.RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, destination, false);
|
||||
return state == RecipientDatabase.RegisteredState.REGISTERED;
|
||||
} catch (IOException e1) {
|
||||
Log.w(TAG, e1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLocalSelfSend(@NonNull Context context, @NonNull Recipient recipient, boolean forceSms) {
|
||||
return recipient.isLocalNumber() &&
|
||||
!forceSms &&
|
||||
TextSecurePreferences.isPushRegistered(context) &&
|
||||
!TextSecurePreferences.isMultiDevice(context);
|
||||
}
|
||||
|
||||
private static void sendLocalMediaSelf(Context context, long messageId) {
|
||||
try {
|
||||
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
|
||||
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
OutgoingMediaMessage message = mmsDatabase.getOutgoingMessage(messageId);
|
||||
SyncMessageId syncId = new SyncMessageId(Recipient.self().getId(), message.getSentTimeMillis());
|
||||
|
||||
for (Attachment attachment : message.getAttachments()) {
|
||||
attachmentDatabase.markAttachmentUploaded(messageId, attachment);
|
||||
}
|
||||
|
||||
mmsDatabase.markAsSent(messageId, true);
|
||||
mmsDatabase.markUnidentified(messageId, true);
|
||||
|
||||
mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
|
||||
mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
|
||||
|
||||
if (message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
|
||||
mmsDatabase.markExpireStarted(messageId);
|
||||
expirationManager.scheduleDeletion(messageId, true, message.getExpiresIn());
|
||||
}
|
||||
} catch (NoSuchMessageException | MmsException e) {
|
||||
Log.w("Failed to update self-sent message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendLocalTextSelf(Context context, long messageId) {
|
||||
try {
|
||||
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
SmsMessageRecord message = smsDatabase.getMessage(messageId);
|
||||
SyncMessageId syncId = new SyncMessageId(Recipient.self().getId(), message.getDateSent());
|
||||
|
||||
smsDatabase.markAsSent(messageId, true);
|
||||
smsDatabase.markUnidentified(messageId, true);
|
||||
|
||||
mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
|
||||
mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
|
||||
|
||||
if (message.getExpiresIn() > 0) {
|
||||
smsDatabase.markExpireStarted(messageId);
|
||||
expirationManager.scheduleDeletion(message.getId(), message.isMms(), message.getExpiresIn());
|
||||
}
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w("Failed to update self-sent message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidBroadcastList(@NonNull List<OutgoingSecureMediaMessage> messages) {
|
||||
if (messages.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int attachmentSize = messages.get(0).getAttachments().size();
|
||||
|
||||
for (OutgoingSecureMediaMessage message : messages) {
|
||||
if (message.getAttachments().size() != attachmentSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingEncryptedMessage(Recipient recipient, String body, long expiresIn) {
|
||||
super(recipient, body, expiresIn, -1);
|
||||
}
|
||||
|
||||
private OutgoingEncryptedMessage(OutgoingEncryptedMessage base, String body) {
|
||||
super(base, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecureMessage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingEncryptedMessage(this, body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class OutgoingEndSessionMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingEndSessionMessage(OutgoingTextMessage base) {
|
||||
this(base, base.getMessageBody());
|
||||
}
|
||||
|
||||
public OutgoingEndSessionMessage(OutgoingTextMessage message, String body) {
|
||||
super(message, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEndSession() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingEndSessionMessage(this, body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingIdentityDefaultMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingIdentityDefaultMessage(Recipient recipient) {
|
||||
this(recipient, "");
|
||||
}
|
||||
|
||||
private OutgoingIdentityDefaultMessage(Recipient recipient, String body) {
|
||||
super(recipient, body, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingIdentityDefaultMessage(getRecipient());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingIdentityVerifiedMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingIdentityVerifiedMessage(Recipient recipient) {
|
||||
this(recipient, "");
|
||||
}
|
||||
|
||||
private OutgoingIdentityVerifiedMessage(Recipient recipient, String body) {
|
||||
super(recipient, body, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityVerified() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingIdentityVerifiedMessage(getRecipient(), body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingKeyExchangeMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingKeyExchangeMessage(Recipient recipient, String message) {
|
||||
super(recipient, message, -1);
|
||||
}
|
||||
|
||||
private OutgoingKeyExchangeMessage(OutgoingKeyExchangeMessage base, String body) {
|
||||
super(base, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKeyExchange() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingKeyExchangeMessage(this, body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
public class OutgoingPrekeyBundleMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingPrekeyBundleMessage(OutgoingTextMessage message, String body) {
|
||||
super(message, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreKeyBundle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingPrekeyBundleMessage(this, body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingTextMessage {
|
||||
|
||||
private final Recipient recipient;
|
||||
private final String message;
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
|
||||
public OutgoingTextMessage(Recipient recipient, String message, int subscriptionId) {
|
||||
this(recipient, message, 0, subscriptionId);
|
||||
}
|
||||
|
||||
public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId) {
|
||||
this.recipient = recipient;
|
||||
this.message = message;
|
||||
this.expiresIn = expiresIn;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
protected OutgoingTextMessage(OutgoingTextMessage base, String body) {
|
||||
this.recipient = base.getRecipient();
|
||||
this.subscriptionId = base.getSubscriptionId();
|
||||
this.expiresIn = base.getExpiresIn();
|
||||
this.message = body;
|
||||
}
|
||||
|
||||
public long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public int getSubscriptionId() {
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
public String getMessageBody() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public boolean isKeyExchange() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSecureMessage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEndSession() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPreKeyBundle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityVerified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static OutgoingTextMessage from(SmsMessageRecord record) {
|
||||
if (record.isSecure()) {
|
||||
return new OutgoingEncryptedMessage(record.getRecipient(), record.getBody(), record.getExpiresIn());
|
||||
} else if (record.isKeyExchange()) {
|
||||
return new OutgoingKeyExchangeMessage(record.getRecipient(), record.getBody());
|
||||
} else if (record.isEndSession()) {
|
||||
return new OutgoingEndSessionMessage(new OutgoingTextMessage(record.getRecipient(), record.getBody(), 0, -1));
|
||||
} else {
|
||||
return new OutgoingTextMessage(record.getRecipient(), record.getBody(), record.getExpiresIn(), record.getSubscriptionId());
|
||||
}
|
||||
}
|
||||
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingTextMessage(this, body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
public class TelephonyServiceState {
|
||||
|
||||
public boolean isConnected(Context context) {
|
||||
ListenThread listenThread = new ListenThread(context);
|
||||
listenThread.start();
|
||||
|
||||
return listenThread.get();
|
||||
}
|
||||
|
||||
private static class ListenThread extends Thread {
|
||||
|
||||
private final Context context;
|
||||
|
||||
private boolean complete;
|
||||
private boolean result;
|
||||
|
||||
public ListenThread(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Looper looper = initializeLooper();
|
||||
ListenCallback callback = new ListenCallback(looper);
|
||||
|
||||
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
telephonyManager.listen(callback, PhoneStateListener.LISTEN_SERVICE_STATE);
|
||||
|
||||
Looper.loop();
|
||||
|
||||
telephonyManager.listen(callback, PhoneStateListener.LISTEN_NONE);
|
||||
|
||||
set(callback.isConnected());
|
||||
}
|
||||
|
||||
private Looper initializeLooper() {
|
||||
Looper looper = Looper.myLooper();
|
||||
|
||||
if (looper == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
return Looper.myLooper();
|
||||
}
|
||||
|
||||
public synchronized boolean get() {
|
||||
while (!complete) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private synchronized void set(boolean result) {
|
||||
this.result = result;
|
||||
this.complete = true;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListenCallback extends PhoneStateListener {
|
||||
|
||||
private final Looper looper;
|
||||
private volatile boolean connected;
|
||||
|
||||
public ListenCallback(Looper looper) {
|
||||
this.looper = looper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(ServiceState serviceState) {
|
||||
this.connected = (serviceState.getState() == ServiceState.STATE_IN_SERVICE);
|
||||
looper.quit();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user