I have read Best way to include debug code for including debug only code in android and was really helpful.
what I'm asking and couldn't find answer for is:
Is debug only code suggested by above solutions completely removed from release type apk?
By using the method described in the suggested answer of the link you provided, the debug only code is removed by the compiler from the release type apk when setting DEV_MODE=false.
If you need to have automatic switching between debug and release code without having to remember to set a constant variable, you will have to add a debug folder next to your main folder in your src and re-implement any class you need to modify.
Related
I have been working on android app development from past 4 months and now I have developed my first app and as it is easy to decompile a apk so we should use dex or proguard for shrinking and protection.The problem is I have read in an article that proguard may change the code so sometimes a app may misbehave ,this is my first app and I don't want to mess up.So before using proguard in my app I have few questions -
1.What are the points to keep in mind before using proguard.
2.I read you can use keep command but proguard will not obfuscate that code and it will remain same,so I want my all code but as I will use keep it won't do anything.
3.How to make sure that the after functioning of app is same as before after using proguard.
4.Is is necessary to sign app or make key for using proguard?
Question1. What to keep in mind!
The docs state that there may be unintended events that occur from using proguard
Be aware that code shrinking slows down the build time, so you should
avoid using it on your debug build if possible. However, it's
important that you do enable code shrinking on your final APK used for
testing.
After ProGuard shrinks your code, reading a stack trace is difficult (if not impossible) because the method names are obfuscated.
I believe this answers question 3
The key word here is test, test, test! The moment you create your release apk. Test the functionality against your use cases to see if the application is still running the way it should.
If you don't have tests yet I would recommend write some at least unit tests before you release and test the proguard app against that.
Question 4: No you do not need a key to use proguard. I have used it on my debug builds before.
So your typical release build variant could look something like this:
//AndroidStudio3.0.1Canary
release {
postprocessing {
removeUnusedCode true
removeUnusedResources true
obfuscate true
optimizeCode true
proguardFile 'proguard-rules.pro'
}
}
I have an ant build setup for my Android project, and I've been reading guides and tutorials all over stackoverflow and online, but cannot seem to understand how to make this work. Basically in my code I have a variable, "isDebugVersion" (which will print out logs, and a few other things). When I build with ant, I want that variable in my code to be set to "false". I'm looking around and I cannot find the custom_rules.xml examples even though it's listed in the build.xml file.
So the variable is in com.example.application.Globals, and it's listed as isDebugVersion. Can someone please give me an example for how to manipulate this variable using an ant build script?
You can a file named custom_rules.xml to the root folder of your project.
Inside define any property you want.
Note that what you are trying to achieve could be simpler using BuildConfig.DEBUG. This file is in the gen folder of your project, close to R.java. It is generated during the build and the constant DEBUG will be set to false during debug builds and to true in release.
So if you type ant release, you will get false. With eclipse or ant debug, you will get true.
You could also learn how to use RoboGuice, it has an interesting logging solution.
You can use this constant for all purposes like changing the google map api key from debug to release key. For an example, follow this thread.
I have several options - both in code and in the manifest file - that I would like to easily toggle on and off based on whether it's a debug build or release build.
What's the best way to handle things like this in an Android application?
You could use properties files, e.g. one for prod and one for dev. Then you could create an Ant script with two targets, a prod build and a dev build, where the appropriate properties file is copied prior to the APK being built. Make sure that the properties files are copied using the same name, then you can access the deployed one, irrespective of the environment you built for.
In addition to what Tyler mentioned, if you are looking at including optional code in case it is a Debug and not having that code if its a release, then you could look at using the BuildConfig file that is generated by the ADT.
As per the docs: " Added a feature that allows you to run some code only in debug mode. Builds now generate a class called BuildConfig containing a DEBUG constant that is automatically set according to your build type. You can check the (BuildConfig.DEBUG) constant in your code to run debug-only functions such as outputting debug logs."
You will find this file in the Project/gen folder, the same place where the R.java is generated.
Now with Android Studio and Gradle it is easy to do this using the auto generated flag BuildConfig.DEBUG. Like:
if (BuildConfig.DEBUG) {
// Debug code
} else {
// Resease code
}
I am facing problem. I need to build one app in two ways, first build is for development (testing) use, second build should be production version. Are there any ways how to do it programatically? (with some build engines) I mean that both apps shloud run on one device at the same time if possible. Both version are APK from one Android project.
Thanks
Personally I use this to determine whether I am in debugging mode:
final PackageInfo pinfo = getPackageInfo(ctx);
final boolean debugMode = (pinfo.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
This code is based on the debuggable attribute of the Application tag of the android-manifest.xml:
If this attribute is explicitely set to true debugMode will be set to true.
But if it is explicitely set to false or not present in the xml (implicit values), debugMode will be set to false.
Doing this way you cannot run both app on the same device at the same time as two APK need two different package name to be installed concurrently. So you have to build two eclipse projects, each one having its own package name (for example com.example.myapp.debug and com.example.myapp), and why not using a common lib (com.example.myapp.common) that would contain almost all your code:
com.example.myapp.debug has its debuggable flag set to true
and com.example.myapp has its debuggable flag set to false
As far as I see, you really need to create different applications from you base code. One way to get this done, as I did it, is to use Ant script that copies the entire project source into another directory, say "testing", and while doing so, replaces (e.g. using copy filtering) certain values from XML files, like from AndroidManifest.xml. One of the first things to replace is applications package that needs to be unique for each app. The Java classes like Activities can still reside in the original packages, their names in AndroidManifest.xml just need to be absolute. Once source has been copied and filtered, you can use Ant's antcall task from the main build.xml to build the customized app. So at the end, you can say e.g.: "ant -Denv=testing build" and you have an APK that can be installed next to your production version.
Another alternative is to use Maven that's Android plugins support project overlaying. And of course you can use library projects, see: Android – multiple custom versions of the same app.
I think that the easiest solution is to use some kind of source control tool for this purpose. There are so many good reasons to use source control, that I believe that most developers already use it.
Summery of solution:
Have 2 repositories (or branches), one for development and one for production.
Choose different package name for production and development apps.
Use absolute path for activities rather than relative in manifest file.
Solve the conflict only in the first time that you pull the changes from the development to the production environment.
Description of solution.
I personally works with GIT, I believe that this approach will work with other SCM tools, but I didn't test it.
I have 2 repositories, one for development and one for production (You can get the same effect using production branch, but I preferred different repositories, since I never know when I'll have another developers, and I don't want to give anyone (including me) the chance to do a mistake with the code without having a backup for it.
All you need to do is to set different package name in the manifest file in each repository, for example:
Development manifest package name - dev.com.foo.appName
Production manifest package name - com.foo.appName
For each activity there is a need to use the absolute path rather than the relative approach. Since there is no real option that you will change your package name, and if you do, all the changes are in the manifest file, I don't think that there is almost any drawbacks with this approach.
Then every time that you pull your changes from the developer repository to the production one, there should be a "conflict" on those lines in the manifest files, but actually there will be a conflict only on the first time you pull the code, afterwards the merging tools knows which line you prefer in the production repository.
EDIT
After using this approach for some time I discovered that there is a problem with the generated R file.
The problem:
R file is being generated with package name as defined in the Manifest file in the package attribute. Then all references to R file cannot be find (The package name of the source files is differed from the package name stated in the manifest file).
There are 3 solutions for that problem:
The Good:
This solution is the most robust one, and I suggest you to use it (didn't try it myself though). The idea behind this solution is to generate the R file into a different class name than the one stated in the manifest. In the manifest the package would be dev.com.foo.appName but the R file will be generated to the com.foo.appName.
In order to achieve it please follow this answer
The Bad:
Do NOT use this solution, it is really bad, I'm stating it here that you could avoid it. In each file that using the R file add the import to the R file with the package name is in the manifest. This is a very bad solution, since you will enter a lot of unrelated code, you will need to change it in the production environment, and for every new class you will need to remember to add it.
And the Ugly:
It is better not to use this solution since it is a kind of a hack. This solution is useful only for mature apps that don't have lots of changes in their resources. When ever you change your resources the R file is being generated again, then it is generated to the package name as in the manifest. All you need to do is to change the package name (in the manifest) to be as in the production environment, clean the project, build it again, and change back the package name into the development environment. Then eclipse asks if to change configuration and you choose not to. This way, 2 R files will be exist, one with the development package name and one with the production one. Since in mature apps there are not much resources changes, you will be doing so once in a while. You won't be able to forget about it, since in case that you change a resource you will start seeing weird bugs.
I know question is late, but I will answer.
You may use Gradle.
In build.gradle file you may define separate buildTypes like this:
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
test {
applicationIdSuffix ".test"
versionNameSuffix "t"
debuggable false
}
By set applicationIdSuffix for may install test and release build on one device
For more info go to http://tools.android.com/tech-docs/new-build-system/user-guide
I have an Android project that I recently published to the market after running it through obfuscation with ProGuard.
The project exported without any complications, but how do I know it's been obfuscated? Is there anything I could do to verify that obfuscation was successful?
Look for dump.txt, mapping.txt, seeds.txt and usage.txt. They will probably be in a proguard folder at your project directory. These are created when ProGuard is run on your code.
These are filled with information about the obfuscation, especially useful is mapping.txt which shows what ProGuard turned your various member names in to.
Try to reverse engineer your own application. See what you can read in the code.
Use the following questions:
decompiling DEX into Java sourcecode
http://www.taranfx.com/decompile-reverse-engineer-android-apk
DISCALIMER: I am not the owner of decompileandroid.com and I am not paid to promote it. I am a develper, who is satisfied with this service.
There is actually an easier way than acquiring several different tools and passing the output of one of them to the other (this of course gives you a better control of what's going on). You can use the service
decompileandroid.com
Basically you upload and .apk file and it does all of these steps for you.
Then you can download a .zip file, which contains the decompiled sources.
You can first upload your .apk built in debug mode, then upload an .apk built in release mode. Just make sure that the flag minifyEnabled is set to true in your build.gradle file for the release build.
The difference was pretty obvious in my case - most of my classes were named a,b,c, etc in the minified build.