Obfuscation, code shrinking and optimization
Obfuscation is carried out during the optional build step of shrinking an app to remove unused code and resources. It protects the app by making it difficult to reverse engineer or debug, while leaving it semantically identical to the original. It is usually only performed on the release version of an app, enabling you to continue to debug your app during development. Obfuscation may impact the performance of your app, so it is necessary to measure the performance to determine whether further configuration is needed to mitigate any issues.
There are a couple of tools available for shrinking and obfuscating an app: Google's R8 tool (the Android default) and Nagra's KOP4J plugin. This page describes how to enable each of these, leaving the fine details to the official documentation.
R8
R8 may also be colloquially referred to as ProGuard, but it is actually ProGuard's replacement as of Android Gradle plugin 3.4.0. R8 is compatible with the same rules used by ProGuard; full details are provided in the official documentation at: https://developer.android.com/studio/build/shrink-code.
Configuring R8
R8 configuration uses ProGuard rules, which modify its default behaviour by enabling or disabling features, and instructing it not to obfuscate or shrink specific classes. The complete set of ProGuard rules can be found at: https://www.guardsquare.com/en/products/proguard/manual/usage.
ProGuard rules files
The Android Gradle plugin generates proguard-android-optimize.txt which contains configuration that applies to the majority of Android projects; R8 should be configured to use this by default (see below).
It may be necessary to define app-specific rules to work around issues caused by limitations in R8's ability to correctly analyse code in certain situations, such as when your code uses reflection or calls native code via JNI (the Java Native Interface). In cases like these, you may need to force R8 to keep specific code rather than stripping it out. To define these rules, create your own rules file - for example, named proguard-rules.pro - and place it in the app-level directory.
A basic rules file may look something like this (comments are preceded by #):
Custom ProGuard Rules
# Keep MyJNIClass
-keep public class com.example.MyJNIClass
# Keep all classes in com.example.database_package, but not in its subpackages
-keep public class com.example.database_package.*
# Keep all classes in com.example.open_package, and those in its subpackages
-keep public class com.example.open_package.**
SDK embedded rules
In addition to the default rules in proguard-android-optimize.txt and those specified by the developer, the OpenTV Player SDK 4 library contains its own set of rules that will be applied automatically when R8 is used to obfuscate the app. This protects the OpenTV Player SDK 4 while requiring no additional work from the developer.
Applying R8 to your app
The following additions to your app-level build.gradle file will enable shrinking, obfuscation and optimization:
App-level build.gradle
android {
buildTypes {
release {
// Enables obfuscation, code-shrinking and optimization
minifyEnabled true
// Enables resource shrinking, removing unused resources
shrinkResources true
// Includes the Android Gradle plugin default rules, with proguard-rules.pro containing app-specific rules
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
...
}
KOP4J
KOP4J is a Nagra-produced code obfuscation tool for Java which supports many of the R8/ProGuard features while adding a number of its own, namely: certificate protection, manifest protection, shelf life protection and string masking.
KOP4J also includes the AnNaNaS (Android Nagra Native Secure) library, which protects native (C/C++) code.
Configuring KOP4J
Configuration for KOP4J uses ProGuard rules, which modify its default behaviour by enabling or disabling features, and instructing it not to obfuscate or shrink specific classes. The complete set of ProGuard rules can be found at: https://www.guardsquare.com/en/products/proguard/manual/usage.
There are additional rules to enable KOP4J-specific features such as string masking that are explained fully in the documentation provided in your KOP4J distribution.
ProGuard rules files
The KOP4J plugin includes the rules file kop-android-default.txt which contains standard configuration settings; KOP4J should be configured to use this by default (see below).
It may be necessary to define app-specific rules to work around issues caused by limitations in KOP4J's ability to correctly analyse code in certain situations, such as when your code uses reflection or calls native code via JNI (the Java Native Interface). In cases like these, you may need to force KOP4J to keep specific code rather than stripping it out. To define these rules, create your own rules file - for example, named proguard-rules.pro - and place it in the app-level directory.
A basic rules file may look something like this (comments are preceded by #):
Custom ProGuard Rules
# Keep MyJNIClass
-keep public class com.example.MyJNIClass
# Keep all classes in com.example.database_package, but not in its subpackages
-keep public class com.example.database_package.*
# Keep all classes in com.example.open_package, and those in its subpackages
-keep public class com.example.open_package.**
SDK embedded rules
In addition to the default rules in kop-android-default.txt and those specified by the developer, the OpenTV Player SDK 4 also includes its own set of rules in a file named proguard.txt contained within the library's JAR file.
Its contents must be copied into one of the ProGuard rules files listed in your KOP4J configuration. This is required to obfuscate the SDK.
In future updates to KOP4J, this manual step will not be required and the rules will be applied automatically.
Applying KOP4J to your app
Adding the dependency to the top-level build.gradle
Extract your KOP4J archive (either zip or tar.gz) to a known location. You can then add the path to the list of repositories, enabling you to add the dependency:
Top-level build.gradle
buildscript {
repositories {
...
flatDir {
dirs '/path/to/kop/installation/directory/bin'
}
}
dependencies {
...
classpath ':kop-gradle:<version>'
}
...
}
Applying the plugin to your app
App-level build.gradle
...
// Apply the plugin, taking care not to place it before the `com.application.android` plugin
apply plugin: 'com.nagra.kop'
...
android {
...
buildTypes {
release {
// In contrast to R8, `minifyEnabled` must be set to `false`
minifyEnabled false
// Include the KOP4J plugin's default rules, followed by your app-specific rules
proguardFiles kop.getDefaultKopFile('kop-android-default.txt'), 'proguard-rules.pro'
...
}
}
}
Disabling AnNaNaS
OpenTV Player SDK 4 contains native libraries that are already protected by KOP - a related, but separate tool to KOP4J - which provides the same rooting, emulation and debugging protections as AnNaNaS. To prevent build failures it is necessary to disable AnNaNaS to prevent it attempting to apply its own protection mechanisms, therefore clashing with KOP.
It is disabled by adding the following to one of your ProGuard rules files:
proguard-rules.pro
-kop-hash-strategy java