how to send protobuf as part of XML - android

i have create a protobuf sample code in android as follows
Person john =
Person.newBuilder()
.setId(1234)
.setName("John Doe")
.setEmail("jdoe#example.com")
.addPhone(
Person.PhoneNumber.newBuilder()
.setNumber("555-4321")
.setType(Person.PhoneType.HOME))
.build();
now i want to send this john object as a part of xml building block over network
so far i have seen following methods so that i can send bytes over network
john.toByteArray() and john.toByteString()
but i think when i will embed into xml tag as follows it will be the string representation only and from that i can not get the data back
"<data>" + john.toByteArray() + "</data>"
so how can i pass the protobuf message with XML ?
note: i don't want to use the base64 encoding as it will eventually increasing the size of a block

The fundamental problem here is that protobuf encoding is binary while XML is text. You can't embed binary data directly into text; you need to encode it as text somehow.
Unfortunately, there is simply no way to do that without increasing the data size. If size is your concern, base64 is likely your best option -- this is exactly what it was designed to do.
Another possibility would be to encode the message in protobuf text format using .toString() and then parse it using com.google.protobuf.TextFormat. This will produce a human-readable encoding, but it will be much larger than the binary encoding.
Yet another option would be to write a custom translator which uses the protobuf reflection iterfaces (e.g. com.google.protobuf.Message#getField()) to read individual fields and convert them to nested XML elements. However, this is complicated and will probably end up taking even more space than protobuf text format.

These are the options that I'm aware of:
using this 3rd party library.
With this method, you can generate xml that you can embed in your outer xml
using the TextFormat API, though parsing seem to be possible only in c.
from protobuf to string format:
TextFormat.shortDebugString((myProtobufMessage);
from string format to protobufm in c++ code
TextFormat:parseFromString(dataString, &myProtobufMessage);
(I didn't try this myself, but I saw this reference).
With this method you generate a String that you can embed in your XML, and on the receiving end, take that String and convert it to protobuf Message objects.
using protobuf > binary > base64 - instead of xml altogether. You can probably send all the data in the wrapping XML inside the protobuf message. This is what I do.
With this method you can forget about XML and use protobuf for everything. This is the original purpose of protobuf, and this is what it is best for.

Related

Is there a way to add XML code to an XML file from a Kotlin code?

The question might seem incomprehensible just from the title alone so let me elaborate on what I mean. From what little I've dabbled in HTML and JavaScript, you could add HTML lines to the HTML file from using a Javascript function in the script.js file and it would add those HTML lines you've written into the function to the HTML file on execution and it would work as if you've written it in the HTML file to begin with. That was my understanding of how it worked, at least, if I'm wrong on my assessment feel free to correct me on that matter.
Anyway, I'm wondering if we could do a similar thing in Android Studio where we can use a Kotlin function to add an XML line/attribute/command like 'app:srcCompat="#drawable/whatever"' to an XML file.
Of course the question doesn't come from a mere sense of wonder. I currently have an application with a fragment that's supposed to get some football teams from the Room database and display them in CardViews using RecyclerView. In those cards, the team's name and their logo should be displayed. I don't have logos as image files in the Room database itself, however there is a column that stores the names of the drawable files in which the team logos are stored. (For example: Team A's logo is stored in the drawable's as 'teama.png' and it has 'teama' stored in a column.)
In the Adapter class of the RecyclerView, I want to use the bind() function to put the name and the logo on the cards. What I'm expecting to do (related to my question overall) is using a function that can take a string parameter ("app:srcCompat="#drawable/teama"") and puts it to the XML file of my team item. Is this possible? I'm open to other solutions as well and can post code if requested.
Thank you for your answer beforehand.
Is there a way to add XML code to an XML file from a Kotlin code?
Yes, but not in the context of what you are asking.
What I'm expecting to do (related to my question overall) is using a function that can take a string parameter ("app:srcCompat="#drawable/teama"") and puts it to the XML file of my team item. Is this possible?
No. You cannot modify the content of a resource XML file at runtime.
From what little I've dabbled in HTML and JavaScript, you could add HTML lines to the HTML file from using a Javascript function in the script.js file and it would add those HTML lines you've written into the function to the HTML file on execution and it would work as if you've written it in the HTML file to begin with.
JavaScript, run in the browser, does not modify the HTML file on the server. It modifies the DOM: the parsed representation of the HTML that is used by the browser to render a UI on the screen.
Similarly, in Android, you will need to update the View objects — created from parsing that resource XML file — to reflect your desired name and logo. This approach is covered in books and courses on Android app development. FWIW, here is a free book of mine on the subject.
Till now this technology is not available and if it is available it's not that famous and in use

Base64 encoding for post in WebView

I am facing a problem with the encoding of a string. First of all, let me explain the context:
I need to make a post and load the content in a webView. For this requirement I need to use webView.postUrl(String url, byte[] postData).
I saw a lot of examples using this method along with EncodingUtils.getBytes("stringToEncode","base64").
The good news is that this works for me. The bad news is that this class is deprecated and you need to add the next code to the gradle file:
android {
useLibrary 'org.apache.http.legacy'
}
I would like to avoid this and use the way it should be.
As far as I know the replacement for this deprecated class is android.util.Base64.
I tried the next codes without success:
webView.postUrl("url", Base64.encode("paramsToEncode".getBytes(),Base64.DEFAULT));
webView.postUrl("url", Base64.encode("paramsToEncode".getBytes(StandardCharsets.UTF_8),Base64.DEFAULT));
According to the documentation of EncodingUtils:
Converts the specified string to a byte array. If the charset is not
supported the default system charset is used. Parameters: data - the
string to be encoded charset - the desired character encoding Returns:
The resulting byte array.
And the documentation for Base64:
input byte: the data to encode flags int: controls certain features of
the encoded output. Passing DEFAULT results in output that adheres to
RFC 2045. Returns byte[]
So I do not know what I am doing wrong. If you struggled with this kind of problem I would appreciate some comments :).
Not sure why your example doesn't work, but the below code seems to be working for me:
webView.postUrl(url, urlParams.getBytes(Charset.forName("UTF-8")));

Protobuf streaming (lazy serialization) API

We have an Android app that uses Protocol Buffers to store application data. The data format (roughly) is a single protobuf ("container") that contains a list of protobufs ("items") as a repeated field:
message Container {
repeated Item item = 1;
}
When we want to save a change to an item, we must recreate the protobuf container, add all the items to it, then serialize it and write it to a file.
The problem with this a approach is it potentially triples the memory used when saving because the data has to first be copied from the model class to the protobuf builder and then to a byte array when the protobuf is serialized, all before writing it out to a file stream.
What we would like is a way to create our protobuf container and lazily serialize it to a stream, then simply add each protobuf item (created from our model data) to the container which serializes and writes it to the stream, rather than keeping all the items in memory until we've created the entire container in memory.
Is there a way to build a protobuf and serialize it lazily to a stream?
If there's not a way to do this officially, are there any libraries that can help? Does anyone have any suggestions or ideas how to solve this in other ways? Alternative data formats or technologies (e.g. JSON or XML containing protobufs) that would make this possible?
For serialization:
protobuf is an appendable format, with individual items being merged, and repeated items being appended
Therefore, to write a sequence as a lazy stream, all you need to do is repeatedly write the same structure with only one item in the list: serializing a sequence of 200 x "Container with 1 Item" is 100% identical to serializing 1 x "Container with 200 Items".
So: just do that!
For deserialization:
That is technically very easy to read as a stream - it all, however, comes down to which library you are using. For example, I expose this in protobuf-net (a .NET / C# implementation) as Serializer.DeserializeItems<T>, which reads (fully lazy/streaming) a sequence of messages of type T, based on the assumption that they are in the form you describe in the question (so Serializer.DeserializeItems<Item> would be the streaming way that replaces Serializer.Deserialize<Container> - the outermost object kinda doesn't really exist in protobuf)
If this isn't available, but you have access to a raw reader API, what you need to do is:
read one varint for the header - this will be the value 10 (0x0A), i.e. "(1 << 3) | 2" for the field-number (1) and wire-type (2) respectively - so this could also be phrased: "read a single byte from the stream , and check the value is 10"
read one varint for the length of the following item
now:
if the reader API allows you to restrict the maximum number of bytes to process, use this length to specify the length that follows
or wrap the stream API with a length-limiting stream, limited to that length
or just manually read that many bytes, and construct an in-memory stream from the payload
rinse, repeat
There is no such thing. A protobuf is a packed structure. In order to do this effectively it would need all the data. You will have to add the "streaming protocol" yourself. Maybe send a protobuf msg every N items.
In the normal java version of Protocol buffers there is Delimited files where you write Protocol-Buffers one at a time. I am not sure if it is in the Android version
aLocation.writeDelimitedTo(out);
As Marc has indicated it easily implemented; just write a length followed
the serialised bytes. In normal (non android) java version of prortocol-buffers you can also do (you have to serialise to a byte array or something similar)
private CodedOutputStream codedStream = null;
public void write(byte[] bytes) throws IOException {
if (bytes != ConstClass.EMPTY_BYTE_ARRAY) {
codedStream.writeRawVarint32(bytes.length);
codedStream.writeRawBytes(bytes);
codedStream.flush();
}
}
and
private CodedInputStream coded;
public byte[] read() throws IOException {
if (coded == null) {
throw new IOException("Reader has not been opened !!!");
}
if (coded.isAtEnd()) {
return null;
}
return coded.readBytes().toByteArray();
Something may be possible in other Protocol-Buffers versions

Comparing two XML files Android

I want to compare two XML files, they are the same as each other. i have one of them in local storage and using bufferReader i put it on String and i get the other one from server and again put it into the String! then i Print the content of them and they are actually the same! nothing differs even spaces!! but when i compare them ( 2 strings) using equalsIgnoreCase they are not equal and always goes to else! which means they are not equal!
can anybody help on this? if no way to compare like this so how can i compare them?
I think it happens due to formatting issue.
You can use XMLUnit to resolve the issue.
XMLUnit will help you in
The differences between two pieces of XML
The outcome of transforming a piece of XML using XSLT
The evaluation of an XPath expression on a piece of XML
The validity of a piece of XML
Individual nodes in a piece of XML that are exposed by DOM Traversal
Did you tried string1.equals(string2)

Android - Getting data from XML file on the web

I need to get data from an XML file in Android. On the iPhone environment, my code is:
NSURL *thisURL = [[NSURL alloc] initWithString:#"http://www.xxx.com/file.xml"];
NSArray *myArray = [[NSArray alloc] initWithContentsOfURL:providerURL];
myArray is now an array of dictionary items initialized with contents from file.xml.
Is there any way to do this in Android? Can someone point me to doc or sample code?
I'm new to the Android environment and just need some direction.
Thanks,
Kevin
See Working with XML in Android for a variety of methods for dealing with XML. Which method to use depends on how big your XML is, and what you want to do with it. '
I'm not sure how it makes any sense to turn XML into an array, so no, none of the methods do that. If you want something similar to that, use Json instead of XML.
After a bit of research, it appears to me that using the Simple XML Serialization framework is going to be my best bet, especially since I do have a relatively simple XML file to read. The result will be a 'list' class with several 'entry' classes which seems like a viable way to handle this...probably better than having an array of classes as was done in the iPhone app.

Categories

Resources