3 WorkShop11_HackFest_Android
Vitalii Koshura edited this page 2023-04-12 19:55:20 +02:00

Android

  1. Installing SDK.

You will want to follow these instructions.

http://developer.android.com/sdk/installing.html

Note, when it asks you for installation directories associated with the android SDK, you should make the directories without spaces in them. This causes issues later that can be resolved but to save a minor headache, create them without spaces.

  1. Install NDK.

Follow the instructions on this page.

http://developer.android.com/sdk/ndk/index.html

Again, install this without spaces in directory names. I installed mine at c:/Android-ndk/

  1. Code Talk.

a. Downloading a file.

To download a file in Java we were able to use simple stream input and output from a URL object.  The code below is pretty straight forward.
//Direct url to download the file from
URL u = new URL("http://home.cddot.net/hello-jni");
URLConnection conn = u.openConnection();
conn.connect();

//File name to save the file.
//Notice the /data/data/com.example.helloandroid/ part of the directory.
//This is the directory of our application to write files into.
//File name saved within this directory could be additional folders.
String filename = "/data/data/com.example.helloandroid/tmpfile.bin";
InputStream input = new BufferedInputStream(u.openStream());
OutputStream output = new FileOutputStream(filename);

byte data[] = new byte[1024];
int count = 0;

//step through the input file and write it to the filename opened earlier.
while((count = input.read(data)) != -1) {
	output.write(data, 0, count);
}

//Clean up file handles.
output.flush();
output.close();
input.close();

a. Change permissions of a file. Next you will be required to change the newly downloaded file into execute mode within the linux environment on the Android OS. To do this is a simple Runtime execution.

//assume process variable was already declared above (Process process = null)
//This line changes permissions of the file to be executable by the owner.
process = Runtime.getRuntime().exec("chmod 744 " + filename);

a. Run your binary file and read the output from stdout to be printed in the log file caught by Dalvik Debuger. This step will execute your binary file and catch the output of stdout. For the purpose of this example our binary catches "hello world" from the binary.

//process still declared from before
process = Runtime.getRuntime().exec(filename);

String s = null;
process.waitFor();
stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
while((s=stdInput.readLine()) != null) {
  //For your sanity when viewing logs in Dalvik, I would add tags...like "WCG" so that you can filter on the logs later.
  Log.i("WCG", s);
}

a. Check to see what the contents of the application directory. This will output the file directory structure to the debugger. From our binary we actually created a new file and wrote data into it. This proves that many of the basics allowed for BOINC exist.

process = Runtime.getRuntime().exec("ls -la /data/data/com.example.helloandroid/");
process.waitFor();
stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));

while((s=stdInput.readLine()) != null) {
	Log.i("WCG", s);
}

a. View the output of Dalvik Debugger This should be simple Here is a screen shot of what we are expected to see. Image

  1. Compile code for the NDK a. Pre-req. You will need to have cygwin installed as well as make version 1.81 from their repository. a. Copy the hello-jni project from samples within Android ndk. When this is ready you will see a file called hello-jni.c that exists within the jni folder. This will be where your Makefile and source code should exist. a. Modify c code that will be compiled. For this it is a VERY simple c program with basic c calls. I just deleted the contents of hello-jni.c and replaced with the contents below for this example.
#include <stdio.h>
#include <string.h>

int main() {
  FILE *file;
  file = fopen("/data/data/com.example.helloandroid/file.txt", "a+");

  //Write text to file to give it some size
  fprintf(file, "HOWDY");
  //Write to stdout.
  printf("HELLO WORLD\n");

  fclose(file);

  return 0;
}

a. Now, since I did not want the application to spawn from a java instance, I had to modify the make file to not build a shared object as this could have caused issues later for boinc.

I changed this line within the Android.mk file
include $(BUILD_SHARED_LIBRARY)
to
include $(BUILD_EXECUTABLE)

a. Compiled the code within cygwin. You will need to navigate to the folder where hello-jni project exists.

cd /cygdrive/c/directorys/
Once you are in that directory, you will need to call ndk-build.  This may vary on where you installed the ndk.
$ /cygdrive/c/cygwin/android-ndk-r6/ndk-build
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
Gdbsetup       : libs/armeabi/gdb.setup
Compile thumb  : hello-jni <= hello-jni.c
Executable     : hello-jni
Install        : hello-jni => libs/armeabi/hello-jni

a. Once this is complete you should have the file called hello-jni in your libs/armeabi/ directory of your project. I uploaded this to my personal server as shown by the code of the java URL earlier.

  1. Run your application in emulator You are now ready to run it on your emulator with dalvik debugger running and you should see similar output as I have noted above.
  2. Several notes about this setup. a. Limitations within c/c++ applications. i. Several include files that could be considered basic do not work. We have tested some of the stream includes and those appear to be missing

i. What version of the c-std is being used. This causes an issue because a simple for loop was not recognized and we were required to shift that to a while loop instead. a. Possible solutions i. cmake was ported and is able to use boost libraries. I am not sure at this time which libraries are included from boost. i. convert source code to fit this standard which should still allow for compiles across other standards a. Hardware thoughts i. Overheating of devices. These machines are not designed well for 100% cpu usage over many hours (no fans, they use the case to disperse heat) i. Battery protection. This is an issue where the device pulls more power than is being supplied by the power adapter. For example, a usb connection to a computer provides 150mA. Where a power adapter that uses a usb cable can provide 1.5 A. A device running will need to detect what power source they are using or find out if after running 100% cpu for 5 minutes the battery has actually lost charge. i. Dynamic interface sizes. Since running on various devices that run the same application, an interface design will have to be fairly flexible to be viewable from a phone size (more height than width) and a tablet screen resolution. Not all screens within classes are even the same size, so an additional challenge.