This has been talked about a few times, with varying states of success but most of the answers I can find are several years in the past.
Essentially, I have an application which has moved to a point where isn't being shared with customers. Customers want to extend the application but we don't want them to have access to the original code -- protecting IP on all that.
The layouts, images, etc... well, we don't care about those as much, only the java code. I could easily compile the java code into a jar and distribute it, but that's only half the answer. The java code still references a whole pile of internal resources.
The scenario I'm working with is jar file contains the following:
In Jar file
- MyActivity extends Activity
- onCreate() within MyActivity sets the contentView to an R-referenced layout from within the jar file.
In client application
- MyClientActivity extends MyActivity
When this is run, I get a ClassNotFoundException on MyClientActivity.
Things I've noticed:
- If I attach the jar code as a library, instead of a jar file, it works.
- If I remove the R reference within onCreate() in MyActivity and remake my jar file, it works.
So, obviously, as pointed earlier, the R references are dead/not accessible. The thing is, this apparently can work, no? If you create an Android application and look at the auto-included APIs, the android.jar file has an R file, with internal layouts/strings/etc... which are being references from within its code.
As others have said before, this seems like a very basic and obvious usage pattern. The fact that it seemingly doesn't work is mind boggling enough to lead one to believe that it does in fact work, it's just not done in an obvious way.
Has anyone ever actually gotten it to work?
Thanks a lot,
-Cord Awtry
Related
I'm having a lot of doubts and after two days of searching I still haven't found a good answer for my problem.
I have an app's project that is already in the store and this project have lots of Activities, Fragments, Services, IntentServices, Layouts, and resources (images, strings, integers, colors, styles, raws, drawables, etc...).
Now, I need to implement a new app that is almost a copy of the first one where I need only to change the background, some resources (but almost 99% stay the same), and maybe in one or two fragments I'll need to change some code (implement different logic statements).
I decided and I think it's natural to convert the all project in an library project.
I did:
1º Create a new project called framework and configured as library. Copied all code and resources (with the exception of assets folder) from the original project to here.
2º In the original project I leave only the manifest, proguard file. I change the manifest and proguard file to reference the classes of the new library.
I tested the app to see if was still working and it was Ok. Until now I did only the separation.
Now, came the problem. I need to create a solution reusable,and scalar for the library that allows me to use it in different apps.
In my original project I created a subclass of Application class that I use for global variables.
Without any others ideas, I decided the following:
1º Convert my MyApplication class in an abstract class. Also, I create an interface ApplicationInterface with some methods like isBackgroundOverlayed() or getBackgroundResource() that I use in the fragments to change the backgrounds or any other logic from the originally defined.
2º In the App's project, I created a new Application class that extends the abstract class MyApplication and implements the interface ApplicationInterface and which is declared in the Application tag in the manifest file.
Conclusion: This all works and I was able to have two app's projects with different background and other images like logos and even change some code logic. An example is in the original App when the user press one certain button, the App shows a dialog choice. In the new app when the user press the button it execute one fragment (without choice).
My concerns: I don't feel this is the best solution for the problem or best practice or good "pattern".
Do you have any ideas?
Thank you in advance!
ps: Sorry if I haven't use this forum properly. I search for an answer but I didn't found any.
I think you have achieved what you wanted, but that was a lengthy and time consuming process. One more thing I would like to mention is you should not change library projects for different applications
As said on Android developers guide :
Library projects contain shareable Android source code and resources that you can reference in Android projects. This is useful when you have common code that you want to reuse.
you can read more from here
Also you have to figure out,which lib is doing which work in case you forget what changes you have made
I would suggest you to keep a separate copy of original project and then import it into new work space in Eclipse (by checking copy project into current work space so that you have a new copy of your project) and consider changing its package name to get a new project
you can refer ans on this link to see how to change package name`
So I'm trying to make myself a little alarm clock app to learn android. Just to do some things that I've always wanted in an alarm clock, and have it be my own. Motivations aside, after coding the interface and a bunch of other functions, I've decided to borrow a bunch of the code, if not most, of the android alarm clock source.
I've already brought in all the res stuff, and I've included all the src files under their original com.android.alarmclock namespace so that they can still reference each other properly. However it refuses to generate the R file for the new files.
When I clean and rebuild and all that, it still generates a build file and an R file for the stuff in my package (com.nathantempelman.alarmapp) but I still get an error on all the android AlarmClock files.
Should I be changing the AlarmClock files so that they reference the R from my package somehow? Or did I miss something when I updated the AndroidManifest file that is stopping another R from building or something?
Or is it something else entirely? Is it a stupid idea to try to drag another application's source into mine? Should I open it up in an external project and try to reference it somehow?
I'd love to hear some ideas, if anyone has had a similar situation.
Thanks for reading.
That is not how it's done. You want your Alarmapp to extend ALarmClock or extend the ALarmCLock classes or interfacces you want or need.
You can't drag source code in like that without re-factoring and tieing up all the loose ends, hence alarmApp extends AlarmClock.
Take a look here Hope this helps
I tried the library method, but that didn't work. In the end, I ended up just dropping the smaller project into the bigger project, combining the strings xml and android manifest, changing the intent classes of the activities in the android manifest, and dragging all the relevant pictures in. Quite a bit of work in the end, but it can be done.
Quick checklist:
Splice android manifest files
- if the package names are different, make sure the package name at the top of your manifest only extends as far as both packages are the same
Make sure all the resources make it over
Splice the strings.xml, styles.xml, and anything else that is common
between the two projects
Thought I'd post this in case someone else tries to do the same thing eventually. Best of luck
The standard advice for sharing code & resources between Android projects is to use a library. Personally I find this works poorly if (a) the shared code changes a lot, or (b) your computer isn't fast enough.
I also don't want to get into deploying multiple APK's, which seems to be necessary when I use dependent projects (i.e. Java Build Path, Projects Tab).
On the other hand, sharing a folder of source code by using the Eclipse linked source feature works great (Java Build Path, Source tab, Link Source button), but for these two issues:
1) I can't use the same technique to share resources. I can create the link to the resources parent folder but then things get wonky and the shared resources don't get compiled (I'm using ADT 21).
2) So then I settle for copying the shared resources into each project, but this doesn't work because either. The shared code can't import the copy of its resources because it doesn't know the package name of the project that uses it. The solution I've been using is to access the resources dynamically, but that has become cumbersome as the number of resources grows.
So, I need a solution to either (1) or (2), or I'll have to go back to a library project. (Or maybe there is another option I haven't thought of?)
Your real problem is (2). Fixing (1) would eliminate some copying, but you would still run into problems with (2).
Unfortunately, that really isn't possible. There's a fair bit of fancy footwork that goes on to make multiple packages possible with library projects, and there's no good way to get that same result without library projects. Anything in res/ of a project is accessed via that project's R class, including your copied resources.
The solution I've been using is to access the resources dynamically
I translated that into you using getIdentifier(). That certainly works. Another approach is to having the hosting app supply resource IDs as parameters to the library code -- this is the pattern that the Android SDK itself uses. This is faster at runtime than the reflection-based getIdentifier(), and it gives the hosting app somewhat more flexibility, but you do wind up adding a bunch of parameters to your methods and constructors as needed to supply the various project-specific R values.
why not just leave the data( strings.xml, main.xml ) in the .xml files? why convert it into the R.java?
it seems that android can read xml ( eg. androidmanifest.xml ). so why not just leave the strins.xml data and main.xml data in .xml form and send those xml's to the android device?
I am new ... maybe I will eventually see that there is a lot more in the R.java other than mere static variables that derived directly from those .xml's.
thanks,
Shannon
so that you can easily reference you object that you have created in you layout, drawable and string files. this class represents all the resources that can be instantiated inside a code or can be used inside your coding
So that you can easily reference your resources ids from your code with the R class object avoiding compile errors, I think
If you have a bug in your program, you want it detected as early as possible.
If resources are retained as XML any bug will be found at runtime (either test-driven or user-driven). Testing can never prove the absence of all defects, so some bugs may be found by the users of your software!
However, if resources are converted to source in R then all references to them will be checked by the compiler. Any bugs (relating to resource references) are detected at this much earlier stage, long before your customers get to seem them.
Transferring the id references of the XML content into code makes it easy to use these references while coding and the correct usage is visible during compile time. So runtime exceptions are avoided.
I do not know if this is the core reason but that's what counts for me :-).
R.java is a handler to all the resources.
You create your resources, and the R.java automatically build a connection between your code and your res. You can easily fetch your various kind of resources from R, and android provide lots of API supporting R.java and its handlers(those ints). You dont need to manually open a stream to res files, do file reading, images decoding and etc. Its great convience.
R.java doesn't contain any data. It's generated by aapt during the build process when it prepares resources to pack them into the APK, including compiling XML files in a format that's easier to read and parse. R.java contains static int members that are only indexes to the packed resources.
See A Detailed Look at the Build Process, and also take a look into a project's bin/ folder.
I have developed some reusable android component which is basically a class . This class has some resource dependencies e.g. some png drawables, some xml layouts etc. So this class referenced the auto-generated R file.I would like to distribute this code in a single package like jar file to other developers for use in their applications.
I have read that the only possible solution is to distribute code together with all my resources, which others have to copy to their "res" folder (source).
So I created a jar file having the class file (say MyClass which is in the package com.xyz.android.app) and resources and tried to use this in my new application.
So I added the jar file to my new applications build path using add external jars option in eclipse and copied all the resources to my new application's res folder. (The activity class say MainActivity of my new application is in com.abc.myapplication package, just for the case if it may helpful)
But when I run this new application there is java.lang.ClassCastException in the MyClass class. I tried to debug the application and then I found that in the MyClass class, there is "R cannot be resolved" problem.
Then I changed MainActivity's package to com.xyz.android.app (which is not the way, other developers will be happy to do), But again the same problem.
But When I just copy the source java file such that both MainActivity.java and MyClass.java are in com.xyz.android.app package then application runs fine.
So if I need to distribute such that other users need not to bother these package naming things,
how can I accomplish this? Please help !!
Edit
In android.jar, there are also some resources. How are they referenced in a project? How are they used in android classes? There is also android.R file?
Is it not possible to do the same thing i.e. to make jar file like android.jar for my reusable code?
As Nic Strong noted, there is nothing much built into the project to manage this, and current indications are that the upcoming changes to the SDK tools may only help a bit.
I am organizing some other tools to help deal with this problem. I hope to have developer documentation published in a few days.
This is not so easy to do at the moment. The problem is the project using your jar does not know to look in there for drawables etc.
The good news is it should soon be possible (hopefully with SDK 2.2 which is rumoured to be released at IO next week). See this blog post http://mobilebytes.wordpress.com/2010/04/27/android-tools-version6-coming/
I've been playing with Mark Murphy's ParcelHelper class at http://github.com/commonsguy/cwac-parcel. In a nutshell, it's a collection of methods that let you access the components of 'R' by name without needing to import 'R' into your code.
If I understand your question right, this is exactly what you want. You may still need to copy some resources, such as styleables, into your project.