I'm trying to develop an external library (not sure if that's the right term) to provide prepackaged functionality in Android projects. Working in Eclipse, I've added the appropriate android.jar file to the build path, and everything is happy both while editing and upon compilation.
However, when I use Android's Handler and Message classes (android.os.Handler, android.os.Message) for inter-thread communication, I get exceptions unless I'm running within an Android app, on the emulator or a device. I can no longer test my library in a "standalone" way without having to go through a running Android target.
Is there any way for me to include these two Android classes and still be able to test my library standalone? Do I need to have the Android source available? Or would it require some sort of conditional compilation hand-waving?
Is there any way for me to include
these two Android classes and still be
able to test my library standalone?
Not readily, by any means I can think of.
Do I need to have the Android source
available?
I don't know where else you would get the implementation from. But, more importantly, those things are not designed to work in isolation outside of the OS, any more than you could just grab a Cocoa class or two and pull them into your Objective-C library and expect them to run on a Windows box.
Off the cuff, knowing nothing about what you're building, I would make whatever dependency you are introducing on Handler and Message be more pluggable. Test outside of Android using a pure-Java implementation, perhaps even just some mocks. Test inside of Android using the real implementation.
You could try the lib Robolectric, that implements the android API so you would be able to create JUnit tests for some isolated code you have:
http://robolectric.org/
Related
In my project I have a set of java objects as part of the model of my application, they are all in a Java Library module as they are pure Java.
The Android app module use them and that's not a problem, I also need to pass these through my activities, so making them Parcelable is the way to go.
But I have some trouble in Android Studio doing so because Parcelable is something from Android and I haven't succeed in using it in the Java module. So I have tested to move my classes in an Android Library, but Android seems to ignore them since they are pure Java, there is an icon with a red J on each one of them. To verify my supposition, I have tested to create a Java class in the Android module, but there is no option to do it.
Is there a way to keep the classes in a separated module, and if so, what is it? Or should I move all the classes in the app module?
(I would prefer to avoid the last solution if possible)
Thank you
Edit: The solution seems to be using an Android library, but I don't know why Android Studio behaves badly with my module, I can't create java class and java packages in the main package of the library:
Also, I can't create packages in pact44 main package:
So I have tested to move my classes in an Android Library, but Android seems to ignore them since they are pure Java.
Ignore them? What do you mean? You created a library module, moved your code into it and then you cannot access this classes from your app module?
To verify my supposition, I have tested to create a Java class in the Android module, but there is no option to do it.
And how do you create activities classes for example? There must be the option for creating a new Java class. If the IDE doesn't give you the option to create a new Java class means that you are trying to create it in a place where you're not supposed to do that.
If you want to separate your library code from the app code but you still want to have access to Android classes in your library the best way is to create a new "android library module". Remember to add the library as dependency in the app build.gradle
Look here : https://developer.android.com/studio/projects/android-library.html
I've written a real-time subsystem for Android that I'd like to test on the desktop. I would like to run tests via a command line tool of my creation. The subsystem depends on Android as follows:
android.os.Looper
android.os.Handler (including Handler.Callback)
android.os.Message
android.util.Log
I need to stub these classes. Robolectric stubs these classes but apparently doesn't allow for custom instances of Looper. Unless someone can point me to functional stubs, I plan to write them myself. I'd rather avoid the complexity of writing a test harness for a full Android emulator.
How do I get Android Studio to use my stubs for these classes in my tool build? I don't want to modify the subsystem to dynamically receive the classes it should use, out of fear of limiting optimization or making code unnecessarily messy. (But I am open to wrapping android.util.Log.)
Thanks for your help!
I am trying to build an application that runs under JavaSE and Android. Most of the code is the same between the two, but there are some specific functions that need to be separated. I use Eclipse. So I decided to put the shared code in a separate project, and then build one more project for Android and one for Java, which reference the shared project. I put all Java and Android specific functions in one class residing in the Java and Android specific projects. These classes are called UtilsJ (for Java) and UtilsA (for Android). The code in the shared project uses a factory to determine at runtime which version it needs to pick, and then calls the class loader to load the right class. Essentially: if property java.vm.name equals Dalvik, load UtilsA, else load UtilsJ (and of course cast to the Utils interface before returning).
My question is simply if this is a good idea or is something going to eventually break? I've never used class loader before. Any other suggestions how to implement this sharing would also be appreciated.
Generating an interface implementation dynamically is certainly a valid technique. For instance, having a data access interface that has multiple implementations; one each for flat files, MySQL and WebDAV. The program can pick an implementation at run time based on system/platform properties.
But this feels different. If I saw that I had a Java app and an Android app that had a lot of common code, my goal would be to create an Eclipse project that generates a jar file that I could just drop into the libraries of both projects. In that case, the jar file wouldn't contain any code that was incompatible with one platform or the other. So there wouldn't be any reason to have a platform-specific implementation.
Let's take your example some code reading an initialization file. If it's common code, you have an input parameter which is a file. On Android, maybe it's "/data/data/com.whatever.blahblahblah" and on Java you're getting the "user.dir" system parameter for the top level directories. But one way or another, it's a File, and you hand it to your common setup method. That's okay. But if your initialization file read code e.g. needs a Context to get a Resource to read the file for Android, then it's not common code. And it doesn't belong in a library jar for a JVM-hosted app.
So I think that in your case the platform-specific implementation classes are overkill. If it's common code, it's the same code — period.
Let's talk about another example in your comment. If you are using desktop Java, then you are probably using Swing or AWT, so you still have the same issue of running some network task off the UI thread, notifying when it completes, maybe even updating some progress indicator UI while it's processing. Same function, same operation, but the code is so different that I can't see how having it in the same library next to an AsyncTask version could be of any benefit.
And testing might get tricky. Obviously JUnit will work for everything, but some tests would need to run on a device or emulator.
I stated that it was a valid technique, and of course you may have other compelling reasons to choose the multi-platform option. You asked the question; is anything going to break? My answer is: Probably not, but why risk dealing with some heartburn down the road? Speaking for myself, I wouldn't do it. If I had to support multiple MVC apps, my common library would have nothing but M.
How can I execute a block of code in an android project without having to launch the emulator.
I don't want to deal with the android lifcycle -> I want to test the logic of my app ONLY.
What I have in mind is to create another java project and define dependencies so that I can access the classes that are in my android project.
I would like to launch a kind of Main() method to bypass the emulator... Is it possible?
Thanks!
Look into unit testing. Fits your problem almost perfectly.
Not exactly for a block of code but for methods.
There are special launchers such as JUnit that makes the test-running smother and much more fun. You get green and red lights for every test, great satisfaction to get all green.
JUnit is fairly easy to get started with and is well integrated into eclipse.
I'm developing a Java plugin for an existing Java program. The existing program uses a specific version of eclipse.uml2.* and my plugin does too. Unfortunately I need a newer version for my plugin.
In order to run the plugin, I need to export it into a Jar file (with all jars packed). Then the program executes it. But somehow the new eclipse.uml2.* seem to interfere with the program -> it crashes.
Is there a way to "separate" both versions of the jar files?
An approach will be to use a custom class loader in your application. This can very easily introduce bugs that are difficult to trace, so take care.
http://www.devx.com/Java/Article/31614/1954
This is the exact problem OSGi tries to solve. Would it be feasible to rework the Java app to another plugin platform?
This will be difficult. You conceivably try to use class loader tricks to allow both versions of the eclipse.uml.* classes to be loaded in the same JVM. But as far as the JVM would be concerned they would be different sets of classes, and your plugin and the base java app wouldn't be able to exchange instances.
It is probably simpler (and less risky ... in terms of likelihood of success) to rebuild (and if necessary modify) either the base program or your plugin so that they both work with the same version of the eclipse.uml2.* classes.