ProGuard DexGuard и libGDX

Proguard и специальный для Android DexGuard являются оптимизаторами и обфускаторами Java и Android приложений. Они помогают повысить скорость выполнения кода, уменьшить размер приложения, затруднить анализ и понимание алгоритмов работы и модификацию при декомпиляции. Вы может использовать совместно Proguard и DexGuard в вашем libGDX приложении чтобы сделать его более сложным для декомпиляции сторонними лицами, чтобы уменьшить размер и повысить скорость выполнения. В данной статье рассматриваются Proguard правила для libGDX, также вам могут быть полезны правила конфигурации ProGuard для разных библиотек и фреймворков.

Следующий конфигурационный файл позволить libGDX приложению работать совместно с ProGuard

Использование

# Чтобы задействовать ProGuard в вашем проекте отредактируйте project.properties
# для определения proguard.config свойств как описано в этом файле.

# Добавьте сюда  Proguard правилась необходимые для вашего проекта
# По умолчанию флаги в этом файле добавляются к указанным флагам в 
# ${sdk.dir}/tools/proguard/proguard-android.txt 
# Вы можете отредактировать путь и порядок включения, изменив свойства ProGuard 
# включенные в project.properties.

# Подробнее смотрите
# http://developer.android.com/guide/developing/tools/proguard.html

# Добавьте сюда любые -keep правила вашего проекта

# Если ваш проект использует WebView с JS, раскомментируйте следующие строки
# и укажите полное имя JavaScript интерфейс класса.
# -keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

-verbose

-dontwarn android.support.**
-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication
-dontwarn com.badlogic.gdx.utils.GdxBuild
-dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild
-dontwarn com.badlogic.gdx.jnigen.BuildTarget*

-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
   (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
}

-keepclassmembers class com.badlogic.gdx.physics.box2d.World {
   boolean contactFilter(long, long);
   void    beginContact(long);
   void    endContact(long);
   void    preSolve(long, long);
   void    postSolve(long, long);
   boolean reportFixture(long);
   float   reportRayFixture(long, float, float, float, float, float);
}
Proguard и рефлексия

Обратите внимание, что вам также необходимо будет добавить -keep для классов, которые вы используете через рефлексию! Более подробную информацию смотрите в документации ProGuard / DexGuard.

Чтобы использовать ProGuard/DexGuard в Android проекте вы можете воспользоваться следующим build.gradle файлом, который находится в android/ директории, но не корневой build.gradle файл.

android {
   buildToolsVersion "19.0.3"
   compileSdkVersion 19

   signingConfigs {
       mySignature {
           storeFile     file('/home/eric/.android/debug.keystore')
           storePassword 'android'
           keyAlias      'androiddebugkey'
           keyPassword   'android'
       }
   }

   defaultConfig {
       signingConfig signingConfigs.mySignature
   }

   sourceSets {
       main {
           manifest.srcFile 'AndroidManifest.xml'
           java.srcDirs = ['src']
           resources.srcDirs = ['src']
           aidl.srcDirs = ['src']
           renderscript.srcDirs = ['src']
           res.srcDirs = ['res']
           assets.srcDirs = ['assets']
       }

       instrumentTest.setRoot('tests')
   }

   buildTypes {
       release {
           minifyEnabled true
           proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
           proguardFile 'proguard-project.txt'
       }
   }
}

// необходимо добавить общие JNI библиотеки в APK при компиляции CLI
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
   pkgTask.jniFolders = new HashSet()
   pkgTask.jniFolders.add(new File(projectDir, 'libs'))
}

task copyAndroidNatives() { 
   file("libs/armeabi/").mkdirs();
   file("libs/armeabi-v7a/").mkdirs();
   file("libs/x86/").mkdirs();

   configurations.natives.files.each { jar ->
       def outputDir = null
       if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
       if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
       if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
       if(outputDir != null) {
           copy {
               from zipTree(jar)
               into outputDir
               include "*.so"
           }
       }
   }
}

task run(type: Exec) {
   def adb = "$System.env.ANDROID_HOME/platform-tools/adb"
   commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.dozingcatsoftware.bouncy.android/com.dozingcatsoftware.bouncy.android.AndroidLauncher'
}

// настраивает проект Android Eclipse, используя старую сборку на основе Ant.
eclipse {
   sourceSets {
       main {
           java.srcDirs "src", 'gen'
       }
   }

   jdt {
       sourceCompatibility = 1.6
       targetCompatibility = 1.6
   }

   classpath {
       plusConfigurations += project.configurations.compile        
       containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'       
   }

   project {
       name = appName + "-android"
       natures 'com.android.ide.eclipse.adt.AndroidNature'
       buildCommands.clear();
       buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
       buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
       buildCommand "org.eclipse.jdt.core.javabuilder"
       buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
   }
}

// настраивает проект Android Idea, используя старую сборку на основе Ant.
idea {
   module {
       sourceDirs += file("src");
       scopes = [ COMPILE: [plus:[project.configurations.compile]]]        

       iml {
           withXml {
               def node = it.asNode()
               def builder = NodeBuilder.newInstance();
               builder.current = node;
               builder.component(name: "FacetManager") {
                   facet(type: "android", name: "Android") {
                       configuration {
                           option(name: "UPDATE_PROPERTY_FILES", value:"true")
                       }
                   }
               }
           }
       }
   }
}