Libgdx with Proguard apk size is bigger than without - libgdx

When I want to use Proguard with libgdx then the apk size gets bigger than without. Without it has a size of 3.01MB but with it has over 5MB and the classes.dex is like 4MB. The app include Admob, Google Play Services(trough BaseGameUtils) and Universal TweenEngine. I use the following proguard file:
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
-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* {
<init>(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);
}
-keep class com.badlogic.** {*;}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames #com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
#com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}

Related

How to access protected method of Java jar file's class

I am using a Java command-line application (which is open-source) as a jar file for my jrubyonrails project. The main application is like following
public class Decoder extends Annotator {
public Decoder() {
super();
}
public static void main(String[] args) {
... // Do something that I don't want
myDesiredMethod();
... // And some other thing
}
...
}
There are many steps which I want to skip, I only want myDesiredMethod function. And it is a protected method from the parent Annotator class.
public class Annotator extends Helper {
...
protected SomeClass myDesiredMethod(boolean reMap) throws Exception { ... }
...
}
Annotator class does not have any public constructor so that I cannot:
ann = Annotator.new
It raises this error: TypeError: no public constructors for Annotator.
Then I try to implement another class which inherits Annotator in order to access myDesiredMethod. This is the jruby code I have tried so far
require 'java'
require 'decoder.jar'
java_import java.util.ArrayList
java_import java.lang.StringBuilder
module MyModule
class RuDecoder < Annotator
include_package 'com.decoder'
def self.my_method
myDesiredMethod
end
end
It returns the error: NoMethodError: undefined method 'myDesiredMethod' for MyModule::RuDecoder:Class. Seems jruby does not look for the method of the parent class.
Is there any solution in my case, I don't want to rebuild the java library to jar and manually put it into my program every time it has an update.
Turns out that I made thing over-complicated. I can call the default constructor of Annotator as following:
constructors = Annotator.java_class.declared_constructors.first
constructors.accessible = true
annotator = constructors.new_instance.to_java
And use simple call myDesiredMethod: annotator.myDesiredMethod

Apache CXF DSOGI with JSON on Karaf

I am trying to create a RESTful web service in Karaf 4.0.8 with Apache CXF DOSGI. The service is being called but I am getting this error: No message body writer has been found for class....
Any suggestion is welcome. Thank you!!!
Component:
#Component(immediate = true, property = {
"service.exported.interfaces=*",
"service.exported.configs=org.apache.cxf.rs",
"org.apache.cxf.rs.provider=com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider",
"org.apache.cxf.rs.address=/integr" })
public class AccountRestService implements AccountWebUserIdResource {
...
}
Interface:
------------
#GET
#Produces({
"application/json"
})
AccountWebUserIdResource.GetAccountByWebUserIdResponse getAccountByWebUserId(
#PathParam("webUserId")
String webUserId,
#QueryParam("sc")
String sc,
#QueryParam("fields")
String fields)
throws Exception
;
Entity:
#JsonInclude(JsonInclude.Include.NON_NULL)
#Generated("org.jsonschema2pojo")
#JsonPropertyOrder({
"href",
"crm_member_id",
"email_address",
"account_status"
})
public class Account {
/**
*
* (Required)
*
*/
#JsonProperty("href")
private String href;
/**
*
* (Required)
*
*/
#JsonProperty("crm_member_id")
private String crmMemberId;
/**
*
* (Required)
*
*/
#JsonProperty("email_address")
private String emailAddress;
....
At least with CXF-DOSGi 2 your code probably will not work. Loading the provider from a class name is problematic in OSGi anyway as the CXF DOSGi code has no visibility of the com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider class.
In CXF-DOSGi this can be done using an intent. This is more OSGi friendly as the JacksonJsonProvider is then directly used as a class and so OSGi class loading works nicely. It is also necessary to set a bus property to all to override the jacksonprovider as the spec normally would not allow this.
cxf.bus.prop.skip.default.json.provider.registration=true
The intent class looks like this:
#Component(property = "org.apache.cxf.dosgi.IntentName=jackson")
public class JacksonIntent implements Callable<List<Object>> {
public List<Object> call() throws Exception {
return Arrays.asList((Object)new JacksonJaxbJsonProvider());
}
}
The intents provide a generic way to define features and other overrides for CXF without directly influencing your service class.
The intent then has to be referenced in the service using the service property service.exported.intents=jackson.
I just added a jackson example to CXF-DOSGi.
Another small obstacle is that the current cxf-jackson feature misses a bundle. See CXF-7298.

Proguard "Unmarshalling" error Google SIgnIn , Firebase Auth, Google Drive, In App Billing

I am receiving at run time:
Class not found when unmarshalling: com.google.android.gms.common.api.Scope and
Class not found when unmarshalling:
com.google.android.gms.auth.api.signin.internal.SignInConfiguration
errors when creating an release version of my app.
My build.gradle
minSdkVersion 21
targetSdkVersion 23
versionCode 10
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
// compile 'com.googlecode.java-diff-utils:diffutils:1.3.0 (This is inside primke)'
compile 'com.github.thorbenprimke:realm-recyclerview:0.9.20'
compile 'com.android.support:recyclerview-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
compile 'com.android.support:support-v4:24.0.0'
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.google.firebase:firebase-auth:9.0.2'
compile 'com.google.android.gms:play-services-auth:9.0.2'
compile 'com.android.support:cardview-v7:24.0.0'
compile 'com.google.android.gms:play-services-drive:9.0.2'
compile 'com.google.android.gms:play-services-gcm:9.0.2'
}
apply plugin: 'com.google.gms.google-services'
I have attempted to -keep these classes but it doesn't seem to take as the error still exists. Perhaps it is in there twice somehow. I keep adding things to the rule.pro file based on searches for similar problems and now have a "kitchen sink" rules file. I'm sure there is redundancy in the file and perhaps that is part of the problem. Any assistance would be greatly appreciated. I'm new at this so a point to examples is also appreciated.
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.google.android.gms.auth.api.signin.internal.SignInConfiguration
-keep class com.google.android.gms.common.api.Scope
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames #com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
#com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
-keep interface com.google.** { *;}
-keep class * extends com.google.api.client.json.GenericJson {
*;
}
-dontwarn com.google.**
-dontwarn com.google.android.gms.**
-dontwarn com.google.android.gms.R**
-dontnote com.google.android.gms.cast.**
-dontnote com.google.android.gms.common.**
-dontnote com.google.android.gms.dynamic.**
-dontnote com.google.android.gms.internal.**
# Keep all enum values and valueOf methods. See
# http://proguard.sourceforge.net/index.html#manual/examples.html
# for the reason for this. Also, see http://crbug.com/248037.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Preserve sufficient information for simple Serializable classes.
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class com.android.vending.billing.**
-keep public class com.google.android.gms.**
-keep class com.google.** {*;}
-keep class com.newrelic.** {*;}
-keep class com.google.android.gms.auth.*
-keep class com.google.android.gms.auth.api.Auth
-keep class com.google.android.gms.auth.api.signin.GoogleSignInAccount
-keep class com.google.android.gms.auth.api.signin.GoogleSignInOptions
-keep class com.google.android.gms.auth.api.signin.GoogleSignInResult
-keep class com.google.android.gms.common.ConnectionResult
-keep class com.google.android.gms.common.GoogleApiAvailability
-keep class com.google.android.gms.common.Scopes
-keep class com.google.android.gms.common.SignInButton
-keep class com.google.android.gms.common.api.GoogleApiClient
-keep class com.google.android.gms.common.api.OptionalPendingResult
-keep class com.google.android.gms.common.api.ResultCallback
-keep class com.google.android.gms.common.api.Status
-keep class com.google.api.services.drive.**
-keep class com.google.android.gms.drive.Drive
-keep class com.google.android.gms.drive.DriveApi
-keep class com.google.android.gms.drive.DriveContents
-keep class com.google.android.gms.drive.DriveFile
-keep class com.google.android.gms.drive.DriveFolder
-keep class com.google.android.gms.tasks.OnCompleteListener
-keep class com.google.android.gms.tasks.Task
-keep class com.google.firebase.auth.AuthResult
-keep class com.google.firebase.auth.FirebaseAuth
-keep class com.google.firebase.auth.FirebaseUser
-keep class com.google.firebase.auth.GoogleAuthProvider
-keep class com.google.firebase.auth.AuthCredential
Here's my build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath "io.realm:realm-gradle-plugin:1.0.1"
classpath 'com.google.gms:google-services:3.0.0'
}
}
allprojects {
repositories {
jcenter()
maven { url 'https://maven.fabric.io/public' }
maven { url "https://jitpack.io" }
mavenLocal()}
}
I thought that maybe I could use the Jack and Jill method but ran into Complier error so I quit there. Suggestions or Solutions?
You seem to have some duplicate rules, if you add a rule like this:
-keep class com.google.** {*;}
you do not need any other rule that includes com.google.*, so you can remove all of these:
-keep class com.google.android.gms.auth.*
-keep class com.google.android.gms.auth.api.Auth
-keep class com.google.android.gms.auth.api.signin.GoogleSignInAccount
-keep class com.google.android.gms.auth.api.signin.GoogleSignInOptions
-keep class com.google.android.gms.auth.api.signin.GoogleSignInResult
-keep class com.google.android.gms.common.ConnectionResult
-keep class com.google.android.gms.common.GoogleApiAvailability
-keep class com.google.android.gms.common.Scopes
-keep class com.google.android.gms.common.SignInButton
-keep class com.google.android.gms.common.api.GoogleApiClient
-keep class com.google.android.gms.common.api.OptionalPendingResult
-keep class com.google.android.gms.common.api.ResultCallback
-keep class com.google.android.gms.common.api.Status
-keep class com.google.api.services.drive.**
-keep class com.google.android.gms.drive.Drive
-keep class com.google.android.gms.drive.DriveApi
-keep class com.google.android.gms.drive.DriveContents
-keep class com.google.android.gms.drive.DriveFile
-keep class com.google.android.gms.drive.DriveFolder
-keep class com.google.android.gms.tasks.OnCompleteListener
-keep class com.google.android.gms.tasks.Task
-keep class com.google.firebase.auth.AuthResult
-keep class com.google.firebase.auth.FirebaseAuth
-keep class com.google.firebase.auth.FirebaseUser
-keep class com.google.firebase.auth.GoogleAuthProvider
-keep class com.google.firebase.auth.AuthCredential
Furthermore, you are using firebase & play-services 9.0.2, but I would suggest upgrading to 9.2.0:
compile 'com.google.firebase:firebase-auth:9.2.0'
compile 'com.google.android.gms:play-services-auth:9.2.0'
compile 'com.google.android.gms:play-services-drive:9.2.0'
compile 'com.google.android.gms:play-services-gcm:9.2.0'
There have been reports that release 9.0.2 is missing some rules to keep internal classes, so it wont work reliably with ProGuard.

How to run jul-to-slf4j bridge once per JVM?

I'd like to run Surefire in parallel mode (multiple JVMs) where each JVM must run:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
exactly once before the first test. How can this be done?
There are various ways to make some code run at the beginning of a test suite.
Here are 4 (I'm sure there are more):
JUnit via RunWith Suite with Suite.SuiteClasses and BeforeClass (adapted from examples in SuiteTest):
#RunWith(Suite.class)
#SuiteClasses({FirstTest.class, SecondTest.class/*, ...*/, LastTest.class})
public static class AllWithSLF4JBridgeHandler {
#BeforeClass
public static void registerRootLoggerHandlers() {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
TestNG with BeforeSuite:
/**
* Base class for each test class (i.e. every test class should extend this class).
*/
public abstract class BaseTest {
#BeforeSuite
public void registerRootLoggerHandlers() {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
TestNG with Guice:
/**
* Test module. Each test class should be annotated with `#Guice(TestModule.class)`.
*/
public class TestModule implements Module {
#Override
public void configure(Binder binder) {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
Static initialization blocks (test-framework independent):
/**
* Base class for each test class (i.e. every test class should extend this class).
*/
public abstract class BaseTest {
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
I'm not sure how all of these methods work with Surefire's parallel mode. Methods 1 and 2 may not work there but I believe methods 3 and 4 should.
Another option would be to not use the programmatic installation of the SLF4JBridgeHandler but to use a java.util.logging.config file or class (see LogManager):
"java.util.logging.config.file":
logging.properties file:
// register SLF4JBridgeHandler as handler for the j.u.l. root logger
handlers = org.slf4j.bridge.SLF4JBridgeHandler
System property assignment:
java -Djava.util.logging.config.file=/path/to/logging.properties ...
This works well if you know the path to your logging file beforehand.
"java.util.logging.config.class":
Using a file may not be a good option if you're deploying a WAR and don't know where the file will be, etc. so alternatively you can create a logging config class:
public class SLF4JBridgeHandlerInitializer {
public SLF4JBridgeHandlerInitializer() throws IOException {
String loggingConfigurationString = "handlers = " + SLF4JBridgeHandler.class.getName();
InputStream inputStream = new ByteArrayInputStream(loggingConfigurationString.getBytes());
LogManager.getLogManager().readConfiguration(inputStream);
}
}
System property assignment:
java -Djava.util.logging.config.class=package.SLF4JBridgeHandlerInitializer ...
I've done this before and it has worked well for me (SLF4JBridgeHandler.Initializer by mfulton26 · Pull Request #57 · qos-ch/slf4j).
These final two options should initialize each JVM instance as long as the appropriate system property is set.

How do I get proguard working with sjersey?

Trying to use Jersey with Scala, via a fork of SJersey, and obfuscating it with ProGuard.
I've got all of this stuff:
-keepattributes SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Signature,InnerClasses
and I'm doing this:
-keep public class com.example.*JsonSeralisedClasses {
public *;
}
but when I encode stuff with jersey nothing comes out!
Figured out eventually that SJersey doesn't use public methods, but introspects onto private fields, so one needs to do this:
-keep public class com.example.*JsonSeralisedClasses {
public protected private *;
}
See protected private is the difference.
Alernatively, you can annotate everything with #BeanProperty (which makes public accessors that are preserved using the original config).