title: java.lang.NoClassDefFoundError: com.acme.R$layout referencing android library
body: <p>I have an Android library project with a custom authenticator and an Activity that provides a login screen for the authenticator. The authenticator works fine when included directly in my main app, but I would like to put the authenticator into a separate android library. When I run the main android application project which references this library, I get a 'java.lang.NoClassDefFoundError: com.acme.R$layout' in the Activity's onCreate method when it calls setContentView with the R.layout. </p>
  
  <p>I am using an android gradle build. I have published the libraries to a local maven repository and the main project seems to be building without any issues. I have decompiled the class.dex file in the debug apk in build/outputs/apk and I can see that the R$layout.class file from the library is present, so I am at a complete loss as to what might be the problem.</p>
  
  <p>Here is the service which implements the custom authenticator:</p>
  
  <pre><code>public class AcmeAuthenticatorService extends Service {
  
  public static final String ACME_ACCOUNT_TYPE = "acme-oauth";
  public static final String ACME_ACCESS_TOKEN_TYPE = "acme-oauth-access-token";
  
  
  private static Authenticator authenticator;
  
  private Authenticator getAuthenticator() {
      if (authenticator == null)
          authenticator = new Authenticator(this);
      return authenticator;
  }
  
  @Override
  public IBinder onBind(Intent intent) {
      if (intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT))
          return getAuthenticator().getIBinder();
      return null;
  }
  
  private static class Authenticator extends AbstractAccountAuthenticator {
      private final Context context;
  
      Authenticator(Context ctx) {
          super(ctx);
          this.context = ctx;
      }
  
      @Override
      public Bundle addAccount(AccountAuthenticatorResponse response,
                               String accountType,
                               String authTokenType,
                               String[] requiredFeatures,
                               Bundle options) throws NetworkErrorException {
          return makeAuthIntentBundle(response, options);
      }
  
      private Bundle makeAuthIntentBundle(AccountAuthenticatorResponse response, Bundle options) {
          Bundle reply = new Bundle();
          Intent i = new Intent(context, AcmeAccountAuthenticatorActivity.class);
          i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
          i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
          if (options != null)
              i.putExtras(options);
          reply.putParcelable(AccountManager.KEY_INTENT, i);
          return reply;
      }
  
      @Override
      public Bundle getAuthToken(AccountAuthenticatorResponse response,
                                 Account account,
                                 String authTokenType,
                                 Bundle options) throws NetworkErrorException {
          return null;
      }
  
      @Override
      public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
          return null;
      }
  
      @Override
      public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
          return null;
      }
  
      @Override
      public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
          return null;
      }
  
      @Override
      public String getAuthTokenLabel(String authTokenType) {
          return null;
      }
  
      @Override
      public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
          return null;
      }
  }
  }
  </code></pre>
  
  <p>Here is the Activity which handles login:</p>
  
  <pre><code>import com.acme.R;
  
  public class AcmeAccountAuthenticatorActivity extends AccountAuthenticatorActivity {
  private AccountManager accountManager;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      //NoClassDefFoundError occurs for this line
      setContentView(R.layout.activity_account_auth);
  
      accountManager = AccountManager.get(this);
  
      WebView webview = (WebView)findViewById(R.id.web_view);
      WebSettings webSettings = webview.getSettings();
      webSettings.setJavaScriptEnabled(true);
      if ( webview == null ) {
          Log.e("TAG", "Web view not found!!");
      } else {
          //Do authentication
      }
  }
  }
  </code></pre>
  
  <p>Here is the layout xml for the login activity:</p>
  
  <pre><code>&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/container"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.acme.AcmeAccountAuthenticatorActivity"
  tools:ignore="MergeRootFrame" &gt;
  
  &lt;LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:padding="8dp"&gt;
      &lt;WebView
          android:id="@+id/web_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          /&gt;
  &lt;/LinearLayout&gt;
  &lt;/FrameLayout&gt;
  </code></pre>
  
  <p>In the applications section of the manifest for the library I have:</p>
  
  <pre><code>    &lt;activity android:name="com.acme.AcmeAccountAuthenticatorActivity"
          android:label="Login"&gt;
      &lt;/activity&gt;
  
      &lt;service android:name="com.acme.AcmeAuthenticatorService"
               android:permission="com.acme.AUTHENTICATE_ACME_ACCOUNTS"&gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.accounts.AccountAuthenticator"/&gt;
          &lt;/intent-filter&gt;
          &lt;meta-data android:name="android.accounts.AccountAuthenticator"
              android:resource="@xml/authenticator"/&gt;
      &lt;/service&gt;
  </code></pre>
  
  <p>And the build.gradle for the library:</p>
  
  <pre><code>buildscript {
      repositories {
          jcenter()
          mavenCentral()
      }
      dependencies {
          classpath 'com.android.tools.build:gradle:0.12.+'
      }
  }
  
  apply plugin: 'com.android.library'
  apply plugin: 'maven-publish'
  
  version '1.0-SNAPSHOT'
  group 'com.acme'
  
  repositories {
      mavenLocal()
      mavenCentral()
  }
  
  android {
      compileSdkVersion 19
      buildToolsVersion "20.0.0"
  
      defaultConfig {
          applicationId "com.acme.test"
          minSdkVersion 16
          targetSdkVersion 19
      }
  
      buildTypes {
          release {
              runProguard false
              proguardFiles getDefaultProguardFile('proguard-project.txt'), 'proguard-rules.txt'
          }
      }
  }
  
  dependencies {
      compile 'com.android.support:support-v4:19.0.0'
      compile 'com.android.support:appcompat-v7:19.0.0'
  }
  
  def getArtifactFullPath() {
      return "${buildDir}/outputs/aar/${project.name}-${project.version}.aar"
  }
  
  android.libraryVariants
  publishing {
      publications {
          maven(MavenPublication) {
              artifact getArtifactFullPath()
          }
      }
  }
  </code></pre>
  
  <p>Then in the android application I do the following to trigger the auth activity:</p>
  
  <pre><code>    final AccountManagerFuture&lt;Bundle&gt; future = accountManager.addAccount(AcmeAuthenticatorService.ACME_ACCOUNT_TYPE, AcmeAuthenticatorService.ACME_ACCESS_TOKEN_TYPE, null, null, this, new AccountManagerCallback&lt;Bundle&gt;() {
          @Override
          public void run(AccountManagerFuture&lt;Bundle&gt; future) {
              try {
                  Bundle bnd = future.getResult();
                  showMessage("Account was created");
                  Log.d("acme", "AddNewAccount Bundle is " + bnd);
  
              } catch (Exception e) {
                  e.printStackTrace();
                  showMessage(e.getMessage());
              }
          }
      }, null);
  </code></pre>
  
  <p>Here is the build.gradle for the android application:</p>
  
  <pre><code>buildscript {
      repositories {
          jcenter()
          mavenCentral()
      }
      dependencies {
          classpath 'com.android.tools.build:gradle:0.12.+'
      }
  }
  
  apply plugin: 'com.android.application'
  apply plugin: 'maven'
  
  repositories {
      mavenLocal()
      mavenCentral()
  }
  
  android {
      compileSdkVersion 19
      buildToolsVersion '20.0.0'
  
      defaultConfig {
          applicationId "com.acme.myapp"
          minSdkVersion 16
          targetSdkVersion 19
      }
  
      buildTypes {
          release {
              runProguard false
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
          }
      }
  }
  
  dependencies {
      compile 'com.acme:acme-auth:1.0-SNAPSHOT'
      compile 'com.android.support:support-v4:19.+'
      compile 'com.android.support:appcompat-v7:19.+'
  }
  </code></pre>
  
  <p>and here is the logcat:</p>
  
  <pre><code>E/AndroidRuntime(27992): FATAL EXCEPTION: mainE/AndroidRuntime(27992): Process: com.acme.myapp, PID: 27992
  E/AndroidRuntime(27992): java.lang.NoClassDefFoundError: com.acme.R$layout
  E/AndroidRuntime(27992):        at com.acme.AcmeAccountAuthenticatorActivity.onCreate(AcmeAccountAuthenticatorActivity.java:29)
  E/AndroidRuntime(27992):        at android.app.Activity.performCreate(Activity.java:5231)
  E/AndroidRuntime(27992):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
  E/AndroidRuntime(27992):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
  E/AndroidRuntime(27992):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
  E/AndroidRuntime(27992):        at android.app.ActivityThread.access$800(ActivityThread.java:135)
  E/AndroidRuntime(27992):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
  E/AndroidRuntime(27992):        at android.os.Handler.dispatchMessage(Handler.java:102)
  E/AndroidRuntime(27992):        at android.os.Looper.loop(Looper.java:136)
  E/AndroidRuntime(27992):        at android.app.ActivityThread.main(ActivityThread.java:5001)
  E/AndroidRuntime(27992):        at java.lang.reflect.Method.invokeNative(Native Method)
  E/AndroidRuntime(27992):        at java.lang.reflect.Method.invoke(Method.java:515)
  E/AndroidRuntime(27992):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
  E/AndroidRuntime(27992):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
  E/AndroidRuntime(27992):        at dalvik.system.NativeStart.main(Native Method)
  W/ActivityManager(  575):   Force finishing activity com.acme.myapp/com.acme.AcmeAccountAuthenticatorActivity
  W/ActivityManager(  575):   Force finishing activity com.acme.myapp/.MainActivity
  W/ActivityManager(  575): Activity pause timeout for ActivityRecord{42071a70 u0 com.acme.myapp/com.acme.AcmeAccountAuthenticatorActivity t75 f}
  </code></pre>
  
  <p><strong>Update</strong></p>
  
  <p>I've created a <a href="https://github.com/kldavis4/android-NoClassDefFoundError-example" rel="noreferrer">sample project</a> that demonstrates the issue on github. Please see the README for instructions on building and reproducing the error.</p>