How to send data to ble? - android

I have use mBluetoothGatt.writeDescriptor(descriptor) or writeCharacteristic(characteristic)
to send data to ble devices.
but the devices can't received.I don't konw why?
This is my code :
public void writeDataToBel() {
if ((gattCharacteristics_send.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
System.out.println("have permission");
}
String send_data = "d300000000060000000000000000d900";
gattCharacteristics_send.setValue(send_data);
gattCharacteristics_send
.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
boolean sendStatus = mBluetoothGatt
.writeCharacteristic(gattCharacteristics_send);
System.out.println("status-->" + sendStatus);
}

Make sure that the characterisitic you are writing to has a write permission. you can perform the check in the following way:
if((gattCharacteristics_send.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE ) > 0) {
gattCharacteristics_send.setValue(send_data);
boolean sendStatus = mBluetoothGatt.writeCharacteristic(gattCharacteristics_send);
}

I have resolved it:
"d300000000060000000000000000d900" chageTo byte[]
public static byte[] changeToByte(String sendData) {
byte[] myByte = new byte[16];
int[] myInt = new int[16];
for (int i = 0; i < myByte.length; i++) {
myInt[i]=Integer.valueOf(sendData.substring(i*2, (i+1)*2), 16);
}
for (int i = 0; i < myByte.length; i++) {
myByte[i] = (byte) myInt[i];
}
return myByte;
}

Related

POS bluetooth printer leaving some margin at start and then starts printing in Android App

I am implementing POS bluetooth printer with ESC/POS commands and trying to print bitmap image.
Image is getting printing but always it is printing some white space at start and then printing an image,because of which i am not able to print 1 image per label.
following is my code for printing and image
int bmpNewWidth = bmp.getWidth();
int bmpNewHeight = bmp.getHeight();
byte[] printBMPPackageHead = ESCUtil.bmpCmdHead(bmpMode,bmpNewWidth);
int bmpBlockHeight = 0;
int bmpBlockNums =0;
if((bmpMode == 0) || (bmpMode ==1))
{
bmpBlockHeight = 8;
}
else if((bmpMode == 32) || (bmpMode ==33))
{
bmpBlockHeight = 24;
}
else
{
Log.d(TAG,"****bmpMode set error!!*****");
return (new byte[1]);
}
bmpBlockNums = ((bmpNewHeight % bmpBlockHeight) == 0)? (bmpNewHeight/bmpBlockHeight) : (bmpNewHeight/bmpBlockHeight +1);
int bmpBlockCMDSize = printBMPPackageHead.length + bmpNewWidth*bmpBlockHeight/8;
byte[] bmpPrintData = new byte[bmpBlockNums*bmpBlockCMDSize];
for(int n = 0; n < bmpBlockNums; n++)
{
byte[] bmpBlockPxBytes = getBitmapBlockData(n,bmpNewWidth,bmpBlockHeight,bmp);
byte[][] bmpBlockPrintData = {printBMPPackageHead,bmpBlockPxBytes};
System.arraycopy(ESCUtil.byteMerger(bmpBlockPrintData),0,bmpPrintData,n*bmpBlockCMDSize,bmpBlockCMDSize);
}
return bmpPrintData;
}
and
public static byte[] bmpCmdHead(int mode, int bitmapWidth)
{
//byte[] result = new byte[]{ESC,42,0,0,0};
byte[] result = new byte[]{ESC,42,0,0,0};
result[2] = (byte)mode;
result[3] = (byte)(bitmapWidth%256);
result[4] = (byte)(bitmapWidth/256);
return result;
}
public static byte[] getBitmapBlockData(int blocknum, int bmpWidth, int bmpBlockHeight, Bitmap bmp)
{
int blockHeightBytes = bmpBlockHeight/8;
byte[] blockData = new byte[bmpWidth*blockHeightBytes];
for (int i = 0;i < bmpWidth; i++)
{
for(int j = 0;j < blockHeightBytes;j++)
{
for(int p = 0; p < 8; p++)
{
byte px = px2Byte(i,blocknum * bmpBlockHeight+j*8+p,bmp);
blockData[i*blockHeightBytes+j] |= (px << (7-p));
}
}
}
return blockData;
}
this is it.Before calling this function i have called only init printer command that's it.
Please help me. Thanks in advance.

Unzip Password Protect Zip file is slow, How to make it fast?

I using the following class for UnZip password-protected file but unzipping to too much slow to fast it or any improvement in such class or method. Thanks in advance.
Class for Unzip Password Protect Zip file.
public class ZipDecryptInputStream extends InputStream {
private static final int[] CRC_TABLE = new int[256];
private static final int DECRYPT_HEADER_SIZE = 12;
private static final int[] LFH_SIGNATURE = {0x50, 0x4b, 0x03, 0x04};
static {
for (int i = 0; i < 256; i++) {
int r = i;
for (int j = 0; j < 8; j++) {
if ((r & 1) == 1) {
r = (r >>> 1) ^ 0xedb88320;
} else {
r >>>= 1;
}
}
CRC_TABLE[i] = r;
}
}
private final InputStream delegate;
private final String password;
private final int[] keys = new int[3];
private State state = State.SIGNATURE;
private int skipBytes;
private int compressedSize;
private int value;
private int valuePos;
private int valueInc;
public ZipDecryptInputStream(InputStream stream, String password) {
this.delegate = stream;
this.password = password;
}
#Override
public int read() throws IOException {
int result = delegate.read();
if (skipBytes == 0) {
switch (state) {
case SIGNATURE:
if (result != LFH_SIGNATURE[valuePos]) {
state = State.TAIL;
} else {
valuePos++;
if (valuePos >= LFH_SIGNATURE.length) {
skipBytes = 2;
state = State.FLAGS;
}
}
break;
case FLAGS:
if ((result & 1) == 0) {
throw new IllegalStateException("ZIP not password protected.");
}
if ((result & 64) == 64) {
throw new IllegalStateException("Strong encryption used.");
}
if ((result & 8) == 8) {
throw new IllegalStateException("Unsupported ZIP format.");
}
result -= 1;
compressedSize = 0;
valuePos = 0;
valueInc = DECRYPT_HEADER_SIZE;
state = State.COMPRESSED_SIZE;
skipBytes = 11;
break;
case COMPRESSED_SIZE:
compressedSize += result << (8 * valuePos);
result -= valueInc;
if (result < 0) {
valueInc = 1;
result += 256;
} else {
valueInc = 0;
}
valuePos++;
if (valuePos > 3) {
valuePos = 0;
value = 0;
state = State.FN_LENGTH;
skipBytes = 4;
}
break;
case FN_LENGTH:
case EF_LENGTH:
value += result << 8 * valuePos;
if (valuePos == 1) {
valuePos = 0;
if (state == State.FN_LENGTH) {
state = State.EF_LENGTH;
} else {
state = State.HEADER;
skipBytes = value;
}
} else {
valuePos = 1;
}
break;
case HEADER:
initKeys(password);
for (int i = 0; i < DECRYPT_HEADER_SIZE; i++) {
updateKeys((byte) (result ^ decryptByte()));
result = delegate.read();
}
compressedSize -= DECRYPT_HEADER_SIZE;
state = State.DATA;
// intentionally no break
case DATA:
result = (result ^ decryptByte()) & 0xff;
updateKeys((byte) result);
compressedSize--;
if (compressedSize == 0) {
valuePos = 0;
state = State.SIGNATURE;
}
break;
case TAIL:
// do nothing
}
} else {
skipBytes--;
}
return result;
}
#Override
public void close() throws IOException {
delegate.close();
super.close();
}
private void initKeys(String password) {
keys[0] = 305419896;
keys[1] = 591751049;
keys[2] = 878082192;
for (int i = 0; i < password.length(); i++) {
updateKeys((byte) (password.charAt(i) & 0xff));
}
}
private void updateKeys(byte charAt) {
keys[0] = crc32(keys[0], charAt);
keys[1] += keys[0] & 0xff;
keys[1] = keys[1] * 134775813 + 1;
keys[2] = crc32(keys[2], (byte) (keys[1] >> 24));
}
private byte decryptByte() {
int temp = keys[2] | 2;
return (byte) ((temp * (temp ^ 1)) >>> 8);
}
private int crc32(int oldCrc, byte charAt) {
return ((oldCrc >>> 8) ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]);
}
private enum State {
SIGNATURE, FLAGS, COMPRESSED_SIZE, FN_LENGTH, EF_LENGTH, HEADER, DATA, TAIL
}
}
Usage
InputStream zin = new FileInputStream(new File(zipFilePath));
ZipDecryptInputStream inputStream = new ZipDecryptInputStream(zin, "myPassWord");
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry ze ;
while ((ze = zis.getNextEntry()) != null) {
FileOutputStream fos = new FileOutputStream(unzipAtLocation + File.separator + ze.getName());
int BUFFER = 2048;
byte[] data = new byte[BUFFER];
int count;
while ((count = zis.read(data, 0, BUFFER)) != -1) {
fos.write(data, 0, count);
}
}
zis.close();
Did you consider using ByteArrayOutputStream instead of FileOutputStream? I have also problem with reading files the other day, which took to much time and I found somewhere in google example with ByteArrayOutputStream and that helps a lot
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] ba = new byte[(int) files[i].length()];
for (int readNum; (readNum = fis.read(ba)) != -1; ) {
bos.write(ba, 0, readNum);
}

Android Bluetooth input stream not reading full array

I'm creating an app to read string values over Bluetooth serial port. My data receiving but in two parts. If I send $F00,A,B,0,M# via bluetooth it only reads $ in first part and F00,A,B,0,M# in next part. I provided my code here. Please do correct me if I'm wrong.
InputStream inputStream=null;
int avilableBytes=0;
public ConnectedThread(BluetoothSocket socket){
InputStream temp=null;
try{
temp=socket.getInputStream();
}catch (IOException e){
e.printStackTrace();
}
inputStream=temp;
}
public void run() {
try{
int bytes;
while (true){
try{
avilableBytes=inputStream.available();
if (avilableBytes>0){
byte[] buffer=new byte[avilableBytes];
bytes=inputStream.read(buffer);
final String readMessage=new String(buffer,0,bytes);
bt_handler.obtainMessage(handlerState,bytes,-1,readMessage).sendToTarget();
Log.d("PRAVEEN",readMessage);
}
}catch (IOException e){
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
Data are like stream bytes and can not be processed immediately when it comes with a few bytes. Data will not come all at once as a single packet. You have to use the other byte[] buffer (MainBuffer) in which you will gradually save incoming byte and move the index in that buffer. Then, from time to time (e.g. in the timer once per second) take data from the main buffer and processed it. By default you must implement some data frame with a separator (eg. Data * data * data * - Many ways to do it good or bad). I dealt with this in .net via Xamarin, but just as an example it may be helpfull :
update example, format
In ConnectedThread :
public override void Run()
{
while (true)
{
try
{
int readBytes = 0;
lock (InternaldataReadLock)
{
readBytes = clientSocketInStream.Read(InternaldataRead, 0, InternaldataRead.Length);
Array.Copy(InternaldataRead, TempdataRead, readBytes);
}
if (readBytes > 0)
{
lock (dataReadLock)
{
dataRead = new byte[readBytes];
for (int i = 0; i < readBytes; i++)
{
dataRead[i] = TempdataRead[i];
}
}
Bundle dataBundle = new Bundle();
dataBundle.PutByteArray("Data", dataRead);
Message message = btlManager.sourceHandler.ObtainMessage();
message.What = 1;
message.Data = dataBundle;
btlManager.sourceHandler.SendMessage(message);
}
}
catch (System.Exception e)
{
btlManager.btlState = BTLService.BTLState.Nothing;
}
}
}
In BTLHandler :
public override void HandleMessage(Message msg)
{
switch (msg.What)
{
case 1:
{
byte[] data = msg.Data != null ? msg.Data.GetByteArray("Data") : new byte[0];
btlService.BTLReceiveData(data);
}
break;
}
}
public void BTLReceiveData(byte[] data)
{
lock (dataReadLock)
{
for (int i = 0; i < data.Length; i++)
{
dataRead[dataReadWriteCursor] = data[i];
dataReadWriteCursor++;
}
}
}
In Timer :
int tmpWriteCursor = dataReadWriteCursor;
int tmpReadCursor = dataReadReadCursor;
lock (dataReadLock)
{
int newBytes = dataReadWriteCursor - dataReadReadCursor;
for (int i = 0; i < newBytes; i++)
{
dataReadMain[dataReadReadCursor] = dataRead[dataReadReadCursor++];
}
}
bool odradkovani = false;
string tmpRadek = "";
int lastLineIndex = 0;
List<string> list = new List<string>();
for (int i = LastWriteLineIndex; i < tmpWriteCursor; i++)
{
if (dataReadMain[i] >= 32 && dataReadMain[i] <= 255)
{
tmpRadek += (char)dataReadMain[i];
}
else if (dataReadMain[i] == 13) odradkovani = true;
else if (dataReadMain[i] == 10)
{
if (odradkovani)
{
odradkovani = false;
list.Add(Utils.GetFormatedDateTime(DateTime.Now) + " " + tmpRadek);
tmpRadek = "";
lastLineIndex = i + 1;
}
}
else
{
tmpRadek += "?" + dataReadMain[i].ToString() + "?";
}
}
WriteDataToLog(list);
LastWriteLineIndex = lastLineIndex;

How to covert String to byte for BLE mBluetoothGatt.writeCharacteristic?

I am developing in Android BLE.
I try to send string to BLE device(like TI CC2541) , and it seems can not send string direct to BLE device.
It need to convert the String to Byte.
I have search some information , there has someone use URLEncoder.encode.
But I am not sure which is the answer what I need.
But how to convert the String to Byte?
The following code is writeCharacteristic for BLE
public void writeString(String text) {
// TODO Auto-generated method stub
BluetoothGattService HelloService = mBluetoothGatt.getService(HELLO_SERVICE_UUID);
BluetoothGattCharacteristic StringCharacteristic = HelloService.getCharacteristic(UUID_HELLO_CHARACTERISTIC_WRITE_STRING);
mBluetoothGatt.setCharacteristicNotification(StringCharacteristic , true);
int A = Integer.parseInt(text);
//How to convert the String to Byte here and set the Byte to setValue ?????
StringCharacteristic .setValue(A, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
mBluetoothGatt.writeCharacteristic(StringCharacteristic );
Log.d(TAG, "StepCount Characteristic End!");
}
How to convert the String to Byte?
Where you get your String:
byte[] strBytes = text.getBytes();
byte[] bytes = context.yourmWriteCharacteristic.getValue();
Please add a null check too like:
if (bytes == null) {
Log.w("Cannot get Values from mWriteCharacteristic.");
dismiss();// equivalent action
}
if (bytes.length <= strBytes.length) {
for(int i = 0; i < bytes.length; i++) {
bytes[i] = strBytes[i];
}
} else {
for (int i = 0; i < strBytes.length; i++) {
bytes[i] = strBytes[i];
}
}
Now, something like:
StepCount_Characteristic.setValue(bytes);
mBluetoothGatt.writeCharacteristic(StepCount_Characteristic);
I found the following code help me convert the string.
private byte[] parseHex(String hexString) {
hexString = hexString.replaceAll("\\s", "").toUpperCase();
String filtered = new String();
for(int i = 0; i != hexString.length(); ++i) {
if (hexVal(hexString.charAt(i)) != -1)
filtered += hexString.charAt(i);
}
if (filtered.length() % 2 != 0) {
char last = filtered.charAt(filtered.length() - 1);
filtered = filtered.substring(0, filtered.length() - 1) + '0' + last;
}
return hexStringToByteArray(filtered);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
private int hexVal(char ch) {
return Character.digit(ch, 16);
}
If you want to convert string value. you just need to call like the following:
String text;
byte[] value = parseHex(text);

Android: onRecieve's intent getSerializableExtra(String key) returns null

So i have this code here;
myIntent.putExtra("schedule",serializableClass);
and this intent goes to my Broadcast Reciever and i did get that serializable as below,
public void onRecieve(Context context, Intent intent)
{
Schedule s = (Schedule) intent.getSerializableExtra("schedule");
}
but it always returns even though when i put the Extras its not null, even checked before passing it on myIntent.putExtra() i really don't know what happen returns, why does it always returns null?.. anyone knows this problem?
The cast is wrong, i would be more easier to pass the serialized string and do deserialization. I' m using this class.
public final class ObjectSerializer {
private ObjectSerializer() {
}
public static String serialize(Serializable obj) throws IOException {
if (obj == null)
return "";
try {
ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
objStream.writeObject(obj);
objStream.close();
return encodeBytes(serialObj.toByteArray());
} catch (Exception e) {
throw new IOException("Serialization error: " + e.getMessage(), e);
}
}
public static Object deserialize(String str) throws IOException {
if (str == null || str.length() == 0)
return null;
try {
ByteArrayInputStream serialObj = new ByteArrayInputStream(
decodeBytes(str));
ObjectInputStream objStream = new ObjectInputStream(serialObj);
return objStream.readObject();
} catch (Exception e) {
throw new IOException("Serialization error: " + e.getMessage(), e);
}
}
public static String encodeBytes(byte[] bytes) {
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ('a')));
strBuf.append((char) (((bytes[i]) & 0xF) + ('a')));
}
return strBuf.toString();
}
public static byte[] decodeBytes(String str) {
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length(); i += 2) {
char c = str.charAt(i);
bytes[i / 2] = (byte) ((c - 'a') << 4);
c = str.charAt(i + 1);
bytes[i / 2] += (c - 'a');
}
return bytes;
}
}
after that use like this:
String scheduleSerialization = ObjectSerializer.serialize(schedule);
myIntent.putExtra("schedule",scheduleSerialization);
the last thing to do is:
public void onRecieve(Context context, Intent intent)
{
String serial = intent.getStringExtra("schedule");
if(serial!=null)
Schedule s = (Schedule) ObjectSerializer.deserialize(serial) ;
}
Using Serializable on Android is discouraged because it is slow. If you look at the android source code you will see that
the usually break down the information into multiple keys and send them as primitive types (Integer, String, etc..)
when that can't be done, the will use a Parcelable object

Categories

Resources