3

Here is the code to convert an image to byte array and and send to ble device i am not able to send complete data and its stopping nearly at 1kb

what are the methods to send large data to ble . will it be appropriate to use delay in the data transfer and if so can you share the code

if anyone has any code to send data upto 1mb please do share

public class RxTxActivity extends Activity {

byte[] imageInByte,SendByte;
private static int IMG_RESULT = 1;
String ImageDecode;
ImageView imageViewLoad;
Button LoadImage;
Intent intent;
String[] FILE;

String[] SAImage,SAsent;

private final static String TAG = DeviceControlActivity.class.getSimpleName();

public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

private TextView mCharaDescriptor;
private TextView mConnectionState;
private TextView mDataField;
private TextView mDeviceAddressTextView;

private String mServiceUUID, mDeviceAddress;
private String mCharaUUID, mDeviceName;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
        new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = true;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private Button EditButton;
private Button CharaSubscribeButton;
private EditText EditText;

private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
private String CHARA_DESC = "";
private String properties = "";

private Context context = this;

// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder service) {
        mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
        if (!mBluetoothLeService.initialize()) {
            Log.e(TAG, "Unable to initialize Bluetooth");
            finish();
        }
        // Automatically connects to the device upon successful start-up initialization.
        mBluetoothLeService.connect(mDeviceAddress);

        mBluetoothLeService.readCustomDescriptor(mCharaUUID, mServiceUUID);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        mBluetoothLeService = null;
    }
};

// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device.  This can be a result of read
//                        or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(final Context context, Intent intent) {
        final String action = intent.getAction();
        switch (action) {
            case BluetoothLeService.ACTION_GATT_CONNECTED:
                mConnected = true;
                updateConnectionState(R.string.connected);
                invalidateOptionsMenu();
                break;
            case BluetoothLeService.ACTION_GATT_DISCONNECTED:
                mConnected = false;
                updateConnectionState(R.string.disconnected);
                invalidateOptionsMenu();
                break;
            case BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED:
                break;
            case BluetoothLeService.ACTION_DATA_AVAILABLE:
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(context, "Data Received!", Toast.LENGTH_SHORT).show();
                    }
                });
                displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
                break;
            case BluetoothLeService.ACTION_DESCRIPTOR_AVAILABLE:
                Log.i("Receiving data", "Broadcast received");
                displayDescriptor(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
            default:
                break;
        }
    }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.data_transfer);

    imageViewLoad = (ImageView) findViewById(R.id.imageView1);
    LoadImage = (Button)findViewById(R.id.button1);

    LoadImage.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

            startActivityForResult(intent, IMG_RESULT);

        }
    });



    final Intent intent = getIntent();

    Log.i("OnCreate", "Created");

    mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
    mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
    mServiceUUID = intent.getStringExtra("Service UUID");
    mCharaUUID = intent.getStringExtra("Characteristic UUID");
    CHARA_DESC = intent.getStringExtra("Characteristic Descriptor");
    properties = intent.getStringExtra("Characteristic properties");

    // Sets up UI references.
    ((TextView) findViewById(R.id.device_address_rxtx)).setText("Characteristic UUID: " + mCharaUUID);
    ((TextView) findViewById(R.id.characteristic_Descriptor)).setText("Characteristic Descriptor: " + CHARA_DESC);
    ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);

    mConnectionState = (TextView) findViewById(R.id.connection_state);
    mConnectionState.setText("Connected");

    mDataField = (TextView) findViewById(R.id.data_value);
    EditText = (EditText) findViewById(R.id.characteristicEditText);
    EditButton = (Button) findViewById(R.id.characteristicButton);
    CharaSubscribeButton = (Button) findViewById(R.id.characteristic_Subscribe);
    mCharaDescriptor = (TextView) findViewById(R.id.characteristic_Descriptor);

    EditButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            String str = EditText.getText().toString();
            mBluetoothLeService.writeCustomCharacteristic(str, mServiceUUID, mCharaUUID);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(context, "Message Sent!", Toast.LENGTH_SHORT).show();
                }
            });
            mBluetoothLeService.readCustomDescriptor(mCharaUUID, mServiceUUID);
        }
    });

    CharaSubscribeButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            if (properties.indexOf("Indicate") >= 0) {
                mBluetoothLeService.subscribeCustomCharacteristic(mServiceUUID, mCharaUUID, 1);
            } else if (properties.indexOf("Notify") >= 0) {
                mBluetoothLeService.subscribeCustomCharacteristic(mServiceUUID, mCharaUUID, 2);
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(context, "Characteristic Subscribed!", Toast.LENGTH_SHORT).show();
                }
            });
            mBluetoothLeService.readCustomDescriptor(mCharaUUID, mServiceUUID);
        }
    });

    checkProperties();
    getActionBar().setTitle(mDeviceName);
    getActionBar().setDisplayHomeAsUpEnabled(true);
    Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
    bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}

private void checkProperties() {
    if (properties.indexOf("Write") >= 0) {
    } else {
        EditButton.setEnabled(false);
    }
    if (properties.indexOf("Indicate") >= 0) {
    } else {
        CharaSubscribeButton.setEnabled(false);
    }
}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
    if (mBluetoothLeService != null) {
        final boolean result = mBluetoothLeService.connect(mDeviceAddress);
        Log.d(TAG, "Connect request result=" + result);
    }
}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(mGattUpdateReceiver);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(mServiceConnection);
    mBluetoothLeService = null;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.gatt_services, menu);
    if (mConnected) {
        menu.findItem(R.id.menu_connect).setVisible(false);
        menu.findItem(R.id.menu_disconnect).setVisible(true);
    } else {
        menu.findItem(R.id.menu_connect).setVisible(true);
        menu.findItem(R.id.menu_disconnect).setVisible(false);
    }
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_connect:
            mBluetoothLeService.connect(mDeviceAddress);
            return true;
        case R.id.menu_disconnect:
            mBluetoothLeService.disconnect();
            return true;
        case android.R.id.home:
            onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

private void updateConnectionState(final int resourceId) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mConnectionState.setText(resourceId);
        }
    });
}

private void displayData(String data) {
    if (data != null) {
        mDataField.setText(data);
    }
}

private void displayDescriptor(final String data) {
    if( data != null){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mCharaDescriptor.setText(mCharaDescriptor.getText().toString() + "\n" + data);
            }
        });
    }
}


private static IntentFilter makeGattUpdateIntentFilter() {
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
    intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
    intentFilter.addAction(BluetoothLeService.ACTION_DESCRIPTOR_AVAILABLE);
    return intentFilter;
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    try {

        if (requestCode == IMG_RESULT && resultCode == RESULT_OK
                && null != data) {


            Uri URI = data.getData();
            String[] FILE = { MediaStore.Images.Media.DATA };


            Cursor cursor = getContentResolver().query(URI,
                    FILE, null, null, null);

            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(FILE[0]);
            ImageDecode = cursor.getString(columnIndex);
            cursor.close();

            imageViewLoad.setImageBitmap(BitmapFactory
                    .decodeFile(ImageDecode));

        }
    } catch (Exception e) {
        Toast.makeText(this, "Please try again", Toast.LENGTH_LONG)
                .show();
    }

}


public void ClickConvert(View view) {

    TextView txtView;
    txtView=(TextView)findViewById(R.id.textview_byte);

    ImageView imageView = (ImageView) findViewById(R.id.imageView1);
    Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    imageInByte = baos.toByteArray();
    String response ;
    response = byteArrayToString(imageInByte);
    // response = new sun.misc.BASE64Encoder().encode(imageInByte);
    //String s = javax.xml.bind.DatatypeConverter.printHexBinary(imageInByte);
    //String str = new String(imageInByte, "UTF-8");
    txtView.setText(response);


}
public static String byteArrayToString(byte[] data){
    String response = Arrays.toString(data);

    String[] byteValues = response.substring(1, response.length() - 1).split(",");
    byte[] bytes = new byte[byteValues.length];

    for (int i=0, len=bytes.length; i<len; i++) {
        bytes[i] = Byte.parseByte(byteValues[i].trim());
    }

    String str = new String(bytes);
    return str.toLowerCase();
}




public void ClickImage(View view) {

    final int num= imageInByte.length;
    int i,j,l,h;
       j=num/20;
    Toast.makeText(getApplicationContext(), "loop : " + j,  Toast.LENGTH_SHORT).show();
    for (i = 0; i <= j; i++) {
           l=20*i;
           h=20*(i+1);
           SystemClock.sleep(40); //ms
           SendByte = Arrays.copyOfRange(imageInByte, l, h);
           String str = new String(SendByte);
           mBluetoothLeService.writeCustomCharacteristic(str, mServiceUUID, mCharaUUID);
           runOnUiThread(new Runnable() {
               @Override
               public void run() {
               }
           });
           mBluetoothLeService.readCustomDescriptor(mCharaUUID, mServiceUUID);
   }
}

}

Here is the code for writecustomCharacteristics

 public void writeCustomCharacteristic(String str, String serviceUuid, String charaUuid) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    /*check if the service is available on the device*/
    BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString(serviceUuid));
    if(mCustomService == null){
        Log.w(TAG, "Custom BLE Service not found");
        return;
    }

    /*byte[] value = parseHex(str);

    *//*get the read characteristic from the service*//*
    BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString(charaUuid));
    mWriteCharacteristic.setValue(value);
    mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);*/

    byte[] strBytes = str.getBytes();

    BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString(charaUuid));
    mWriteCharacteristic.setValue(strBytes);
    mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);

}
  • Please share your complete code of writeCustomCharacteristic method – Christopher Jan 18 '18 at 12:59
  • 1
    Possible duplicate of [Sending Large File via BLE API on android](https://stackoverflow.com/questions/48250732/sending-large-file-via-ble-api-on-android) – Christopher Jan 18 '18 at 13:01
  • Which portion is sent? Only a fraction of each byte array? Only the first n byte arrays? Please be more specific with your error. – Thern Jan 18 '18 at 16:08
  • 1
    @Christopher i have posted my complete code , i have added a delay of 40ms and able to transfer complete data but its taking nearly 20m time can anyone suggest any other method to other than delay – Cherala Vivek Jan 19 '18 at 12:31
  • @Nebr i am able to send complete data now by using a delay of 40ms but its taking 20 minutes , i want a method to transfer it quickly and my file size is 200kb – Cherala Vivek Jan 19 '18 at 12:33
  • @CheralaVivek The delay seems not to be the problem. If you send 20 Bytes per write (which is the maximum for a single (short) write), you need 10000 operations to deliver 200kB. This makes for a delay of 40 seconds, which is small compared to the overall time of 20 minutes. – Thern Jan 19 '18 at 13:56
  • @CheralaVivek But you still didn't show the writeCustomCharacteristic method itself. – Thern Jan 19 '18 at 13:57
  • @Nebr i have added write custom characteristics can u help me out – Cherala Vivek Feb 06 '18 at 05:16
  • It looks okay. Can you check if you get a write response for each write request? But then, with the 40 ms delay it should not pile up and cause a buffer overflow. I currently don't see what could cause the problem. The code looks fine. – Thern Feb 06 '18 at 06:16
  • @Nebr i am able to send data without loosing any data but its taking a lot of time like 20 min for 200 kb is there any better method to decrease the time – Cherala Vivek Feb 06 '18 at 06:17
  • @Nebr i also want to receive data from the ble device can u share or suggest me regarding receiving data – Cherala Vivek Feb 06 '18 at 06:18
  • Normally it shouldn't take that long. How does the sending pattern look like? One write request per 200 ms? Or many write requests at the beginning and then slowing down? (For receiving data, you have to configure the device for notifications/indications on the corresponding characteristic. Please read about the details in the specification.) – Thern Feb 06 '18 at 07:26
  • @Nebr i am sending 10 bytes of data and delaying it for 40ms i will update the code so that u can see it – Cherala Vivek Feb 06 '18 at 07:40
  • It is not a question of code. What does your device actually do? Does it send write requests each 40 ms, does it start with 40 ms and slows down, does it always send in 200 ms intervals etc.? The code tells us how it should be, but we need to know how it actually is. – Thern Feb 06 '18 at 08:54
  • @Nebr once see the ClickImage function in the RxTxactivity of my code u will be able to understand how its working – Cherala Vivek Feb 06 '18 at 09:33
  • 1
    You seem to think that your device does what the code says. It is often not the case. Buffers may be full, connection may be lost, whatever. I understand that you WANT to send a write request after 40 ms delay, but just because the code says so, it is not guaranteed that the device actually DOES it that way. – Thern Feb 06 '18 at 12:03

0 Answers0