Editing GRAndWalkthrough
Jump to navigation
Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 6: | Line 6: | ||
* Open Android Studio | * Open Android Studio | ||
** File > New> New Project | ** File <s>> New</s>> New Project | ||
** Give it a name and a company domain | ** Give it a name and a company domain | ||
** Select the type -- probably Phone and Tablet | ** Select the type -- probably Phone and Tablet | ||
** And the API level is | ** And the API level is "API 21: Android 5.0 (Lollipop)" | ||
** Select a Blank Activity | ** Select a Blank Activity | ||
** Give the main activity a name (e.g., GrTemplate or stick with MainActivity) | ** Give the main activity a name (e.g., GrTemplate or stick with MainActivity) | ||
Line 37: | Line 37: | ||
* Create a new '''jni''' directory. | * Create a new '''jni''' directory. | ||
** app | ** app > src >main <s>> Right Click</s>> New <s>> Directory</s>> 'jni' | ||
** This makes a folder app/src/main/jni | ** This makes a folder app/src/main/jni | ||
* Add the Android makefiles we provide | * Add the Android makefiles we provide | ||
** [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/GrAndroid.mk GrAndroid.mk]: This declares and allows us to pull in all of the GNU Radio dependencies for building the JNI library. | ** [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/GrAndroid.mk GrAndroid.mk]: This declares and allows us to pull in all of the GNU Radio dependencies for building the JNI library. | ||
*** Note that it assumes we've put the [http://gnuradio.org/data/android/grandroid.tar.gz dependencies] into /opt/grandroid. | *** Note that it assumes we've put the [http://gnuradio.org/data/android/grandroid.tar.gz dependencies] into /opt/grandroid. | ||
**** If not, change that up top in the | **** If not, change that up top in the "GRLIBPATH" variable. | ||
*** This creates: | *** This creates: | ||
**** GR_WHOLE_STATIC_LIBRARIES: libUHD | **** GR_WHOLE_STATIC_LIBRARIES: libUHD | ||
Line 62: | Line 62: | ||
* We've created the '''jni''' directory where our flowgraph lives. | * We've created the '''jni''' directory where our flowgraph lives. | ||
* Add a new file to this directory: Right-Click - | * Add a new file to this directory: Right-Click -> New > New C/C++ Source File | ||
** name this file fg.cpp and see the [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/fg.cpp flowgraph file] in the GrTemplate repo. | ** name this file fg.cpp and see the [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/fg.cpp flowgraph file] in the GrTemplate repo. | ||
< | <pre>// Required | ||
#include | #include | ||
// We'll likely want these | // We'll likely want these | ||
#include | #include | ||
#include | #include | ||
// Get any GNU Radio headers | // Get any GNU Radio headers | ||
#include | #include | ||
#include | #include | ||
#include | #include | ||
#include | #include | ||
// Other block headers next | // Other block headers next | ||
Line 83: | Line 83: | ||
gr::top_block_sptr tb; | gr::top_block_sptr tb; | ||
extern | extern "C" { | ||
JNIEXPORT void JNICALL | JNIEXPORT void JNICALL | ||
Line 89: | Line 89: | ||
jobject thiz) | jobject thiz) | ||
{ | { | ||
GR_INFO( | GR_INFO("fg", "FgInit Called"); | ||
// Declare our GNU Radio blocks | // Declare our GNU Radio blocks | ||
Line 97: | Line 97: | ||
// Construct the objects for every block in the flwograph | // Construct the objects for every block in the flwograph | ||
tb = gr::make_top_block( | tb = gr::make_top_block("fg"); | ||
src = gr::blocks::null_source::make(sizeof(gr_complex)); | src = gr::blocks::null_source::make(sizeof(gr_complex)); | ||
thr = gr::blocks::throttle::make(sizeof(gr_complex), 10000); | thr = gr::blocks::throttle::make(sizeof(gr_complex), 10000); | ||
Line 103: | Line 103: | ||
// Connect up the flowgraph | // Connect up the flowgraph | ||
tb- | tb->connect(src, 0, thr, 0); | ||
tb- | tb->connect(thr, 0, snk, 0); | ||
} | } | ||
Line 111: | Line 111: | ||
jobject thiz) | jobject thiz) | ||
{ | { | ||
GR_INFO( | GR_INFO("fg", "FgStart Called"); | ||
tb- | tb->start(); | ||
} | } | ||
Line 119: | Line 119: | ||
jobject thiz) | jobject thiz) | ||
{ | { | ||
GR_INFO( | GR_INFO("fg", "FgStop Called"); | ||
tb- | tb->stop(); | ||
tb- | tb->wait(); | ||
GR_INFO( | GR_INFO("fg", "FgStop Exited"); | ||
} | } | ||
Line 129: | Line 129: | ||
jobject thiz) | jobject thiz) | ||
{ | { | ||
return env- | return env->NewStringUTF(tb->edge_list().c_str()); | ||
} | } | ||
}</ | }</pre> | ||
* This flowgraph is very simple and just creates the following flowgraph: | * This flowgraph is very simple and just creates the following flowgraph: | ||
** <code>null_source - | ** <code>null_source -> throttle -> null_sink</code> | ||
* There are four JNI functions declared here that we can use from our Java app: | * There are four JNI functions declared here that we can use from our Java app: | ||
** FgInit: Where we ceate the blocks and construct the flowgraph. | ** FgInit: Where we ceate the blocks and construct the flowgraph. | ||
Line 147: | Line 147: | ||
* Add another C++ file called [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/settmp.cpp settmp.cpp] that looks like: | * Add another C++ file called [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/jni/settmp.cpp settmp.cpp] that looks like: | ||
< | <pre>#include | ||
#include | #include | ||
#include | |||
extern | extern "C" { | ||
JNIEXPORT void JNICALL | JNIEXPORT void JNICALL | ||
Line 159: | Line 158: | ||
{ | { | ||
const char *tmp_c; | const char *tmp_c; | ||
tmp_c = env- | tmp_c = env->GetStringUTFChars(tmpname, NULL); | ||
setenv( | setenv("TMP", tmp_c, 1); | ||
} | } | ||
}</ | }</pre> | ||
== Set up the MainActivity to call SetTMP == | == Set up the MainActivity to call SetTMP == | ||
* In the [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/java/org/gnuradio/grtemplate/MainActivity.java main activity Java file], setup the JNI interface functions and call SetTMP in the onCreate function. | * In the [https://github.com/trondeau/GrTemplate/blob/master/app/src/main/java/org/gnuradio/grtemplate/MainActivity.java main activity Java file], setup the JNI interface functions and call SetTMP in the onCreate function. | ||
'''''' For access to the JNI call, put the following at the bottom of the activity class: | |||
<pre> public native void SetTMP(String tmpname); | <pre> public native void SetTMP(String tmpname); | ||
static { | static { | ||
System.loadLibrary( | System.loadLibrary("fg"); | ||
}</pre> | }</pre> | ||
'''''' The library name is 'fg' because that's what we put into the Android.mk file's LOCAL_MODULE value. | |||
'''''' In the onCreate function, just add this line: | |||
<pre> @Override | <pre> @Override | ||
Line 188: | Line 186: | ||
.... | .... | ||
}</pre> | }</pre> | ||
'''''' This uses Java to get information about the application's cache directory, which is unknown by us or by the C++ application. We get it through these Android calls, and then pass it to the C++ part, which will set the environmental variable TMP to this directory. GNU Radio knows to look at TMP when setting up the scheduler. | |||
* Similarly, let's add the flowgraph control JNI function to the MainActivity class | * Similarly, let's add the flowgraph control JNI function to the MainActivity class | ||
Line 196: | Line 194: | ||
public native void FgStop(); | public native void FgStop(); | ||
public native void FgRep();</pre> | public native void FgRep();</pre> | ||
'''''' Then in the onCreate function, add the init and start functions after SetTMP: | |||
<pre> FgInit(); | <pre> FgInit(); | ||
Line 208: | Line 206: | ||
* Tell Android Studio about the NDK: | * Tell Android Studio about the NDK: | ||
'''''' Under Gradle Scripts > local.properties | |||
''''''* Add a line fo the NDK: | |||
''''''* ndk.dir=/opt/ndk | |||
'''''' Or wherever you installed the NDK on your system. | |||
* | * Next, we have to modify Gradle Scripts > "build.gradle (Module: app)" (Can also find this under the '''app''' directory). | ||
< | '''''' Here we will tell Android Studio not to try and do its own thing with the NDK but to run the command 'ndk-build' from the path directly. This makes sure that the build system uses our Android.mk file, which is important because we have a lot of libraries to install ourselves and there isn't a better way to do this in Android Studio. | ||
'''''' Add the following lines just after the 'buildToolsVersion' line: | |||
<pre> // SETUP TO USE OUR OWN Android.mk FILE | |||
sourceSets.main { | sourceSets.main { | ||
jniLibs.srcDirs = ['src/main/libs'] | jniLibs.srcDirs = ['src/main/libs'] | ||
Line 231: | Line 233: | ||
tasks.withType(JavaCompile) { | tasks.withType(JavaCompile) { | ||
compileTask - | compileTask -> compileTask.dependsOn ndkBuild | ||
}</ | }</pre> | ||
== Build the Project == | == Build the Project == | ||
* If it complains about UTF-8 incompatibility, look down in the bottom right corner for the setting to click on and switch this project to UTF-8. | * If it complains about UTF-8 incompatibility, look down in the bottom right corner for the setting to click on and switch this project to UTF-8. | ||
* Open up a terminal and go to the application's main directory, | * Open up a terminal and go to the application's main directory, "AppName/app/src/main" and run the android update project command: | ||
<pre>$ android update project -p . -s -t android-21</pre> | <pre>$ android update project -p . -s -t android-21</pre> | ||
'''''' I am sure there is a way to do this within Android Studio itself, but I've yet to figure out how. (Note: Tools | '''''' I am sure there is a way to do this within Android Studio itself, but I've yet to figure out how. (Note: Tools>Android>'Sync Project with Gradle Files') | ||
* Build the program: Build - | * Build the program: Build -> Make Project (or Ctrl + F9) | ||
* At this point, if everything was done correctly above, the build should end with | * At this point, if everything was done correctly above, the build should end with "BUILD SUCCESSFUL" in the Messages tab at the bottom of the Android Studio interface. | ||
* Build the project with the fg.cpp we wrote. It will take a few seconds for the ndk-build to run, and you'll likely see a handful of warnings about the Android LOG levels, which you can ignore (or help us fix them!). You should not get any errors. | * Build the project with the fg.cpp we wrote. It will take a few seconds for the ndk-build to run, and you'll likely see a handful of warnings about the Android LOG levels, which you can ignore (or help us fix them!). You should not get any errors. | ||