use of android.util.Base64 in project kdeconnect-android by KDE.
the class SmsMmsUtils method sendMessage.
/**
* Sends SMS or MMS message.
*
* @param context context in which the method is called.
* @param textMessage text body of the message to be sent.
* @param addressList List of addresses.
* @param attachedFiles List of attachments. Pass empty list if none.
* @param subID Note that here subID is of type int and not long because klinker library requires it as int
* I don't really know the exact reason why they implemented it as int instead of long
*/
public static void sendMessage(Context context, String textMessage, @NonNull List<SMSHelper.Attachment> attachedFiles, List<SMSHelper.Address> addressList, int subID) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean longTextAsMms = prefs.getBoolean(context.getString(R.string.set_long_text_as_mms), false);
boolean groupMessageAsMms = prefs.getBoolean(context.getString(R.string.set_group_message_as_mms), true);
int sendLongAsMmsAfter = Integer.parseInt(prefs.getString(context.getString(R.string.convert_to_mms_after), context.getString(R.string.convert_to_mms_after_default)));
TelephonyHelper.LocalPhoneNumber sendingPhoneNumber;
List<TelephonyHelper.LocalPhoneNumber> allPhoneNumbers = TelephonyHelper.getAllPhoneNumbers(context);
Optional<TelephonyHelper.LocalPhoneNumber> maybeSendingPhoneNumber = allPhoneNumbers.stream().filter(localPhoneNumber -> localPhoneNumber.subscriptionID == subID).findAny();
if (maybeSendingPhoneNumber.isPresent()) {
sendingPhoneNumber = maybeSendingPhoneNumber.get();
} else {
if (allPhoneNumbers.isEmpty()) {
// We were not able to get any phone number for the user's device
// Use a null "dummy" number instead. This should behave the same as not setting
// the FromAddress (below) since the default value there is null.
// The only more-correct thing we could do here is query the user (maybe in a
// persistent configuration) for their phone number(s).
sendingPhoneNumber = new TelephonyHelper.LocalPhoneNumber(null, subID);
Log.w(SENDING_MESSAGE, "We do not know *any* phone numbers for this device. " + "Attempting to send a message without knowing the local phone number is likely " + "to result in strange behavior, such as the message being sent to yourself, " + "or might entirely fail to send (or be received).");
} else {
// Pick an arbitrary phone number
sendingPhoneNumber = allPhoneNumbers.get(0);
}
Log.w(SENDING_MESSAGE, "Unable to determine correct outgoing address for sub ID " + subID + ". Using " + sendingPhoneNumber);
}
if (sendingPhoneNumber.number != null) {
// If the message is going to more than one target (to allow the user to send a message to themselves)
if (addressList.size() > 1) {
// Remove the user's phone number if present in the list of recipients
addressList.removeIf(address -> sendingPhoneNumber.isMatchingPhoneNumber(address.address));
}
}
try {
Settings settings = new Settings();
TelephonyHelper.ApnSetting apnSettings = TelephonyHelper.getPreferredApn(context, subID);
if (apnSettings != null) {
settings.setMmsc(apnSettings.getMmsc().toString());
settings.setProxy(apnSettings.getMmsProxyAddressAsString());
settings.setPort(Integer.toString(apnSettings.getMmsProxyPort()));
} else {
settings.setUseSystemSending(true);
}
settings.setSendLongAsMms(longTextAsMms);
settings.setSendLongAsMmsAfter(sendLongAsMmsAfter);
settings.setGroup(groupMessageAsMms);
if (subID != -1) {
settings.setSubscriptionId(subID);
}
Transaction transaction = new Transaction(context, settings);
List<String> addresses = new ArrayList<>();
for (SMSHelper.Address address : addressList) {
addresses.add(address.toString());
}
Message message = new Message(textMessage, addresses.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
// If there are any attachment files add those into the message
for (SMSHelper.Attachment attachedFile : attachedFiles) {
byte[] file = Base64.decode(attachedFile.getBase64EncodedFile(), Base64.DEFAULT);
String mimeType = attachedFile.getMimeType();
String fileName = attachedFile.getUniqueIdentifier();
message.addMedia(file, mimeType, fileName);
}
message.setFromAddress(sendingPhoneNumber.number);
message.setSave(true);
// This is the reason why there are separate branch handling for SMS and MMS.
if (transaction.checkMMS(message)) {
Log.v("", "Sending new MMS");
// transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
sendMmsMessageNative(context, message, settings);
} else {
// Cross fingers and hope Klinker's library works for this case
transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
}
} else {
Log.v(SENDING_MESSAGE, "Sending new SMS");
transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
}
// TODO: Notify other end
} catch (Exception e) {
// TODO: Notify other end
Log.e(SENDING_MESSAGE, "Exception", e);
}
}
use of android.util.Base64 in project kdeconnect-android by KDE.
the class LanLinkProvider method identityPacketReceived.
/**
* Called when a new 'identity' packet is received. Those are passed here by
* {@link #tcpPacketReceived(Socket)} and {@link #udpPacketReceived(DatagramPacket)}.
* <p>
* If the remote device should be connected, this calls {@link #addLink}.
* Otherwise, if there was an Exception, we unpair from that device.
* </p>
*
* @param identityPacket identity of a remote device
* @param socket a new Socket, which should be used to receive packets from the remote device
* @param connectionStarted which side started this connection
*/
private void identityPacketReceived(final NetworkPacket identityPacket, final Socket socket, final LanLink.ConnectionStarted connectionStarted) {
String myId = DeviceHelper.getDeviceId(context);
final String deviceId = identityPacket.getString("deviceId");
if (deviceId.equals(myId)) {
Log.e("KDE/LanLinkProvider", "Somehow I'm connected to myself, ignoring. This should not happen.");
return;
}
// If I'm the TCP server I will be the SSL client and viceversa.
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
// Do the SSL handshake
try {
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
// Device paired with and old version, we can't use it as we lack the certificate
BackgroundService.RunCommand(context, service -> {
Device device = service.getDevice(deviceId);
if (device == null)
return;
device.unpair();
// Retry as unpaired
identityPacketReceived(identityPacket, socket, connectionStarted);
});
}
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + identityPacket.getString("deviceName") + " trusted:" + isDeviceTrusted);
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
sslsocket.addHandshakeCompletedListener(event -> {
String mode = clientMode ? "client" : "server";
try {
Certificate certificate = event.getPeerCertificates()[0];
identityPacket.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + identityPacket.getString("deviceName") + " secured with " + event.getCipherSuite());
addLink(identityPacket, sslsocket, connectionStarted);
} catch (Exception e) {
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + identityPacket.getString("deviceName"), e);
BackgroundService.RunCommand(context, service -> {
Device device = service.getDevice(deviceId);
if (device == null)
return;
device.unpair();
});
}
});
// Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
new Thread(() -> {
try {
synchronized (this) {
sslsocket.startHandshake();
}
} catch (Exception e) {
Log.e("KDE/LanLinkProvider", "Handshake failed with " + identityPacket.getString("deviceName"), e);
// String[] ciphers = sslsocket.getSupportedCipherSuites();
// for (String cipher : ciphers) {
// Log.i("SupportedCiphers","cipher: " + cipher);
// }
}
}).start();
} catch (Exception e) {
Log.e("LanLink", "Exception", e);
}
}
Aggregations