Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RX Android & Proguard #350

Closed
supercairos opened this issue Nov 14, 2016 · 22 comments
Closed

RX Android & Proguard #350

supercairos opened this issue Nov 14, 2016 · 22 comments

Comments

@supercairos
Copy link

supercairos commented Nov 14, 2016

Hi,

I ran into a small issue when releasing into pro-guard.The method AndroidSchedulers.mainThread() makes the subscription to never be called:

This will not work (Hello will never show):

mRestService.login(email, password)
                .flatMap(user -> Observable.zip(
                        mRestService.checkUuid(user._token), 
                        Observable.just(user),
                        (v, u) -> (User) u // Pass user throught
                ))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(user -> { Log.v(TAG, "Hello") }, throwable -> { });

This works as expected :

mRestService.login(email, password)
                .flatMap(user -> Observable.zip(
                        mRestService.checkUuid(user._token), 
                        Observable.just(user),
                        (v, u) -> (User) u // Pass user throught
                ))
                .subscribeOn(Schedulers.io())
                //  .observeOn(AndroidSchedulers.mainThread())
                .subscribe(user -> runOnUiThread(() -> { Log.v(TAG, "Hello") }), throwable -> { });

I'm using Jack and the latest AndroidStudio Gradle plugin (2.2.2)
I've attached my proguard file in case you want to have a look:
proguard-rules.txt

@jakubvimn
Copy link

@supercairos Are you sure this is proguard related? Does the first example work without proguard?
Could you simplify your example, so that it can be copied and run independently? Maybe the problem is not with the AndroidSchedulers.mainThread() itself but with how it interacts with your code.

@artem-zinnatullin
Copy link
Contributor

I don't see any correlation between this issue and ProGuard rules, maybe you store resulting subscription and unsubscribe it somewhere and it creates "race" condition so you unsubscribe from the chain before it completes?

@supercairos
Copy link
Author

supercairos commented Nov 14, 2016

Race condition was a good idea, but i disabled the code that manage subscription and I still have the issue :(

Yes, try to run this sample :

          Observable.range(10, 20)
                            .flatMap(integer -> Observable.zip(
                                    Observable.just(integer),
                                    Observable.just(30),
                                    (integer1, integer2) -> integer1
                            ))
                            .doOnNext(integer -> Log.v("RxJava", "1) >> " + integer))
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(integer -> Log.v("RxJava", "2) >> " + integer), throwable -> {
                            }))

Without proguard :
RxJava: 1) >> 10
RxJava: 1) >> 11
RxJava: 1) >> 12
RxJava: 1) >> 13
RxJava: 1) >> 14
RxJava: 1) >> 15
RxJava: 1) >> 16
RxJava: 1) >> 17
RxJava: 1) >> 18
RxJava: 1) >> 19
RxJava: 1) >> 20
RxJava: 1) >> 21
RxJava: 1) >> 22
RxJava: 1) >> 23
RxJava: 1) >> 24
RxJava: 1) >> 25
RxJava: 2) >> 10
RxJava: 2) >> 11
RxJava: 2) >> 12
RxJava: 2) >> 13
RxJava: 2) >> 14
RxJava: 2) >> 15
RxJava: 2) >> 16
RxJava: 2) >> 17
RxJava: 2) >> 18
RxJava: 2) >> 19
RxJava: 2) >> 20
RxJava: 2) >> 21
RxJava: 2) >> 22
RxJava: 2) >> 23
RxJava: 1) >> 26
RxJava: 2) >> 24
RxJava: 2) >> 25
RxJava: 2) >> 26
RxJava: 1) >> 27
RxJava: 1) >> 28
RxJava: 1) >> 29
RxJava: 2) >> 27
RxJava: 2) >> 28
RxJava: 2) >> 29

With proguard :
RxJava: 1) >> 10
RxJava: 1) >> 11
RxJava: 1) >> 12
RxJava: 1) >> 13
RxJava: 1) >> 14
RxJava: 1) >> 15
RxJava: 1) >> 16
RxJava: 1) >> 17
RxJava: 1) >> 18
RxJava: 1) >> 19
RxJava: 1) >> 20
RxJava: 1) >> 21
RxJava: 1) >> 22
RxJava: 1) >> 23
RxJava: 1) >> 24
RxJava: 1) >> 25
(it doesn't go until 29... Sometime 25 sometime less)

Using my work around (with runOnUiThread()) works as expected :

          Observable.range(10, 20)
                            .flatMap(integer -> Observable.zip(
                                    Observable.just(integer),
                                    Observable.just(30),
                                    (integer1, integer2) -> integer1
                            ))
                            .doOnNext(integer -> Log.v("RxJava", "1) >> " + integer))
                            .subscribeOn(Schedulers.io())
//                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(integer -> runOnUiThread(() -> Log.v("RxJava", "2) >> " + integer)), throwable -> {
                            }))

@supercairos
Copy link
Author

These are my dependencies :

ext {
    support = '25.0.0'
    play_services = '9.8.0'

    // HTTP
    okhttp = '3.4.1'
    retrofit = '2.1.0'
    glide = '3.7.0'

    // DEPS INJECTION
    dagger = '2.6'

    // VIEW INJECTION
    butterknife = '8.4.0'

    // DEBUG
    stetho = '1.4.1'
}

dependencies {
    compile "com.android.support:support-annotations:${support}"
    compile "com.android.support:support-v4:${support}"
    compile "com.android.support:design:${support}"
    compile "com.android.support:appcompat-v7:${support}"
    compile "com.android.support:cardview-v7:${support}"
    compile "com.android.support:recyclerview-v7:${support}"
    compile "com.android.support:palette-v7:${support}"

    // Firebase
    releaseCompile "com.google.firebase:firebase-crash:${play_services}"

    // GSON
    compile 'com.google.code.gson:gson:2.7'

    // RxJava
    compile 'io.reactivex:rxandroid:1.2.1'
    // Because RxAndroid releases are few and far between, it is recommended you also
    // explicitly depend on RxJava's latest version for bug fixes and new features.
    compile 'io.reactivex:rxjava:1.1.6'

    // OkHttp
    compile "com.squareup.okhttp3:okhttp:${okhttp}"
    compile "com.squareup.okhttp3:logging-interceptor:${okhttp}"

    compile "com.squareup.retrofit2:retrofit:${retrofit}"
    compile "com.squareup.retrofit2:converter-gson:${retrofit}"
    compile "com.squareup.retrofit2:adapter-rxjava:${retrofit}"

    // Glide
    compile "com.github.bumptech.glide:glide:${glide}"
    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@jar'

    // Dagger
    compile "com.google.dagger:dagger:${dagger}"
    annotationProcessor "com.google.dagger:dagger-compiler:${dagger}"

    // Butterknife
    compile "com.jakewharton:butterknife:${butterknife}"
    annotationProcessor "com.jakewharton:butterknife-compiler:${butterknife}"

    // ###################### DEBUG
    // Setho
    debugCompile "com.facebook.stetho:stetho:${stetho}"
    debugCompile "com.facebook.stetho:stetho-okhttp3:${stetho}"

    // ###################### CUSTOM
    // Setho
    customCompile "com.facebook.stetho:stetho:${stetho}"
    customCompile "com.facebook.stetho:stetho-okhttp3:${stetho}"
}

@JakeWharton
Copy link
Member

Please provide a full sample that demonstrates the problem with as minimal
amount of code as possible.

On Mon, Nov 14, 2016 at 5:41 AM Romain Caire notifications@github.com
wrote:

These are my dependencies :

ext {
support = '25.0.0'
play_services = '9.8.0'

// HTTP
okhttp = '3.4.1'
retrofit = '2.1.0'
glide = '3.7.0'

// DEPS INJECTION
dagger = '2.6'

// VIEW INJECTION
butterknife = '8.4.0'

// DEBUG
stetho = '1.4.1'

}

dependencies {
compile "com.android.support:support-annotations:${support}"
compile "com.android.support:support-v4:${support}"
compile "com.android.support:design:${support}"
compile "com.android.support:appcompat-v7:${support}"
compile "com.android.support:cardview-v7:${support}"
compile "com.android.support:recyclerview-v7:${support}"
compile "com.android.support:palette-v7:${support}"

// Firebase
releaseCompile "com.google.firebase:firebase-crash:${play_services}"

// GSON
compile 'com.google.code.gson:gson:2.7'

// RxJava
compile 'io.reactivex:rxandroid:1.2.1'
// Because RxAndroid releases are few and far between, it is recommended you also
// explicitly depend on RxJava's latest version for bug fixes and new features.
compile 'io.reactivex:rxjava:1.1.6'

// OkHttp
compile "com.squareup.okhttp3:okhttp:${okhttp}"
compile "com.squareup.okhttp3:logging-interceptor:${okhttp}"

compile "com.squareup.retrofit2:retrofit:${retrofit}"
compile "com.squareup.retrofit2:converter-gson:${retrofit}"
compile "com.squareup.retrofit2:adapter-rxjava:${retrofit}"

// Glide
compile "com.github.bumptech.glide:glide:${glide}"
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@jar'

// Dagger
compile "com.google.dagger:dagger:${dagger}"
annotationProcessor "com.google.dagger:dagger-compiler:${dagger}"

// Butterknife
compile "com.jakewharton:butterknife:${butterknife}"
annotationProcessor "com.jakewharton:butterknife-compiler:${butterknife}"

// ###################### DEBUG
// Setho
debugCompile "com.facebook.stetho:stetho:${stetho}"
debugCompile "com.facebook.stetho:stetho-okhttp3:${stetho}"

// ###################### CUSTOM
// Setho
customCompile "com.facebook.stetho:stetho:${stetho}"
customCompile "com.facebook.stetho:stetho-okhttp3:${stetho}"

}


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#350 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEWTpl5u2RsMN1BCOnOmzTG-CCTjjks5q-GTqgaJpZM4KxKHX
.

@supercairos
Copy link
Author

supercairos commented Nov 20, 2016

Try this project : https://github.com/supercairos/rxjava_proguard_error

It's a fairly barebone project. It's the default project created by Android Studio 2.3 C + the added code provided above and Jack enabled.

I've included a keystore and registered it in the gradle so you don't have to create one.
Try building a debug apk -> Works as expected, release apk -> only output some 1) and no 2)

Note : I had to add some lines to the proguard.pro files as Jack doesn't seams to read it directly from the AAR?

@hahn
Copy link

hahn commented Jan 11, 2017

is this question (my question) related? http://stackoverflow.com/questions/41581958/rxjava-android-not-working-in-release-mode-signed-apk

when in debug mode, my app working fine, but after generate apk release, not working :(

@Zulqurnain
Copy link

i have the same issue , client is asking for release apk and now every functionality that relates to rxjava is not working , in debug mode it works as expected.

build.gradle(project)

apply plugin: 'com.android.application' //or apply plugin: 'java'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'com.jakewharton.hugo'
apply plugin: 'android-apt'
def AAVersion = '4.1.0'

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.2'

    defaultConfig {
        applicationId "com.jutt.example1"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 4
        versionName "1.0"
        multiDexEnabled false
    }
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources false
            zipAlignEnabled true
            //debuggable false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    compileOptions {
        targetCompatibility 1.8
        sourceCompatibility 1.8
    }

}

apt {
    arguments {
        // you should set your package name here if you are using different application IDs
        // resourcePackageName "your.package.name"

        // You can set optional annotation processing options here, like these commented options:
        // logLevel 'INFO'
        // logFile '/var/log/aa.log'
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    apt "org.androidannotations:androidannotations:$AAVersion"
    compile "org.androidannotations:androidannotations-api:$AAVersion"
    compile 'com.android.support:multidex:1.0.1'
    // Retrofit & OkHttp
    compile 'com.android.support:appcompat-v7:25.1.0'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.2'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.afollestad.material-dialogs:core:0.9.0.2'
    compile 'com.android.support:support-v4:25.1.0'
    compile 'com.github.ganfra:material-spinner:1.1.1'
    compile 'com.android.support:design:25.1.0'
    compile 'org.apache.commons:commons-lang3:3.4'
    compile 'com.wdullaer:materialdatetimepicker:2.5.0'
    compile 'io.reactivex:rxandroid:1.2.1'
// Because RxAndroid releases are few and far between, it is recommended you also
// explicitly depend on RxJava's latest version for bug fixes and new features.
    compile 'io.reactivex:rxjava:1.1.6'

    compile 'com.trello:rxlifecycle:1.0'

// If you want to bind to Android-specific lifecycles
    compile 'com.trello:rxlifecycle-android:1.0'

// If you want pre-written Activities and Fragments you can subclass as providers
    compile 'com.trello:rxlifecycle-components:1.0'
}

build.gradle(module)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0-beta2'
        classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
        classpath 'me.tatarka:gradle-retrolambda:3.3.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        // replace with the current version of the android-apt plugin
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}


allprojects {
    repositories {
        jcenter()
        mavenCentral()
        mavenLocal()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

progaurd:


# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/zulqurnainjutt/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

-optimizationpasses 5
#-allowaccessmodification
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose

#your package path where your gson models are stored
-keep class com.jutt.example1.model.** { *; }

# Retrofit, OkHttp, Gson
-keepattributes *Annotation*
-keepattributes Signature
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
-dontwarn rx.**
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
    @retrofit.http.* <methods>;
}
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# OkHttp3
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**

# Rxjava-promises

-keep class com.darylteo.rx.** { *; }

-dontwarn com.darylteo.rx.**

# RxJava 0.21

-keep class rx.schedulers.Schedulers {
    public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
    public <methods>;
}
-keep class rx.schedulers.TestScheduler {
    public <methods>;
}
-keep class rx.schedulers.Schedulers {
    public static ** test();
}

## Retrolambda specific rules ##

# as per official recommendation: https://github.com/evant/gradle-retrolambda#proguard
-dontwarn java.lang.invoke.*

@Zulqurnain
Copy link

Zulqurnain commented Jan 15, 2017

what more info is needed ? @JakeWharton

@nikiizvorski
Copy link

nikiizvorski commented Jan 19, 2017

It seems this will affect a lot from this great library.....anyway thanks for bringing the great lib @JakeWharton and all the work your team and you have provided to us completely free. Are there any news about this bug did anyone manage to fix it i am experiencing the same issue right now and nothing works... For me everything is working fine until the release and after that i think the problem is inside the AndroidScheduler.mainThread() seems like the problem is in the Scheduler....

@digitalbuddha
Copy link
Contributor

I can confirm that debug is working but release is stopping between 15-25 emissions. I did some digging. The issue is not proguard but Jack.

Here's what I did to the above sample:
Remove Jack, remove lambdas.
Try to run release
I get following log

Warning:rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.ConcurrentCircularArrayQueue: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.ConcurrentSequencedCircularArrayQueue: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.MpmcArrayQueueConsumerField: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.MpmcArrayQueueProducerField: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.MpscLinkedQueue: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.SpmcArrayQueueConsumerField: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.SpmcArrayQueueProducerField: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.SpscArrayQueue: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.SpscUnboundedArrayQueue: can't find referenced class sun.misc.Unsafe
Warning:rx.internal.util.unsafe.UnsafeAccess: can't find referenced class sun.misc.Unsafe
Warning:there were 44 unresolved references to classes or interfaces.
Warning:Exception while processing task java.io.IOException: Please correct the above warnings first.
Error:Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> java.io.IOException: Please correct the above warnings first.

I add -dontwarn **.** and run again. This time output is correct.

Next I turn Jack back on but this time with the above line in the proguard rules. The output is still incorrect.

Another data point: Jack without proguard works fine

Not sure if this helps.

@nikiizvorski
Copy link

I don't have jack enabled and i am not using any java 1.8 at all and it still doesn't work in release.

@calber
Copy link

calber commented Feb 24, 2017

I had the same error, I check the dependencies and its turn out the problem was mixing Rxjava with RxJava2.
failing configuration:
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
correct (the problem disappeared in my case)
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

@nikiizvorski
Copy link

Yep please look into your RxJava and RxAndroid versions look's like the old latest version have some problems but if you use the new version of Rx2 and i suggest you do you will not have any problems with that there are new configurations. And the library just rocks this time! Seems really great so far! Thanks guys

@546201056
Copy link

What is jack

@AkshayChordiya
Copy link

I'm facing the same issue where the debug build is running perfect and release without minify (proguard) is working perfect but the same release build with minify is failing on the Rx side.
@JakeWharton Any updates regarding the same?

@hahn
Copy link

hahn commented Aug 24, 2017

@AkshayChordiya try RxJava2

@AkshayChordiya
Copy link

AkshayChordiya commented Aug 24, 2017

@hahn I'm already using RxJava2

@jemshit
Copy link

jemshit commented Nov 8, 2017

@546201056 Jill's friend

@vanniktech
Copy link
Contributor

vanniktech commented Jul 10, 2018

This can also be closed then since only RxJava 1.x requires Proguard rules which is EOL.

@JakeWharton
Copy link
Member

ProGuard rules. Nothing requires ProGuard.

@vanniktech
Copy link
Contributor

Yeah corrected it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests