How to point android build system at different android.jar file - android

I have created an "extended" android.jar file that includes classes that are only known internal to the Android system using this guide. In the guide, the author suggests creating a new platform in android-sdk-linux/platforms/ to build against that includes the extended android.jar file.
The problem I have with this is that I want to be able to keep this file in version control as part of the build system (and I would rather not keep the entire Android SDK in version control). So what I would like to do is to simply keep the extended android.jar in version control with my app, and then at build time, have my build system point to the extended android.jar instead of the one kept in android-sdk-linux/platforms/android-/. Is this possible, and if so, what's the best way to go about doing this?

The way to do this is as follows:
In the build.xml file for your app, there should be a line that looks something like this:
<import file="custom_rules.xml" optional="true" />
This allows you to import a file in your build that enables you to customize build rules. You may or may not have this file, depending on if you've customized your build already.
To point the build at your custom android.jar file, you can make the custom_rules.xml file look something like this (or just add the line containing the classpath if you already have created a custom_rules.xml file):
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" default="debug">
<property name="java.compiler.classpath" value="custom_libs/android.jar" />
</project>
Obviously the value you enter for the classpath depends on your build system. I simply added a "custom_libs" directory next to the custom_rules.xml file, and placed my custom android.jar in there.

Related

Android Studio creates app folder

I am working with Android Studio 1.1.0 on a MacBook Pro with OS X 10.9.5.
When I import projects (Eclipse) I find the source code is put under a folder named "app".
Ok, so far so good. The projects build and .apk files named app-debug.apk and app-debug-unaligned.apk are generated. They execute fine on the emulator and target device (Samsung Galaxy S5).
I wanted to rename the app folder as well as the .apk files.
The project name is tcpcommclient. I wanted to change the module name "app" to "TCP_Client". (not sure if I am allowed to do that).
I found the following in stackoverflow:
Why is my APK name generic?
Which said if I changed the folder name (app) I should also change settings.gradle. I did and that didn't work. I keep getting:
Error:Android Source Generator: [tcpcommclient] AndroidManifest.xml file not found
I looked through my project for instances of ":app" and found three of the:
workspace.xml
settings.gradle
app.imi
in which I changed to ":TCP_Client". I also notice that app.imi (should be manually renamed?) is still around under TCP_Client.
What also happens is that the folder "app" seems to be created by Android Studio even when I deleted it manually. Also another app.imi file is created there which contains the following text:
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
It seems like somehow I have Android Studio configured for this project so that it wants to see the source and the AndroidManifest.xml under the "app" folder.
Is there a way to change the name "app" to another name (namely "TCP_Client") and have that be the name of the .apk file?
Thanks in advance.
Jim
To rename a module:
Rename the folder from app to TCP_Client
In settings.gradle, replace include ':app' by include ':TCP_Client'.
Then resync the project with the Gradle files.
This is because Android Studio is a stripped-down version of IntelliJ IDEA that only allows you to create Gradle projects, and the Gradle plugin is nowhere near ready for prime time.
The easiest thing to do is just use a mature product like IDEA or Eclipse. But if you must use Studio, it's useful to know that app is actually the name of the Gradle module that it creates without bothering to ask you for a name. If you want a different name, create another module with the name you want, then delete the app module.

Creating and distributing jar files in Android

In my android application I have to separately implement a certain functionality and needs to make a library file(.jar) out of it.
Main idea is then I can distribute that jar file, so that other applications can easily integrate this functionality using the jar file within their apps.
Following I have indicate the Minimum and Target SDK versions that are in the Manifest file.
android:minSdkVersion="7"
android:targetSdkVersion="15"
I know I can create a library project to implement that specific functionality and have a reference for it from my main project. And then to distribute the jar file that creates under the bin folder of the library project.
I have couple of questions reagrding this.
1) Since I didn't find any good tutorial explaining this thing, bit not sure if this is the way to go (Distributing the jar file creates under bin folder).
2) Also the jar file that creates under the bin folder of the library project is with the same project name(Eg:- LibraryProjectName.jar). Is it okay if I rename it for what I want before I distribute it?
3) Are there any other alternative or good ways of doing this?
Any help would be highly appreciated. Thanks in advance.
Since I didn't find any good tutorial explaining this thing, bit not sure if this is the way to go(Distributing the jar file creates under bin folder).
I wouldn't. That JAR is an artifact of consuming the library project and may or may not be suitable for third parties. Besides, if you really need an Android library project, the JAR is insufficient.
Is it okay if I rename it for what I want before I distribute it?
JAR names can be whatever you want.
Are there any other alternative or good ways of doing this?
First, do not create an Android library project unless you need to ship resources along with the code (or JAR). And, in that case, you will need to distribute the JAR and all the resources (and the manifest and pretty much everything else in the project).
Second, create your own JAR, such as by adding a <jar> operation to your Ant script. That way, you are in control over exactly what goes in there, how it got compiled, etc., rather than making assumptions about the JAR that the build system created as a by-product.
For example, here is a jar target from one of my CWAC projects:
<target name="jar" depends="debug">
<jar
destfile="bin/CWAC-EndlessAdapter.jar"
basedir="bin/classes"
/>
</target>

Export android library project for reuse without source code

I need to export a library project without the source code for security reasons. Unfortunately the jar file generated within a library project does not contain the resources. I cannot expect the users of this library to deal with any resources needed by the library.
There have been similar post to this one, but I am yet to see a solution.
The following recipe used to work, though I have not tried it very recently:
Step #1: Get the library project working as-is. I will refer to the directory holding this project as $ORIG.
Step #2: If you have not done so already, create your Ant build scripts in $ORIG using android update project.
Step #3: Add a task to $ORIG/build.xml that creates a JAR file, something like:
<target name="jar" depends="debug">
<jar
destfile="bin/YOUR-LIBRARY-NAME-GOES-HERE.jar"
basedir="bin/classes"
/>
</target>
Step #4: Copy your entire library project from $ORIG into another directory, which I'll call $DIST.
Step #5: Get rid of the src/ tree in $DIST except for the root src/ directory itself.
Step #6: Move bin/YOUR-LIBRARY-NAME-GOES-HERE.jar into $DIST/libs/. This effectively replaces your source code from src/ with its compiled equivalent.
Step #7: Get rid of $DIST/bin/ as it is no longer needed.
$DIST now holds an Android library project that is the equivalent of $ORIG, except that the src/ tree is replaced by libs/YOUR-LIBRARY-NAME-GOES-HERE.jar.
Since the Google Play Services package from the SDK Manager is packaged this way, not only do I assume the recipe still works, but it would appear to be reasonably officially endorsed.
Note that there is new build system in the works that may give us more options here. If you are reading this question in, say, 2014, be sure to check to see if there are better alternatives.
One idea I've heard mention of is using a regular Library project with a reference to a Jar file which is where you would put all of your proprietary code. All of the assets would need to be in your library project and would be readable by the users of your library.
Keep in mind that anyone with apktool can extract these files from the final APK anyways.
However, the code in the JAR would not be readable and your users would need to reverse engineer them which can be difficult, especially if you obfuscate it.

android build: add jar to endstate via command-line builds

With respect to this question, simply putting a jar into the /libs does not auto-magically include that jar into the .dex when invoking, say, ant debug. Not at least with Android SDK ver 15.
I've verified this by comparing the same project created two different ways. First (call it 'Alpha'), by Eclipse. Second, via android create project ..., blah blah blah (the Ant way, call it 'Bravo').
Both Alpha and Bravo I built using ant debug. Comparing their /bin dirs, the jar under <project_root>/libs is missing from Bravo's *.d; Alpha's aren't.
What magic is Eclipse embedding during project creation?
Better still, how can I ensure a jar is passed to ant debug|release when building a project, that a jar is included in the endstate?
You may just have to adjust the build.xml to include something like the following in the -pre-build node if you want to hardwire it in. You can also add this in a custom target in the build.xml file that would able you do include from the command line when you want. Something like the following could work.
<target name="add-jar">
<copy file="${src.folder}/YourJarHere.jar" tofile="libs/YourJarHere.jar" overwrite="true"/>
</target>
Where ${src.folder} is defined in your ant.properties file.
Something like src.folder=PATHOFYOURJAR
Then you should be able to run
ant debug add-jar
including the file.
I have had to manually create the libs folder in the past but I don't see why you can't do this through the build.xml file. Hope this helps!

Android – multiple custom versions of the same app

Whats the best way to deploy several customized versions of a Android application?
Currently I have a script to exchange the resource folder for getting a customized version of my app. It works great, but all custom versions still have the same package name in the AndroidManifest.xml. Therefore it is not possible to install two customized versions of the app at the same time.
This is one solution for this problem, but that has to be done by hand
Can you think of a more easy solution, or how this could be built into a skript?
(btw: it is not for a porn/spam/whatever app, not even a paid one)
Perhaps the built-in Android "library" concept was not fully baked at the time of the original post, but it may be the preferred method as of 2011. Follow these steps for an ant build:
Starting from a working app (let's call it directory "myOrigApp", package com.foo.myapp), just add this line to "default.properties" to make it a library:
android.library=true
Now create a new app in a sibling directory in any way you prefer (let's call it directory "sibling", package com.foo.myVariant). Using Intellij Idea, for example, create a project 'from scratch' with directory 'sibling' and it will create all the files/directories you would normally need.
In that new, sibling directory edit "default.properties" to add the dependency:
android.library.reference.1=../myOrigApp
Copy over the Manifest from the original dir:
cd sibling
cp ../myOrigApp/AndroidManifest.xml ../myOrigApp/local.properties ../myOrigApp/build.properties .
Edit that copied Manifest file to change its package name to your new variant, "com.foo.myVarient"; that's the only change.
If you just run the ant build scripts, you may be done. (I had to just set up signing keys.)
If you want to set up an IDE like Idea to have the library project as a dependent of the variant project, follow these steps to add a library project to the variant project (assumes you already have a project set up for both):
Open the original project, bring up Project Settings, select your Facet and check "Is Library Project" and save.
Open the variant project, bring up Project Settings, select Modules
Add a module
Select “Import existing module”
Browse to the Original directory (myOrigApp) and select its .iml file (IntelliJ project source file)
Click "Finish." (The library project is added as a module within the variant project.)
In the modules list click over the Variant project to select it.
On the right hand side select the "Dependencies" tab.
Click "Add…"
Choose "Module dependency…" (A list should appear that includes the name of the module/library you previously added to the project--perhaps the only entry in the list).
Select the library project you added and press OK. (It will be added to the list of dependencies of your project.)
Press OK to finish configuring the project. (You should see 2 modules, with the library's resources and classes available and recognized in the Variant project.)
What I did for something similar to this is to just use an antlib task and then go through all java and xml files to replace my old package string to the new package string. It didn't matter if the files were not in the correct src paths according to the package. Just doing a regex replace for all the files was enough for me to get this working...
For example to replace it in all your java files under the src directory:
<replaceregexp flags="g" byline="false">
<regexp pattern="old.package.string" />
<substitution expression="new.package.string" />
<fileset dir="src" includes="**/*.java" />
</replaceregexp>
You definitely want to use Gradle flavors that comes natively, encouraged even, on Android Studio.
It seems to explain all the basics really well. I just finished converting to Gradle today, and it works great. Custom app icons, names, and strings, etc.
As the website explains, part of the purpose behind this design was to make it more dynamic and more easily allow multiple APKs to be created with essentially the same code, which sounds similar what you're doing.
I probably didn't explain it the best, but that website does a pretty good job.
The linked-to solution does not have to be done by hand. Bear in mind that the package attribute in the <manifest> element does not have to be where the code resides, so long as you spell out the fully-qualified classes elsewhere in the manifest (e.g., activity android:name="com.commonsware.android.MyActivity" rather than activity android:name=".MyActivity"). Script your manifest change and use Ant to build a new APK. AFAIK, that should work.
Support Multiple Partners
Prepare config.xml
Build project for different partner
<!--partner.dir, pkg.name, ver.code, ver.name are input from command line when execute 'ant' -->
<!-- set global properties for this build -->
<property name="build.bin" location="bin"/>
<property name="build.gen" location="gen"/>
<property name="src" location="src"/>
<property name="res" location="res"/>
<target name="preparefiles" description="Prepare files for different partner" >
<delete dir="${build.bin}" />
<delete dir="${build.gen}" />
<copy todir="${res}" overwrite="true" />
<fileset dir="${partner.dir}/res" />
</copy>
<!-- change the import in all Java source files -->
<replaceregexp file="AndroidManifest.xml"
match='android.versionCode="(.*)"'
replace='android.versionCode="${ver.code}"'
byline="false">
<replaceregexp file="AndroidManifest.xml"
match='android.versionName="(.*)"'
replace='android.versionName="${ver.name}"'
byline="false">
<replaceregexp file="AndroidManifest.xml"
match='package="(.*)"'
replace='package="${pkg.name}"'
byline="false">
<!-- change the package name in AndroidManifest -->
<replaceregexp flags="g" byline="false">
<regexp pattern="import(.*)com.myproject.com.R;" />
<substitution expression="import com.${pkg.name}.R;" />
<fileset dir="${src}" includes="**/*.java" />
</replaceregexp>
<replaceregexp flags="g" byline="false">
<regexp pattern="(package com.myproject.com;)" />
<substitution expression="\1
import com.${pkg.name}.R;" />
<fileset dir="${src}" includes="**/*.java" />
</replaceregexp>
</target>
Prepare Files
$ ant -f config.xml -Dpartner.dir="xxx" -Dpkg.name="xxx" -Dver.code="xxx" -Dver.name="xxx" preparefiles
Create build.xml
Build
$ ant debug
or
$ ant release
I'm using the maven-android-plugin to achieve this. Specify one AndroidManifest.xml for the generated-sources goal and another AndroidManifest.xml for the final apk goal. That way the source code project retains the actual source code package name during generation of the R class and the build phase, while the market adapted manifest package name is in the second AndroidManifest.xml which is included in the final apk file.
I wound up with a script that patches the sources; patching the source sounds risky, but in presence of version control the risk is acceptable.
So I made one version, committed the source, made the other version, committed the source, and looking at diffs wrote a patching script in Python.
I am not sure if it is the best solution. (And the code misses some os.path.joins)
The heart of the script is the following function:
# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,mandatory=True):
with open(fname, 'r+') as f:
read_data = f.read()
pattern = r"("+re.escape(before)+r")\w+("+re.escape(after)+r")"
replacement = r"\1"+newtext+r"\2"
new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
if replacements_made and really:
f.seek(0)
f.truncate()
f.write(new_data)
if verbose:
print "patching ",fname," (",replacements_made," occurrence", "s" if 1!=replacements_made else "",")"
elif replacements_made:
print fname,":"
print new_data
elif mandatory:
raise Exception("cannot patch the file: "+fname)
And you may find the following one of use:
# Change the application resource package name everywhere in the src/ tree.
# Yes, this changes the java files. We hope that if something goes wrong,
# the version control will save us.
def patchResourcePackageNameInSrc(pname):
for root, dirs, files in os.walk('src'):
if '.svn' in dirs:
dirs.remove('.svn')
for fname in files:
fileReplace(os.path.join(root,fname),"import com.xyz.",pname,".R;",mandatory=False)
There is also a function that copies assets from x-assets-cfgname to assets (earlier it turned out that for me it is more convenient to have a subdirectory in assets).
def copyAssets(vname,force=False):
assets_source = "x-assets-"+vname+"/xxx"
assets_target = "assets/xxx"
if not os.path.exists(assets_source):
raise Exception("Invalid variant name: "+vname+" (the assets directory "+assets_source+" does not exist)")
if os.path.exists(assets_target+"/.svn"):
raise Exception("The assets directory must not be under version control! "+assets_target+"/.svn exists!")
if os.path.exists(assets_target):
shutil.rmtree(assets_target)
shutil.copytree(assets_source, assets_target, ignore=shutil.ignore_patterns('.svn'))
Well, you get the idea. Now you can write your own script.
I think the best way is to create a new project and copy the stuff. steps,
- create new android project without a class
- create package (package name should be corresponding to the one in the manifest file), or just copy the package name in the 'gen' folder
- copy the java files
- copy the drawable folders
- copy the layout files
- copy any other file(s) used in ur project
- copy manifest file's data
this has been simpler for me for the task

Categories

Resources