a simple question but Ive realised im not sure of the answer for this one....
If I am creating an android application with a library package named
com.example.one
and then i create another app and include another package with the name
com.example.one
which has a slightly refactored class, could this cause any problems in either of the apps?
The reason i ask is recently I had a problem with some google source code and it was down to the fact that a device manufactorer had included the same libs in the custom OS that I had used in my apk, and it was not happy! (or so i was told)
If anyone can fill me in here, as i obviosuly dont understand something quite findamental here :)
thankx
EDIT: a good link on the diff between Android and Java package names http://blog.javia.org/android-package-name/
The classloader can't load two versions of the same class. It picks just one. But which one gets picked is undefined. So yes - it causes troubles.
Some platforms (java-ee) have options to specify jar precendence for these cases. I don't know about android.
Update: If my initial understanding is not correct, i.e. you are not having the same jar (library) twice on the classpath, but instead are starting 2 separate apps with different versions of the jar - then they won't interfere with each other (and hence no problems)
Actually, it shouldn't cause problems in the case of two separate Android apps. Android Apps run in Sandboxes, i.e. the Classloader of app A does not see any classes of app B and vice-versa.
This is obviously different for system wide-libraries. They are accessible by the classloader (of course) and will cause troubles if you have the same class in your app.
Yes, this can cause problems, but only if you have classnames that conflict within the package.
This doesn't seem to be an issue with your app though as you have two apps and two libraries (see answer from LordT)
Any easy workaround is to include the the app/library name in the package. For example:
com.app1.example.one
com.app2.example.one
That eliminates confusion & interference between the two packages.
Related
This discussion involves getting a way to load different jars in different Operating Systems.
Case Scenario
I am working on a specific OS known as NSK. Its an unix flavour and powers the HP NSK Servers. I am running one of my middleware app ( a java application) on NSK. The requirement is to make this app off-platform. i.e. it must work in other platforms like LINUX or Windows as well.
To implement this, I introduced 1 more jar. Now I need to introduce a logic where-in the JVM must load the appropriate jar at runtime (jar1 on NSK and jar2 on any other non-NSK platform). I used the following logic to implement:
Code:
if (System.getProperty(os.name).equals("NSK"))
load jar1
else
load jar2
The above code works fine until I hit one of the Security exceptions "SecurityException" in getProperty API used above. This tells that the user running the app does not have necessary permission to use getProperty(). So, the above logic goes for a toss here.
Is there any way to tackle this exception and still be able to find out OS details and load the correct jar? Or better, are there any better logic to implement the same?
Please refer the below link for more details about getProperty(..)
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html
Thanks in advance
Regards,
Pabitra
Given that Java is platform independent and only loads the classes you use, I would have one JAR which has everything you need and only load the class which are appropriate for your platform.
Doing what you suggest requires a sub class loader which just add complexity which doesn't appear to be needed.
If you can't access a system property you can actively test your library and see which one work on your system. I am sure there is a method or class which working in one case but not the other or your wouldn't need two sets of code.
I have several applications that differ mostly based on resources. As of now, I'm copying the code around to each application. This can be problematic. An example, fixing a bug in one, and forgetting to update to the others.
I don't think creating a JAR is appropriate for this situation, as these are application specific UI classes, (actually android activity classes in specific) including the actual app start-up code.
It may be possible to include these source files into several packages, but then I have the problem that each file specifies a specific package name on the first line.
Most of the code is related to the UI and Activity processing. (The actual common code is already in a library). A similar question is posted here.
Are there any elegant solutions to this situation?
A jar is absolutely appropriate for this situation. You should split your application into layers, separating the application-specific classes from the shared code.
I solved this by going with Android Library projects. (Not sure of the details, perhaps they are ultimately jars) Check out details here, specifically the section 'Setting up a Library Project'.
I basically put in all my activity classes (except for the start-up one) into the library.
For true non-UI bound code, JARs, do seem to be the way to go.
I agree with artbristol.
I also recommend to use Maven and:
release the common jars to a corporate Maven repository
declare a dependency with specific versions on these jar artifacts
Like this you don't break applications if you do some incompatible changes.
I am trying to create a runnable JAR using Eclipse, but an running into problems. The Eclipse workspace contains two separate projects which depend on the same library. I can create the runnable JAR, but the problem is when I run it I receive a java.lang.NoSuchMethodError exception.
I believe I'm receiving the java.lang.NoSuchMethodError exception because the libraries are different versions. Is there a common solution to fix this problem? If not, what would you recommend I do?
If the major version number changes it means that backwards compatibility may have changed.
You could try with the latest version and hope that they just did add methods and that the old way of working, but even if NoSuchMethod exception is not thrown there is no guarantee (maybe with the new API you should call differente methods to get the same results).
I would contact the provider of the library and ask them if compatibility is broken. If they do not answer or it is broken, and you have the source code, the only possibility would be refactoring one of the libraries (probably 1.0); v.g. putting all of it in new packet v1. Then you would have to change the project that depends of it.
If none of the above works, then the solution would be an OSGi container or to setup project A and project B as two different executables and setup project B as a server that answer project A messages. Messy
The fix is to only include one version of the library which can satisfy both of the libraries that use it. If that's not possible, you'll have to find a different way of going about things such that you can eliminate the conflict. Options include:
Remove one or more of the uses from your code that are causing the NoSuchMethodError.
Modify the source of one or more of the libraries so they can happily coexist.
Use an OSGi container, which would allow you to have two versions of the same library in the same application.
As SJuan stated, you could use OSGI to set it up correctly. http://en.wikipedia.org/wiki/Java_Classloader#JAR_hell
I am very new to java and android development and to learn I am trying to start with an application to gather statistics and information like munin does. I am trying to be able to load "plugins" in my application. These plugins are already in the application but I don't want to have to invoke them all separately, but be able to iterate over them. I was trying to use serviceloader but could never get the META-INF/services into my apk. So I am wondering if it is possible to use serviceloader on android
Thanks
EDIT: I am asking about java.util.ServiceLoader, I think it should, but I can't figure out how to get my services folder into META-INF on the apk
There is an open bug report against this issue. See https://code.google.com/p/android/issues/detail?id=59658
The META-INF folder is deliberately excluded from the APK by ApkBuilder; the only comment in ApkBuilder.java is "we need to exclude some other folder (like /META-INF)" but there is no other explanation.
Even after adding META-INF with ant, you will still get in trouble if you want to use Proguard, which refuses to replace the content of META-INF/services/* files or rename them (that's another story, the author wants to keep Proguard agnostic).
However, people using maven may want to check https://github.com/pa314159/maven-android-plugin (the branch named "modified"), that tries to solve both issues. It is a fork from the original "android-maven-plugin" I modified one month ago for my own Android projects.
It also provides a patch for Proguard-4.7
Hope this helps, any feedback is welcome.
I've figured out a solution that may work for some situations. Instead of ServiceLoader, I'm using the org.openide.util.Lookup class / library that comes with NetBeans - it is a superset of ServiceLoader. It does not require NetBeans itself and seems to work ok with Eclipse. It is necessary to replace whatever ServiceLoader functionality you are using in your application with Lookup equivalents, and add the org-openide-util-lookup library. Then, you can just do something like this:
Lookup lookup = new ProxyLookup(Lookup.getDefault(),
Lookups.metaInfServices(myClass.getClassLoader(), "services/"));
And move your ServiceLoader files from META-INF/services/ to services/.
Note that, because of the ProxyLookup, this will continue to work on standard Java environments unchanged (i.e., in those cases it will continue to look in META-INF/services).
Here is a link to the documentation for the library: http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/Lookups.html
UPDATE
After working with this for a couple of days, it seems to function well - I move between environments (standard Java and Android) and it works properly in each location. The primary downside is having to manually copy the files to the /services directory.
It is possible. You may want to check http://developer.android.com/reference/java/util/ServiceLoader.html
ServiceLoader is stuff from the Java language that is not really relevant on Android. I recommend not using it. If you just want to find a list of classes within your .apk to load, there are all kinds of ways to do this -- put in XMl file in res/xml that lists them, use reflection, annotations, etc.
I have an app written with GWT and GAE where every supported city has its own app. Clearly this is not the best way to manage the map so I want to merge them all into one app. Currently my app is at the urls sub1.myapp.com, sub2.myapp.com, sub3.myapp.com, etc, and I want them to be at myapp.com/sub1 ,myapp.com/sub2, etc. All the supported cities share common code, so I'm going to put all the that code in one module, and have a different module for each piece of unique code block. Is this going about it the right way? How will the different modules interact?
Also, I currently have JSPs at sub1.myapp.com/listofsomesort and I would like to move these to myapp.com/sub1/listofsomesort. Is there a simple way to accomplish this?
By making a module with EntryPoint for each old application, in one and the same application. Each module has one 'welcome page' which you can put in different directories. All the shared code can go into another module. The shared code can be used by the inherit setting in other modules.
The only thing I bumped into was that when you deploy to GAE, ALL modules should have an entry point, also the library modules. I solved it by adding a dummy EntryPoint to them, that does nothing, but still searching for a better solution. See my question at How to deploy GWT Project containing GWT modules without entry points with Eclipse GAE plugin?.
This seems like the job for Code Splitting :) It might require some changes in the structure of your code, though - depends how tightly coupled your classes are. A compile report should tell you if your code splits up nicely, or if not, where the connections are.