10

I have two programs. First is a desktop app (C#) and the other is an android app.

The C# one makes some text files and puts them in some of android app folders. So we can have multiple android apps with different contents. the android app is pre-compiled. and the c# app just puts the test files in (with 7za) and repackages it (with zipalign).

The problem is, All of these apps have a single source! means same package name and same app name!

And as you know, android considers same package names as same apps! How can i solve this problem? and create separate apps from a single android app with different text files (contents)

More details: I have a single android app (test.apk). My C# app should edit this zip file and repackage it. putting text files in assets folder is working good. But by this method, the C# app output's apks all are the same! i can't install them on mobile separately, because android OS replaces them on each other.

Mbt925
  • 1,317
  • 1
  • 16
  • 31
  • Have tried read latest google guide on the topic? Sometime maybe (if possible) that change our point of view and complying a standard behavior can save a lot of coding. The _key concept_ of android OS is that the application lifetime is handled by the operating system. Your question seems to touch something that should be done in a predefined way, before all I'll try to adhere to _Google_ guidelines. Here for user reference http://developer.android.com/index.html. – jay Mar 19 '13 at 20:07
  • I have tried to replace AndroidManifest.xml. but in a apk file, the manifest.xml is coded as binary. how can i convert my new .xml file to binary coded form as like as the original one? – Mbt925 Mar 20 '13 at 06:46
  • If you own the source code, it is much much better to do what you asked in the raw source other than the pre-compiled apk. You can use build tools (Ant, Maven and Gradle) standardize, simplify and automate the build process. – yorkw Mar 24 '13 at 20:21
  • Do you own the source code? If not, how do you happen to be using the APK? Is it a legacy APK for which the source has been lost? Without source code, anything you do will probably be a kluge. With it, there are many better approaches (such as a Project Library) that could be used to specialize your app's code into multiple apps. – Carl Mar 24 '13 at 21:29
  • i own the source code, but the problem is i want to use just jdk on user's PC. i am using the APK, because i assume there is no tool to compile my source code on user's PC. – Mbt925 Mar 25 '13 at 06:31

4 Answers4

8

I found myself in a similar situation.

I had a single app but built for different customers (having specific customization like resources, properties...). I eventually decided to manage the whole thing using maven.

What I've done is creating a "config" folder in my codebase and inside it I've added pro customer a folder containing the properties, string, pictures related to him.

My structure is something like this:

MyAppBase
 src/
 build/
 BaseAndroidManifest.xml
 ...
 config/
   customerA/
      logo.png
      customerA.xml
      customerA.properties
   customerB/
   customerC/
   ...

Using maven artifacts for copying, move, replace I've then managed to build customer specific apk in the following way:

1) Create a temporary customer specific source folder where all code is copied to

<copy todir="src_${customer}">
  <fileset dir="src"/>
</copy>

2) Rename packages and imports

<!-- Rename main package -->
<move file="src_${customer}/ch/wizche/myapp" tofile="src_${customer}/ch/wizche/${customer}"/>
<!-- Replace package imports with the newly one -->
<replace dir="src_${customer}/" value="ch.wizche.${customer}">
  <include name="**/*.java"/>
  <replacetoken>ch.wizche.myapp</replacetoken>
</replace>

3) Replace specific resources based on the customer

<!-- Copy images icon to the drawable folder -->
<copy file="./configs/${customer}/ic_launcher_l.png" tofile="./res/drawable-ldpi/ic_launcher.png" overwrite="true" verbose="true"/>
<copy file="./configs/${customer}/ic_launcher_m.png" tofile="./res/drawable-mdpi/ic_launcher.png" overwrite="true" verbose="true"/>

4) Replace "Template" AndroidManifest and injecting customer versions, names, ...

 <copy file="./BaseAndroidManifest.xml" tofile="./AndroidManifest.xml" overwrite="true" verbose="true"/>
 <replace file="./AndroidManifest.xml" value="ch.wizche.${customer}" token="ch.wizche.myapp"/>
 <replace file="./AndroidManifest.xml" value="android:versionCode="${versionCode}" token="android:versionCode="1"/>

5) Signing using customer alias

6) Building APK

7) Deleting temporary customer folder

So, to build a customer specific app, I just need to:

mvn install -Dcustomer=customerA -P release

Hope this may give you some inputs.

Wizche
  • 893
  • 13
  • 32
  • Thank your for the answer. my app is going to install on user's PC. by using your approach, what should i install on user's system but JDK? – Mbt925 Mar 25 '13 at 06:35
  • One of the differences between your problem and mine is that, you build the user-specific version on your system, but my app wants to do that on user's system – Mbt925 Mar 25 '13 at 06:51
  • You will need the Android SDK too. Further the user needs the source code of the app. Why not use a build server? I.e. the user configure his parameter from the C# App and then when it comes to build you push the user configuration to a build server, make the build and let the user download the APK from it. – Wizche Mar 25 '13 at 09:23
  • Your idea is good. I can't count on internet, Because in my country, internet is not something accessible at anytime on user's PC! – Mbt925 Mar 25 '13 at 13:00
  • 1
    I think you are running out of options here. If you want changing the compiled package (apk) instead of building it on the user's PC, it's likely that you will find some obstacles along the way (classes.dex, manifest in binary format, signing). PS: You can convert the binary AndroidManifest using https://code.google.com/p/androguard/wiki/Usage#Androaxml – Wizche Mar 25 '13 at 14:18
  • yes, i agree with you. editing manifest file alone, does not enable us to get different apps. as you know, just the package name is matter. – Mbt925 Mar 25 '13 at 21:31
  • 1
    Of course, you will need to refactor package name everywhere in code, this means you will have to decompile the classes.dex and perform your changes manually to the smali (disassembled). Have a look at http://forum.xda-developers.com/showthread.php?t=2011489 – Wizche Mar 26 '13 at 08:38
  • changing app package name, does not need re-factoring anything in code! i just need to change package name in manifest file and convert it to binary-coded form. How can i convert the manifest file to binary-coded form? i need a small command line approach. – Mbt925 Mar 29 '13 at 05:44
  • Of course you need to change everywhere the reference to your resources, normally you referece to R with your package name, if you change this, your import have to reflect the new package name. for example if you import com.myapp.one.R and you change your package name to com.myapp.two, you will need to reference to com.myapp.two.R – Wizche Mar 29 '13 at 13:11
  • As described here http://stackoverflow.com/questions/8209816/android-is-it-possible-to-manually-change-somethings-in-manifest-file-directly you have to RECOMPILE with apktool. Furthermore you will also need to change package structure within classes.dex because your Activity will be located somewhere else. Not sure if you can succeed without recompiling. – Wizche Mar 29 '13 at 13:29
  • 1
    No, app package name is different from java package name. i just need to edit androidmanifest.xml and convert it back to binary form. for more info about package name, see this link: http://blog.javia.org/android-package-name/ – Mbt925 Mar 29 '13 at 14:16
  • I check your answer as accepted answer. however, my question right now is: how to convert manifest file to binary form? – Mbt925 Mar 31 '13 at 06:03
  • Thanks! I never tried this but I've read that with apktool is possible, there is a dedicated thread on XDA: http://forum.xda-developers.com/showthread.php?t=893617 give it a try – Wizche Mar 31 '13 at 08:41
  • apktool encode the whole folder to apk, but i just need to encode the manifest file. – Mbt925 Mar 31 '13 at 09:41
3

I had a similar problem where i wanted multiple apks with different resolutions of graphics in each (a single apk with all images for all display sizes was too big).

I ended up creating a custom build process where i inserted a 'prebuild' AntTask that basically copied over the correct resources for the build and preprocessed the source such that the package was updated for each apk..

can't find any official docs but this should be a good start..using-ant-to-automate-building-android

legspeleo
  • 87
  • 2
  • Thank you for the answer. I don't want to use ant, because i can't install it on users PC. – Mbt925 Mar 20 '13 at 06:40
  • how about pointing ANT_HOME to the bundled eclipse version .. in fact the whole thing can still be run from eclipse if set up right – legspeleo Mar 20 '13 at 15:38
  • the point is, the android app is pre-compiled. So i want to do these stuffs by desktop-side app (C#). – Mbt925 Mar 23 '13 at 06:20
2

You might try distributing an unsigned .apk, then sign it using different keys from within the C# app. I've used signapk.jar to sign unsigned .apk's from the command line.

The risk is that you're distributing private keys to your customers. If that's not a concern, since in a sense, they're building their own apps with your tool, then it might be worth a shot.

See the following lines for more info:

How To Sign APK Zip Files

Android App Code Signing without Eclipse on Windows

Community
  • 1
  • 1
Chuck Spohr
  • 626
  • 4
  • 10
  • I tested two signed versions of the same app. but after installing the first one, in order to install the second one, the first one should be uninstalled first! – Mbt925 Mar 29 '13 at 05:36
  • OK, well, I wasn't sure if it would work. I thought Android might allow two apps with the same name if they had different keys. – Chuck Spohr Mar 29 '13 at 14:08
  • I haven't tried this myself, but I saw an apk tool that allows you to decrypt the manifest, change it, and put it back. http://stackoverflow.com/questions/4191762/how-to-view-androidmanifest-xml-from-apk-file and http://code.google.com/p/android-apktool/ – Chuck Spohr Mar 29 '13 at 14:32
  • i have the manifest file, so i don't need to decrypt it. i just need to encrypt it to binary form. apktool convert the whole apk. i need a simple code or tool to do just this conversion. – Mbt925 Mar 29 '13 at 14:59
  • Another idea: Could you distribute a set of pre-made encrypted manifests, all with different names? Number them, or something, and allow the user to select which number to use for a given build? Then your c# program would pick the one of the users choosing, and package it up with that manifests package name. Crazy idea, but hey! – Chuck Spohr Mar 29 '13 at 16:18
  • yeh, but it's limited! i prefer do it the hard way but not limited. – Mbt925 Mar 29 '13 at 16:58
1

There is good discussion of this at How to support multiple android version in your code?, which looks at creating multiple versions of an app. The answers contain a clear strategy for doing this, and details of the process involved.

Community
  • 1
  • 1
Neil Townsend
  • 6,024
  • 5
  • 35
  • 52