Может кто-нибудь сказать мне, что я делаю не так? Извините, это длинный вопрос, но я прочитал много постов и перепробовал много вещей, даже больше, чем те, которые описаны ниже.
Я пытаюсь передать файлы по Bluetooth, используя образец BluetoothChat в качестве базы, и я не могу успешно передать что-либо более 1024k. Я стремлюсь, чтобы приложение передавало файлы регулярно (что-то вроде 1 файла в минуту) без взаимодействия с пользователем (после того, как пользователь запустил его), поэтому необходимо сделать это прозрачно; поэтому стараюсь делать это в коде, а не использовать намерения.
1) Основы. В BluetoothFragment у меня есть
private void transferFile(String file) {
File imageFile = new File(getActivity().getExternalFilesDir(null), file);
if (!imageFile.exists()) {
...; return;
} else {
try {
byte[] myByteArray = new byte[(int)imageFile.length()];
FileInputStream fis = new FileInputStream(imageFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(myByteArray,0,myByteArray.length);
mBluetoothService.transferOut(myByteArray);
} catch (IOException e) {
e.printStackTrace();
и в BluetoothService
public void transferOut(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
r.transferOut(out);
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
...
public void transferOut(byte[] buffer) {
try {
//tried this
// mmOutStream.write(buffer);
//then this
// for(int i = 0 ; i < buffer.length ; i++) {
// mmOutStream.write(buffer[i]);}
//then this. All had same results.
mmOutStream.write(buffer, 0, buffer.length);
...
public void run() {
byte[] buffer = new byte[1024];
int bytes, current;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
Если файл <1024 КБ, то обработчик в BluetoothFragment правильно записывает его на диск; если оно больше, оно обрезается. </p>
2) Нашел это предложение повторить чтение. Изменена функция ConnectedThread run () на
try {
bytes = mmInStream.read(buffer, 0, buffer.length);
current = bytes;
do {
bytes = mmInStream.read(buffer, current, buffer.length - current);
if (bytes >= 0)
current += bytes;
} while (bytes > -1);
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
но он остается в цикле do, по-видимому, не получая байтов закрытого соединения -1).
3) Другая версия
public void run() {
byte[] imgBuffer = new byte[2048 * 2048];
int pos = 0;
while (mState == STATE_CONNECTED) {
try {
byte[] buffer = new byte[2048];
int bytes = mmInStream.read(buffer);
System.arraycopy(buffer, 0, imgBuffer, pos, bytes);
pos += bytes;
mHandler.obtainMessage(Constants.MESSAGE_READ, pos, -1, imgBuffer)
.sendToTarget();
Иногда это работает, но даже тогда это занимает много времени (может быть, 20 минут на несколько МБ - плюс иногда конечный результат - это предыдущее изображение! Даже во время тестирования я удалил его вручную!).
4) Размер отправляемого файла. Чтобы проверить концепцию, начали с 2-х шагов. Размер отправляемого файла:
File imageFile = new File(getActivity().getExternalFilesDir(null), file);
String inputString = FILE_LENGTH + (int)imageFile.length();
byte[] myByteArrayLgth = new byte[1024];
myByteArrayLgth = inputString.getBytes();
mService.transferOutFileLength(myByteArrayLgth);
Затем в ConnectedThread запустите () вручную указав размер файла, чтобы минимизировать ошибки. Пробовал несколько способов, последний был таким:
public void run() {
byte[] buffer = new byte[80 * 1024];
int bytes, current;
int targetFileSize = 57828;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
current = bytes;
while (current < targetFileSize) {
bytes = mmInStream.read(buffer);
current = current + bytes;
}
mHandler.obtainMessage(Constants.MESSAGE_READ, current, -1, buffer)
.sendToTarget();
Также изменил запись на диск
fos.write(readBuf, 0, arg1); //arg1 is filesize
Этот созданный файл правильного типа (jpeg) и размера, но не может быть отображен (предположительно поврежден).
Может кто-нибудь увидеть что-то не так или предложить лучший способ?
Может быть, размеры сообщений / чанков Bluetooth и последовательность слишком непредсказуемы; Может быть, я должен рассмотреть вопрос об использовании Wi-Fi?
Я тестирую 2 устройства на Android 8.0.0 и 4.4.3. (так что SDK 19).