Я следовал этому codelab о Материальных Компонентах, и после его завершения я подумал, что мне следует потренироваться в написании некоторых тестов инструментовки. Приложение работает отлично. Но я получаю эту ошибку, когда запускаю любой из тестов:
java.lang.RuntimeException: android.view.InflateException: Binary XML file line #37: Binary
XML file line #37: Error inflating class
com.google.android.material.textfield.TextInputLayout
at androidx.test.runner.MonitoringInstrumentation.runOnMainSync(MonitoringInstrumentation.java:450)
at androidx.test.core.app.ActivityScenario.onActivity(ActivityScenario.java:564)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:300)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
at com.google.codelabs.mdc.kotlin.shrine.LoginFragmentTest.username_and_password_editTexts_visible(LoginFragmentTest.kt:64)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1941)
Caused by: android.view.InflateException: Binary XML file line #37: Binary XML file line #37: Error inflating class com.google.android.material.textfield.TextInputLayout
Caused by: android.view.InflateException: Binary XML file line #37: Error inflating class com.google.android.material.textfield.TextInputLayout
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:861)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at com.google.codelabs.mdc.kotlin.shrine.LoginFragment.onCreateView(LoginFragment.kt:19)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:317)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:301)
at androidx.test.core.app.ActivityScenario.lambda$onActivity$2$ActivityScenario(ActivityScenario.java:551)
at androidx.test.core.app.ActivityScenario$$Lambda$4.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1959)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6236)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:248)
at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:222)
at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:150)
at com.google.android.material.internal.ThemeEnforcement.obtainTintedStyledAttributes(ThemeEnforcement.java:120)
at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:424)
at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:396)
... 38 more
Test running failed: Instrumentation run failed due to 'Process crashed.'
Мои зависимости gradle:
dependencies {
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:core:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:runner:1.3.0-alpha04'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha04'
debugImplementation ('androidx.fragment:fragment-testing:1.2.2'){
exclude group: 'androidx.test', module : 'core'
}
}
Я пытался изменить версию зависимости материала, но без удачи.
Файл моих стилей :
<style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
Фрагмент Файл макета:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/loginPageBackgroundColor"
tools:context=".LoginFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="24dp"
android:paddingTop="16dp">
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="48dp"
android:layout_marginBottom="16dp"
app:srcCompat="@drawable/shr_logo"
android:contentDescription="@string/shr_logo_content_description" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="132dp"
android:text="@string/shr_app_name"
android:textAllCaps="true"
android:textSize="16sp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:hint="@string/shr_hint_username"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/username_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_password"
app:errorEnabled="true"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:inputType="textPassword"
>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/next_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text = "@string/shr_button_next"
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:layout_toStartOf="@id/next_button"
android:layout_toLeftOf="@id/next_button"
android:text="@string/shr_button_cancel"
style="@style/Widget.MaterialComponents.Button.TextButton"
/>
</RelativeLayout>
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>
Код в строке 37 находится первый TextInputLayout
Фрагмент реализации:
import android.os.Bundle
import android.text.Editable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.shr_login_fragment.*
import kotlinx.android.synthetic.main.shr_login_fragment.view.*
class LoginFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.shr_login_fragment, container, false)
view.next_button.setOnClickListener {
if(isPasswordValid(password_edit_text.text)){
view.password_text_input.error = null
// the false so as to not return back to the login screen again
(activity as NavigationHost).navigateTo(ProductGridFragment(),false)
}else{
view.password_text_input.error = getString(R.string.shr_error_password)
}
}
view.password_edit_text.setOnKeyListener { _, _, _ ->
if(isPasswordValid(password_edit_text.text)){
view.password_text_input.error = null
}
false
}
view.cancel_button.setOnClickListener {
view.password_edit_text.setText("")
view.username_edit_text.setText("")
}
return view
}
private fun isPasswordValid(text: Editable?): Boolean{
return text!=null && text.length >= 8
}
}