Android Bluetooth and sending an unsigned Hex value - android

I am currently working on a Android application that takes values from a text box and then sends it over bluetooth, all operations are in Hex values.
I have a convertion method that can take the string make give me the unsigned integer for the string, but once i place it in the byte array it becomes signed and the board that receives this cannot do signed hex.
This is how the process works:
//sample string to send
String toSend = "0BDD";
//sending the byte[] to the board over bluetooth
btOutputStream.write(SendByteData(toSend));
// --- perform the conversion to byte[] ---
public static byte[] SendByteData(String hexString)
{
byte[] sendingThisByteArray = new byte[hexString.length()/2];
int count = 0;
for( int i = 0; i < hexString.length() - 1; i += 2 )
{
//grab the hex in pairs
String output = hexString.substring(i, (i + 2));
//convert the 2 characters in the 'output' string to the hex number
int decimal = (int)(Integer.parseInt(output, 16)) ;
//place into array for sending
sendingThisByteArray[count] = (byte)(decimal);
Log.d(TAG, "in byte array = " + sendingThisByteArray[count]);
count ++;
}
return sendingThisByteArray;
}
The issue is as follows:
When the for for loop runs through the string and picks up "0B" it correctly gives me integer 11; then when the loop runs through "DD" it give me integer 221 which is also correct
When I perform the operation of
sendingThisByteArray[count] = (byte)(decimal);
11 gets correctly placed in sendingThisByteArray[0]
but for sendingThisByteArray[1] the number 221 gets changed to -35
I know that Java has signed bytes.. is there a way to put/place/change the byte array so i can place and number 221 or any other value higher than 127?
your help is greatly appreciated

You can convert from a signed integer to unsigned byte like this, by binary AND'ing it with 0xFF:
sendingThisByteArray[count] = (byte)(decimal & 0xFF);
This way you can send values from 0 to 255

I found the problem, when i tried to do unsigned hex into a byte array it would always put a sign, i had to create single byte to retain the unsigned hex
int zeroA = (int)(Integer.parseInt("0D", 16));
sendStream.write(unsignedToBytes((byte) zeroA));

Related

Converting int 0 to binary in android studio

I am converting 4 integers into binary and everything works fine until it has to convert a zero.
for example:
int subnet1 = 255;
int subnet2 = 255;
int subnet3 = 255;
int subnet4 = 0;
binarystring = Integer.toBinaryString(subnet1)
+ Integer.toBinaryString(subnet2)
+ Integer.toBinaryString(subnet3)
+ Integer.toBinaryString(subnet4);
BinaryView.setText(binarystring);
text would look like this: 11111111 11111111 11111111 0 (without the space inbetween)
why wont it convert the 0 to 00000000 ??
Because value for "0000000" is same for "0" that's why it set as "0".
If you want to print that result. Just make a string of "0000000" for printing. Because int value always convert it.
Why? By design. From the documentation:
This value is converted to a string of ASCII digits in binary (base 2) with no extra leading 0s.
(Emphasis added.)
If you want 8 characters, append the result to a string of 7 zeros, and take the last 8 characters. In pseudo code:
intermediateString = "0000000" + Integer.toBinaryString( 0 ); // obviously don't hard code zero; just for example
finalString = intermediateString.substring( intermediateString.length() - 8);
If you read the documentation here: https://developer.android.com/reference/java/lang/Integer.html#toBinaryString(int)
It tells you:
The unsigned integer value is the argument plus 232 if the argument is negative; otherwise it is equal to the argument. This value is converted to a string of ASCII digits in binary (base 2) with no extra leading 0s.

Android signed int to unsigned int conversion

I'm trying to convert a signed decimal to an unsigned decimal, but I don't know how to do that.
The Android device is communicating with another iOS device, and we need to send color codes from one platform to another. Because these platforms has different data types (Java signed data types and iOS unsigned data types) we need to make conversions in order to have the same colors on both sides.
This is what I have made so far:
// Parse and retrieve color code from the backend server
int unsignedColor = getColorFromBackend();
// Now add an alpha channel 'FF' and make it unsigned color
int signedColor = toSignedColor(unsignedColor);
// The signed value is -14701818
// Now try to make the conversion back, from signed to unsigned
int conversion = toUnsignedColor(signedColor);
// The value is: 129712 which is not the value I want (2075398)
private int toUnsignedColor(int signedColor) {
String hex = Integer.toHexString(signedColor);
hex = hex.substring(2, hex.length() - 1);
// hex = "1FAB06";
int unsignedInt = Integer.parseInt(hex, 16);
return unsignedInt;
}
private int toSignedColor(int unsignedColor) {
String hexColor = String.format("#%06X", (0xFFFFFFFF & unsignedColor));
// hexColor = "#FF1FAB06";
int signedColor = Color.parseColor(hexColor);
return signedColor;
}
// This is an example
private int getColorFromBackend() {
return 2075398;
}
The best and clearest way to pass colors in json, without signed/unsigned issues, is to pass them as a Hex string.
This will also make the json color value more understandable.
I have managed to convert the signed integer value back to unsigned by shifting the bits:
// 2075398;
int unsigned = parseColor("color_code");
// -14701818
int signedColor = unsigned | (0xFF << 24);
// Now convert back to signed integer, wihch is: 2075398 (no alpha)
int converted = signedColor & ((1 << 24) - 1);
// With alpha
view.setColor(signedColor);

How to get byte by byte from byte array

I am getting response from server in string format like
V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D410240x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101
Then I am converting it in to byte array because i need to get value from this byte by byte.
I tried to use
Arrays.copyOfRange(original,
from , to);
but it work on index basis not on byte basis.
I also tried following solution but it also truncating String(if I use string instead of byte[]) on length basis.
public static String truncateWhenUTF8(String s, int maxBytes) {
int b = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// ranges from http://en.wikipedia.org/wiki/UTF-8
int skip = 0;
int more;
if (c <= 0x007f) {
more = 1;
} else if (c <= 0x07FF) {
more = 2;
} else if (c <= 0xd7ff) {
more = 3;
} else if (c <= 0xDFFF) {
// surrogate area, consume next char as well
more = 4;
skip = 1;
} else {
more = 3;
}
if (b + more > maxBytes) {
return s.substring(0, i);
}
b += more;
i += skip;
}
return s;
}
I know how to calculate string in byte length but it giving only full string length in byte like
Here is how I need to extract packet on byte basis.
Above codes and parameters is only example. I need to get byte by byte from string/byte array.
I searched lot but didn't get any solution or link which I can refer. I am not getting how to split string using byte length because I know byte length for each parameter and for value also.
Please give me any reference or hint.
To determine what is equal to one byte in a String is not trivial. Your String contains bytes in hexadecimal text form: 0x0D (one byte, equal to 13), but also contains values as substrings. For example 1024 can be interpreted as an integer which in this case fits into 2 bytes, but could also be interpreted as a text made up by 4 chars, totaling to 8 bytes.
Anyways, I would split the string using a regular expression, and then further split the parts to length and value:
String message = "V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D41024"+
"0x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101";
String regex = "(0)(x)(\\w\\w)";
String[] parts = message.split(regex);
Log.d(TAG,"HEADER = "+parts[0]);
for (int i=1; i<parts.length; i++) {
String s = parts[i];
// Only process if it has length > 0
if (s.length()>0) {
String len = "", val = "";
// String s is now in format LVVVV where L is the length, V is the value
if (s.length() < 11) {
// 1 character indicates length, up to 9 contains value
len = s.substring(0, 1);
val = s.substring(1);
} else if (s.length() > 10) {
// 2 characters indicate length, up to 99 contains value
len = s.substring(0, 2);
val = s.substring(2);
} else if (s.length() > 101) {
// 3 characters indicate length, up to 999 contains value
len = s.substring(0, 3);
val = s.substring(3);
}
Log.d(TAG, "Length: " + len + " Value: " + val);
}
}
This produces the following output:
D/Activity: HEADER = V1YYZZ
D/Activity: Length: 0 Value: 001
D/Activity: Length: 1 Value: 1205
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 21 Value: TATADOCOMOINTERNET101
Then you can check the packages (the first two package in the header is not needed), convert Strings to whatever you would like (e.g. Integer.parseInt(val))
If you explain the structure of the header (V1YYZZ0x0000010x0D0x0011205), I can improve my answer to find the message count.
I think it is doable with Scanner
import java.util.Scanner;
public class Library {
public static void main(String[] args) {
String s = "V1YYZZ0x0000010x0D0x001120"
+ "50x0C152031962061900x0D410240x0E152031962061900x0F410240x1"
+ "021TATADOCOMOINTERNET101";
// Skip first 9? bytes. I'm not sure how you define them
// so I just assumed it is 26 chars long.
s = s.substring(26, s.length());
System.out.println(s);
Scanner scanner = new Scanner(s);
// Use byte as delimiter i.e. 0xDC, 0x00
// Maybe you should use smth like 0x[\\da-fA-F]{2}
// And if you want to know that byte, you should use
// just 0x and get first 2 chars later
scanner.useDelimiter("0x\\w{2}");
// Easily extracted
int numberOfParams = scanner.nextInt();
for (int i = 0; i < numberOfParams; i++) {
String extracted = scanner.next();
// Length of message
int l = extracted.length();
boolean c = getLength(l) == getLength(l - getLength(l));
l -= getLength(l);
l = c ? l : l-1;
System.out.println("length="
+ extracted.substring(0, extracted.length()-l));
System.out.println("message="
+ extracted.substring(extracted.length()-l, extracted.length()));
}
// close the scanner
scanner.close();
}
// Counting digits assuming number is decimal
private static int getLength(int l) {
int length = (int) (Math.log10(l) + 1);
System.out.println("counted length = " + length);
return length;
}
}
We definitely need more information about rules, how string is formed. And what exactly you need to do. This code might be good enough you. And without comments it is really short and simple.
This is not a answer to accessing a byte array byte by byte, but is an answer for the situation in which you find yourself.
Your explanation and description have the appearance of being confused as to what it is that you are really getting from the server (e.g. it is quite hard to represent "V1YYZZ0x0000010x0D0x001120" as a 9 byte field (note it probably ends on the 2, not the 0)). Alternately, that you are using the wrong method to get it from the server, or not getting it as the intended data type.
Your code indicates that you believe that what you are getting is a UTF8 string. The data shown in your question does not appear to indicate that it is intended to be in that format.
Keep in mind when doing something like this that some other programmer had to create structure for the data that you are seeing. They had to define it somewhere with the intent that it be able to be decoded by their intended recipients. Unless there are other considerations (security, minimal bandwidth, etc.), such formats are usually defined in a way that is both easy to encode and decode.
The existence of the multiple "0x"-ASCII-encoded hexadecimal numbers --particularly the single byte representing the parameter (called "varam" in your graphic)-- strongly implies that this data was intended to be interpreted as a ASCII encoded string. While that might not be the case, it should be kept in mind when looking at the problem from a larger perspective.
You are having to put too much effort into decoding the information you are getting from the server. It, probably, should be relatively easy unless there are considerations why it would have intentionally been made difficult.
All of this indicates that the real problem exists in an area for which you have provided us with no information.
Step back:
Think about things like:
How are you receiving this from the server (what function/interface)?
In the call requesting the information from the server is there a way to specify the encoding type be bytes, an ASCII string, or some other format that is easier to deal with than UTF8? At a minimum, it appears to be clear that the data was not intended to be handled as a UTF8 string. There should be a way for you to get it without it having been converted to UTF8.
Also, you should try to find an actual specification for the format of the data. You have not explained much about the source, so it may be you are reverse-engineering something and have no access to specifications.
Basically, it looks like this is a problem where it might be a good idea to step back and ask if you are starting from the point that makes it easiest to solve and if you are headed in the right direction for doing so.
I'm sure I'm missing something obvious...
String.getBytes();
And if you want to process it in order taking defined objects from the array, just wrap using
ByteBuffer.wrap();
The result being something along the lines of:
String s = "OUTPUT FROM SERVER";
byte[] bytes = s.getBytes();
ByteBuffer bb = ByteBuffer.wrap(bytes);
What did I miss from the initial question? :/

android nfc - mifare classic 1k Increment operation tranceive failed

I want to store an integer value and increment or decrement it with API function.
I have readed the card with an utility and this is the content of block 5:
It seems that there is not any value block.
This is my code:
int sector = 5;
this.mClassic.connect();
boolean success = this.mClassic.authenticateSectorWithKeyA(sector, MifareClassic.KEY_DEFAULT );
if(success){
int firstBlock = mClassic.sectorToBlock(sector);
Log.i("MIFARE CLASSIC", "first block of the given sector:" + firstBlock);
//set the value = 0
byte[] zeroValue = {0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,};
//save this value
mClassic.writeBlock(firstBlock, zeroValue);
//increment the value and store it
this.mClassic.increment(firstBlock, 1);
this.mClassic.transfer(firstBlock);
// read the incremented value by converting it in integer from bytearray
b = readSector(firstBlock);
data = b.toByteArray();
value = 0;
for (int i = 0; i < data.length; i++)
{
value = (value << 8) + (data[i] & 0xff);
}
Log.i("MIFARE CLASSIC", "After increment " + value);
}
mClassic.close();
I have returned tranceive failed at this.mClassic.increment(firstBlock, 1);
I don't understand what I am doing wrong...who can help me?
Thanks a lot.
The Mifare 1K does a data-integrity check on the value-block. Your zeroValue block is unfortunately not a valid value-block. Therefore the tag complains and you get an error.
You can find the format in the Mifare Datasheets (worth reading!)
However, the format of the value-block is simple:
byte 0..3: 32 bit value in little endian
byte 4..7: copy of byte 0..3, with inverted bits (aka. XOR 255)
byte 8..11: copy of byte 0..3
byte 12: index of backup block (can be any value)
byte 13: copy of byte 12 with inverted bits (aka. XOR 255)
byte 14: copy of byte 12
byte 15: copy of byte 13
If you store your 32 bit value using the format above, your code will very likely just work.

Converting sections of byte arrays to integer values

I am currently making an android application which accepts bluetooth measurement from a device. The way the data is packaged is in 4 bytes. I need to get two values out of these bytes.
First value is made up of: 6bit and 7bit of first byte and bit 0 to bit 6 of byte 2
Second values is simpler and consists of the full 3rd byte.
What is a good way to access these bit values, combine them and convert them to integer values? Right now i'm trying to convert from byte array to bitset, and then access individual bits to create new bytes that would then be converted to a integer.
Thanks, and please ask if I am not being clear enough.
I figured it out: I converted the byte array to int using this method
public static int byteArrayToInt(byte[] b, int offset) {
int value = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
value += (b[i + offset] & 0x000000FF) << shift;
}
return value;
}
Then I used the method pokey described. Thanks for your help!
im not sure if i understood your format correctly.
Does this bitmask correspond to your first value?
0xC07F0000
That is bits 16-22,30,31 (zero based indexing used here, i.e. bit 31 is last bit).
Another thing, is your value expected to be signed or unsigned?
Anyway, if it is the way i assume then you can convert it like this with some bitmasks:
unsigned int val = 0xdeadbeef;
unsigned int mask1 = 0xC0000000;
unsigned int mask2 = 0x007F0000;
unsigned int YourValue = (val&mask1)>>23 | (val&mask2)>>16;
Do that in the same way with your other values. Define a bitmask and shift it to the right. Done.
Cheers

Categories

Resources