So i want to use the MessageApi and not the DataApi to send multiple items to the wearable. However the sendMessage() of the MessageApi only allows a byte array to be sent.
For reference:
Wearable.MessageApi.sendMessage(mGoogleApiClient,
String id,
String path,
byte[] bytes)
My guess would be to create an array of byte arrays and then serialize that into one big byte array and send it off.
To make things clearer these are the steps in pseudo code:
byte[][] arrayOfByteArrays;
String a --> convert to byte[];
Bitmap b --> convert to byte[];
Add a and b byte[]'s to arrayOfByteArrays;
Serialize arrayOfByteArrays to just a byte[] and send it off;
Is this the correct approach? or Should I just call sendMessage() multiple times? Thanks.
In general, it is more efficient (battery, bandwidth, ...) to send one message instead of multiple ones. However, there may be other factors involved in your specific case that may warrant sending multiple messages. Looking at your pseudo code, I noticed you are also trying to send a bitmap using the MessageApi. That, in general, is not the best approach to send across an image, or other types of assets; you can use Assets or you can use ChannelApi. Otherwise, the approach of serializing a bunch of small objects and putting them into one byte array and then desrializing at the other end would work; one simple way to do so (if dealing with simple objects) is to use json as a serialization means.
Related
I want to make a custom sipdroid client by using reverse byte order. I think that makes other Voip clients cannot decode these data.
So I read the code of the SipDroid. I found RTP data goes this way:
1. AudioRecord.read(originalPCM)
2. encode(originalPCM, encodedData)
3. rtp_socket.send(rtp_packet) //the encodeData is rtp_packet's data part
And the other side is:
1. rtp_receive(rtp_packet)
2. decode(encodeData, PCMData) //the encodeData is rtp_packet's data part
3. AudioTrack.write(PCMData)
So I modified the SipdroidSocket class. In send method, I add the following code at the beginning.
byte[] b = pack.getData();
reverse(b);
pack.setData(b);
And add the following code at the end of the receive method.
byte[] b = pack.getData();
reverse(b);
pack.setData(b);
I think in this way, the two client can work as usual. But it failed. And I don't know the reason. Please help me to find out why. Thanks.
You should not reverse the hole buffer unless you receive 2,4,8 bytes at a time.
You should treat the data as elements of 2,4,8 bytes depending on how the data
were stored. The code i see here will not work.
suppose you have a buffer of data bytes 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
stored as 4 byte elements of 0x04030201-0x08070605.
Reversing the hole buffer will produce 0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01
which is wrong because you will end up with 0x05060708-0x04030201
If you reverse one element(4 bytes) at a time.
Keep in mind that the size of an element depends on how the values were stored
Heres my situation:
I have a RESTful WCF service running on my server, the service is meant to get various types of data about people from a database and makes that data available as a single JSON object. It works great!
[EDIT]There is another service that maintains an image cache in the file system on the server. When a request is sent to the RESTful service, that service then requests an image from the image service. If the image is already in the cache (same width, height and person as the request), it returns that (as a byte array). We MUST use this service to retrieve images.
Now what I want is the image of that person. In our database, the image is a long raw (ew). However, I have dealt with that issue already (previous paragraph). The image is now a Byte array. I am pretty new to android and I am not sure what the best way to retrieve this image is. What I thought I could do was add the byte array to the JSON object and then use the base64 decoder to convert it into a drawable image. However, everytime I try, it times out and tells me it expected ',' or ']' at some arbitrary index of the char buffer for the JSON object.
I have been able to pull the small bits of data out of the JSON object without an issue, but now that there is a huge byte array in it, the JSONObject hates me. What would be a better way to get this image from my service?
Base64 encode the byte array to get a string.
Add the string to JSON object and send it.
When JSON is received, get out the string.
Base64 decode it to get back the byte array.
Use byte array to create Image.
See this question on storing images, it's always better to store this sort of data on file system. If possible deprecate that field, and create a script to move existing images to file system.
You should then store the images on a file system (or some sort of content management system) which can be retrieved by a URL.
Then store the URL in the database. you can then send this in your json object.
{
...
image_url:<url from database>
...
}
When the client receives this it will make a call to that URL and download the image.
Your client will have to make a separate call to retrieve the image but it's generally better than filling your database with binary data. This can also work to your advantage if you want to display data fast while allowing the image to be downloaded in the background.
Better than using Base64 encoding is this way of returning Stream (from WCF RAW programming)
[OperationContract, WebGet]
public Stream GetTestImage(Image image)
{
MemoryStream stream = new MemoryStream();
image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
return stream;
}
I'm a little confused about how to send data over a Bluetooth connection. In the Android API documentation, from the Bluetooth Chat example, the class BluetoothChat.java constructs a Handler object. Within there is a switch statement, and a MESSAGE_WRITE case. Do I need to implement similar code to send Strings over Bluetooth? A case statement for each String I want to send? In particular I want to send (name,value) pairs so I know what is sent and what it's value is. How do I implement this? If, following the example, I call BluetoothChatService.write(String.getBytes()) a bunch of times to send...? Then how would I know which strings are associated with which names? Please help.
I'm using Google's Protocol Buffers to send structured data over bluetooth connections in my Android app. protobuf takes care of figuring out how to serialize the message for you so that you only have to send a byte value (length of the message) and then the serialized message; the library takes care of unserializing the message on the other end and populating the fields of a custom object. Definitely take a look at it; it made the writing of a custom bluetooth socket protocol quite easy.
Serialize pairs to any of formats which allows byte representation. Such as XML or JSON. Or even your custom format, it wouldn't be difficult for pairs of strings. And then send it.
For simple pairs of strings (Such as names), you could simply use some character to define when the first string stops, and the next begins.
For example, I use a format such as this to send a set of 3 strings from one device to another:
String toSend = partOne + ":" + partTwo + ":" + partThree;
On the other device, to get the strings you sent, use the String.split() method like so:
String parts[] = received.split(":",3);
The 2nd parameter is a limit to how many times to split. In this example, there are 3 strings, so split 3 times max.
The downside to doing this is that you need to use characters that will never be in all but the last string.
In my application, I used this method to send data about text messages, and the first 2 parts are the phone number and timestamp, so there can never be a : in it. For names, a newline would probably work.
If your going to send more complex data, definitely use something like Protocol Buffers.
My app currently requests a JSON file with some text and other data from my server. I want to add functionality so that it also downloads a very small image (like an icon) through the same file [without creating an additional request]. Is it possible to do so, and how would I go about it (base64?)
Should be eminently reasonable: look at http://developer.android.com/reference/android/util/Base64.html. All you'd need to do is:
Read your icon into a byte[] array on the server.
(Assuming your server is in java) Use something like http://iharder.sourceforge.net/current/java/base64/ to write the byte[] array into a StringOutputStream through http://iharder.sourceforge.net/current/java/base64/api/index.html?Base64.OutputStream.html.
Add the contents of the String to the JSON file.
On the android device call http://developer.android.com/reference/android/util/Base64.html#decode%28java.lang.String,%20int%29 to convert the JSON attribute into a byte[] array.
You can then pass the byte array to http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeByteArray%28byte[],%20int,%20int,%20android.graphics.BitmapFactory.Options%29 or one of its brethren functions (you may have to play with image formats/encodings to get it to swallow your byte array correctly).
Voila! You have a Bitmap you can use.
Let me know how that works out.
I recently created a program that gets medi-large amounts of xml data and converts it into arrays of Strings, then displays the data.
The program works great, but it freezes when it is making the arrays (for around 16 seconds depending on the size).
Is there any way I can optimize my program (Alternatives to string arrays etc.)
3 optimizations that should help:
Threading
If the program freezes it most likely means that you're not using a separate thread to process the large XML file. This means that your app has to wait until this task finishes to respond again.
Instead, create a new thread to process the XML and notify the main thread via a Handler when it's done, or use AsyncTask. This is explained in more detail here.
Data storage
Additionally, a local SQLite database might be more appropriate to store large amounts of data, specially if you don't have to show it all at once. This can be achieved with cursors that are provided by the platform.
Configuration changes
Finally, make sure that your data doesn't have to be reconstructed when a configuration change occurs (such as an orientation change). A persistent SQLite database can help with that, and also these methods.
You can use SAX to process the stream of XML, rather than trying to parse the whole file and generating a DOM in memory.
If you find that you really are using too much memory, and you have a reason to keep the string in memory rather than caching them on disk, there are certainly ways you can reduce the memory requirements. It's a sad fact that Java strings use a lot of space. They require two objects (the string itself and an underlying char array) and use two bytes per char. If your data is mostly 7-bit ASCII, you may be better of leaving it as a UTF-8 encoded byte stream, using 1 byte per character in the typical case.
A very effective scheme is to maintain an array of 32k byte buffers, and append the UTF-8 representation of each new string onto the first empty space in one of those arrays. Your reference to the string becomes a simple integer: PTR = (buffer index * 32k) + (buffer offset). "PTR/32k" yields the index of the desired byte buffer, and "PTR % 32k" yields the location within the buffer. Use either an initial length byte or a null terminator to keep track of how long the string is. When you need to access one of the strings, don't allocate a new String object: unpack it into a mutable StringBuilder or work directly with the UTF-8 byte representation.
The above approach is obviously a lot more work, but can save you between a factor of 2 and 6 in memory usage (depending on the length of your strings). However, you should beware of premature optimization. If your problem is with the processing time to parse your input, or is somewhere else in your program, you could find that you've done a lot of work to fix something that isn't your bottleneck and thus get no improvement at all.