Reading contents of DataOutputStream - android

Can anyone tell me if there is a way to read/output the contents of a DataOutputStream? I am obtaining one using
new DataOutputStream( httpUrlConnection.getOutputStream() );
and am writing some post data to it. I would like to be able to see what data i am posting after writing to this output stream but cannot find a simple way.
Thanks for any help!

Sure you can 'see' the 'contents' of a DataOutputStream - I imagine it wouldn't be what you expected though! I imagine what you want to be able to do is examine the data getting passed through the stream, quite impossible with the regular class - indeed the very definition of a stream is that it doesn't contain all the data being managed by it, at any one time.
If you really need to be able to audit the data that you've supplied to any output stream then you could do something like this:
import java.io.DataOutputStream;
public class WatcherOutputStream extends DataOutputStream {
private byte[] data = null;
public WatcherOutputStream(OutputStream delegateStream) {
super(delegateStream);
}
public void write(byte[] b) {
// Store the bytes internally
// Pass off to delegate
super.write(b);
}
}
The data saving code and remaining write methods are left to you as an exercise. Of course, this is a horrible way to track the data you are writing out to the stream - it's an extra layer of overhead in both memory and speed. Another options would be to use AOP to examine the data as you write it. This method has the advantages of being less intrusive to your code, and easily maintainable in that you can easily add and remove point cuts without modifying your main program. I suspect that AOP may be more complicated a solution than you are looking for right now, but I am including this link to more reading, just in case it will be helpful.

Related

How to use libstagefright's MediaBuffer properly?

I:
Create android::MediaBufferGroup;
Fill it up with multiple buf_group.add_buffer(new android::MediaBuffer(bufsize)); on initialisation;
Do buf_group->acquire_buffer(&buffer) when I need a buffer to send somewhere;
Use buffer->data() to get actual memory location to store the data at, use set_range and set up metadata, then feed the buffer into other component;
That other component releases the buffer, retuning them back to the MediaBufferGroup.
It works, but not reliably. Sometimes acquired buffer's data() returns NULL, sometimes the program crashes on release()...
How to use MediaBufferGroup properly? Should I use some synchronization?
Almost all your steps are correct. The one point which is not clear is in step 4. Typically, MediaBuffer is pulled by a consumer from a producer through a read call. So, I presume in your setup,
All steps mentioned above are performed by the producer
Consumer invokes mSource->read(&newBuffer); where newBuffer is defined as MediaBuffer *newBuffer;
At producer's end, MediaBuffer *mBuffer;. The read call would be processed and output shall be populated as *out = mBuffer;.
For safety, please initialize mBuffer to NULL after this step.
After consuming the buffer, the consumer shall release the buffer newBuffer->release;
Again, for safety, please initialize newBuffer to NULL after this step.
With these changes, I presume your code should work fine based on your description.
MediaBuffer is a basic container in stagefright framework.
About the usage of MediaBuffer/MediaBufferGroup/MediaSource, There are some simple examples code under the ASOP frameworks/av/cmds/stagefright.
Pay attention to the implementation of class SineSource and its usage.

Can I read a local text file line by line into a string array?

The question "How to read a local (res/raw) file line by line?" deals with a similar issue but I was unable to construct a solution base on the answers provided there. I did get a very useful piece of info (the DataInputStream class which has a readLine method), and I have been researching this on the developer website and trying to make it work.
What I am trying to do is read information stored in successive lines of a text file into a string array, such that the first line is the first array element, the second line is the next array element, etc... and then this string array is going to be used to populate text fields in the next activity that is opened. This is all happening inside of a switch case (depending on the case i.e. which list item is selected, a different text file is loaded).
Here is what I have so far:
//Retrieve necessary text file for inputstream
InputStream buildinginfo = getResources().openRawResource(R.raw.testbuilding);
class DataInputStream extends FilterInputStream{
protected DataInputStream(InputStream buildinginfo) {
super(buildinginfo);
// TODO Auto-generated constructor stub
int i;
String[] building_info;
//Assign lines of text to array
for(i=0; i<5; i++){
building_info[i] = buildinginfo.readLine();
}
}
}
So far the editor is okay with it except for these errors, and I am not experienced enough to make sense of them. I understand what they are saying but not how to fix them. The errors are in the section inside the switch case where I am trying to set up the input stream and assign the values.
Most importantly, in the line where the readLine command takes place, I get:
"- The method readLine is undefined for the type DataInputStream"
"- The method readLine is undefined for the type InputStream"
This I do not understand because if I am not mistaken, it says here (http://developer.android.com/reference/java/io/DataInputStream.html) that the DataInputStream class has the readLine method available (I found out about this from the question referred to above). Obviously I have not used the DataInputStream correctly, but I can't seem to figure out how. I have looked through several questions on here and referred to the page linked above several times.
If anybody can see what I am doing wrong I would appreciate your help very much. If I am barking up the wrong tree entirely for this type of task, I apologize for wasting time, but some guidelines or a referral to an appropriate tutorial resource would be much appreciated. I have spent the last two days trying to figure out these errors.
Okay, so nobody else has helped you out here ... here goes.
Essentially you've made a wrong turn in your understanding of how to use API classes.
Your code is attempting to define the DataInputStream class. You want to use the one that is already provided by the API instead. By redefining the class you are actually masking the API class (you definitely don't want that).
So if you look at the documentation for DataInputStream you'll see a constructor. This allows you to create an instance of a class. This is what you want instead :)
InputStream buildinginfo = getResources().openRawResource(R.raw.testbuilding);
DataInputStream myDIS = new DataInputStream(buildinginfo);
//you've now got an instance of DataInputStream called myDIS
String firstString = myDIS.readLine();
//voila ... your firstString variable should contain some text
There's also an issue with you array code ... but I would not use an array in this way.
You should use ArrayList, then read the lines in a while loop so you don't need to tinker with the size.
First let's get rid of this line (I'll comment it out:
//String firstString = myDIS.readLine();
And create an instance of an ArrayList which is a template class so note the String in the angle brackets denotes what sort of elements we want in our array:
ArrayList<String> list = new ArrayList<String>();
You can use the add method to add elements to the arraylist.
We're going to do the whole thing in one go, don't worry I'll explain after ...
String myLine; //declare a variable
//now loop through and check if we have input, if so append it to list
while((myLine=myDIS.readline())!=null) list.add(myLine);
The last line is a bit chewy but when you assign the myLine variable this returns a result which you can compare with NULL ... once the last line is read, the readline function will return null. The condition of the while loop equates to false and drops out of the loop.
There is a simple helper function called toArray to turn your array list into a simple array.
String[] myStringArray = list.toArray(new String[list.size()])
You now have the desired output. I would suggest watching some videos on Android to get a general feel for the language, but I hope this helped you inderstand where the mistake was.

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

Using multiple methods in a transaction

I'm making an Android app, which gets its information from XML files.
I'm filling the information in a database, for easier acces during the program's runtime, thanks to the power of queries.
However it came to my attention, that using Transactions greatly improves speed, so naturally, I want to use that.
My problem is the following tho;
In the idea of abstraction, after parsing all the information of one subject, the information gets send to the correct entity (class), and inside that entity there is a method that will add it in the database. After that, it returns to the parser which continues to read the next subject, which in it's turn will be send to right (and probably different) class again.
This is implemented with a switch statement, with every case pointing to a different class constructor.
If I want to use the speed of transactions, I would need to start a transaction already before the parsing, run through the parsing and query building (as far as I understand, all queries build within the transaction, are collected and in the end all executed as a bunch) and then end the transaction, once the whole file is parsed.
To make this a bit clearer, or faster to read; The code idea would be;
Class parser(){
database.beginTransaction();
try{
// start parsing in a whole different class, which also points to SQL queries (in different classes again) in the entitys with a switch
}catch(Exception e){
database.endTransaction();
}
database.endTransaction();
}
I hope i formulated my question clearly enough.
Kind regards,
Yes, you've got the general idea. However, you need to be careful to mark the transaction as successful when you finish parsing, and also to ensure the transaction is always closed even in the event of an exception.
Example from the docs:
db.beginTransaction();
try {
// do all the parsing in here
...
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}

How to pass binary data between two apps using Content Provider?

I need to pass some binary data between two android apps using Content Provider (sharedUserId is not an option).
I would prefer not to pass the data (a savegame stored as a file, small in size < 20k) as a file (ie. overriding openFile()) since this would necessitate some complicated temp-file scheme to cope with concurrency with several content provider accesses and a running game.
I would like to read the file into memory under a mutex lock and then pass the binary array in the simplest way possible.
How do I do this?
It seems creating a file in memory is not a possibility due to the return type of openFile().
query() needs to return a Cursor. Using MatrixCursor is not possible since it applies toString() to all stored objects when reading it.
What do I need to do? Implement a custom Cursor? This class has 30 abstract methods.
Do I read the file, put it in a SQLite db and return the cursor?
The complexity of this seemingly simple task is mindboggling.
Why not giving the data as Base64 string?
Have you tried using streams? That will work
From the documentation:
"If the table entry is a content: URI, you should never try to open and read the file directly (for one thing, permissions problems can make this fail). Instead, you should call ContentResolver.openInputStream() to get an InputStream object that you can use to read the data."
Link: http://developer.android.com/guide/topics/providers/content-providers.html
Maybe something like this, if you are using Intents:
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
InputStream is = getContentResolver().openInputStream(intent.getData())
...

Categories

Resources