Передача файлов через Bluetooth> 1024k - PullRequest
0 голосов
/ 03 сентября 2018

Может кто-нибудь сказать мне, что я делаю не так? Извините, это длинный вопрос, но я прочитал много постов и перепробовал много вещей, даже больше, чем те, которые описаны ниже.

Я пытаюсь передать файлы по 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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...