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.
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.