I am using my Android app to launch a native binary. I would like to display the output of that binary in a small window in my application. How would I go about either displaying the output in a TextView or showing the terminal in a small window (preferred)?
Thanks.
The gist of the article that Alex linked to is that Runtime.exec() returns a Process object, which lets you get the process' standard output (and stderr, too) as Java streams via Process.getOutputStream()/getErrorStream(). Get them, read them in a thread (they do properly block - you don't want to block the UI thread), pass the data back to the UI thread. Much, much better. I rescind my previous answer.
The article also recommends wrapping the stream in a BufferedReader so that you can do readLine.
Here's one scheme. NDK is not necessary for this one.
You create a temporary file in your app's data dir. You run the binary, specifying the same file as an output direction in the command line using Runtime.exec(). The command line you'll have to specify would invoke not the binary itself, but sh, and one of the command line parameters would be a redirection: >myfile.txt.
You then start a worker thread that reads the same file. You'll need to carefully implement new data detection - as this is a file, not a pipe, the reading operation will simply terminate once the end of file is reached; it won't block until new data appears.
Then you pass the data from the worker thread using Activity.runOnUiThread() or Handler.post() to the main thread, where it's used to update TextView's content.
A cleaner way would involve creating a pipe pair with mkfifo() and redirecting output in place using dup2() from a pipe handle to the file handle value 1 (stdout). That's how they normally do it in the C/Linux world. There's probably an Android example out there, I've never done that.
Oh, and before you do all that, make sure the binary does not have a more palatable interface. More often than not, Linux binaries are based on a static/dynamic library where all the yummy functionality is, one that can be linked with and called directly.
EDIT: Especially if it's logcat. There are other ways to read a log in Android.
Related
If something happens in my app I want to kill the app there and then. In swift I can use fatalError(), is there a java equivalent?
I don't there's any method equivalent to fatalError in Android.
If you want to kill the entire process then you can use android.os.Process.killProcess(android.os.Process.myPid());.
To mimic the same behaviour of fatalError you'll probably have to implement it yourself.
The behaviour you'll need to add besides killing the process is
to log a message, you can to this by using Log
print the file and line number, for this you can follow this thread on SO
Kotlin's Preconditions.kt file includes an error(message: Any) function that, in turn, throws an IllegalStateException[1].
As long as you're not swallowing the exception, it should kill the app much like fatalError().
[1] Source code
I am reading a small .json file with a couple of lines in it. It is stored on the user's device in the internal app folder.
all I do is this:
JSONObject jsonObject = new JSONObject(MyUtils.inputStreamToString(MyUtils.fileToFileInputStream(context.getFileStreamPath("last_update.json"))));
dateOfLastUpdate = jsonObject.getString("lastUpdate");
At the moment I've wrapped an async task around it.
What if I remove the async task and run this on the main UI thread?
Should we ALWAYS async ALL I/O operations?
Yes, you should always use async operations for I/O.
The only reasonable exception I can think about - is when you have some kind of configuration/key file that you need to read before showing any type of UI.
Consider these arguments in support of AsyncTask:
What happens if there is a problem with the FS? I imagine you would want a "Loading.." animation to play, with, possibly an option to cancel? In case of main-thread access you will just have a app freeze.
You currently have only the "lastUpdate" field in your file, hence it's small, and it may be tempting to read it directly (takes no time at all). Do your co-developers know it has to remain small? Are you enforcing it somehow? Small "just one line to store" files have the tendency to grow into huge configuration files with time. It's better to just make access async now, since it doesn't tax you to do so.
Consider what happens if you change the storage medium. It's on the FS now, maybe you'll have to move it to the cloud in the future? Or the new Android comes with special "slower but cheaper" long-term storage? Would you rather be sure that it still "just works", or hunt down every invocation in your app to make sure they're all async and won't fail in runtime?
All in all - leaving it as an async task doesn't hurt you - but protects against a lot of potential headaches in the future.
In my app, I have an Activity, which is basically a form for the user to enter data which is then inserted into a database table via a ContentResolver. How do I test this Activity?
My first attempt was to use ActivityInstrumentationTestCase2 which gives me full instrumentation to simulate entering data. However, the underlying ContentProvider is not closed and destroyed between each test, which leaves the database in an unknown state at the beginning of subsequent tests.
My second attempt was to use ActivityUnitTestCase and inject a mock context that can clean up the database for each test. However, this doesn't allow me to enter text or click on buttons in the activity as it is never actually drawn on the test device.
Does anyone have any suggestions about what else I can try?
it seems that what you've been using is intended for library development
You should look at the monkey binary here , which works great for me.
If you're not satisfied with it you could use monkeyRunner which provides more control over the tests you're running.
Edit :
As far as the database testing goes , cant you use the sqlite3 binary for a simple query after each test?
Edit2:
I am thinking of a .sh script that does the following :
Runs monkey for a while - you can specify the number of events for the monkey to send
Invoke sqlite3 with a query that would check the database integrity into a log file (sqlite3 command can take sql query as a second parameter, and you can use ">" to write the output into some file)
Repeat.
There are tons of examples for .sh scripting on the net so you shouldn't have problem with that.
I am assuming you're doing all this in adb shell, but if you're not, make sure to set all your environment variables correctly. Particularly ANDROID_ROOT, ANDROID_ASSETS and ANDROID_DATA should be set to "/system","/system/app" and "/data" accordingly . Also don't forget to "chmod" the .sh file to be executable ( chmod 777 file.sh ).
Another suggestion is to generate and keep track of the monkey random seeds so you can repeat certain inputs that are causing you problems. You can specify a seed with -s parameter.
To run system Command like "ping" in android device , we can use Process to execute them.
I have difficulty in accessing that data which is replied by system for systme commands.
how to set that data in proper format? how to access it and store in different type of variables?
You might want to look at Root Tools - they make it dead simple.
Edit: Ofcourse this works also for non-root commands on non-root devices ... look at getShell(boolean wantRoot)
I assume you executed your command by getting the DataOutputStream for the process. The same way, you can get the command's output by getting the DataInputStream for the same process. However, this will show you all the output. You will have to implement separate logic to parse through this output, make some sense of it and further process it. I suggest you first get the DataInputStream and print out the output, so you get a better idea. There is no easy way to do this, except probably the answer from Eugen Rieck.
Suppose I have an array of shorts of length 1,000,000 and that I need this to be generated or loaded into RAM (ideally within a few seconds) when my app starts and before I get an activity thread timeout.
I'll then have quick access to its entries during runtime.
How would you go about loading this to memory from file? Loading from txt file? From an SQLite file (with two integer columns in a single table, one for index and the other for value)?
Is it possible for an activity to request a longer idle time before it's deemed to have timed out?
The solution to your problem would be to spawn a thread to do the file reading. This is going to be a high level overview so you can track down the relevant items. It will address item 2 first, then item 1.
First, you need to get your long running processing off the UI thread. The 'idle' time responsiveness issue (application not responding) is because you are tying up the UI thread which is needed to do other actions. The thread cannot be reading a file and drawing the screen at the same time (at least not well).
I've found the easiest way to do this is using the Java ExecutorServices. What you want to do is package the logic for reading the file or database into a java Runnable or Callable and then run that using an ExecutorService. The executor will take care of starting a thread and reclaiming those resource when they are no longer in use.
One key issue to be aware of is that, once you create another thread, you need to be careful when updating the UI. Because ui objects are not thread safe, you can only update the ui from the UI thread (common sense, right?). If you are in an activity, you can do this by calling runOnUiThread() or you can create your own Handler in one of the ACtivity methods called by the UI thread in the first place.
Sam Dufel said:
Hmm... You could really pack that down if you could come with a format to replace all the dummy entries with just a count. Eg, 10,000 zeros get replaced by a pair of flag bytes followed by 10,000
Additionally, you may see increased speed by spawning multiple read threads. If you could break the file up into two files which would allow two threads to execute simultaneously you could see a significant speed up (depending on what else you need to do to the data). A sort of divide an conquer for loading up your data from file. A cursory google search should give you information on how to load shorts from a file. You should most definitely consider using a binary format given your specifications.