invalid conversion from 'byte*' to 'byte' - android

invalid conversion from 'byte*' to 'byte'
i have write this arduino function
byte receiveMessage(AndroidAccessory acc,boolean accstates){
if(accstates){
byte rcvmsg[255];
int len = acc.read(rcvmsg, sizeof(rcvmsg), 1);
if (len > 0) {
if (rcvmsg[0] == COMMAND_TEXT) {
if (rcvmsg[1] == TARGET_DEFAULT){
byte textLength = rcvmsg[2];
int textEndIndex = 3 + textLength;
byte theMessage[textLength];
int i=0;
for(int x = 3; x < textEndIndex; x++) {
theMessage[i]=rcvmsg[x];
i++;
delay(250);
}
return theMessage;
delay(250);
}
}
}
}
}
this is the error
In function byte receiveMessage(AndroidAccessory, boolean) invalid conversion from byte*' to 'byte"
this function is to receive the data from the android and return it as a byte array

You need to use dynamic allocation, or pass the array to the function as a parameter which is a better solution in your case
void receiveMessage(AndroidAccessory acc, boolean accstates, byte *theMessage){
if (theMessage == NULL)
return;
if(accstates){
byte rcvmsg[255];
int len = acc.read(rcvmsg, sizeof(rcvmsg), 1);
if (len > 0) {
if (rcvmsg[0] == COMMAND_TEXT) {
if (rcvmsg[1] == TARGET_DEFAULT){
byte textLength = rcvmsg[2];
int textEndIndex = 3 + textLength;
int i=0;
for(int x = 3; x < textEndIndex; x++) {
theMessage[i]=rcvmsg[x];
i++;
delay(250);
}
return;
}
}
}
}
}
with this, you will call the function passing the array to it, for example
byte theMessage[255];
receiveMessage(acc, accstates, theMessage);
/* here the message already contains the data you read in the function */
But you can't return a local variable, because the data is only valid in the scope where the variable is valid, in fact it's invalid right outside the if (rcvmsg[0] == COMMAND_TEXT) block, because you defined it local to that block.
Note: please read Wimmel's comment, or you could set the last byte to '\0' if it's just text, and then use the array as a string.

As far as the error is concerned you are returning the incorrect value.
theMessage is a byte array not a byte
Also the last answers explains why cant you return local variable pointer

Related

Splitting a byte[] into multiple byte[] arrays

I am trying to "chunk" up the bytes of an image. This will allow me to upload a large image in bytes array. I have the image currently stored as one large byte[]. I would like to split the byte array into byte[]'s with a each exactly of 5 MB.
public static byte[][] divideArray(byte[] source, int chunksize) {
byte[][] ret = new byte[(int) Math.ceil(source.length / (double) chunksize)][chunksize];
int start = 0;
int parts = 0;
for (int i = 0; i < ret.length; i++) {
if (start + chunksize > source.length) {
System.arraycopy(source, start, ret[i], 0, source.length - start);
} else {
System.arraycopy(source, start, ret[i], 0, chunksize);
}
start += chunksize;
parts++;
}
Log.d("Parts", parts + "");
return ret;
}
Call It by
divideArray(common.fullyReadFileToBytes(wallpaperDirectory), 5 * 1024 * 1024)
You can use copyOfRange for that:
T[] copyOfRange (T[] original,
int from,
int to);
In your case, something like this:
Byte[] copyOfRange (original,
0,
5000000);
make sure you calculate the offset:
class test {
// this is just for dummy data
public static byte[] getTestBytes() {
byte[] largeByteArray = new byte[50_000_000];
for(int i = 0; i < 50_000_000; i ++) {
largeByteArray[i] = 0;
}
return largeByteArray;
}
// this method splits your byte array into small portions
// and returns a list with those portions
public static List<byte[]> byteToPortions(byte[] largeByteArray) {
// create a list to keep the portions
List<byte[]> byteArrayPortions = new ArrayList<>();
// 5mb is about 5.000.000 bytes
int sizePerPortion = 5_000_000;
int offset = 0;
// split the array
while(offset < largeByteArray.length) {
// into 5 mb portions
byte[] portion = Arrays.copyOfRange(largeByteArray, offset, offset + sizePerPortion);
// update the offset to increment the copied area
offset += sizePerPortion;
// add the byte array portions to the list
byteArrayPortions.add(portion);
}
// return portions
return byteArrayPortions;
}
// create your byte array, and split it to portions
public static void main(String[] args) {
byte[] largeByteArray = getTestBytes();
List<byte[]> portions = byteToPortions(largeByteArray);
// work with your portions
}
}
Something cool: the value to does not have to be an index inside the array, it checks that for you without erroring and copies a subset that is valid to the intended array.
These answers work fine but has optimization issues. They allocate extra space of the whole chunk size irrespective of the only actual bytes of memory the array needs to allocate for copying the data.
Here is the solution for this problem.
private fun divideDataIntoChunks(source: ByteArray, chunkSize: Int): kotlin.collections.ArrayList<ByteArray> {
val result: ArrayList<ByteArray> = ArrayList()
if (chunkSize <= 0) {
result.add(source)
} else {
for (chunk in source.indices step chunkSize) {
result.add(source.copyOfRange(chunk, min(chunk+chunkSize,source.size)))
}
}
return result
}

Arduino send long string to Android

I'm trying to send long String to Android via bluetooth.
but,
It looks like the picture.
some characters are changed.
how can I get an exact full string?
arduino code :
for(int i=0;i<16;i++){
String rec = String(P[i], HEX);
if(rec.length()<2) rec = "0"+rec;
BTSerial.println(rec);
delay(50);
P is a byte array. Thanks.
Try it without String objects:
// return '0' .. 'F'
char hexnibble(byte nibble) {
nibble &= 0x0F; // just to be sure
if (nibble > 9) return 'A' + nibble - 10;
else return '0' + nibble;
}
void loop() {
byte P[16];
// ... fill P somehow ...
char rec[33];
for(int i=0;i<16;i++){
rec[2*i] = hexnibble(P[i] >> 4);
rec[2*i+1] = hexnibble(P[i] & 0x0F);
}
rec[32] = 0; // string terminator
Serial.println(rec); // just for debugging
delay(1000);
}

How to hook system calls of my android app

I want to intercept the connect() system call and use my own custom implementation. The custom implementation will do some action like printing a log for simplicity and then call the system implementation further.
I looked at Audrey's blog where the approach is to patch the PLT. But unfortunately this code is crashing when trying to change the address in the relocation table.
After goggling a while i came across This already answered question. But the approach described here gives me the following error.
*****jump to case label [-fpermissive] jni/test.cpp:107:20: error: crosses initialization of 'uint32_t entry_page_start' jni/test.cpp:106:15: error: crosses initialization of 'uint32_t page_size'*****
the hook call method from the Andrey's blog after the suggested changes Here, looks like this.
int hook_call(char *soname, char *symbol, unsigned newval) {
soinfo *si = NULL;
Elf32_Rel *rel = NULL;
Elf32_Sym *s = NULL;
unsigned int sym_offset = 0;
if (!soname || !symbol || !newval)
return 0;
si = (soinfo*) dlopen(soname, 0);
if (!si)
return 0;
s = soinfo_elf_lookup(si, elfhash(symbol), symbol);
if (!s)
return 0;
sym_offset = s - si->symtab;
rel = si->plt_rel;
/* walk through reloc table, find symbol index matching one we've got */
for (int i = 0; i < si->plt_rel_count; i++, rel++) {
unsigned type = ELF32_R_TYPE(rel->r_info);
unsigned sym = ELF32_R_SYM(rel->r_info);
unsigned reloc = (unsigned)(rel->r_offset + si->base);
unsigned oldval = 0;
if (sym_offset == sym) {
switch(type) {
case R_ARM_JUMP_SLOT:
// YOUR LINES
uint32_t page_size = getpagesize();
uint32_t entry_page_start = reloc& (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
/* we do not have to read original value, but it would be good
idea to make sure it contains what we are looking for */
oldval = *(unsigned*) reloc;
*((unsigned*)reloc) = newval;
return 1;
default:
return 0;
}
What wrong am I doing, Am i putting the mProtect() method at some wrong place ? do we have anyone who has done it with the help of Andrey's blog ? Any other approach ? I am blocked. Any help would be appreciated.
The error hast nothing to do with the mProtect(). This is actually the exact same place I have placed the code snippet as well. Here is my code and it works fine:
void* hook_call(char *soname, char *symbol, void* newval) {
soinfo *si = NULL;
Elf32_Rel *rel = NULL;
Elf32_Sym *s = NULL;
unsigned int sym_offset = 0;
if (!soname || !symbol || !newval)
return 0;
si = (soinfo*) dlopen(soname, RTLD_LAZY);
if (!si)
return 0;
s = soinfo_elf_lookup(si, elfhash(symbol), symbol);
if (!s)
return 0;
sym_offset = s - si->symtab;
rel = si->plt_rel;
const char *strtab = si->strtab;
Elf32_Sym *symtab = si->symtab;
/* walk through reloc table, find symbol index matching one we've got */
int i;
for (i = 0; i < si->plt_rel_count; i++, rel++) {
unsigned type = ELF32_R_TYPE(rel->r_info);
unsigned sym = ELF32_R_SYM(rel->r_info);
unsigned reloc = (unsigned)(rel->r_offset + si->base);
//unsigned oldval = 0;
void* pOldFun;
if (sym_offset == sym) {
switch(type) {
case R_ARM_JUMP_SLOT:
//Set appropriate memory access rights
uint32_t page_size = getpagesize();
uint32_t entry_page_start = reloc& (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
pOldFun = (void *)*((unsigned *)reloc);
*((unsigned int*)reloc)= (unsigned)newval;
return pOldFun;
default:
return 0;
}
}
}
return 0;
}
The *jump to case label ... error: crosses initialization normally occurs when variables are not correctly initilized when using the switch case i.e. initialized in one case and used in another. Have a look at this question. A similar error occurred and was resolved.

Android - Strip extra \r\n's in stream?

Updated question: I am trying to connect to a terminal emulator using a library in android, this will connect to a serial device and should show me sent/received data. I should be able to send data over the connection via a text box below the terminal or by typing in the terminal itself and hitting enter on the keyboard in both cases.
When I was sending data via textbox I had to append \n to the data to get to a new line when I pressed the enter key like so:
mEntry = (EditText) findViewById(R.id.term_entry);
mEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
/* Ignore enter-key-up events. */
if (event != null && event.getAction() == KeyEvent.ACTION_UP) {
return false;
}
Editable e = (Editable) v.getText();
String data = e.toString() + "\n";
sendOverSerial(data.getBytes());
TextKeyListener.clear(e);
return true;
}
});
And the write method:
public void write(byte[] bytes, int offset, int count) {
super.write(bytes, offset, count);
if (isRunning()) {
doLocalEcho(bytes);
}
return;
}
When I was hitting enter after typing in the terminal session itself no new line was occurring at all. So I had to test the data for \r and replace it with \r\n:
private void doLocalEcho(byte[] data) {
String str = new String(data);
appendToEmulator(data, 0, data.length);
notifyUpdate();
}
public void write(byte[] bytes, int offset, int count) {
// Count the number of CRs
String str = new String(bytes);
int numCRs = 0;
for (int i = offset; i < offset + count; ++i) {
if (bytes[i] == '\r') {
++numCRs;
}
}
if (numCRs == 0) {
// No CRs -- just send data as-is
super.write(bytes, offset, count);
if (isRunning()) {
doLocalEcho(bytes);
}
return;
}
// Convert CRs into CRLFs
byte[] translated = new byte[count + numCRs];
int j = 0;
for (int i = offset; i < offset + count; ++i) {
if (bytes[i] == '\r') {
translated[j++] = '\r';
translated[j++] = '\n';
} else {
translated[j++] = bytes[i];
}
}
super.write(translated, 0, translated.length);
// If server echo is off, echo the entered characters locally
if (isRunning()) {
doLocalEcho(translated);
}
}
So that worked fine, now when I typed in the terminal session itself and hit enter i got the newline I wanted. However now every time I send data from the text box with with \n there was an extra space between every newline as well as getting the extra newline.
http://i.imgur.com/gtdIH.png
So I thought that when counting the number of carriage returns peek ahead at the next byte, and if it is '\n' don't count it:
for (int i = offset; i < offset + count; ++i) {
if (bytes[i] == '\r' &&
(
(i+1 < offset + count) && // next byte isn't out of index
(bytes[i+1] != '\n')
) // next byte isn't a new line
)
{
++numCRs;
}
}
This fixed the problem of the spaces...but that was rather stupid as I am now back in a circle to the original problem, if I type directly in the terminal there is no new line, as it sees the \r\n and sees the next byte is invalid. What would be the best way to get both working together? I either have these weird extra spaces and all input is fine, or normal spacing and I can't enter text directly from the terminal, only the textbox. I assume it's really easy to fix, I just am scratching my head looking at it.
EDIT: Not fixed, thought I had but then when I enter directly from the terminal enter does not produce a new line. It must be because the \n is ignored after the \r
I have most of this fixed. When counting the number of carriage returns peek ahead at the next byte, and if it is '\n' don't count it:
for (int i = offset; i < offset + count; ++i) {
if (bytes[i] == '\r' &&
(
(i+1 < offset + count) && // next byte isn't out of index
(bytes[i+1] != '\n')
) // next byte isn't a new line
)
{
++numCRs;
}
}
The only problem left now is that I still get the prompt back twice like this:
switch#
switch#

Parse big xml file in android

In my application there is a search option. If the user enters a search value, I have to get a value from the webservice. I am getting a large webservice value. In my webservice string values are coming. I am getting like <> like xml character entity reference like. I want to replace all characters and parse xml. Can anybody tell me how to do this and give an example?
I tried with StringBuffer for unescapexml character, I am getting out of memory error
public String unescapeXML(String str) {
if (str == null || str.length() == 0)
return "";
StringBuffer buf = new StringBuffer();
int len = str.length();
for (int i = 0; i < len; ++i) {
char c = str.charAt(i);
if (c == '&') {
int pos = str.indexOf(";", i);
if (pos == -1) { // Really evil
buf.append('&');
} else if (str.charAt(i + 1) == '#') {
int val = Integer.parseInt(str.substring(i + 2, pos), 16);
buf.append((char) val);
i = pos;
} else {
String substr = str.substring(i, pos + 1);
if (substr.equals("&"))
buf.append('&');
else if (substr.equals("<"))
buf.append('<');
else if (substr.equals(">"))
buf.append('>');
else if (substr.equals("""))
buf.append('"');
else if (substr.equals("&apos;"))
buf.append('\'');
else if (substr.equals(" "))
buf.append(" ");
else
// ????
buf.append(substr);
i = pos;
}
} else {
buf.append(c);
}
}
return buf.toString();
}
I tried with stream, I am not able to do it. Can anybody give an example how to do this?
You should not parse it on your own. There are better ways - SAX or DOM.
This resource contains a lot of useful inforamtion about these both ways (and code examples too): http://onjava.com/pub/a/onjava/2002/06/26/xml.html
Take a look here in order to get more details about android included parsers :
http://developer.android.com/reference/javax/xml/parsers/package-summary.html
But make your own parser with SAX is probably the best choice in your case ;)

Categories

Resources