java.lang.NoClassDefFoundError:com.acme.R$layout引用android库
我有一个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文件存在,因此我完全不知道可能是什么问题 以下是实现自定义验证器的服务: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版本
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}