I have multiple Android applications, and I've created a common Android library project, and a common Java library project (The Android library project compiles the java one). These libraries are filled with common components that I use for all my Android apps.
I'm using gradle as my build system.
I'm using git for versioning.
What would be the best way to link everything together? Keep in mind things are still being added / changed in the library, and I need a way to propagate changes to all the Android apps. Copy / Paste wouldn't be a great option. I've tried a few things, and they aren't working out very well, so I'd love some input.
EDIT: It's probably also worth mentioning that multiple people are working on these projects. It's not just me.
The current version of Android Studio has a limitation that all of its modules must be under the project's root directory in the filesystem, and this limitation hampers a lot of people in your situation, because frequently they want those common libraries to live someplace else. It seems like this is the case for you as well.
We're in the process of lifting this limitation in Android Studio, and soon you'll be able to have modules outside the project root. I think this might be the best solution for you -- you can pull your common libraries from wherever makes sense in source control, put them wherever makes sense in your filesystem, and link them up into whatever projects need them. However, this isn't available yet, but will show up in v0.5.0, which will hopefully go out this week. I haven't personally tested it in our dev builds and can't vouch for how well it works, but at any rate it should be coming along soon.
Some developers have worked around the limitations by adding script to their settings.gradle files to set different module root directories. They say it works, but I find it a little scary because the IDE just isn't expecting things to work that way, and I don't know for sure if there are problems with it.
If you read other answers to this question on Stack Overflow, they're written before this feature was implemented and will have different advice. If you don't want to wait for 0.5.0 or there are problems in it that prevent you from using it, you can follow that general advice, which is to have your common code compile to libraries that you publish to a Maven repository (which can be local to your machine or common to the developers in your group), and pick up those libraries with Maven-style dependency statements in the projects that need them. This has the disadvantage that you'll need to open up separate projects to edit the code in those libraries, along with a more complex build process, but it will work.
Related
I'm migrating from Eclipse to Android Studio, and I've done a bit of reading. I understand the theory of Eclipse workspaces/projects vs AS projects/modules, but I'm having a hard time figuring out how to best reproduce my Eclipse setup, or if it's even what Android Studio wants me to do.
I have two applications. For the sake of illustration, let's call them EmployeeApp and CustomerApp. These are different applications in every sense - different packages, wildly different source, everything; as far as I can see, they are certainly not just product flavours.
However they both use a lot of library modules, and for the most part, they use the same ones. They also live under the same structure in the same repo.
I wrote separate Gradle scripts for both apps before this migration, and that's what I used to import them. In that way, I can import the top level applications, and end up with two projects in two windows, like this:
The trouble with this is that if someone changes a library project, they at the very least need to know whether it's broken the two apps that depend on it, so ideally I want them in the same view.
First question then: now that it's 2016, does Android Studio allow me to do that, and is it regarded as an intended usage?
If so: how do I do it? I've tried importing the missing parts of one into the other using the 'Import Module' feature, but it apparently does very little.
I think I've resolved this myself. Only time will tell if it's actually an appropriate solution in practice or not.
The problem stemmed from the fact that I'd basically created two independent Gradle scripts, i.e:
Android\EmployeeApp\build.gradle
Android\CustomerApp\build.gradle
whereas what made this work was a top-level build as well, i.e.:
Android\build.gradle
Android\EmployeeApp\build.gradle
Android\CustomerApp\build.gradle
This didn't contain much:
dependencies {
project(":EmployeeApp")
project(":CustomerApp")
}
and then build.settings simply included one of these pairs for every project:
include ':Services'
project(':Services').projectDir = new File(settingsDir, './Services')
I then imported that top level build.gradle and almost all was well.
I did have to do a bit more, like move repositories and allProjects to the top level, but this will be specific to whatever you have.
I have a piece software that should delivered to many customers.
Each build should get a customized set of assets (icons , splash screen etc. ) and a bunch of config files, but also a different app id (eg. com.myself.myapp.customer1 ; com.myself.myapp.customer2 etc... )
Also I need builds for different OSes like Android, iOS , PlayBook.
The way I handled this up to now was:
I created a new Application.mxml for each customer, which opened the right locations and passed the files to the MainController.
This leaves it to me to pick the right assets, certificates and iOS-provisioning files to be packaged each time I need to compile, and I had to repeat this steps for each customer, which is very error-prone and , especially in case of iOS, extremely time-consuming.
So I need to get into automated building quickly...
I already downloaded and installed gradle/gradleFX, but I don't find the documentation very friendly to beginners in this subject.
Now the questions:
How do I have to convert the (Flash Builder- ) given project structure to conform the gradle conventions? Are there FB-plugins or tools I could use?
Can I use gradleFX to build for debug sessions as well? FB 4.7 has a lot of issues with that I really like to circumvent.
Can an ipa be "signed" and packaged with assets after it's principle compilation, so I don't have to wait 15 mins for each compile?
Many thanks
How do I have to convert the (Flash Builder- ) given project structure
to conform the gradle conventions? Are there FB-plugins or tools I
could use?
There is nothing to convert. Unless your project structure is extremely exotic, you should be able to configure GradleFx to work with it.
Note that by default GradleFx uses some Maven-style conventions: for instance, the default source folder will be src/main/actionscript. If you want to configure a typical FlashBuilder project you'll have to explicitly declare the source folder:
srcDirs = ['src']
As for FB plugins: there are none. But you can use an "external build tool" instead of FB's built-in configuration. IntelliJ IDEA has Gradle support, but nothing specifically for GradleFx. GradleFx itself has a flashbuilder plugin, but its purpose is to generate an FB-compatible project from a build script - I don't think that's what you're looking for.
Can I use gradleFX to build for debug sessions as well? FB 4.7 has a
lot of issues with that I really like to circumvent.
You can build a debug-enabled version of your application simply by setting the debug flag to true (as described in Adobe's mxmlc docs). GradleFx does not expose all compiler options in its API (there's just too many of them), however you can use the additionalCompilerOptions to define whatever additional compiler flags you require:
additionalCompilerOptions = ['-debug=true']
I don't know how you should tell FlashBuilder to hook up to the compiled swf for its debug session though :( Perhaps through the "external build tool" configuration.
Can an ipa be "signed" and packaged with assets after it's principle
compilation, so I don't have to wait 15 mins for each compile?
I know too little of mobile support to give you a meaningful answer here, but I can tell you that a major upgrade in this area is in the works right now and will be released soon. Perhaps you should ask this question on http://support.gradlefx.org/; #Slevinbe is very helpful and quick to answer.
I don't find the documentation very friendly to beginners in this
subject
If the docs don't work for you, perhaps the example projects might be more helpful. That said, you could help us make the docs better for beginners by telling us how we could improve them. Just start a discussion on support.gradlefx.org
Multiple outputs
One more thing: your main issue seems to be that you need to create multiple outputs from a single code base. This is one thing that GradleFx doesn't provide out-of-the-box (yet). However, there's a fairly unobtrusive workaround that I've described on my blog. If you find the basic concepts difficult to grasp, then I suggest you don't start with this part, but rather concentrate on getting a single project building first.
I have an Android app that's downloaded primarily from Android Market (now, Google Play). We made a few tweaks to the source and also submitted to the Amazon App Store to see what sort of traction it gets. I'm now looking for a sustainable way to develop from a common code base and yet build so that I can submit to either/both.
Amazon's store has some restrictions about available APIs, and hence I'd like to conditionally remove/modify features from that version. Since Java doesn't support traditional conditional compilation, and conditionally including files in Eclipse doesn't seem trivial (is it even possible?), I wanted to ask what others are doing to solve this.
Admittedly, I'm no Eclipse/Java expert so feel free to school me.
What I'm looking for in a solution:
Building/debugging using Eclipse.
Static code files, with environment/settings toggles to control what to build.
No duplicate code or conditional logic in code to pick code flow at runtime
Is this something you've solved for Android apps specifically, or for other Java/Eclipse based projects? Suggestions for where to begin?
It's quite easy to do in the newest versions of ADT (version 17), though I do find it makes compilation a bit longer:
Create a new Android project (proj-A)
Go to Project->Properties, select Android, and check "Is Library"
Move all your common code to proj-A, import all the necessary libraries
Create a new Android project for Google Play (proj-B)
Go to Project->Properties, select Android, and add Proj-A to the Library
Repeat #4&5 for the Amazon version
If you have some variables that should be set differently for each sub project (i.e. boolean GOOGLE_PLAY_VERSION to enable Google Play specific functions), you have to create another project to contain these values since you can't have projects that reference one-another in a circular fashion. You can solve this by adding the following steps:
Pull all of your sub-project specific variables into one or more Classes that just serves as container(s) for these variables
Create a "dummy" Java project (dummy)
Config proj-A to add a new Source link to the bin directory of dummy
Add the config Classes in each sub-project with project-specific changes
Profits!
Note that the variables in dummy should not be set as final, otherwise it will override sub-project's setting.
This may seem like quite a bit of up-front work, but has worked quite well for me as far as version control goes.
Edit:
Now with Google's move to Android Studio & Gradle, it may be better to move to that if you are starting a new project if you want to support multiple APKs, see Android dev site's Building Your Project with Gradle#Work with build variants. It definitely doesn't hurt to evaluate that option before deciding.
Unfortunately, it's sort of a convention in Android to change flow at runtime based on what would be in C/C++-land conditional compilation.
Our app has to maintain different behavior for different API levels, so we've created some application-level constants that are initialized statically based on API-level information available to us, and used throughout the code. This is the way that Google does things in their examples (for example, see the ActionBarCompat compatibility library, and in particular the factory method used here).
You could create an interface CustomBuild, and implement it in AmazonBuild and GooglePlayBuild, then use a static getBuild() method to switch functionality as necessary:
if(getBuild().shouldEnableFeatureX()){
doStuff();
} else {
doDifferentStuff();
}
Then all you've got to worry about switching between builds is a line or two of code in the factory along with maintaining which things you want enabled in which versions. Or you could include a different version of a static class CustomBuild for each build.
I'm going to second the suggestion of others above re: switching to something like Maven for building; it should make your life much easier once you have it set up.
I'm also going to say you should make the core of the app a library as suggested above, and have two different modules (one for amazon, one for play store) that depend on the library but each only contain the one custom factory file (or just a static class for each type of build that contains the same "should I do this thing?" methods... once you have the infrastructure it's just a matter of preference).
I haven't actually tried this yet, but it's something I've thought about.
How about using Eclipse's ability to link to files from a directory outside your workspace?
Start with one Eclipse project: for the sake of argument, say it's the Google Play version.
Now build a second project, beginning with asking Eclipse to link (not copy) the source files from your first project.
To develop the second project, add classes that subclass ones from the original project to realize your modifications. For resources, you can use some combination of includes, attribute overrides, and selectors.
Where it's not possible to subclass or extend, then obviously you'll have to just copy the original source file and hack on it. If you're really OCD about it, you can probably just maintain a patch set rather than a whole redundant set of files.
What do you think, will it work?
You may create manually two projects in Eclipse pointing to the same source folders but with different inclusion/exclusion filters and different target directories.
Then two Ant targets using properties to switch excluded files from javac fileset are enough to generate corresponding jar files.
The aim is to get a clean application for each target, without any code from the other one.
With features listed as pluggable behaviors in a property file or XML configuration, your runtime will adapt itself with the addition of menu entries.
I've been doing a lot of research to try to set up my development environment to produce highly maintainable code, essentially. I've found many tools for Java/Android around, and the more I research or try to use more it seems that I end up running around in circles. Is there anyone that can give me solid advice on these things? A lot of my search results are out of date, and/or partial. They at best get me one piece of the set up, but don't work well with each other.
Tools I've tried to integrate into my development:
Code Coverage
TDD
Build tools
Dependency Injection
Compatibility libraries
Continuous Integration
I wanted to have a nice MVC structure to my project, with proper scoping of objects, so I discovered Roboguice/Guice and using interfaces/abstract classes to expose the API of the underlying implementation. This I got to work fine for me so far, though not for testing yet. I need an older-SDK compatible Action Bar, so I was lead to ActionBarSherlock in the Android Office Hours. I can add the Android Library Project fine it seems.
Then I discovered (at least for the current stable version) you have to do some maneuvering to get it to work with Roboguice because of the compatibility library. The solution pointed to using Maven to handle the dependencies. So I look into converting my Android project to a Maven Android project (it's something I was considering doing anyways for the cleaner project dependency management). Now I believe I have Maven, Android, and Eclipse (yes, I forgot, Eclipse is another variable in this equation) to work together. But now I'm having issues using the ActionBarSherlock library when importing it through an apklib-type dependency as the guide mentions. Can't "find symbol: class FragmentActivity" for example. I try to make a new Android Library Project with the "target/unpack/apklibs/" Maven produces, but can only get empty Android projects missing an AndroidManifest.xml.
Then I try to find how I could add code coverage for my testing suite, and I find Emma, EclEmma, and Robotium. It seems that those only "work" with Ant builds, in particularly, I've only read things for Emma that seem to require major modifications of the default Android files and build script to support the code coverage reporting. I'm now hesitant to move forward on those because I don't want to destroy my Android development base pursuing old advice, and it requires Ant not Maven, but my earlier work needs Maven.
I'm hesitant to ask such a question because it seems broad, but they are important tools for developing production code so people must be using them, and I can't seem to figure out how to get a nice subset of them working simultaneously. Is there any experienced advice for this issue?
This is more of a side note. All tools you are mentioning are wonderful but please remember that all of them come at the cost of adding bulk to your app. My rule of thumb is: no more than 150-200K of added weight. So I have a tendency to use simple and built-in packages. I get much more mileage on good reusability of my code and I'm really picky about any code repetition. So, refactor, refactor and refactor. Eclipse provides wonderful facilities for that
I know there are a lot of questions out there about multiple Android versions pertaining to free/paid versions but this might be a little different.
My app currently uses AdMob for advertising and it's published on the Android Market and on the Samsung App Store. Unfortunately, the Samsung store will require everyone to migrate to their own Ad Network in the future, Samsung AdHub. Both AdMob and AdHub have their own libraries, their own SDKs.
I'm looking for a solution to build 2 different versions, one including AdMob the another including AdHub (and all the necessary code). What solutions do I have to easily build 2 versions without much hassle when it's time for a new version release?
Lots of solutions recommend to move the main project into a library project and then build 2 other apps which include the library project (the base project). But I'm not very fond of that solution (I prefer to keep my app in one single project, if possible) and I'm trying to look for alternatives and then make up my mind about which one is better for my needs.
I'd think you should make this possible in your code using the Strategy design pattern. It suites well and can be switched at any trigger your like (even on runtime). If you make a facade for each jar file you will be able to change the dependencies while building, having the same source code.
Other option with this method is just making some configuration in your application that determines which library to use.
Some interesting solutions can be found here:
https://groups.google.com/d/topic/android-developers/8pRugcnzR_E/discussion
The way to go now is to use Android Studio and use different Gradle flavors for each app. Thus, if you fix core functionality, you can quickly do a build for each appstore with it's own ad network.
Library Projects is the way to go. Create a base project where you implement all the common stuff and then create two separate project that use the common one as a "Library". then just implement the rest needed to make the Apps behave differently.