В итоге я написал собственную функцию отправки / кодирования электронной почты. Это хорошо сработало для отправки PDF-вложений. Я не использовал другие функции в производстве.
Примечание. Несмотря на то, что спецификация достаточно решительно, что вы должны использовать\r\n для разделения заголовков, я нашел, что это работает только тогда, когда я использовал PHP_EOL. Я тестировал это только на Linux. YMMV
<?php
# $args must be an associative array
# required keys: from, to, body
# body can be a string or a [tree of] associative arrays. See examples below
# optional keys: subject, reply_to, cc, bcc
# EXAMPLES:
# # text-only email:
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/plain because we're passing a string that doesn't start with '<'
# 'body' => 'Hi, testing 1 2 3',
# ));
#
# # html-only email
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/html because we're passing a string that starts with '<'
# 'body' => '<h1>Hi!</h1>I like <a href="http://cheese.com">cheese</a>',
# ));
#
# # text-only email (explicitly, in case first character is dynamic or something)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/plain because we're passing a string that doesn't start with '<'
# 'body' => array(
# 'type' => 'text',
# 'body' => $message_text,
# )
# ));
#
# # email with text and html alternatives (auto-detected mime types)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'alternatives',
# 'body' => array(
# "Hi!\n\nI like cheese",
# '<h1>Hi!</h1><p>I like <a href="http://cheese.com">cheese</a></p>',
# )
# )
# ));
#
# # email with text and html alternatives (explicit types)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'alternatives',
# 'body' => array(
# array(
# 'type' => 'text',
# 'body' => "Hi!\n\nI like cheese",
# ),
# array(
# 'type' => 'html',
# 'body' => '<h1>Hi!</h1><p>I like cheese</p>',
# ),
# )
# )
# ));
#
# # email with an attachment
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'mixed',
# 'body' => array(
# "Hi!\n\nCheck out this (inline) image",
# array(
# 'type' => 'image/png',
# 'disposition' => 'inline',
# 'body' => $image_data, # raw file contents
# ),
# "Hi!\n\nAnd here's an attachment",
# array(
# 'type' => 'application/pdf; name="attachment.pdf"',
# 'disposition' => 'attachment; filename="attachment.pdf"',
# 'body' => $pdf_data, # raw file contents
# ),
# "Or you can use shorthand:",
# array(
# 'type' => 'application/pdf',
# 'attachment' => 'attachment.pdf', # name for client (not data source)
# 'body' => $pdf_data, # raw file contents
# ),
# )
# )
# ))
function email2($args) {
if (!isset($args['from'])) { return 1; }
$from = $args['from'];
if (!isset($args['to'])) { return 2; }
$to = $args['to'];
$subject = isset($args['subject']) ? $args['subject'] : '';
$reply_to = isset($args['reply_to']) ? $args['reply_to'] : '';
$cc = isset($args['cc']) ? $args['cc'] : '';
$bcc = isset($args['bcc']) ? $args['bcc'] : '';
#FIXME should allow many more characters here (and do Q encoding)
$subject = isset($args['subject']) ? $args['subject'] : '';
$subject = preg_replace("|[^a-z0-9 _/#'.:&,-]|i", '_', $subject);
$headers = "From: $from";
if($reply_to) {
$headers .= PHP_EOL . "Reply-To: $reply_to";
}
if($cc) {
$headers .= PHP_EOL . "CC: $cc";
}
if($bcc) {
$headers .= PHP_EOL . "BCC: $bcc";
}
$r = email2_helper($args['body']);
$headers .= PHP_EOL . $r[0];
$body = $r[1];
if (mail($to, $subject, $body, $headers)) {
return 0;
} else {
return 5;
}
}
function email2_helper($body, $top = true) {
if (is_string($body)) {
if (substr($body, 0, 1) == '<') {
return email2_helper(array('type' => 'html', 'body' => $body), $top);
} else {
return email2_helper(array('type' => 'text', 'body' => $body), $top);
}
}
# now we can assume $body is an associative array
# defaults:
$type = 'application/octet-stream';
$mime = false;
$boundary = null;
$disposition = null;
$charset = false;
# process 'type' first, because it sets defaults for others
if (isset($body['type'])) {
$type = $body['type'];
if ($type === 'text') {
$type = 'text/plain';
$charset = true;
} elseif ($type === 'html') {
$type = 'text/html';
$charset = true;
} elseif ($type === 'alternative' || $type === 'alternatives') {
$mime = true;
$type = 'multipart/alternative';
} elseif ($type === 'mixed') {
$mime = true;
$type = 'multipart/mixed';
}
}
if (isset($body['disposition'])) {
$disposition = $body['disposition'];
}
if (isset($body['attachment'])) {
if ($disposition == null) {
$disposition = 'attachment';
}
$disposition .= "; filename=\"{$body['attachment']}\"";
$type .= "; name=\"{$body['attachment']}\"";
}
# make headers
$headers = array();
if ($top && $mime) {
$headers[] = 'MIME-Version: 1.0';
}
if ($mime) {
$boundary = md5('5sd^%Ca)~aAfF0=4mIN' . rand() . rand());
$type .= "; boundary=$boundary";
}
if ($charset) {
$type .= '; charset=' . (isset($body['charset']) ? $body['charset'] : 'UTF-8');
}
$headers[] = "Content-Type: $type";
if ($disposition !== null) {
$headers[] = "Content-Disposition: {$disposition}";
}
$data = '';
# return array, first el is headers, 2nd is body (php's mail() needs them separate)
if ($mime) {
foreach ($body['body'] as $sub_body) {
$data .= "--$boundary" . PHP_EOL;
$r = email2_helper($sub_body, false);
$data .= $r[0] . PHP_EOL . PHP_EOL; # headers
$data .= $r[1] . PHP_EOL . PHP_EOL; # body
}
$data .= "--$boundary--";
} else {
if(preg_match('/[^\x09\x0A\x0D\x20-\x7E]/', $body['body'])) {
$headers[] = "Content-Transfer-Encoding: base64";
$data .= chunk_split(base64_encode($body['body']));
} else {
$data .= $body['body'];
}
}
return array(join(PHP_EOL, $headers), $data);
}
Сначала убедитесь, что у вас никогда не было более одного невыполненного запроса GATT за раз. См. Android BLE BluetoothGatt.writeDescriptor () иногда возвращает false .
Когда вы получаете onCharacteristicChanged, вы можете использовать getValue непосредственно для объекта характеристики, чтобы получить уведомленное значение.
После вызова readCharacteristic необходимо дождаться onCharacteristicRead, прежде чем вы сможете вызвать getValue.
Объявлены эти строки до device.connectGatt()
AdvertiseSettings advertiseSettings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setConnectable(true)
.setTimeout(0)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.build();
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(false)
.addServiceUuid(new ParcelUuid(FP_SERVICE_UUID))
.build();
mBluetoothAdapter.getBluetoothLeAdvertiser().startAdvertising(advertiseSettings, advertiseData, new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
// Log.d(TAG, "BluetoothLeAdvertiser, onStartSuccess --> $isConnectable : " + settingsInEffect.isConnectable());
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
// Log.d(TAG, "BluetoothLeAdvertiser, onStartSuccess --> errorCode : " + errorCode);
}
});
...