Splitting a string at n-th character with different length - android

i am trying to split string. I am using
for (String part : getParts(RESPONSE_STRING, 3)) {
// System.out.println(" MY STRING " + part);
partlist.add(part);
}
private static List<String> getParts(String string, int partitionSize) {
List<String> parts = new ArrayList<String>();
int len = string.length();
for (int i = 0; i < len; i += partitionSize) {
parts.add(string.substring(i, Math.min(len, i + partitionSize)));
}
return parts;
}
MY input is 0130010010102255051
output : 013 001 001 010 225 505 1
but i want my output
013 001 001 01 02 255 051
How do i achive this output ? Any idea of how to get my characters ? Many Thanks

Related

Why when reading NFCtag with Android phone you get different tag ID then when reading with dedicated reader?

I am using an Android Cilico F750 and the dedicated RFID reader is CF-RS103.
The RFID tag type is MIFARE Ultralight type C.
When read with a dedicated card reader the id of tag is: 2054270212(10 digit).
But when read with Android phone the id is: 36139312876727556(17digit) and reversed id is: 1316602805183616 (16digit).
Does anyone know why this happens and if its possible to convert the 10digit id to 17digit id or vice versa.
I use intents to detect tag and to resolve intent I use this:
public void resolveIntent(Intent intent){
String action = intent.getAction();
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
||NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
||NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
{
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs;
if(rawMsgs!=null)
{
msgs= new NdefMessage[rawMsgs.length];
for(int i=0; i<rawMsgs.length; i++)
{
msgs[i]=(NdefMessage) rawMsgs[i];
}
}
else
{
byte[] empty = new byte[0];
byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] payload = dumpTagData(tag).getBytes();
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,id,payload);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
msgs= new NdefMessage[] {msg};
}
displayMsgs(msgs);
}}
And this are my helper functions:
private void displayMsgs(NdefMessage[] msgs)
{
if(msgs==null || msgs.length==0) {
return;
}
StringBuilder builder = new StringBuilder();
List<ParsedNdefRecord> records= NdefMessageParser.parse(msgs[0]);
final int size = records.size();
for(int i=0;i<size;i++)
{
ParsedNdefRecord record = records.get(i);
String str = record.str();
builder.append(str).append("\n");
}
text.setText(builder.toString());
}
private String dumpTagData(Tag tag) {
StringBuilder sb = new StringBuilder();
byte[] id = tag.getId();
sb.append("ID (hex): ").append(toHex(id)).append('\n');
sb.append("ID (reversed hex):").append(toReversedHex(id)).append('\n');
sb.append("ID (dec): ").append(toDec(id)).append('\n');
sb.append("ID (reversed dec):").append(toReversedDec(id)).append('\n');
String prefix = "android.nfc.tech.";
sb.append("Technologies: ");
for (String tech: tag.getTechList()) {
sb.append(tech.substring(prefix.length()));
sb.append(", ");
}
sb.delete(sb.length() - 2, sb.length());
for (String tech: tag.getTechList()) {
if (tech.equals(MifareClassic.class.getName())) {
sb.append('\n');
String type = "Unknown";
try {
MifareClassic mifareTag = MifareClassic.get(tag);
switch (mifareTag.getType()) {
case MifareClassic.TYPE_CLASSIC:
type = "Classic";
break;
case MifareClassic.TYPE_PLUS:
type = "Plus";
break;
case MifareClassic.TYPE_PRO:
type = "Pro";
break;
}
sb.append("Mifare Classic type: ");
sb.append(type);
sb.append('\n');
sb.append("Mifare size: ");
sb.append(mifareTag.getSize() + " bytes");
sb.append('\n');
sb.append("Mifare sectors: ");
sb.append(mifareTag.getSectorCount());
sb.append('\n');
sb.append("Mifare blocks: ");
sb.append(mifareTag.getBlockCount());
} catch (Exception e) {
sb.append("Mifare classic error: " + e.getMessage());
}
}
if (tech.equals(MifareUltralight.class.getName())) {
sb.append('\n');
MifareUltralight mifareUlTag = MifareUltralight.get(tag);
String type = "Unknown";
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
type = "Ultralight";
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
type = "Ultralight C";
break;
}
sb.append("Mifare Ultralight type: ");
sb.append(type);
}
}
return sb.toString();
}
private String toHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = bytes.length - 1; i >= 0; --i) {
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
if (i > 0) {
sb.append(" ");
}
}
return sb.toString();
}
private String toReversedHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; ++i) {
if (i > 0) {
sb.append(" ");
}
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
}
return sb.toString();
}
private long toDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = 0; i < bytes.length; ++i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}
private long toReversedDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = bytes.length - 1; i >= 0; --i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}`
EDIT: I managed to resolve this issue by truncating the 7-byte HEX ID to 4-bytes.
And then formating the decimal ID if its total lenght is less than 10 digits with this statement that basically adds zeroes from left side if DEC ID is smaller than 10 digits:
String strFinal=String.format("%010d", Long.parseLong(str));
This document that describes how the ID is converted from HEX8 TO DEC10 helped me alot aswell: https://www.batag.com/download/rfidreader/LF/RAD-A200-R00-125kHz.8H10D.EM.V1.1.pdf
And a huge thanks to #Andrew and #Karam for helping me resolve this!
The card reader on the PC is configured wrong, it is configured by default to display the ID as 10 digit decimal number (4 byte) when the card has a 7 byte ID.
It thus has to loose some data, it is doing this by truncating the ID to the first 4 bytes of the 7 byte ID
Use the software on the PC change the output format to something suitable for the ID size on the Mifare Ultralight C cards (8 Hex?)
or
Use Mifare Classic cards instead as these had 4 byte ID
or
truncate the 7 byte ID to 4 bytes e.g. change bytes.length to 4 (a hard coding to the first 4 bytes in the 7 byte ID) in your code and handle the fact that there is a very large number (around 16.7 million) of Mifare Ultralight C cards that will seem to have the same "ID" as you want to display it
This is because the spec's give by a seller on Amazon https://www.amazon.co.uk/Chafon-CF-RS103-Multiple-Support-Compatible-Black/dp/B017VXVZ66 (I cannot find any details on the manufacturer's site)
It says "Default output 10 digit Dec, control output format through software. "
"Support with windows,linux and android system, but can only set output format in windows pcs.No programming and software required, just plug and play. "
The only sensible answer is move everything to use a 7 byte ID.
I don't know why are you trying always to convert to decimal?
and please try to explain more about the code you use to read the UID.
about your numbers and to convert 17 digits to 10 digits; I convert both of them to Hex:
36139312876727556(17digit) in Hex : 8064837A71AD04.
2054270212(10 digit) in Hex: 7A71AD04
as you notice you can just tirm first three bytes to get the 10 digits.
and I do belive the both of them are not the UID. but the 7bytes as sayed Andrew, and you already read it in the your photo : (04:B5:71:7A:83:64:80)
So I think the answer is that because you are converting a 7 byte ID to decimal you are getting variable lengths of numbers because of the conversion to decimal.
"The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive)."
From https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Could generate a decimal number with 1,2 or 3 characters thus as decimal the id can vary in length.
It also looks like that conversion is going wrong as in theory it should have negative numbers in there as well.
It is much better to handle it as a hex string if you want it to be human readable.
The correct method in Java to convert the 2 pages of the ID to hex is
StringBuilder Uid;
for (int i = 0; i < result.length; i++) {
// byte 4 is a check byte
if (i == 3) continue;
Uid.append(String.format("%02X ", result[i]));
}
Note as per the spec sheet of the card https://www.nxp.com/docs/en/data-sheet/MF0ICU2_SDS.pdf (Section 7.3.1)
There is check byte that is part of the ID, while this will always be the same on the same card and will still give you a unique ID it is technically not part of the ID.
Or if not reading at a low level then
https://developer.android.com/reference/android/nfc/Tag#getId()
will get you the id.
Note that the "36139312876727556(17digit) and reversed id" when converted to hex and reversed actual is 7 bytes and start with the right number.
The 10 digit just looks like the first 4 bytes of the 7 byte number also reversed.

Sqlite real data invalid(cannot reproduce)

I have text file and I convert it to insert query with transaction (thousands record).
The insert query I used is wrap with transaction like this.
public static void bulkInsert(DatabaseWrapper db, String tableName, String[] columns, String[][] values){
StringBuilder stringBuilder = new StringBuilder();
int index = 0;
String head = "INSERT OR REPLACE INTO " + tableName + " (" + TextUtils.join(",", columns) + ") VALUES ";
while (index < values.length) {
stringBuilder.setLength(0);
stringBuilder.append(head);
for (int i = 0; i < 500; i++) {
if (index < values.length) {
if (i != 0) stringBuilder.append(",");
stringBuilder.append("(").append(TextUtils.join(",",values[index])).append(")");
} else {
break;
}
index++;
}
db.execSQL(stringBuilder.toString());
}
}
then I found that single record out of 3964 records that has real value from 10.86 become 1.95223612752995e-314 but the others look fine.
I have no clue what happen here.
Edited1
Example of text file are like this
1004500803 KH1 001 P01 344 8850123136016 0000 0000010.86 00000 00000
0054 30082017080
1004500803 KH1 001 P01 345 8850123136023 0000 0000010.86 00000 00000
0055 30082017077
1004500803 KH1 001 P01 199 8850123123337 0001 0000007.24 00000 00000
0061 30082017081
1004500803 KH1 001 P01 032 8850123130410 0000 0000010.86 00000 00000
0065 30082017074
1004500803 KH1 001 P01 383 8850123135040 0001 0000010.86 00000 00000
0071 30082017074
each position of text data are fix in code so decided to convert column name and value into array of string
String[][] fileValues;
fileValues = PRS.getValueArrays();
public String[][] getValueArrays() {
try {
File file = new File(Constant.Path.MASTER_FILE_PATH, getFileName());
List<String[]> list = new ArrayList<>();
if (file.exists()) {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "TIS-620"));
String line;
while ((line = br.readLine()) != null && !line.isEmpty() && !line.contains("EOF")) {
String[] valueArray = new String[fileIndex.length];
for (int i = 0; i < fileIndex.length - 1; i++) {
valueArray[i] = line.substring(fileIndex[i], fileIndex[i + 1]).trim();
}
valueArray[fileIndex.length - 1] = line.substring(fileIndex[fileIndex.length - 1], lineLength).trim();
list.add(valueArray);
}
br.close();
String[][] valueList = new String[list.size()][];
return list.toArray(valueList);
}
} catch (IOException | NullPointerException e) {
e.printStackTrace();
}
return null;
}
and this is function i parse text file to string arrays (may have some business logic)
public static String[][] parsePrsFileToPresaleValues(String[][] fileValue) {
String[][] result = new String[fileValue.length][];
sumRawPrice = 0;
for (int i = 0; i < fileValue.length; i++) {
String[] fromFile = fileValue[i];
double price = Double.parseDouble(fromFile[7]);
sumRawPrice += price;
result[i] = getPresaleValue(
fromFile[0],
fromFile[5],
Integer.parseInt(fromFile[6]),
fromFile[8].equals("00000") ? 9999 : fromFile[8].equals("99999") ? 0 : Integer.parseInt(fromFile[8]),
fromFile[9].equals("99999") ? 9999 : fromFile[9].equals("00000") ? 0 : Integer.parseInt(fromFile[9]),
price
);
}
return result;
}
and call bulk insert like this
public static void insertData(DatabaseWrapper db) {
db.beginTransaction();
DbUtil.bulkInsert(db, Presale.NAME, Presale.INSERT_COLUMN, Presale.parsePrsFileToPresaleValues(fileValues));
db.setTransactionSuccessful();
db.endTransaction();
}
this is the result of insert statement string
INSERT OR REPLACE INTO price_methods (code,item_code,promotion_code,price,created_at,updated_at) VALUES ('KB0','8850123110108','000',24.67,1503503909093,1503503909093),('KB0','8850123110115','000',12.71,1503503909101,1503503909101)
Edited2
By the way it's not happen all the time.
This app running like two years and insert data like this about 10k record per day and work fine until this happened
The internal representation of your value has some variance because it can't be represented exactly as a binary floating point number. This is especially a problem if you are casting it between double/float etc.
You haven't posted all of your code so firstly make sure you use the correct column type that suits your usage. Also consider using BigDecimal within your application to take advantage of methods such as its scaling

How to check word in android

example i have
String = "makan"
how to check last character is "n"
and character number 4 = "a"
and character number 3 = "k"
how to check third charcter of last word,
thanks
You can use the strings method as
char c= "string".charAt(index);
To get the characters in the string.
Edit
You can get the string as array of char as-
String str = "string";
char[] charArray = str.toCharArray();
It depends on the language you are using, but in general read the character by index number (-1 because they start at 0) using []. Or with charAt like Sanjeet said.
Java:
String name = "makan";
bool lastCharacterIsN = name[name.length - 1] == 'n';
bool fourthCharacterIsA = name[3] == 'a';
bool thirdCharacterIsK = name[2] == 'k';
Javascript:
var name = "makan";
var lastCharacterIsN = name[name.length - 1] === 'n';
var fourthCharacterIsA = name[3] === 'a';
var thirdCharacterIsK = name[2] === 'k';
You can do this very simply like this.
String _makan = "makan";
int _length = _makan.length();
System.out.println(" Index of n " +_makan.indexOf("n"));
System.out.println("Length of String : " + _length);
System.out.println("character at last : " + _makan.charAt(_length-1));
System.out.println("character number 3 : " + _makan.charAt(2));
System.out.println("character number 4: " + _makan.charAt(3));

How get Mifare Ultralight 16 digits UID reading with Nexus 5

I'm very new in NFC for Android. I need very much code example or good tutorial for Java for how get Mifare Ultralight 16 digits UID reading with Nexus 5
I only know how to get 7 digits UID for MifareClassic from here
Reading the tag UID of Mifare classic card, but there is no examples for Mifare Ultralight.
This is another example to get UID for Mifare Classic. What do I need to change to make it read for Mifare Ultralight? And I don't understand what performs in ByteArrayToHexString()
byte[] nfcUID = null;
if (intent != null && (nfcUID = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)) != null) {
uid = ByteArrayToHexString(nfcUID);
private String ByteArrayToHexString(byte[] inarray) { // converts byte arrays to string
int i, j, in;
String[] hex = {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
};
String out = "";
for (j = 0; j < inarray.length; ++j) {
in = inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out += hex[i];
i = in & 0x0f;
out += hex[i];
}
return out;
}
Thank you very much!
First of all, MIFARE Classic tags usually have a 4 byte UID (also called nUID). Newer MIFARE Classic tags also have 7 byte UIDs. MIFARE Ultralight tags always have a 7 byte UID.
This UID is what you will get from
byte[] uid = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Or from
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] uid = tag.getId();
If you convert that UID into hexadecimal digits (as you indicated with the method in your post), you will get:
an 8 digit number if the UID has 4 bytes, or
a 14 digit number if the UID has 7 bytes.
So there is no way that you can get a 16 digit hexadecimal number for a MIFARE Ultralight tag.
As MIFARE Ultrlaight UIDs (or actually any 7 byte UIDs from NXP) have the form 0x04xxxxxxxxxxxx, converting this to a decimal number would give you at maximum a 16 digit number (0x04FFFFFFFFFFFF = 1407374883553279). So you might be trying to achieve this. However, converting a 4 byte UID to decimal would still not result in a 7 digit number.
Converting to hexadecimal representation
You could use something like this to convert the UID from byte array to a string of hexadecimal digits:
public static String convertByteArrayToHexString (byte[] b) {
if (b != null) {
StringBuilder s = new StringBuilder(2 * b.length);
for (int i = 0; i < b.length; ++i) {
final String t = Integer.toHexString(b[i]);
final int l = t.length();
if (l > 2) {
s.append(t.substring(l - 2));
} else {
if (l == 1) {
s.append("0");
}
s.append(t);
}
}
return s.toString();
} else {
return "";
}
}
This method takes each byte of the byte array, converts it to a 2-digit hexadecimal number and concatenates all these 2-digit numbers into a string.
Converting to decimal representation
public static String convertByteArrayToDecString (byte[] b) {
if (b != null) {
BigInteger n = new BigInteger(1, b);
return n.toString();
} else {
return "";
}
}

What the value mean convert from string to Hex for BLE?

I am developing BLE in Android.
And I try to send string value to BLE device
It seem the string need to convert to byte before send to BLE device.
I found some code like the following , the code seems can convert the string value to byte.
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);
}
I call the above function before send the string to the BLE device like the following code.
byte[] value = parseHex(text);
mCharacteristic.setValue(value);
mBluetoothGatt.writeCharacteristic(mCharacteristic);
The BLE device will show the value which I have send to it. But the value is strange and I did not under stand what it mean.
The value what I send and the value show from BLE device are like the following.
Send BLE Show
1 1
2 2
9 9
10 16
11 17
20 32
30 48
40 64
70 112
90 144
99 153
100 16
I did not understand what the value mean show on BLE device...
Does someone help me ?
You are sending the hex values, which is a base 16 system, but your BLE Show values are in decimal.
Therefore sending 10 in hex is 1*16+0*1=16 in decimal. Similarly, 99 is 9*16+9*1=153 in decimal

Categories

Resources