Tag Archive: java


Android applications are bundled and distributed as apk(s), aka Android application package.To make an APK file, a program for Android is first compiled, and then all of its parts are packaged into one file. An APK file contains all of that program’s code (such as .dex files), resources, assets, certificates, and manifest file. As is the case with many file formats, APK files can have any name needed, provided that the file name ends in “.apk”.

Apk Contents:

An APK file is an archive that usually contains the following files and directories:

  • META-INF directory:
    • MANIFEST.MF: the Manifest file
    • CERT.RSA: The certificate of the application.
    • CERT.SF: The list of resources and SHA-1 digest of the corresponding lines in the MANIFEST.MF file; for example:
 Signature-Version: 1.0
 Created-By: 1.0 (Android)
 SHA1-Digest-Manifest: wxqnEAI0UA5nO5QJ8CGMwjkGGWE=
 ...
 Name: res/layout/exchange_component_back_bottom.xml
 SHA1-Digest: eACjMjESj7Zkf0cBFTZ0nqWrt7w=
 ...
 Name: res/drawable-hdpi/icon.png
 SHA1-Digest: DGEqylP8W0n0iV/ZzBx3MW0WGCA=
  • lib: the directory containing the compiled code that is specific to a software layer of a processor, the directory is split into more directories within it:
    • armeabi: compiled code for all ARM based processors only
    • armeabi-v7a: compiled code for all ARMv7 and above based processors only
    • arm64-v8a: compiled code for all ARMv8 arm64 and above based processors only[7][8]
    • x86: compiled code for x86 processors only
    • x86_64: compiled code for x86 64 processors only
    • mips: compiled code for MIPS processors only
  • res: the directory containing resources not compiled into resources.arsc (see below).
  • assets: a directory containing applications assets, which can be retrieved by AssetManager.
  • AndroidManifest.xml: An additional Android manifest file, describing the name, version, access rights, referenced library files for the application. This file may be in Android binary XML that can be converted into human-readable plaintext XML with tools such as AXMLPrinter2, android-apktool, or Androguard.
  • classes.dex: The classes compiled in the dex file format understandable by the Dalvik virtual machine
  • resources.arsc: a file containing precompiled resources, such as binary XML for example.

Decompilation process:

Our prerequisite would be these 3 tools:

  • dex2jar: Used to convert the apk to jar file. Can be downloaded from here.

  • JD-GUI: Used to view the contents/source from the jar file decompiled in previous step. Details are here.

  • apktool: For reverse engineering the apk to extract files and folders. This can be used to extract the manifest individually and then reading from it. It is available here for download.

dex2jar and JD-GUI are used together. dex2jar converts apk to jar file and JD-GUI provides the editor to browse that jar file. To use dex2jar:

  1. Download dex2jar from here and extract it to a separate folder.
  2.  Execute the following command to decompile an apk:

    sh d2j-dex2jar.sh testapp.apk

  3. It might happen that terminal might show you a permissions error related to d2j_invoke.sh while executing step 2, if that happens then provide d2j_invoke.sh with appropriate permissions by executing:

    sudo chmod +x d2j_invoke.sh

  4. Post above steps, testapp.jar should be generated which can be opened and browsed via JD-GUI. This file contains all the decompiled code(.class files)

screenshot17

We are already able to browse the source code using dex2jar and JD-GUI, however, another important tool in the arsenal is apktool, which is a tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications. It also makes working with an app easier because of the project like file structure and automation of some repetitive tasks like building apk, etc. Apps/Apks. Decoding of an apk via apktool can be done by using following command:

apktool d test.apk

Repackaging as an apk can be done by:

apktool b test

JD-GUI, d2j and apktool is the essential tooling required to get an effective and deep insight into 3rd party apps which often exist as black boxes. As shown above, the usage is simple and pretty straight forward. I would request you to share your inputs and experiences in comments with these tools or any others that you might have explored for decoding Android or any other platform apps.

 

Advertisements

Abstract Class Vs Interface

Yes, I do understand the title reflects the age old repetitive interview question. It has been asked again, again and again and then just some more times. But why, why is this so important. Why does every software company on the planet has the question sticking out of their heads. We all know the answer to this(duh??), they all know the answer to this(duh??), and nearly every preparation site answers this, then what is the big fuss about?

Well, the fantastic thing about an iceberg is its tip and then comes in the total size. In a very similar fashion, for this question, everybody understands the syntax but fails to understand the semantics. If you have been reading about this, few well know answers are:

  • Interface is a 100% abstract class
  • Java class(es) can implement multiple interfaces but it can extend only one abstract class.
  • Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”.

All the above arguments talk about the dynamics of implementations of an abstract class and interface(s). Although those are factually correct but lack in answering a fundamental design question, i.e., “When should my software use an abstract class and when should it use an interface”.

To answer this let us begin by asking a few questions, the first one is, Have you ever noticed that when we inherit from interfaces, we use “implements” however when we inherit from an abstract class we use “extends”?, Yes, No? Puzzled?

This little inheritance jargon is the key in understanding the usage of abstract classes vs interfaces. Not only in software engineering but in any engineering field(even in basic english), the keyword “implements” is associated with implementing a functionality and “extends” is associated with extending to enhance the characteristics of a type. Keeping this in mind, Whenever we are implementing we are actually defining “what” a class can do or what it is capable of. For example, a Ball which “is a” Toy is “capable of” bouncing. Got it?, Saw the light?, Not yet?

Maybe Now:

class Ball extends Toy implements Bounceable

So whenever we talk about functionality, think interfaces and whenever we talk about characteristics, think abstract classes(not always, but yes when we analyze in terms of extensions). So, as a general rule of thumb:

Interfaces:

  • Talk about what a class can do.(Functionality)
  • Declare what kind of functionality, a class should implement.
  •  Uses “is capable of” relationship.

Abstract Class(es):

  • Talks about characteristics an object should support.
  • Type of an Object
  • Uses “is a” relationship

Hope this cleared some of the fog.

Android Preference Framework is among st the mostly widely used building blocks of Android. Almost every Android application makes use of the Preferences file in some way or the other and our app is no different.

Our app uses the Android Preferences to store some general keys like,

  • Hardware Make
  • Hardware Model
  • Software Version
  • Date
  • Time
  • Connection State

All the above mentioned values are being retrieved from a sensor and are stored by the App in the preferences, to be displayed to the User in a User Friendly Manner.  However, we ran into a weird problem which had its roots in the Android Preferences during one of our test-runs.

Superficially speaking about the problem, whenever the user tried to retrieve the above mentioned data from the Sensor, the process seemingly happened fine, but whenever the app was restarted after any such scenario, all of the previously stored data in the Preferences file was lost, i.e., the App behaved as a freshly installed app and being launched for the first time! We tried various lenses to view this problem, our most prominent lens(wild guess actually) being that somehow something was overwriting the preferences file to default settings. Another programmer also suggested that “Somehow the Preference object was being null“. We tried to be nice and please everybody by incorporating their hypothesis and applying the suggested fixes and ended up wasting like 2 hours over this so called conventional wisdom!

After blaming the Preference Framework for those 2 hours and interrogating the data associated with it, we could not extract anything meaningful out of it except the OnSharedPreferenceChangeListener. So we decided to find somebody else to blame for the mess being created and turned our attention to the Sensor framework(as the bug always popped out whenever the Sensor data was retrieved). After tracking the changes in the preferences via OnSharedPreferenceChangeListener, it became clear that the Sensor Framework was not only retrieving the data, but was also storing like 10 of those values in the Preferences in a rapid succession and the code doing this looked something like,

updatePreferences(key1, value1);

updatePreferences(key2, value2);

………..

updatePreferences(key10, value10);

As soon as this code was commented, the app behaved normally :-).

This made us realize that it was not about Android Preferences but about the manner in which we were updating those and hence we derived a few cardinal rules about the same,

  • Shared Preferences are NOT designed for storing data which changes often and/or large amounts of data.
  • Shared Preferences are just a file – it has to be opened, parsed, updated and closed every time we do an update operation on it. Doing update operation in a rapid succession might just corrupt the file and restore it to default values which was our case exactly.
  • Do not access Shared Preferences from multiple threads.
  • ‘Conventional wisdom’ can be wrong.

Happy Coding!