Retrofit 2 with Proguard - retrofit2

Without Proguard enabled, retrofit2 work properly... but when enabled, application crash...
Here is my Proguard rules:
-dontwarn retrofit2.Platform$Java8
-dontwarn okio.**
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepattributes *Annotation*
-keepattributes RuntimeVisibleAnnotations
-keepattributes RuntimeInvisibleAnnotations
-keepattributes RuntimeVisibleParameterAnnotations
-keepattributes RuntimeInvisibleParameterAnnotations
-keepattributes EnclosingMethod
-keepclasseswithmembers class * {
#retrofit2.* <methods>;
}
-keepclasseswithmembers interface * {
#retrofit2.* <methods>;
}
-keepclassmembers class demirci.omer.butun.gazeteler.siteler.newspapers.data.model.** { <fields>; }
-keep class demirci.omer.butun.gazeteler.siteler.newspapers.data.model.** { <fields>; }
-keep class demirci.omer.butun.gazeteler.siteler.newspapers.data.ApiEndPoint { <fields>; }
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class retrofit2.converter.gson.** { *; }
I have read below question:
retrofit2 rule
But I have also use retrofit2 converter with POJO. I think problem occur with this...Found this question:
gson-converter
There is two contidion for where problem occur.
Retrofit2 proguard rules is not suitable
Or Retrofit2 converter GSON with POJO is not convert data if fields obfuscated
I dont know with which condition problem occur...
here is my api interface:
public interface ApiEndPoint {
#FormUrlEncoded
#POST("all_newspaper/get_text.php")
Call<NewsContentClass> getContent(#Field("url") String url);
#FormUrlEncoded
#POST("all_newspaper/add_user_url.php")
Call<Void> addUserUrl(#Field("app_name") String appName,#Field("mobile_url") String mobile_url,#Field("desktop_url") String desktop_url);
}

Try adding
-keepclasseswithmembers class * {
#retrofit2.http.* <methods>;
}

try these rules from the retrofit2 site:
########--------Retrofit + RxJava--------#########
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions

Related

HMS Toolkit Conversion (G+H, HMS API 1st) Library (xmsadapter) Not Able to Import

I am trying to port my app from GMS to (G+H) using HMS Toolkit.
After using the Toolkit Convertor, the following line throws an unresolved reference error on import org.xms.f.auth.ExtensionAuth asking to define xms. This obviously means the xmsadapter files (which are generated by the HMS Toolkit Convertor) have not been imported.
How can I fix this error to import the .xms files on import org.xms.f.auth.ExtensionAuth I feel like there's a dependancy that I'm missing?
You can also check your configured obfuscation scripts first.
XMS code generated using the Add HMS API policy will increase the size of your app. You can enable the code reduction function by adding or modifying the following configurations in the app/build.gradle file:
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
If an error message such as "Can't find...", "NoClassDefFoundError", "ClassNotFoundException", "NoSuchFieldException", or "NoSuchMethodException" is displayed after minifyEnabled is set to true, configure the following XMS obfuscation rules in app/proguard-rules.pro:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-keep class com.huawei.agconnect.**{*;}
-keep interface com.huawei.agconnect.**{*;}
-keep class com.huawei.hmf.**{*;}
-keep class com.google.android.gms.**{*;}
-keep interface com.google.android.gms.**{*;}
-keep class com.google.firebase.**{*;}
-keep interface com.google.firebase.**{*;}
-keep class org.xms.**{*;}
-keep interface org.xms.**{*;}
For details,you can refer to this Docs.

How to mock System.getenv() in JUnit [Powermock + Parameterized]

How to mock "System.getenv("...")" in JUnit.
Currently I am doing:
#RunWith(Parameterized.class)
#PowerMockRunnerDelegate(PowerMockRunner.class)
#PrepareForTest(System.class)
public class TestClass extends BaseTest {
public TestClass(String testCase) {
this.testCase = testCase;
}
#Before
#Override
public final void initTable() throws Throwable {
super.initTable();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
}
...
}
I am using both PowerMock and Parameterizedrunner.
I am getting below exception for line:
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
Exception:
org.mockito.exceptions.base.MockitoException:
'afterPropertiesSet' is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
doThrow(exception).when(mock).someVoidMethod();
***
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest({ClassThatCallsTheSystemClass.class}) annotation at the class-level of the test case.
Example with using EasyMock
public class SystemClassUser {
public String performEncode() throws UnsupportedEncodingException {
return URLEncoder.encode("string", "enc");
}
}
And test
#RunWith(PowerMockRunner.class)
#PrepareForTest( { SystemClassUser.class })
public class SystemClassUserTest {
#Test
public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
mockStatic(URLEncoder.class);
expect(URLEncoder.encode("string", "enc")).andReturn("something");
replayAll();
assertEquals("something", new SystemClassUser().performEncode());
verifyAll();
}
}
From:
https://github.com/powermock/powermock/wiki/MockSystem
So, you should add a class that uses the System.getenv, not the System class to #PrepareForTest.
This post explains why it should be done in such way.
Also, I'd like to recommend to use the System Rules library for your case. It has a good way to stub environment variables. PowerMock modifies a class byte code, so it makes test slowly. And even if it not modify a class it at least read class from disk.

Groovy: Delegate instance method to meta class

I'm findind a way easier to implement this kind of feature:
RESTClient client = new RESTClient("https://api.github.com", JSON)
class CoreApi {}
RESTClient.methods*.name.each { name ->
if (! CoreApi.methods.contains(name)) {
CoreApi.metaClass.static."$name" = {Object... args -> client."$name"(*args)}
}
}
and then we can use CoreApi.get(path: "/users/your-user")
Is there any annotation available in groovy for implement this kind of behaviour? What's it called?
You are looking for #Delegate
class CoreApi {
#Delegate RESTClient client
}
But it doesn't work for static methods
Static methods, synthetic methods or methods from the GroovyObject interface are not candidates for delegation

JNI RegisterNatives() can't find class method after running ProGuard

If I set minifyEnabled = true in Gradle setting for my Android app, calling the JNI function RegisterNatives() from the JNI shared library doesn't find its target class anymore. I tried a number of ProGuard rules but still can't get it to work.
Java code:
package net.pol_online.hyper;
...
public class Hyper extends Application {
...
public native static void initializeLibrary(Context context, int maxImageMemoryCacheSize);
...
}
JNI code:
static JNINativeMethod _methods[] = {
{"initializeLibrary", "(Landroid/content/Context;I)V", reinterpret_cast<void*>(&_InitializeLibrary)},
...
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
...
_hyperClass = env->FindClass("net/pol_online/hyper/Hyper");
jint error = env->RegisterNatives(_hyperClass, _methods, sizeof(_methods) / sizeof(JNINativeMethod));
assert(error == JNI_OK);
...
}
Gradle build settings (using the experimental Gradle NDK plug-in for Android Studio):
android.buildTypes {
release {
minifyEnabled = true
proguardFiles.add(file("proguard-rules.txt"))
ndk.with {
CFlags.add("-Werror")
cppFlags.add("-Werror")
}
}
}
ProGuard rules:
-keep class butterknife.** {
*;
}
-keep class **$$ViewBinder {
*;
}
-keepclasseswithmembernames class * {
#butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
#butterknife.* <methods>;
}
-dontwarn butterknife.internal.**
-keep public class net.pol_online.hyper.**
-dontnote android.support.v4.**
-dontwarn android.support.v4.**
The crash at launch:
Failed to register native method net.pol_online.hyper.Hyper.initializeLibrary(Landroid/content/Context;I)V in /data/app/net.pol_online.hyper-1/base.apk
java.lang.NoSuchMethodError: no static or non-static method "Lnet/pol_online/hyper/Hyper;.initializeLibrary(Landroid/content/Context;I)V"'
You do not include the default Proguard configuration for android:
proguardFiles getDefaultProguardFile('proguard-android.txt')
which includes a configuration to keep all native methods:
-keepclasseswithmembernames class * {
native <methods>;
}
This should fix the issue as well and is highly suggested.

"Duplicate Zip Entry" (from Proguard) - renderscript-v8.jar

I am developing android application in Android Studio. There is no problem when I build the project an export signed APK without Proguard, but when I try to build the project with ProGuard(minifyEnabled true), there is an Proguard build failed with error like this:
Error:Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> java.io.IOException: Can't write [user\myapplication\app\build\intermediates\transforms\proguard\release\jars\3\1f\main.jar] (Can't read [user]sdkpath\SDK\build-tools\23.0.0\renderscript\lib\renderscript-v8.jar(;;;;;;**/*.class)] (Duplicate zip entry [renderscript-v8.jar:android/support/annotation/Keep.class]))
Here is my build.gradle codes
...
defaultConfig {
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
checkReleaseBuilds false
}
}
dependencies {
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.google.android.gms:play-services:8.4.0'
compile 'com.google.android.gms:play-services-analytics:8.4.0'
compile project(':libraries:gpuimage')
compile 'it.sephiroth.android.library.horizontallistview:hlistview:1.2.2'
}
Here is my proguard-rule.pro
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
public void *(android.view.MenuItem);
}
-keep class *.R
-keep class *.R$* {*;}
-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }
-keep public class * extends android.support.v4.view.ActionProvider {
public <init>(android.content.Context);
}
## Google AdMob specific rules ##
## https://developers.google.com/admob/android/quick-start ##
-keep public class com.google.ads.** {
public *;
}
## Google Analytics 3.0 specific rules ##
-keep class com.google.analytics.** { *; }
#-keep class it.sephiroth.** {*;}
-dontwarn it.sephiroth.**
Proguard Troubleshooting Say this
Warning: can't write resource ... Duplicate zip entry
Your input jars contain multiple resource files with the same name. ProGuard continues copying the resource files as usual, skipping any files with previously used names. Once more, the warning may be an indication of some problem though, so it's advisable to remove the duplicates. A convenient way to do so is by specifying filters on the input jars. There is no option to switch off these warnings.
android The standard Android build process automatically specifies the input jars for you. There may not be an easy way to filter them to remove these warnings. You could remove the duplicate resource files manually from the input and the libraries.
But i didn't figured out the which jar i added twice in my build..!
This might be related to a bug in renderscript-v8.jar in BuildTools 23.0.0, which included it's own copy of the annotation library and might cause error when used with some other support library.
I would suggest you try use BuildTools 23.0.3 and see if the problem goes away. 23.0.3 also included several other fixes for RenderScript.

Resources