0

My situation is that I want both free and full versions of the same Google Play Store (GPS) app. To satisfy GPS, I had the choice of figuring out GPS API for in-app purchases or creating a second package. I chose the latter path since the former was far from easy to follow (couldn't implement after trying for parts of 3 days).

Before realizing that a second package would be necessary, I had designed the app so that merely changing two imports (package names), one boolean assignment (FREE: true or false), and a couple of lines of AndroidManifest.xml (icon and app name) I could easily change the code from free to full and back again.

All well and good. Then came first bug: actionbar overflow "dashes" didn't appear on a tablet.

So I have two hunks of 99%-identical java and xml code. When I find the need to change code in future, I don't want to have to make two probably-identical changes. And figuring out the GPS API is not likely to penetrate my brain anytime soon.

In trying to answer my own question before posting, I just ran across this here, without further explanation:

I was using Android Libraries to build Free/Paid versions of my app. [With] the new Gradle Build Variants concept... you can now automatically build different signed APKs out of the same code.

It received an upvote, but that doesn't make it credible.

Is it?

If it is, I'm also not sure if it applies to me. The message from GPS when I made the changes alluded to earlier within the same package was that I needed different package names for the free and full versions, and that quote doesn't mention packages, although maybe it's a way around separate packages. I wish I knew.

If the quote applies to having ONE package upload TWO versions of an app to GPS, what do I have to do to make gradle do so?

EDIT--

I was sure there was no way until I found this. Is this a way to avoid near-duplicate apps and packages?

Community
  • 1
  • 1
DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • 1
    Yes, that answer is credible. If Gradle seems like black magic to you, learn a little bit of "Groovy". That's the language Gradle uses for its scripts. http://trygroovy.appspot.com/tutorial – Stephan Branczyk May 01 '15 at 20:55
  • 1
    Sounds like your Google searching is giving you the answers you need. Have you tried implementing any of the things you've found? – ianhanniballake May 01 '15 at 21:00
  • @ianhanniballake--I'm studying the Answer below and reading the link I posted. I'll get this, but may have to come back for more help. Thanks for the encouragement! – DSlomer64 May 01 '15 at 21:14
  • @StephanBranczyk--thank you for the encouragement and the link. This is gonna be fun. Once I make it work! – DSlomer64 May 01 '15 at 21:15

1 Answers1

4

Yes, Build Variants are the answer to your problem.

First, I recommend reading the Build Variants documentation on the Android tools site.

What you want in the end is two product flavors. Inside each product flavor closure you can specify the applicationId (formerly packageName) for that flavor. Your build.gradle will look something like this:

productFlavors {
    paid {
        applicationId "com.example.paid"
    }

    free {
        applicationId "com.example.free"
    }
}

When you build your app, you will now get an APK with every possible combination of product flavor and build type. These are called build variants. For your app, you will probably end up with something like debugFree, debugPaid, releaseFree, and releasePaid variants.

You just upload the releaseFree and releasePaid APKs to Google Play (as separate apps) when you want to release.

As for your issue of having duplicated code: When you create a new product flavor or build type, you can create a set of source files (resources, Java classes, etc.) to go along with that flavor.

By default, all your code goes into the main source set (this is the main folder in your project).

If you want to add some Java classes that provide different functionality for your free variant, you can put those classes in <project root>/app/src/free/java instead of <project root>/app/src/main/java.

For example, you might put a FlavorConstants class containing your boolean flag in both the free and the paid folders. Whenever you reference FlavorConstants in your code, it will be the correct FlavorConstants for whichever flavor is currently running on your device.

Bryan Herbst
  • 66,602
  • 10
  • 133
  • 120
  • @Tanis.7x--Thanks! I had just convinced myself that this would be what I'd need to do, but I don't know jack squat about gradle, so your post convinces me to study what you've said--including reading about gradle build variants--and give it a big try. There goes the weekend, maybe. I'll accept yours as the answer when I get it to work. – DSlomer64 May 01 '15 at 21:15
  • it should be `applicationId` and not `packageName` – Kai May 02 '15 at 00:32