2

I am integrating Back4App into my app and am following the android tutorials step by step and am now in the live-query portion of the tutorial and encountered an issue with duplicate okhttp3 libraries. I am able to build the project successfully, however when attempting to run, I receive compilation error stating

Program type already present: okhttp3.internal.ws.WebSocketReader$FrameCallback

My App level build.gradle is

apply plugin: 'com.android.application'
android {
    compileSdkVersion 27
    defaultConfig {
        applicationId 'my.app.id'

        //multiDexEnabled true

        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"


        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }

    configurations.all {
        // OkHttp 3.5.0+ includes the websockets API, so we need this to prevent a conflict
        //exclude module: 'okhttp-ws'
    }

    packagingOptions {
        exclude 'META-INF/rxjava.properties'
    }
}

dependencies {
    // Google GCM Firebase stuff
    implementation 'com.parse.bolts:bolts-android:1.4.0'
    implementation 'com.google.firebase:firebase-core:16.0.3'

    implementation 'com.google.firebase:firebase-messaging:17.3.0'

    // Back4App library
    implementation 'com.parse:parse-android:1.16.3'


    // Back4App Live Query Client
    // *************************************************** //
    implementation 'com.github.tgio:parse-livequery:1.0.3'
    // *************************************************** //

    // in-app billing
    implementation 'com.android.billingclient:billing:1.1'
    // Arch COmponents ViewModelProviders Library
    implementation "android.arch.lifecycle:extensions:$rootProject.lifecycle_version"
    annotationProcessor "android.arch.persistence.room:compiler:$rootProject.room_version"
    // For Room Dependencies
    implementation "android.arch.persistence.room:runtime:$rootProject.room_version"
    //implementation "android.arch.persistence.room:compiler:$room_version"
    // Room -- Optionales
    implementation "android.arch.persistence.room:rxjava2:$rootProject.room_version"
    // Room Test helpers
    testImplementation "android.arch.persistence.room:testing:$rootProject.room_version"
    implementation 'de.hdodenhof:circleimageview:2.2.0'
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.android.support:support-v4:27.1.1'
    implementation 'com.android.support:support-v13:27.1.1'
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'org.jetbrains:annotations-java5:15.0'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    implementation 'com.android.support:support-vector-drawable:27.1.1'
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    // AndroidJUnitRunner and JUnit Rules
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    // Espresso dependencies
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-accessibility:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-web:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso.idling:idling-concurrent:3.0.2'
    // Espresso dependency either "compile" or "androidTestImplementation", depends on app's implementation
    androidTestImplementation 'com.android.support.test.espresso:espresso-idling-resource:3.0.2'
    // Required -- JUnit 4 framework
    testImplementation 'junit:junit:4.12'
    // Optional -- Mockito framework
    testImplementation 'org.mockito:mockito-core:2.15.0'
    androidTestImplementation 'com.android.support:support-annotations:27.1.1'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
}

repositories {
    jcenter()
    google()
    maven {
        url "https://maven.google.com"
    }
}
apply plugin: 'com.google.gms.google-services'

this is the Activity that I am testing

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;

import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.SaveCallback;

import org.json.JSONObject;

import tgio.parselivequery.BaseQuery;
import tgio.parselivequery.LiveQueryClient;
import tgio.parselivequery.LiveQueryEvent;
import tgio.parselivequery.interfaces.OnListener;

public class QueryExample extends AppCompatActivity {

    // Subscription
    final tgio.parselivequery.Subscription sub = new BaseQuery.Builder("message")
            .where("destination", "pokelist")
            .addField("content")
            .build()
            .subscribe();



    // Back4App's Parse setup
    private void initializeParse() {

        Parse.initialize(new Parse.Configuration.Builder(this)
                .applicationId(getResources().getString(R.string.back4app_server_url))
                .clientKey(getResources().getString(R.string.back4app_client_key))
                .server("https://parseapi.back4app.com/")
                .build());

        initLiveQueryClient();
    }

    // Init Live Query Client
    private void initLiveQueryClient() {

        // Example: 'wss://livequerytutorial.back4app.io'
        LiveQueryClient.init("wss://"+"myprototype.back4app.io",
                getResources().getString(R.string.back4app_app_id),
                true);

        LiveQueryClient.connect();
    }

    int numPokes = 0;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_live_query_example);
        EditText pokeText = findViewById(R.id.pokeText);

        initializeParse();

        sub.on(LiveQueryEvent.CREATE, new OnListener() {
            @Override
            public void on(JSONObject object) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        EditText pokeText = findViewById(R.id.pokeText);
                        numPokes++;
                        if(numPokes == 1) {
                            pokeText.setText("Poked " + numPokes + " time.");
                        }
                        else {
                            pokeText.setText("Poked " + numPokes + " times.");
                        }
                    }
                });
            }
        });

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                ParseObject poke = new ParseObject("Message");
                poke.put("content", "poke");
                poke.put("destination", "pokelist");
                poke.saveInBackground(new SaveCallback() {
                    @Override
                    public void done(ParseException e) {
                        Snackbar.make(view, "Poke has been sent!", Snackbar.LENGTH_LONG)
                                .setAction("Action", null).show();
                    }
                });
            }
        });
    }
}

I notice when commenting out

implementation 'com.github.tgio:parse-livequery:1.0.3'

from my app level build.gradle, am able to compile and run the app, however the QueryExample Activity above crashes due to it missing the okhttp3-ws import

I have researched numerous Stack Overflow questions regarding this problem and implemented this solution Here. The reasoning is explained in this Github Forum (deprecation) however, similar to cinder92 comment on Mar 21, 2017 , the problem persists. Has anyone gone through this issue and if so found a solution? My Activity briefly ran until it crashed with error log

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.kungfu.tuga, PID: 25976
                  java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/ws/WebSocketListener;
                      at tgio.parselivequery.LiveQueryClient.getNewRequestId(LiveQueryClient.java:128)
                      at tgio.parselivequery.BaseQuery$Builder.<init>(BaseQuery.java:100)
                      at com.kungfu.tuga.utilities.the_wire.QueryExample.<init>(QueryExample.java:27)
                      at java.lang.Class.newInstance(Native Method)
                      at android.app.Instrumentation.newActivity(Instrumentation.java:1174)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2669)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
                      at android.app.ActivityThread.-wrap11(Unknown Source:0)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
                      at android.os.Handler.dispatchMessage(Handler.java:106)
                      at android.os.Looper.loop(Looper.java:164)
                      at android.app.ActivityThread.main(ActivityThread.java:6494)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
                   Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.ws.WebSocketListener" on path: DexPathList[[zip file "/data/app/com.kungfu.tuga-9jJWU4yht8e1tuYOuZmIQQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.kungfu.tuga-9jJWU4yht8e1tuYOuZmIQQ==/lib/x86, /system/lib, /vendor/lib]]
                      at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
                      at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
                      at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                      at tgio.parselivequery.LiveQueryClient.getNewRequestId(LiveQueryClient.java:128) 
                      at tgio.parselivequery.BaseQuery$Builder.<init>(BaseQuery.java:100) 
                      at com.kungfu.tuga.utilities.the_wire.QueryExample.<init>(QueryExample.java:27) 
                      at java.lang.Class.newInstance(Native Method) 
                      at android.app.Instrumentation.newActivity(Instrumentation.java:1174) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2669) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
                      at android.app.ActivityThread.-wrap11(Unknown Source:0) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
                      at android.os.Handler.dispatchMessage(Handler.java:106) 
                      at android.os.Looper.loop(Looper.java:164) 
                      at android.app.ActivityThread.main(ActivityThread.java:6494) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
InsaneCat
  • 2,115
  • 5
  • 21
  • 40
  • I don't see okhttp library in your build.gradle. – AIK Sep 05 '18 at 07:49
  • 1
    @AIK it comes bundled in with the android SDK as per [This Link](https://stackoverflow.com/questions/26000027/does-android-use-okhttp-internally)..So my error is due to 'implementation 'com.github.tgio:parse-livequery:1.0.3' adding okhttp3-ws duplicate, I know this because when I comment this implementation out, I don't see errors from compilation but other errors (Object/Classes cannot be found in activity that depend on aforemention dependency) – Alyosha_Karamazov Sep 05 '18 at 17:58

1 Answers1

3

Yes, I faced this issue too, however, if you set your gradle like this:

implementation ('com.parse:parse-android:1.16.3'){
    exclude group: "com.squareup.okhttp3"
}

It will work without any trouble. (:

Charles
  • 531
  • 2
  • 11
  • I actually tried excluding different groups because I had the name wrong but I did NOT encapsulate my dependency within the parenthesis ( ) fml..I voted your answer as the correct one. Much Obliged – Alyosha_Karamazov Sep 06 '18 at 00:34