Search code examples
androidgoogle-mapsmakefilegoogle-play-servicesnoclassdeffounderror

How to solve java.lang.NoClassDefFoundError for com.google.android.gms.R$styleable error?


I use Google Maps in a project and build it with Android.mk. But still (after days of research) cann't figure out how to solve NoClassDefFoundError which crashes the apk in time Google Maps fragment inflation is happen. Can any inside me about a way it have to be solved? Detalization is below.

Google Play Services library is added in the following way:

#Adding classpath to Google Play Services classes
LOCAL_CLASSPATH += $(LOCAL_PATH)/google-play-services_lib/bin/
...
#Google Play Services
LOCAL_STATIC_JAVA_LIBRARIES += google-play-services \
                                google-play-services_lib
...
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += google-play-services:libs/google-play-services.jar \
                                        google-play-services_lib:libs/google-play-services_lib.jar

Build goes fine but application throws runtime error when tries to inflate layout with Google Maps fragment. LogCat:

**java.lang.NoClassDefFoundError**:
java.lang.NoClassDefFoundError: com.google.android.gms.R$styleable
    at com.google.android.gms.maps.GoogleMapOptions.createFromAttributes(Unknown Source)
    at com.google.android.gms.maps.MapFragment.onInflate(Unknown Source)
    at android.app.Activity.onCreateView(Activity.java:4996)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:695)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:769)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
    at com.mapsvisitor.ui.MapsFragment.onCreateView(MapsFragment.java:81)
    ...

Code:

final View layout = inflater.inflate(R.layout.maps_layout, null);

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map_main"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:orientation="vertical">
        <fragment
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.google.android.gms.maps.MapFragment" />
</LinearLayout>

Solution

  • The problem is in that when you use dependency project as a library the generated JAR (google-play-services_lib.jar) is not suitable for independent use (as java static libraries). As solution simple use JAR generated by Eclipse export instead in the following way Export > Java > JAR file with selected src and gen folders to export: enter image description here

    The following snippet helps to define that com.google.android.gms.R and nested classes are unavailable (com.google.android.gms.R$attr, com.google.android.gms.R$color, etc):

    void isClassesAvailable(List<String> classes) {
        for(String cl: classes) {
            try {
                Class.forName(cl);
            }
                catch (ClassNotFoundException e) {
                Log.w(TAG, e.getMessage());
            }
        }
    }
    

    How JAR is packed for dependency project (with src folder classes. See folder "android" below): enter image description here

    How JAR has to be packed for robust static library (with src and gen folder classes. See folders "android" and "com" below): enter image description here

    However before idiomatically right solution which uses Eclipse export light hack becomes the GTD. Simple repacking google-play-services_lib.jar with google-play-services_lib/bin/classes content and previously presented there ones makes all resource's classes available.