Java – ClassNotFoundException with Parse and Facebook

ClassNotFoundException with Parse and Facebook… here is a solution to the problem.

ClassNotFoundException with Parse and Facebook

I

hope you can help me solve the problem I am facing. I’m trying to integrate Facebook login into my application using Parse, but I get a ClassNotFoundException error when calling the method

 ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginActivity.this, permissions, new LogInCallback()

Error stack trace:

05-15 10:36:00.749    3936-3936/kstr14.tipper E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: kstr14.tipper, PID: 3936
java.lang.IllegalStateException: Could not execute method of the activity
        at android.view.View$1.onClick(View.java:4007)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at android.view.View$1.onClick(View.java:4002)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/parse/ParseTaskUtils;
        at com.parse.ParseFacebookUtils.logInWithReadPermissionsInBackground(ParseFacebookUtils.java:173)
        at kstr14.tipper.Activities.LoginActivity.facebookLoginPressed(LoginActivity.java:170)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at android.view.View$1.onClick(View.java:4002)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.parse.ParseTaskUtils" on path: DexPathList[[zip file "/data/app/kstr14.tipper-1/base.apk"], nativeLibraryDirectories=[/vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
        at com.parse.ParseFacebookUtils.logInWithReadPermissionsInBackground(ParseFacebookUtils.java:173)
        at kstr14.tipper.Activities.LoginActivity.facebookLoginPressed(LoginActivity.java:170)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at android.view.View$1.onClick(View.java:4002)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Suppressed: java.lang.ClassNotFoundException: com.parse.ParseTaskUtils
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
        ... 16 more
 Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

I have the following jar file in my lib folder:
Parse-1.9.1.jar
javax.mail.jar
bolt -android-1.2.0.jar
ParseFacebookUtilsV4-1.9.2.jar

I’ve tried various things with the dependency section of the build.gradle file, as I suspect this bug is due to some libraries not being included correctly, but none of my attempts worked. I tried different ways to specify the compiled jar file and the jar in a different order.
Currently my build.gradle file looks like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    defaultConfig {
        applicationId "kstr14.tipper"
        minSdkVersion 21
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        debug {
            debuggable true
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'),     'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile fileTree(include: ['*.jar'] ,dir: 'libs')
    compile files('libs/bolts-android-1.2.0.jar')
    compile 'com.parse.bolts:bolts-android:1.2.0'
    compile files('libs/Parse-1.9.1.jar')
    compile files('libs/ParseFacebookUtilsV4-1.9.2.jar')
    compile files('libs/javax.mail.jar')
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.facebook.android:facebook-android-sdk:4.0.0'
    compile 'com.google.android.gms:play-services:7.0.0'
}

Does anyone have any suggestions?

Oh, and by the way, when my app crashes with an error, I press OK and then the Facebook login screen shows up anyway. So I want facebook jar to import normally, the problem is parsing jar. However, I was using Pars jar before I tried to integrate Facebook, and it worked just fine. I imported bolts jar at the same time as I imported Facebook jar, because I read somewhere that it was necessary, so it could be an issue with bolts jar?

Edit: Add code for LoginActivity:

package kstr14.tipper.Activities;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;

import com.facebook.FacebookSdk;
import com.parse.LogInCallback;
import com.parse.ParseException;
import com.parse.ParseFacebookUtils;
import com.parse.ParseObject;
import com.parse.ParseUser;
import com.parse.SignUpCallback;

import java.util.ArrayList;
import java.util.List;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import kstr14.tipper.Data.Category;
import kstr14.tipper.Data.Group;
import kstr14.tipper.Data.Tip;
import kstr14.tipper.R;

public class LoginActivity extends ActionBarActivity {

 UI elements for default login fragment
private EditText usernameDefaultLogin;
private EditText passwordDefaultLogin;

 UI elements for sign up fragment
private EditText usernameSignup;
private EditText emailSignup;
private EditText passwordSignup;
private EditText reenterPasswordSignup;

@Override
protected void onCreate(Bundle savedInstanceState) {
    getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    getSupportActionBar().hide();

 initalize facebook
    FacebookSdk.sdkInitialize(getApplicationContext());

 Initialize Parse
    ParseObject.registerSubclass(Tip.class);
    ParseObject.registerSubclass(Category.class);
    ParseObject.registerSubclass(Group.class);
    ParseObject.registerSubclass(ParseUser.class);

 check cache for current user - if found go directly to MainActivity
    ParseUser currentUser = ParseUser.getCurrentUser();
    if(currentUser != null) {
        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        startActivity(intent);
    }

 otherwise set fragment to the default login screen
    DefaultLoginFragment defaultLoginFragment = new DefaultLoginFragment();
    getSupportFragmentManager().beginTransaction()
            .add(R.id.fragment_container, defaultLoginFragment).commit();
}

 Required for making Facebook login work
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    ParseFacebookUtils.onActivityResult(requestCode, resultCode, data);
}

/**
 * Method called when sign up button pressed on the default login fragment
 * Switches the default login fragment with a sign up fragment
 * @param view
 */
public void defaultSignUpPressed(View view) {
    SignUpFragment signUpFragment = new SignUpFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

 Replace the default login fragment with the sign up fragment,
     and add the transaction to the back stack so the user can navigate back
    fragmentTransaction.replace(R.id.fragment_container, signUpFragment);
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();
}

/**
 * Method called when login button pressed on the default login fragment
 * Attempts to log in the user, if successful goes to MainActivity
 * @param view
 */
public void defaultLoginPressed(View view) {
     initialize UI elements for default login fragment
    usernameDefaultLogin = (EditText) findViewById(R.id.usernameDefaultLoginFragment);
    passwordDefaultLogin = (EditText) findViewById(R.id.passwordDefaultLoginFragment);

 fetch input and attempt login
    String username = usernameDefaultLogin.getText().toString();
    String password = passwordDefaultLogin.getText().toString();
    ParseUser.logInInBackground(username, password, new LogInCallback() {
        public void done(ParseUser user, ParseException e) {
             if (user != null) {
                  Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                  startActivity(intent);
             } else {
                  Toast.makeText(getApplicationContext(), "Login failed.", Toast.LENGTH_SHORT).show();
             }
        }
    });
}

/**
 * Method called when sign up button pressed in sign up fragment
 * Attempts to register the user, if successful goes to MainActivity
 * @param view
 */
public void signupPressed(View view) {
     UI elements for sign up fragment
    usernameSignup = (EditText) findViewById(R.id.usernameSignupFragment);
    emailSignup = (EditText) findViewById(R.id.emailSignupFragment);
    passwordSignup = (EditText) findViewById(R.id.passwordSignupFragment);
    reenterPasswordSignup = (EditText) findViewById(R.id.reenterPasswordSignupFragment);

String username = usernameSignup.getText().toString();
    String email = emailSignup.getText().toString();
    String password1 = passwordSignup.getText().toString();
    String password2 = reenterPasswordSignup.getText().toString();

 validate passwords and email
    if(!validatePassword(password1, password2)) {
        Toast.makeText(getApplicationContext(), "Passwords do not match, try again.", Toast.LENGTH_SHORT).show();
    } else if (!validateEmail(email)) {
        Toast.makeText(getApplicationContext(), "Please enter a valid email.", Toast.LENGTH_SHORT).show();
    } else {
        ParseUser user = new ParseUser();
        user.setUsername(username);
        user.setPassword(password1);
        user.setEmail(email);
        user.signUpInBackground(new SignUpCallback() {
            public void done(ParseException e) {
                if (e == null) {
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                } else {
                    Toast.makeText(getApplicationContext(), "Sign up failed. Please try again.", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

public void facebookLoginPressed(View view) {
    List<String> permissions = new ArrayList<String>();
    permissions.add("public_profile");
    ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginActivity.this, permissions, new LogInCallback() {
        @Override
        public void done(ParseUser user, ParseException err) {
            if (user == null) {
                Log.d("MyApp", "Uh oh. The user cancelled the Facebook login.");
            } else if (user.isNew()) {
                Log.d("MyApp", "User signed up and logged in through Facebook!");
            } else {
                Log.d("MyApp", "User logged in through Facebook!");
            }
        }
    });
}

/**
 * Validates that two passwords are equal
 * @param password1
 * @param password2
 * @return
 */
public boolean validatePassword(String password1, String password2) {
    if(password1.equals(password2)) return true;
    else return false;
    }

/**
 * Validates the structure of an email address
 * @param email
 * @return
 */
public boolean validateEmail(String email) {
    boolean result = true;
    try {
        InternetAddress internetAddress = new InternetAddress(email);
        internetAddress.validate();
    } catch (AddressException e) {
        e.printStackTrace();
        result = false;
    }
    return result;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_login, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

if (id == R.id.action_settings) {
        return true;
    }

return super.onOptionsItemSelected(item);
}
}

Solution

Actually, I just had the same problem. Hopefully I can save anyone searching for this issue a lot of trouble. The answer is not to use the old SDK. In fact, all you need to do is make sure you’re using the same version of Parse and ParseFacebookUtils. Take a look at your gradle file above

compile 'com.parse.bolts:bolts-android:1.2.0'
compile files('libs/Parse-1.9.1.jar')
compile files('libs/ParseFacebookUtilsV4-1.9.2.jar')

You are using Parse-1.9.1 and ParseFacebookUtilsV4-1.9.2. I actually made the same mistake. I pulled Parse-1.9.1 from another project and downloaded the SDK again to pull out the FacebookUtils library.

Related Problems and Solutions