APK contains unused resources - android

Yes, I saw that the similar question had been asked some years a go, but was unanswered, so I just had to give it another shot.
I am quite annoyed with the fact that the .apk file for the simple Android app I am building has 4MB in size.
When I analyse the .apk, i see that it contains not only unused classes (which can be stripped with ProGuard), but also all the graphic resources from HoloEverywhere.
I mean, even the drawables for the themes I am not using at all are in the apk.
This behaviour looks very illogical, or it just might be that I am doing something very wrong.
Finally, my question is: Is there a way to make the .APK contain only the needed data?

I mean, even the drawables for the themes I am not using at all are in the apk.
From the standpoint of the build tools, they have no good way of knowing that you are not using those drawables.
This behaviour looks very illogical
You are welcome to build a tool that can reliably detect unused resources and removes them from an APK. Call it ResGuard or something. Even the commercial DexGuard doesn't do this.
Is there a way to make the .APK contain only the needed data?
Delete the stuff that you are not using. You're the only one who knows what that is, and since HoloEverywhere appears to be no longer maintained, it's not like you will have updates to worry about.
Long-term, I understand that there's a plan to have Gradle for Android allow you to filter out resources as part of referencing an AAR. I'm not aware that this is in place just yet, and you'd still need to know what resources should be filtered this way. This would allow you to avoid modifying the original project, though.

Related

Android Source: What is building exactly and is it necessary to test small changes?

For a project, I am changing certain ContentProvider-files in the Application Framework Layer of the Android System. As I am trying different things, I was wondering if it is necessary to build the Android Source for every change I make, or if there is a way to somehow emulate the system without the build?
I am not entirely sure what "building" means, as I cannot find a proper definition including Android as a context. I assume it is some kind of compiling?
Converting the source code into an executable program? In that case I do not think there is another way, is there?
But do I understand building correct in the first place? In that case, I would believe there is no other way than building the system every time and then see how it works out.
So I might have the solution right here, but I was hoping someone could assure me that it is right or maybe tell me why it is not?!
Any help is very much appreciated!
Building in this context means that all Android source files are re-compiled by the java compiler and a massive .jar file is produced. This is the Android.jar file that we see in the library dependencies of an Android application project.
Unfortunately, the short answer is that there is no way out for you except to re-compile the entire blob of the Android framework files each time you make a change. What I can advise you is to plan all your changes beforehand so you don't end up wasting a lot of time.

Multiple targets using same android project in eclipse ADT

I have a base android project that gets tweaked and would like to generate different APKs. Typically the changes are help links, icons/images, hiding certain functions etc.
In iOS (Xcode) and in Win store app (VS 2012 exp), it is possible to create multiple targets to control the resources bundled with the target as well us programmatically change behavior using the C flags.
Is it possible to do the same for an android project using eclipse ADT? The main issue I see is that, each APK changes the bundle signature (like com.xxx.yyy) and since every file has that package com.xxx.yyy in the files, it is not possible to use that file in a different project (which has a signature like comm.aaa.bbb).
In eclipse .apk builds with Ant and don't support multiple APKs build. Of course you can write your own script, but it will be difficult.
Fortunately, there is another build system, which is called Gradle and it's supported by android developers.
http://tools.android.com/tech-docs/new-build-system/user-guide
You are interested in a section called "Build Variants"
But not everything is so simple, Eclipse with ADT and Gradle are not compatible but Android Studio yes.
The source of this problem is Java itself, where you can't have things similar to #ifdef and most compiler don't allow completely replacing a class or part of it either.
I actually have a base project from which I build 6 APKs already, and more soon.
Each APK uses its own package name, however the whole code is under a single package, but that doesn't create any issue.
There's however many issues:
- All resources, all classes will be in the target APKs, whether used or not.
- Different behavior means different code or different resources, each of which must be handled differently.
For resources, it's "quite easy", just make replacement resources in the final application projects. However unused resources will be left over.
For classes, that's where it becomes very complicated.
To create slightly different behavior you can use reflection and interfaces, each APK implementing it's own version of the interface using a common name eg myActivityPrj which is retrieved using reflection.
Sometimes it's also easier to test the APK package name from within the code, so in the Application object, I set some boolean as to which APK is actually running. Making sure to use those only from the UI to avoid any performance hit.
To create very different behavior, for example an activity is not used in an APK, well, could use above method and a flag saying available or not, but what a waste of space inside the APK!
Another option is to break-down the central project in smaller pieces, if at all possible!
To actually make APK smaller, I found only one way so far: create a Java project which will copy the central project and then remove and/or replace files within this copy, from a remote source tree (a directory named "replacement-files" which contains a res and src folder).
For resources, that java project will actually parse all strings.xml and remove unused strings from a hard-coded list, can't trust lint output as some resources are used in sub-projects and lint doesn't care.
So far, the APK that includes all features is about 10MB, one variation is about 4MB, whereas it should actually be less than 2MB. Another variation is about 8MB, whereas it should really be 2 or 3MB. The above method is overly complicated and being able to removed unused code and resources is getting more and more complicated.
I've looked at various other solutions, but they're all very complicated with a lot of restrictions, constraints.
After 4 years of development on Android, my only conclusion is that Java is the poorest choice possible for a mobile device: slow, inefficient, resource hungry, and very inflexible. Looking at the NDK, it appears very inconvenient and very limited.

The library approach to release a free and paid version

I am going to release multiple versions of an app to the Android market / Google Play Store. Now I am looking into the best way to do this.
I've read a lot of questions here about how this is achieved in the easiest way.
I do not want to create application version specific activities, because this could easily lead to code inconsistencies between the different versions. So I want to use the library approach. This also seems to be the easiest way, instead of all the examples I've seen which require hefty amounts of ANT scripting etc
For argument's sake I am going to have:
com.app.library
com.app.free
com.app.paid
com.app.paidmore
My idea is to base code in the library on the package name.
Parts of my activities would not show, or disable functionality based only on package name.
What are the downsides to this approach? I can't seem to find any, but I am curious about the opinions. Ofcourse all application versions would in a sense contain all functionality, but the functionality is disabled on the fly by code. I think it would be a lot of work to modify the code to hack the app to obtain full functionality, but am I right?
This approach seems wrong, in that it would be very easy to modify the apk and distribute it in the modified way.
What are the downsides to this approach?
Your app winds up bigger than it needs to be (e.g., paid functionality residing on a free user's device). And, as you note, it puts all the functionality on the user's device.
I think it would be a lot of work to modify the code to hack the app to obtain full functionality, but am I right?
If it takes more than five minutes, the script kiddie is typing too slow. Decompile, search-and-replace your package name, recompile.
This approach seems wrong, in that it would be very easy to modify the apk and distribute it in the modified way.
That approach actually might take more time -- to perhaps ten whole minutes -- as it may take longer for the script kiddie to figure out exactly what resource needs changing.
Of course, the script kiddies can just grab your paidmore version and attack that, so the fact that your free and paid apps happen to have paidmore functionality is not much of a problem. So, the biggest difference IMHO is APK size, and only you'll know how much that differs between the versions and whether or not it's a problem.

Multiple versions of Android App

Seeing as how there are no preprocessor directives (without jumping through some hurdles), I was wondering if there was an accepted way of doing the following:
Have an android app in the regular ol' android market that uses things like the camera, mic, etc.
Conditionally "swap out" certain features based on some build parameter.
Produce two APKs, one for each store
Ideally, I would want to keep the ANT gymnastics to a minimum ... and also ideally would not have to maintain two sets of files (ie. google_activity_layout.xml and amazon_activity_layout.xml).
edit: this answer looks interesting: https://stackoverflow.com/a/1813873/5416
I have been able to use XMLTask antlib to modify the AndroidManifest.xml as part of the -pre-build hook. I haven't used the mechanism you linked, but I would think that a combination of modifying the permissions and using the linked mechanism would achieve your goal. Since the permissions are checked at runtime vs. at compile time.
You can find the library here: http://www.oopsconsultancy.com/software/xmltask/
One thing to note, it will take some tinkering. My "ant monkey business" did take several hours of tinkering because of the way the apk is compiled together. If you are willing to run the full build a few times it should be less arduous and could probably just ad a completely new task to the beginning of the build.xml that is generated. Let me know if you have questions as I've been tinkering with this stuff a lot.

How do you release two versions of an app on the Market?

I would like to add two versions of my app to the Android Market, one for a few cents, and one free version, with ads. That's a very common practice.
I'm currently building AdMod into my app, and it seems I'll have to change quite a few files, so it seems best to make a separate version of my app for this.
How do you achieve that? A branch? A different repository? Has anyone found a way to keep both apps in the same repository in a reasonable manner?
The title is not misspelled, I do mean "realise", i.e. how people manage the two versions, not how they add them to the Market.
This kind of thing is a complete nightmare - unfortunately the Android build system doesn't really support it in any good way.
We do it by having 99% of the code of our application in a library project. We then create one application project for each different version of the app, each of which use that library.
Where we need different versions of the app to behave differently, we currently achieve that by having different resources that are queried at runtime. We are in the process of moving to using Dependency Injection via RoboGuice, however.
There are elements of this that work reasonably well, and others that don't. It's necessary, for example, to duplicate the AndroidManifest.xml file, which can be error-prone (it's easy, for example, to add a new activity to one manifest and forget to do so in the others). It's a mess, unfortunately, but the least-bad solution we've found.
Personally speaking, I would strongly advise against using branches to achieve this effect. They can work well initially, but will rapidly become a maintenance nightmare.
One side benefit of using a library is that we've found that it makes testing considerably easier. For an example of how to set this up, see:
http://www.paulbutcher.com/2010/09/android-library-project-with-tests-step-by-step/
People usually upload them twice(like two different programs) and just modify the title for adding something like Ad-Free, Donate and things like that. And on the free version just add the Free label and also put on the description that it's Ad-Supported.
Here is an example with the SMS Popup application:
For the Android Market, they are considered different programs, but for us it's the same, but one is Ad-Supported and the other isn't.

Categories

Resources