Search code examples
androidandroid-studioandroid-asynctaskandroid-volleynoclassdeffounderror

Android Studio: NoClassDefFoundError on all classes of the app module


Hi I am developing an application which uses minSdkVersion 17 in Android Studio.

This is my MainActivity.java

package in.co.dryve.customer.activities;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

import in.co.dryve.customer.R;
import in.co.dryve.customer.fragments.AboutUsFragment;
import in.co.dryve.customer.fragments.BookNowFragment;
import in.co.dryve.customer.fragments.HelpFragment;
import in.co.dryve.customer.fragments.HowItWorksFragment;
import in.co.dryve.customer.fragments.MyBookingsFragment;
import in.co.dryve.customer.models.User;
import in.co.dryve.customer.utils.LoginPreferences;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    LoginPreferences loginPreferences;
    private static final int LOGIN_REQ_CODE = 1;
    private static final int PROFILE_REQ_CODE = 2;
    TextView navNameTv, navEmailTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        loginPreferences = new LoginPreferences(this);

        BookNowFragment bookNowFragment = new BookNowFragment();
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container,bookNowFragment);
        fragmentTransaction.commit();

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        View view = navigationView.getHeaderView(0);
        navNameTv = (TextView)view.findViewById(R.id.nav_username);
        navEmailTv = (TextView)view.findViewById(R.id.nav_useremail);
        if(loginPreferences.isLoggedIn()){
            User user = loginPreferences.getUser();
            navNameTv.setText(user.getName().toUpperCase());
            navEmailTv.setText(user.getEmail());
        } else {
            navNameTv.setText(getResources().getString(R.string.login_as_user));
            navEmailTv.setVisibility(View.GONE);
        }
        view.findViewById(R.id.ll_profile).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (loginPreferences.isLoggedIn()) {
                    startActivityForResult(new Intent(MainActivity.this, ProfileActivity.class), PROFILE_REQ_CODE);
                } else {
                    startActivityForResult(new Intent(MainActivity.this, LoginActivity.class), LOGIN_REQ_CODE);
                }
            }
        });
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(loginPreferences.isLoggedIn()){
            navNameTv.setVisibility(View.VISIBLE);
            navEmailTv.setVisibility(View.VISIBLE);
            User user = loginPreferences.getUser();
            navNameTv.setText(user.getName());
            navEmailTv.setText(user.getEmail());
        } else {
            navNameTv.setText(getResources().getString(R.string.login_as_user));
            navEmailTv.setVisibility(View.GONE);
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_book_now) {
            BookNowFragment bookNowFragment = new BookNowFragment();
            bookNowFragment.setContext(MainActivity.this);
            bookNowFragment.setContext(MainActivity.this);
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container,bookNowFragment);
            fragmentTransaction.commit();
            getSupportActionBar().setTitle("Dryve");
        } else if (id == R.id.nav_my_bookings) {
            MyBookingsFragment myBookingsFragment = new MyBookingsFragment();
            myBookingsFragment.setContext(MainActivity.this);
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container,myBookingsFragment);
            fragmentTransaction.commit();
            getSupportActionBar().setTitle("My Bookings");
        } else if (id == R.id.nav_how_it_works) {
            HowItWorksFragment howItWorksFragment = new HowItWorksFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container,howItWorksFragment);
            fragmentTransaction.commit();
            getSupportActionBar().setTitle("How It Works");
        } else if (id == R.id.nav_share) {
            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share_text));
            sendIntent.setType("text/plain");
            startActivity(Intent.createChooser(sendIntent, "Send via"));
        } else if (id == R.id.nav_rate_us) {
            Intent rateUsIntent = new Intent(Intent.ACTION_VIEW);
            rateUsIntent.setData(Uri.parse("market://details?id=in.co.dryve.customer"));
            startActivity(rateUsIntent);
        } else if (id == R.id.nav_help){
            HelpFragment helpFragment = new HelpFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container,helpFragment);
            fragmentTransaction.commit();
            getSupportActionBar().setTitle("Help");
        } else if(id == R.id.nav_about_us){
            AboutUsFragment aboutUsFragment = new AboutUsFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container,aboutUsFragment);
            fragmentTransaction.commit();
            getSupportActionBar().setTitle("About Us");
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

This is the BookNowFragment.java

package in.co.dryve.customer.fragments;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.google.android.gms.fitness.request.DataDeleteRequest;
import com.google.android.gms.maps.model.LatLng;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import in.co.dryve.customer.R;
import in.co.dryve.customer.adapters.VehicleAdapter;
import in.co.dryve.customer.datePicker.DatePickerActivity;
import in.co.dryve.customer.models.Constants;
import in.co.dryve.customer.models.Vehicle;
import in.co.dryve.customer.parsers.VehicleListParser;
import in.co.dryve.customer.serverutils.AppController;
import in.co.dryve.customer.serverutils.ServerRequests;
import in.co.dryve.customer.serverutils.Urls;
import in.co.dryve.customer.utils.Intents;

public class BookNowFragment extends Fragment {

    private static final int REQ_PICKUP_DATE = 4;
    private static final int REQ_RETURN_DATE = 5;
    Context context;
    ListView bikesListView;
    LatLng latLng;
    ProgressBar progressBar;
    LinearLayout pickupTimeLL, returnTimeLL;
    TextView pickupTimeTV, returnTimeTV, pickupTimeLabelTV, returnTimeLabelTV;
    VehicleAdapter adapter;
    Date pickupDate = new Date(), returnDate = new Date();
    boolean isPickupTimeSet, isReturnTimeSet;

    public void setContext(Context context){
        this.context = context;
    }

    public BookNowFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_book_now, container, false);
        bikesListView = (ListView)view.findViewById(R.id.listview_bikes);
        progressBar = (ProgressBar)view.findViewById(R.id.pb_load_vehicle);
        pickupTimeLL = (LinearLayout)view.findViewById(R.id.ll_pickup_time);
        returnTimeLL = (LinearLayout)view.findViewById(R.id.ll_return_time);
        pickupTimeTV = (TextView)view.findViewById(R.id.tv_pickup_time);
        returnTimeTV = (TextView)view.findViewById(R.id.tv_return_time);
        pickupTimeLabelTV = (TextView)view.findViewById(R.id.tv_pickup_time_label);
        returnTimeLabelTV = (TextView)view.findViewById(R.id.tv_return_time_label);
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        this.context = getContext();
        latLng = new LatLng(12.9667,77.5667); //Bangalore LatLng
        isPickupTimeSet =false;
        isReturnTimeSet = false;

        loadVehicles(latLng, 0, 0);

        pickupTimeLL.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, DatePickerActivity.class);
                Calendar calendar = Calendar.getInstance();
                intent.putExtra(Constants.MONTH, calendar.get(Calendar.MONTH));
                intent.putExtra(Constants.YEAR, calendar.get(Calendar.YEAR));
                intent.putExtra(Constants.DATE, calendar.get(Calendar.DATE));
                intent.putExtra(Constants.HOUR, calendar.get(Calendar.HOUR_OF_DAY));
                startActivityForResult(intent, REQ_PICKUP_DATE);
            }
        });

        returnTimeLL.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, DatePickerActivity.class);
                if(isPickupTimeSet){
                    intent.putExtra(Constants.YEAR, pickupDate.getYear()+1900);
                    intent.putExtra(Constants.MONTH, pickupDate.getMonth());
                    intent.putExtra(Constants.DATE, pickupDate.getDate());
                    intent.putExtra(Constants.HOUR, pickupDate.getHours());
                } else{
                    Calendar calendar = Calendar.getInstance();
                    intent.putExtra(Constants.MONTH, calendar.get(Calendar.MONTH));
                    intent.putExtra(Constants.YEAR, calendar.get(Calendar.YEAR));
                    intent.putExtra(Constants.DATE, calendar.get(Calendar.DATE));
                    intent.putExtra(Constants.HOUR, calendar.get(Calendar.HOUR_OF_DAY));
                }
                startActivityForResult(intent, REQ_RETURN_DATE);
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == REQ_PICKUP_DATE){
            if(resultCode == Activity.RESULT_OK){
                isPickupTimeSet = true;
                pickupDate = new Date(data.getIntExtra(Constants.YEAR,0)-1900,data.getIntExtra(Constants.MONTH,0),data.getIntExtra(Constants.DATE,0),data.getIntExtra(Constants.HOUR,0),0);
                pickupTimeLabelTV.setTextSize(12);
                pickupTimeTV.setVisibility(View.VISIBLE);
                pickupTimeTV.setText(new SimpleDateFormat("dd MMM\nhh:mm a", Locale.getDefault()).format(pickupDate.getTime()).toUpperCase());
                if(isPickupTimeSet && isReturnTimeSet)
                    loadVehicles(latLng,pickupDate.getTime(),returnDate.getTime());
            }
        } else if(requestCode == REQ_RETURN_DATE){
            if(resultCode == Activity.RESULT_OK){
                isReturnTimeSet = true;
                returnDate = new Date(data.getIntExtra(Constants.YEAR,0)-1900,data.getIntExtra(Constants.MONTH,0),data.getIntExtra(Constants.DATE,0),data.getIntExtra(Constants.HOUR,0),0);;
                returnTimeLabelTV.setTextSize(12);
                returnTimeTV.setVisibility(View.VISIBLE);
                returnTimeTV.setText(new SimpleDateFormat("dd MMM\nhh:mm a",Locale.getDefault()).format(returnDate.getTime()).toUpperCase());
                if(isPickupTimeSet && isReturnTimeSet)
                    loadVehicles(latLng,pickupDate.getTime(),returnDate.getTime());
            }
        }
    }

    public void loadVehicles(final LatLng latLng, final long pickupTime, final long returnTime){
        String url = Urls.BASE_URL + Urls.SEARCH_NEAR
                + "lat=" + latLng.latitude
                + "&lon=" + latLng.longitude
                + "&pickup_time=" + pickupTime
                + "&drop_time=" + returnTime;

        progressBar.setVisibility(View.VISIBLE);

        JsonArrayRequest jsonObjectRequest = new JsonArrayRequest(Request.Method.GET, url, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                try {
                    progressBar.setVisibility(View.GONE);
                    List<Vehicle> vehicleList = new VehicleListParser().parse(response);
                    initListView(vehicleList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                progressBar.setVisibility(View.GONE);
                Log.e("error",error.getMessage());
                Toast.makeText(context, "ERROR", Toast.LENGTH_SHORT).show();
            }
        });

        AppController.getInstance().addToRequestQueue(jsonObjectRequest);

        /*new AsyncTask<Void,Void,List<Vehicle>>(){
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressBar.setVisibility(View.VISIBLE);
            }

            @Override
            protected List<Vehicle> doInBackground(Void... params) {
                return new ServerRequests().searchVehicles(latLng,pickupTime,returnTime);
            }

            @Override
            protected void onPostExecute(List<Vehicle> vehicleList) {
                super.onPostExecute(vehicleList);
                if(vehicleList!=null){
                    progressBar.setVisibility(View.GONE);
                    initListView(vehicleList);

                }
            }
        }.execute();*/
    }

    public void initListView(final List<Vehicle> vehicleList){
        adapter = new VehicleAdapter(context,vehicleList);
        bikesListView.setAdapter(adapter);
        bikesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if(isPickupTimeSet && isReturnTimeSet)
                    Intents.openBikeDetailActivity(context,vehicleList.get(position),pickupDate, returnDate);
                if(!isPickupTimeSet && isReturnTimeSet)
                    Intents.openBikeDetailActivity(context,vehicleList.get(position),returnDate,false);
                if(isPickupTimeSet && !isReturnTimeSet)
                    Intents.openBikeDetailActivity(context,vehicleList.get(position),pickupDate,true);
                if(!isPickupTimeSet && !isReturnTimeSet)
                    Intents.openBikeDetailActivity(context,vehicleList.get(position));
            }
        });
    }
}

This is the build.gradle file for app

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultConfig {
        applicationId "in.co.dryve.customer"
        minSdkVersion 17
        targetSdkVersion 23
        multiDexEnabled true
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
        }
    }
    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
}
repositories {
    mavenCentral()
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'junit:junit:4.12'
    compile files('libs/razorpay-android-0.10.0.jar')
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services-maps:8.4.0'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services-maps:8.4.0'
    compile 'com.android.support:design:23.1.1'
    compile 'com.facebook.android:facebook-android-sdk:4.8.1'
    compile 'com.facebook.android:audience-network-sdk:4.8.1'
    compile 'com.android.support:cardview-v7:23.1.1'
    compile 'com.squareup.okhttp:okhttp:2.0.0'
    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.google.android.gms:play-services-auth:8.4.0'
    compile 'com.google.android.gms:play-services:8.4.0'
    compile 'com.android.support:multidex:1.0.1'
    compile 'com.google.android.gms:play-services-ads:8.4.0'
    compile 'com.google.android.gms:play-services-identity:8.4.0'
    compile 'com.google.android.gms:play-services-gcm:8.4.0'
    compile 'com.mcxiaoke.volley:library:1.0.19'
}

apply plugin: 'com.google.gms.google-services'

The app works fine on most devices but crashes on few devices. Here are the logs for the crash.

E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.co.dryve.customer, PID: 19380
java.lang.NoClassDefFoundError: in.co.dryve.customer.fragments.BookNowFragment$3
at in.co.dryve.customer.fragments.BookNowFragment.loadVehicles(BookNowFragment.java:169)
at in.co.dryve.customer.fragments.BookNowFragment.onActivityCreated(BookNowFragment.java:97)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1970)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1092)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5256)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2174)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
at android.app.ActivityThread.access$900(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1213)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5072)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)

Initially I was using OkHttpClient for network calls. The app used to crash while initializing the AsyncTask with the same NoClassDefFoundError. Search for a solution but couldn't find a suitable one. Then I observed that the app crashes during all the network calls with the same error. Then I replaced the AsyncTask with Volley JsonArrayRequest. The app still crashes while initializing the JsonArrayRequest with the same error NoClassDefFOundError.

Can someone help me in resolving this issue?

UPDATE: Later I found that this was not the issue with the AsyncTask or JsonArrayRequest but I was thrown NoClassDefFoundError for all the classes in my app library except for the activities. Some how in some mobiles, class definitions for the classes in the app module were not found. Observed in mobiles like MI 3, MI 4, Google Nexus.


Solution

  • Thanks for your answers. The original reason for the NoClassDefFoundError is I forgot to enable MultiDex by setting

     multiDexEnabled true
    

    in the gradle file as suggested here.