java.lang.NoClassDefFoundError:com.acme.R$layout引用android库

java.lang.NoClassDefFoundError:com.acme.R$layout引用android库,android,gradle,android-studio,Android,Gradle,Android Studio,我有一个Android库项目,其中包含一个自定义验证器和一个为验证器提供登录屏幕的活动。验证器直接包含在我的主应用程序中时工作正常,但我想将验证器放在一个单独的android库中。当我运行引用此库的主android应用程序项目时,当活动的onCreate方法使用R.layout调用setContentView时,我在该活动的onCreate方法中得到一个“java.lang.NoClassDefFoundError:com.acme.R$layout” 我使用的是android gradle版本

我有一个Android库项目,其中包含一个自定义验证器和一个为验证器提供登录屏幕的活动。验证器直接包含在我的主应用程序中时工作正常,但我想将验证器放在一个单独的android库中。当我运行引用此库的主android应用程序项目时,当活动的onCreate方法使用R.layout调用setContentView时,我在该活动的onCreate方法中得到一个“java.lang.NoClassDefFoundError:com.acme.R$layout”

我使用的是android gradle版本。我已经将这些库发布到本地maven存储库中,主项目似乎正在构建中,没有任何问题。我已经在build/outputs/apk中的debug apk中反编译了class.dex文件,我可以看到库中的R$layout.class文件存在,因此我完全不知道可能是什么问题

以下是实现自定义验证器的服务:

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;
    }
}
}
以下是处理登录的活动:

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
    }
}
}
以下是登录活动的布局xml:

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

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="8dp">
    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>
</FrameLayout>
    final AccountManagerFuture<Bundle> future = accountManager.addAccount(AcmeAuthenticatorService.ACME_ACCOUNT_TYPE, AcmeAuthenticatorService.ACME_ACCESS_TOKEN_TYPE, null, null, this, new AccountManagerCallback<Bundle>() {
        @Override
        public void run(AccountManagerFuture<Bundle> 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);
然后在android应用程序中,我执行以下操作来触发auth活动:

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

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="8dp">
    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>
</FrameLayout>
    final AccountManagerFuture<Bundle> future = accountManager.addAccount(AcmeAuthenticatorService.ACME_ACCOUNT_TYPE, AcmeAuthenticatorService.ACME_ACCESS_TOKEN_TYPE, null, null, this, new AccountManagerCallback<Bundle>() {
        @Override
        public void run(AccountManagerFuture<Bundle> 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);
下面是日志:

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}
更新

我已经创建了一个在github上演示该问题的。有关生成和复制错误的说明,请参阅自述文件。

只要当前的Android Gradle插件(版本0.12.2)没有修复,解决问题的唯一方法就是从
build.Gradle
中删除
应用程序ID

我会更新这篇文章,一旦这个错误被修复


更新:当前版本0.13.3仍然会产生相同的错误

更新
AndroidManifest.xml中的
,以及
build.gradle中的
applicationId
以获得相同的值

请发布您的代码和日志。我已经在问题中添加了代码。我创建了一份错误报告免费添加更多信息感谢您的评论。我从库中删除了应用程序id,解决了这个问题。我会在你的bug报告中添加评论。不客气!谢谢你在错误通知单上的评论!我会在这里留下一条评论,如果这个bug已经修复,如果你在用gradle构建的子项目中遇到这个问题,你需要从该子项目的
build.gradle
中删除
applicationId
。(即,在根项目的
build.gradle
中找不到它)
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}