android – java.lang.NoClassDefFoundError: java.util.Objects-ThrowExceptions

Exception or error:

I’m getting the following crash report in Android development Console.
My app runs fine on the simulator or devices that I tried the app on, but for some reason on a Galaxy Nexus (Maguro) it doesn’t run. I don’t get any compile errors either.

java.lang.NoClassDefFoundError: java.util.Objects
    at com.nivelsonic.nivelsonic.MyTankActivity$5.onResponse(MyTankActivity.java:199)
    at com.nivelsonic.nivelsonic.MyTankActivity$5.onResponse(MyTankActivity.java:160)
    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
    at android.os.Handler.handleCallback(Handler.java:730)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5103)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)

MyTankActivity.java

public void drawTankStatus() {
        tankView = (TankView) this.findViewById(R.id.vMyTank);
        tvLocation = (TextView) this.findViewById(R.id.tvLocation);
        tvLevel = (TextView) this.findViewById(R.id.tvLevel);
        ivRssi = (ImageView) this.findViewById(R.id.ivRssi);
        ivSettings = (ImageView) this.findViewById(R.id.ivSettings);
        ivAlert = (ImageView) this.findViewById(R.id.ivAlert);

        final Response.Listener<String> responseListener = new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                try {

                    JSONObject jsonResponse = new JSONObject(response);
                    //int success = jsonResponse.getInt("success");
                    JSONArray tank_data = jsonResponse.getJSONArray("tank_data");

                    if (tank_data.length() > 0) {

                        int i;
                        for (i = 0; i < tank_data.length(); i++) {
                            //Log.v("Result--", "" + tank_data.getString(i));

                            JSONObject tankObj = tank_data.getJSONObject(0);

                            location = (String) tankObj.getString("Location");
                            color = (String) tankObj.getString("Color");
                            level = (int) tankObj.getInt("CurrentLevel");
                            rssi = (int) tankObj.getInt("RSSI");
                            phone = (String) tankObj.getString("Phone");
                            status = (int) tankObj.getInt("Status");

                            Integer numOfNotifications = tankObj.getInt("NumberOfNotifications");

                            if (numOfNotifications > 0) {
                                ivAlert.setImageResource(R.drawable.alert_red);
                            } else {
                                ivAlert.setImageResource(R.drawable.alert);
                            }

                            tvLocation.setText(location);

                            if (level <= 55) {
                                tvLevel.setTextColor(Color.parseColor("#064e7b"));
                            } else {
                                // colo rvariable gets set from a value calculated in A_get_tanks.php
                                if (Objects.equals("#FFFFAD", color)) {
                                    tvLevel.setTextColor(Color.parseColor("#064e7b"));
                                } else {
                                    tvLevel.setTextColor(Color.parseColor("#FFFFFF"));
                                }
                            }

                            String levelPercent = Integer.toString(level);

                            tvLevel.setText(levelPercent + "%");

                            if (status != 0) {
                                switch (rssi) {
                                    case 0:
                                        ivRssi.setImageResource(R.drawable.rssi0);
                                        break;
                                    case 1:
                                        ivRssi.setImageResource(R.drawable.rssi1);
                                        break;
                                    case 2:
                                        ivRssi.setImageResource(R.drawable.rssi2);
                                        break;
                                    case 3:
                                        ivRssi.setImageResource(R.drawable.rssi3);
                                        break;
                                    case 4:
                                        ivRssi.setImageResource(R.drawable.rssi4);
                                        break;
                                    case 5:
                                        ivRssi.setImageResource(R.drawable.rssi5);
                                        break;
                                }
                            } else {
                                ivRssi.setImageResource(R.drawable.disconnected);
                            }

                            tankView.drawLevel(level, color);
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };

        Intent intent = getIntent();
        userid = intent.getStringExtra("userid");
        impid = intent.getStringExtra("impid");

        MyTankRequest myTankRequest = new MyTankRequest(userid, responseListener);
        RequestQueue queue = Volley.newRequestQueue(MyTankActivity.this);
        queue.add(myTankRequest);

        if (ivSettings != null) {
            ivSettings.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Intent settingsIntent = new Intent(MyTankActivity.this, SettingsActivity.class);
                    settingsIntent.putExtra("impid", impid);
                    MyTankActivity.this.startActivity(settingsIntent);
                }
            });
        }
    }
How to solve:

The exception is thrown because all static methods of java.util.Objects are available above API 19 (Android 4.4.+).

As you said in comments, your device has API 10 (Android 2.3.+) so that method doesn’t exist in that Android version and NoClassDefFoundError is thrown.

If you want to check api level programmatically you can do:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // your code available only above api 19
} else {
    // compatibility code
}

###

In my case this exception happened on Android 4 after upgrade to Retrofit 2.7.1.
See https://github.com/square/retrofit/blob/master/CHANGELOG.md:

Version 2.7.0 (2019-12-09)

This release changes the minimum requirements to Java 8+ or Android
5+. See this blog post for more information on the change.

New: Upgrade to OkHttp 3.14.4. Please see its changelog for 3.x.

See also https://github.com/square/retrofit/issues/3201 and https://github.com/square/retrofit/issues/3042.

Retrofit depends on OkHttp that refused pre API 21 support in version 3.13.

So, downgrade Retrofit to 2.6.4 or even before 2.6.0. I checked, it solved the problem. Also downgrade Retrofit Gson converter (com.squareup.retrofit2:converter-gson) to 2.6.4.

Leave a Reply

Your email address will not be published. Required fields are marked *