Multiple builds from same code base in Eclipse - java

I'm pretty new to Java and Eclipse coming from an iOS/xCode background. I have an iOS project that has 2 builds, 1 that uses a test server and 1 that uses a live server. In xCode this was simply a case of adding a new build target, a Preprocessor Macro, than using #ifdef in code to use separate url's for each build.
Porting this over to Android, I have this list of things I need to do each time I want to build/test between the 2 versions
TO SWITCH BETWEEN LIVE AND TEST
Rename Application Package com.mybus.myapp/com.mybus.myapptestserver (Right click, Android Tools, Rename Application Package).
Rename com.mybus.myapp folder to com.mybus.myapptestserver.
Change Map API key in manifest
Change SENDER_ID in BeginActivity.java (Notification app ID).
Search and change all references com.mybus.myapp/com.mybus.myapptestserver (Including SharedPreferences).
Change URL's in ConnectionHelper.java and PasswordResetConnection.java
Change icon and label in Manifest for Application & BeginActivity.
Remove crash reporter (ACRA) from MyApplication.java.
Change .setSmallIcon(R.drawable.ic_test_launcher) & .setContentTitle("myapptestserver") in GCMIntentService.java
Surely there is an easier way to build seperate builds and allow them both on a device at the same time?

You could use Ant script to do this. Once you customise your Ant script to handle all these changes, you can get the final output by running the ant release command.
An small example from where you could start with. I have written a post about it. This ant script, doesn't change any values in files, but what it does, is outputs the final apk, with a chosen name format, and puts it in a specified folder.
http://techdroid.kbeanie.com/2011/09/automating-builds-on-android-part-1.html
http://techdroid.kbeanie.com/2011/09/automating-builds-on-android-part-2.html
Disclaimer: These are links to my blog posts.

Related

Expose new ART functionality by changing the Runtime.class of libcore

I have inserted some new functionality in the Android Runtime (ART), and now I want to expose it to the outside world via an interface. As it is native code, I will be using the JNI interface to call this new functionality, in a similar way with the Garbage Collector functionality: Runtime.getInstance().gc().
However, I don't care in building a new SDK that could be used by an IDE, as I will be manually injecting bytecode to .dex files that will make the call.
I have edited the Runtime.java in libcore/luni, and java_lang_Runtime.cc in art in a similar way with the gc() function. I am generating the new libart.so and core-libart.jar and I flash them on a device.
However, when I try to reboot the device, I get the message:
Failed to register native method java.lang.Runtime.myMethod()V in /system/framework/core-libart.jar
...
----- class 'Ljava/lang/Runtime;' cl=0x0 -----
vtable (24 entries, 11 in super):
// 24 entries are listed here. My entry is missing.
...
In the Runtime.java I register the native method and supress some warnings on a full build using #hide. eg,
/** #hide */
public native void myMethod();
In the java_lang_Runtime.cc, I define the function (that will call the ART internal stuff) and register it to the gMethods[] array using a macro. eg,
static void Runtime_myMethod(JNIEnv*, jclass) {
// body
}
NATIVE_METHOD(Runtime, myMethod, "()V")
The device is on a bootloop. Are there any other files that I should have edited? Should I build extra modules, or send any other files on the device?
BTW, I do NOT want to build a new SDK as for calling myMethod I will inject Dalvik bytecode to an APK file. Basically I will get the Runtime instance, and then call the method.
The problem:
Android ships the factory images with framework components being pre-optimised.
The file boot.oat contains pre-optimised code (or odex code), which can be accessed by reading pointers contained in the boot.art file.
These two files contain code only for the boot classpath.
The rest of the framework, and the rest of the system applications (in app and priv-app) folders have standalone odex files.
During this pre-optimisation phase, the dex code is taken out of a framework module (a jar, or an apk), is compiled using dex2oat, and the resulting code resides in the files I just mentioned.
Some of the things I 've tried:
Shipping just the libart.so and core-libart.jar does not work, even though the latter contains the dex code. This is because the runtime is still attempting to read that information from boot.oat.
By modifying the device configuration to do the pre-optimisation, the aosp build system can generate boot.oat|art and the rest of the odex files (more here). I expected that flashing all these should work, but it didn't.
(at least for the marshmallow-release branch, on a nexus6)
I 've tried flashing the whole aosp-generated build, and it didn't work, even with a custom kernel that I 've build with the security features (verity) disabled.
I am sure that some of these should have worked, but there must be something else that should be considered during building the OS.
Solution:
The last resort, was deodexing and thankfully it worked.
I have written a small script that does it for the Nexus 6 on Marshmallow.
The script, during a 1st stage, it takes out all the oat/odex code from relevant places, and de-optimises it to dex code, thanks to the oat2dex and smali projects.
On a 2nd stage, it packs the dex code back, in the framework modules (jars/apks).
Shipping a whole new core-libart.jar to the device still does not work (not sure why), but tinkering the dex files before packing them into the modules does the trick! :))
The libart.so can now find Runtime.myMethod(), which can be invoked by an application (smali tinkering again) to run my code inside ART.

Sharing Android tests between two projects

I'm writing automated unit tests for an Android application, and I have come across a very odd situation.
The application is carefully constructed to target API8 - API 19 without needing multiple releases. One part of the tests, however, requires that I test a specific class without any internet access or mobile data. I've found a very hacky way to do this, but the solution comes in two parts: one for API 10 and above, and one for API 8 that requires a permission not available to applications targeting >= API 10.
What I want to do is to create two test projects, one that targets API 8 and one that targets everything else. What I want to avoid is duplicating the test files that work across all versions. As far as I can tell, there's only the manifest and a Utils class that needs to be different.
Is there any way to store the tests in a central location, and have them included and ran from both tests?
On Eclipse, create the tests to be shared on one of the projects, as usual.
When you are happy with the test result, go to the other folder and create a new Folder inside:
Right Button on Project >> New >> Folder
Press "Advanced Button"
Select "Link to alternate location (Linked Folder)
Press the "Browse..." button and browse to the folder where previous tests are located.
Finally, right click on the linked folder and select:
Build Path >> Use as Source folder.

Endpoint .api file not updated automatically

I am using Java + GPE + Cloud end points.
It used to be the case that my end point api file would automatically update whenever I change the relevant java source code. For some reason this has now stopped working.
I created a very simple dummy endpoint project and the api file is automatically generated here. But not in my real project.
Now to see my changes in api file - I have to click on "Generate Cloud End Point Client Library". This is slow, freezes up eclipse and lowers my productivity.
Any suggestions/ideas ?
Regards,
Sathya
Check your output directory for your classes. If that's changed, it won't properly update the .api file any. I found this out after adding Maven to my Eclipse project, and adding Maven changed my output directory.

Java Distribution Code vs Development Code

I have an application developed in Java that's almost ready for distribution. However, I have a problem switching from my development env to publishing env, and back to development. For instance, in Eclipse, if I just want to do a test run via the run button, I have to change the code so my JMenuItems show up.
In my development environment I had the following that worked well:
JMenuItem[] appItems = new JMenuItem[2];
appItems[0] = new JMenu("New");
appItems[0].setIcon(new ImageIcon(../POS_System/images/new_icon_sm.png")));
But, as I near deployment, to get this to work in the deployable JAR, I need to alter the code:
JMenuItem[] appItems = new JMenuItem[2];
appItems[0] = new JMenu("New");
appItems[0].setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/new_icon_sm.png")));
This is order to reach into the JAR and get the appropriate image.
I have a lot of these JMenuItems. I'd really like to be able to test the app via the run button in Eclipse, as well as create a JAR without changing the code.
Is there a simple way to do this? I thought the getResource method would still allow me to use the JMenus, JMenuItems etc, but they aren't available when I run the program from Eclipse. It seems silly that I would have to keep switching back and forth.
I appreciate any help here.
If you do not want to move your images into the src/ folder as you have suggested, then in Eclipse, you should update your Eclipse configuration under the Project Prooperties -> Java Build Path and add an additional source folder, this one pointing to where you keep your images. I believe this will fix it.

Programmatically generate an Eclipse project

I use eclipse to work on an application which was originally created independently of eclipse. As such, the application's directory structure is decidedly not eclipse-friendly.
I want to programmatically generate a project for the application. The .project and .classpath files are easy enough to figure out, and I've learned that projects are stored in the workspace under <workspace>/.metadata/.plugins/org.eclipse.core.resources/.projects
Unfortunately, some of the files under here (particularly .location) seem to be encoded in some kind of binary format. On a hunch I tried to deserialize it using ObjectInputStream - no dice. So it doesn't appear to be a serialized java object.
My question is: is there a way to generate these files automatically?
For the curious, the error I get trying to deserialize the .location file is the following:
java.io.StreamCorruptedException: java.io.StreamCorruptedException: invalid stream header: 40B18B81
Update: My goal here is to be able to replace the New Java Project wizard with a command-line script or program. The reason is the application in question is actually a very large J2EE/weblogic application, which I like to break down into a largish (nearly 20) collection of subprojects. Complicating matters, we use clearcase for SCM and create a new branch for every release. This means I need to recreate these projects for every development view (branch) I create. This happens often enough to automate.
You should be able to accomplish this by writing a small Eclipse plugin. You could even extend it out to being a "headless" RCP app, and pass in the command line arguments you need.
The barebones code to create a project is:
IProgressMonitor progressMonitor = new NullProgressMonitor();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject("DesiredProjectName");
project.create(progressMonitor);
project.open(progressMonitor);
Just take a look at the eclipse code for the Import Project wizard to give you a better idea of where to go with it.
Use AntEclipse
It can create eclipse projects from ant.
To create java project you can use JavaCore from org.eclipse.jdt.core.JavaCore. As a sourceProject you can use generic project item, which has been suggested by #James Van Huis
IJavaProject javaSourceProject = JavaCore.create(sourceProject);

Categories