Exporting the RenderBox package

Now that we've finished creating this beautiful RenderBox library, how do we reuse it in other projects? This is where modules and .aar files come into play. There are a number of ways to share code between Android projects. The most obvious way is to literally copy pieces of code into the next project as you see fit. While this is perfectly acceptable in certain situations, and in fact should be part of your normal process, it can become quite tedious. What if we have a bunch of files that reference each other and depend on a certain file hierarchy, such as RenderBox? If you're familiar with Java development, you might say, "Well, obviously just export the compiled classes in a .jar file." You would be right, except that this is Android. We have some generated classes as well as the /res folder, which contains, in this case, our shader code. What we actually want is an .aar file. Android programmers might be familiar with .aidl files, which are used for similar purposes, but specifically to establish interfaces between apps, and not encapsulate feature code.

To generate an .aar file, we first need to put our code inside an Android Studio module with a different output than an app. You have a few options from this point onward. We recommend that you create a dedicated Android Studio project, which contains the RenderBox module as well a test app, which will build alongside the library and serve as a means to ensure that any changes you make to the library don't break anything. You can also just copy the renderbox package and the /res/raw folders into a new project and go from there, but eventually, you'll see that a module is much more convenient.

You might think "We're gonna call this new project RenderBox," but you might run into a snag. Basically, the build system can't handle a situation where a project and module have the same name (they would be expected to have the same package name, which is a no-no). If you call your project RenderBox, (technically, you shouldn't have if you followed the instructions) and include an activity, and then create a module called RenderBox, you will see a build error that complains about the project and module sharing a name. If you create an empty project with no activity called RenderBox and add a module called RenderBox, you happen to get away with it, but as soon as you try to build an app from this project, you'll find that you cannot. Hence, we suggest that your next step from here is to create a new project called RenderBoxLib.

Building the RenderBoxLib module

Let's give it a shot. Go to File | New | New Project. Name the project RenderBoxLib.

We don't need a MainActivity class, but we're still going to want one, as discussed, as a test case to ensure that our library works. Adding a test app to the library project not only gives us the convenience of testing changes to the library in a single step, but also ensures that we cannot build a new version of the library without ensuring that an app that uses it can also compile it. Even if your library is free of syntax errors, it might still break compilation when you include it in a new project.

So, go ahead and add an Empty Activity, and click on Finish in the default options.

All familiar territory so far. However, now we're going to create a new module:

  1. Go to File | New | New Module and select Android Library:
    Building the RenderBoxLib module
  2. Name it RenderBox.
    Building the RenderBoxLib module
  3. Now, we have a new folder in our project view:
    Building the RenderBoxLib module

Instead of performing the next steps in Android Studio, let's just use our file manager (Windows Explorer or Finder, or the terminal if you're a pro) to copy our RenderBox files from the existing project into the new one. If you're using version control, you might consider transferring your repository to the new project, or creating an init commit before the copy; it's up to you and how much you care about preserving your history.

We want to copy all your RenderBox code to the new module from the RenderBoxDemo project's /app/src/main/java/com/cardbookvr/renderbox folder to the /renderbox/src/main/java/com/cardbookvr/renderbox folder of RenderBoxLib.

The same goes for the resources; copy them from the RenderBoxDemo project's /app/src/main/res/raw folder to /renderbox/src/main/res/raw.

This means that almost every .java and .shader file that we created in the original project goes into the module of the new project, in their corresponding locations.

We won't be transferring MainActivity.java, or any of the XML files, such as layouts/activity_main.xml or AndroidManifest.xml to the module. These are app-specific files, which are not included in the library.

Once you've copied the files, go back to Android Studio, and click on the Synchronize button. This will ensure that Android Studio has noticed the new files.

Building the RenderBoxLib module

Then, with renderbox selected in the hierarchy panel, initiate a build by navigating to Build | Make Module 'RenderBox' (or Ctrl + Shift + F9). You will see a bunch of errors. Let's take care of them.

RenderBox references the Cardboard SDK, and as such, we must include it in the RenderBox module as a dependency in a similar way to how we do it for the main app, like at the beginning of this project:

  1. Add the Cardboard SDK common.aar and core.aar library files to your project as new modules, using File | New | New Module... and Import .JAR/.AAR Package.
  2. Set the library modules as dependencies to the RenderBox model, using File | Project Structure. In the left-side panel, select RenderBox, then choose the Dependencies tab | + | Module Dependency, and add common and core modules.

Once you sync the project and trigger a build, you will hopefully see those errors related to CardboardView and so on disappear.

Another build. Still, other errors?

This is because of the naming issues mentioned earlier. If the package name of your module doesn't match the package name from the original project (that is, com.cardbookvr.renderbox), you will have to rename it in the copied Java files. Even if these match, we named our original project RenderBoxDemo, which means that the generated R class will be part of the com.cardbookvr.renderboxdemo package. Any import references to this package will need to be changed.

Start by deleting the line that references com.cardbookvr.renderboxdemo (such as the Material Java files). Then, any references to the R class will show up as errors:

Building the RenderBoxLib module

Delete this line, and Android Studio will generate a new valid import line. Try and build it again. If it's error-free, we're good to go.

You will now see references to R show up as errors with a suggestion:

Building the RenderBoxLib module

If you go ahead and press Alt + Enter, Android Studio will add the appropriate import line to your code. If you don't see the Alt + Enter tooltip, try placing your cursor next to R. Using the feature this way, you'll have to select Import Class from the menu you see after pressing Alt + Enter. If you still see errors, make sure that you've copied the shader code into the /renderbox/res/raw folder, and that there aren't other errors interfering with this process. Essentially, we are removing any external references from the code and getting RenderBox to build on its own. We can also accomplish this code fix by simply pasting import com.cardbook.renderbox.R; over import com.cardbook.renderboxdemo.R;. That's probably easier than the first method, but then you wouldn't have learned about Alt + Enter.

Once this is done, we should be able to build without errors. This might seem like a messy way to work, but it doesn't hurt to get messy once in a while. You might even learn something new about the build pipeline you didn't know earlier.

If everything goes well, you will see a file called renderbox-debug.aar in renderbox/build/outputs/aar/. If so, you're done. Whew!

One final thought: you should include renderbox-release.aar in your final applications, but you will lose useful debugging features in the meantime. We will not discuss how to switch back and forth between debug and release in this book, but understanding build configurations is essential to the publication process.

The RenderBox test app

This new project houses the renderbox module, but there's also an app folder that we created in the first place. app is where we can implement a test application to make sure, at a minimum, that the library is built and basically runs.

We're going to do the same thing to the app module in RenderBoxLib that we did in our new projects (like renderbox, app is a module. It turns out that we've been using modules the whole time!):

  1. Right-click on the app folder, go to Open Module Settings, and add the existing renderbox module as a Module dependency with Compile Scope. Notice that the dependencies cannot be circular. Now that renderbox is a dependency of the app, the reverse cannot be true.
  2. Update /res/layout/activity_main.xml and AndroidManifest.xml, as we saw at the top of this chapter. (If you're just copying code, make sure that you change the package= value to the current name, for example, com.cardbookvr.renderboxlib).
  3. Set up class MainActivity extends CardboardActivity implements IRenderBox.
  4. We now also want our MainActivity class to instantiate RenderBox and define a setup() method, just like MainActivity in RenderBoxDemo. In fact, just go ahead and copy the entire MainActivity class from RenderBoxDemo, and make that you do not copy/overwrite the package definition at the top of the new file in your new project.

With any luck, you should be able to click on the green run button, select your target device, and see a running app with our buddy, the vertex color cube. We've officially gone backward in terms of the final result, but our application-specific code is so clean and simple!

Using RenderBox in future projects

Now that we've gone through all of this trouble, let's do a trial run to see how to use our pretty little package all tied up with a bow. One more time. You can perform the following steps to start each of the subsequent projects in this book:

  1. Create a new project, called whatever you like, such as MyCardboardApp, for API 19 KitKat. Include Empty Activity.
  2. Now, go to File | New | New Moduleā€¦. It's a little counterintuitive, but even though we are importing an existing module, we're adding a new one to this project. Choose Import .JAR/.AAR Package.
    Using RenderBox in future projects
  3. You'll need to navigate to the RenderBoxLib/renderbox/build/outputs folder of your RenderBox lib project, and select the .aar file. We recommend that you rename the module to renderbox, as opposed to renderbox-debug. Click on Finish. For a production app, you would want to have two different modules in your project: one for debug and one for release, but we will only be using debug for the projects in this book.
  4. Now that we have this new module, we need to add it as a dependency to the default app. Go back to the familiar Module Settings screen, and head over to the Dependencies tab for app. Click on the plus tab on the right-hand side, and choose Module dependency:
    Using RenderBox in future projects
  5. Then, you can add renderbox:
    Using RenderBox in future projects

We now have a copy of the .aar file in our new project's /renderbox module folder. When you've made changes to the RenderBox library, you just need to build a new .aar file (build menu, MakeProject), overwrite the copy in the new project, and trigger a project sync, or clean and rebuild if you want to be sure. The new project does not maintain a link to the build folder of your library output project.

The remaining steps required to setup a new project are as follows:

  1. Use File | New Module to import the Cardboard SDK .aar packages common and core, and add them as dependencies to the app.
  2. Update /res/layout/activity_main.xml and AndroidManifest.xml, as we've just done for RenderBoxDemo.
  3. Set up the MainActivity class so that it extends CardboardActivity and implements IRenderBox, using the same code as before.
  4. We now also want our MainActivity class to instantiate RenderBox and define a setup() method, just like our MainActivity class in RenderBoxDemo. In fact, just go ahead and copy the entire MainActivity class, and be careful not to copy/overwrite the package definition at the top of the file.

Build and run it yet again. Bagged it! We can now proceed with the cool stuff.

Note

This will be our new project process from now on, since the rest of the projects in this book make use of the RenderBox library module.

A final word on the module process: there's more than one way to peel an orange. You could have just created a new module in the RenderBox demo project, grabbed its output, and been off and running. You can also just copy source files around and try using Git submodules or subtrees to synchronize the sources. This page from the IntelliJ docs discusses some of the finer points as well (https://www.jetbrains.com/idea/help/sharing-android-source-code-and-resources-using-library-projects.html). We've also made certain decisions in terms of keeping the main activity and layout files completely application-specific, and including most or all of our shaders and materials in the RenderBox module, instead of in application code. At any one of these decision points, there are pros and cons, and we recommend that you think carefully about how you structure your own code in future projects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset