I have written so many Roboelectric Test Case and everything is working fine, But the layout containing the SearchView the test case fails , I just altered the searchview to AutoCompleteTextView or TextView or Edittext then the test cases passes ,
I want to know the reason or any fixes that we can do ,if layout containing SearchView.
Below is my Simple Code :
#Test
fun `test add new product fragment launched`() {
val scenario = launchFragmentInContainer<AddNewProductFragment>(
fragmentArgs = getAddNewProductDummyArguments()
)
//Getting the Exception Above only ,I have commented the below code and also checked but still same error
scenario.withFragment {
Assert.assertNotNull(getAddNewProductFragmentBinding())
}
}
Xml Containing the SearchView
<androidx.appcompat.widget.SearchView
android:id="#+id/etProductName"
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"/>
Error:
Binary XML file line #79 in com.sit:layout/fragment_add_new_product: Binary XML file line #79 in com.sit:layout/fragment_add_new_product: Error inflating class androidx.appcompat.widget.SearchView
android.view.InflateException: Binary XML file line #79 in com.sit:layout/fragment_add_new_product: Binary XML file line #79 in com.sit:layout/fragment_add_new_product: Error inflating class androidx.appcompat.widget.SearchView
Here Is my Try :
#Test
fun `test add new product fragment launched`() {
val scenario = launchFragmentInContainer<AddNewProductFragment>(
fragmentArgs = getAddNewProductDummyArguments()
)
scenario.withFragment {
Assert.assertNotNull(getAddNewProductFragmentBinding())
}
}
Instead of SearchView used AppCompatAutoCompleteTextView the above test case pass ,no binary inflation, But in my kotlin file I am using SearchView not AppCompatAutoCompleteTextView.Just for testing I did this
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
android:id="#+id/etProductName"
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"/>
Related
I am working on an existing project which uses DrawerLayout and a custom fragment for side navigation, but when I use data binding it gives inflate exception in XML file at <fragment> tag. Below is my code.
activity_home.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="#+id/layoutParent"
layout="#layout/activity_parent_list_new" />
<fragment
android:id="#+id/navigation_view"
android:name="com.myApp.home.fragment.NavigationDrawerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
HomeActivity.java
public class HomeActivity extends AppCompatActivity{
private ActivityHomeBinding binding;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHomeBinding.inflate(getLayoutInflater());
mExitToast = Toast.makeText(this, getString(R.string.press_to_exit), Toast.LENGTH_SHORT);
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_view);
mNavigationDrawerFragment.setupViews();
mNavigationDrawerFragment.setDrawerListener(this);
}
/*Other Code*/
}
Exception stack trace
Process: com.myApp.debug, PID: 18493
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myApp.debug/com.myApp.home.HomeActivity}: android.view.InflateException: Binary XML file line #27 in com.myApp.debug:layout/activity_home: Binary XML file line #27 in com.myApp.debug:layout/activity_home: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3780)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3942)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:109)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2345)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:233)
at android.os.Looper.loop(Looper.java:344)
at android.app.ActivityThread.main(ActivityThread.java:8212)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
Caused by: android.view.InflateException: Binary XML file line #27 in com.myApp.debug:layout/activity_home: Binary XML file line #27 in com.myApp.debug:layout/activity_home: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #27 in com.myApp.debug:layout/activity_home: Error inflating class fragment
Caused by: java.lang.IllegalArgumentException: Binary XML file line #27: Duplicate id 0x7f0a0682, tag null, or parent id 0x7f0a02e9 with another fragment for com.myApp.home.fragment.NavigationDrawerFragment
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:117)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:295)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:274)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1078)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:970)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1132)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1093)
at android.view.LayoutInflater.inflate(LayoutInflater.java:692)
at android.view.LayoutInflater.inflate(LayoutInflater.java:542)
at androidx.databinding.DataBindingUtil.inflate(DataBindingUtil.java:126)
at androidx.databinding.ViewDataBinding.inflateInternal(ViewDataBinding.java:1409)
at com.myApp.databinding.ActivityHomeBinding.inflate(ActivityHomeBinding.java:72)
at com.myApp.databinding.ActivityHomeBinding.inflate(ActivityHomeBinding.java:58)
at com.myApp.home.HomeActivity.onCreate(HomeActivity.java:118)
at android.app.Activity.performCreate(Activity.java:8129)
at android.app.Activity.performCreate(Activity.java:8109)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1344)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3749)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3942)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:109)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2345)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:233)
PS: Code is working fine without Databinding, but when I try to use data binding it gives this error.
Make sure you have correctly implemented data binding in your project by following the instructions in the Android documentation: https://developer.android.com/topic/libraries/data-binding/start
In your XML layout file, remove the tag for your custom fragment and replace it with a tag. This will allow you to include the layout for your fragment within the DrawerLayout, without using a fragment tag.
In your Java code, use the FragmentManager to add your fragment to the DrawerLayout programmatically. This will allow you to use data binding with your custom fragment without causing conflicts.
Make sure you are using the correct data binding syntax in your XML layout file. For example, if you are using a ViewModel to manage the data for your fragment, you should use tags to define the variables in your layout and use the bind: namespace to access them in your layout.
Here is my xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".ui.payment.PaymentPayPal">
<com.paypal.checkout.paymentbutton.PaymentButtonContainer
android:id="#+id/paymentButtonContainer"
android:layout_width="match_parent"
android:layout_height="#dimen/_50dp"
android:layout_margin="#dimen/_30dp"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
My activity class:
class PaymentPayPal : BaseActivity() {
private val YOUR_CLIENT_ID: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment_pay_pal)
}
}
also tried binding nothing happens
build.gradle(app)
minSdk=21
dependencies {
implementation 'com.paypal.checkout:android-sdk:0.8.1'
}
Error message:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.voterswik/com.voterswik.ui.payment.PaymentPayPal}: android.view.InflateException: Binary XML file line #9 in com.voterswik:layout/activity_payment_pay_pal: Binary XML file line #9 in com.voterswik:layout/activity_payment_pay_pal: Error inflating class com.paypal.checkout.paymentbutton.PaymentButtonContainer
First, this error is due to non-reachable class PaymentButtonContainer
This is because it should build a config before its use, so go to paypal docs
https://developer.paypal.com/limited-release/paypal-mobile-checkout/android/
and check whether implemented correctly, is you "implement configuration on a subclass of Application()" which will call at very start of project. To set the configuration
You cannot use constraints in a LinearLayout.
app:layout_constraintTop_toTopOf="parent"
If you remove that line you will be able to run your app.
You may try these steps.
make sure you have the latest implementation
e.g. implementation'com.paypal.checkout:android-sdk:0.8.8'
make your PayPalCheckout.setConfig in the MainActivity
Create a new Activity and put the PaymentButtonContainer on the new activity.xml
The Code A and Code B are from the project https://github.com/android/databinding-samples.
The Code B display an icon based fun popularityIcon(view: ImageView, popularity: Popularity) and works well.
I find that project can still work well even if I rename #BindingAdapter("app:popularityIcon") to #BindingAdapter("myok:popularityIcon"), just like Code C, why?
Code A
object BindingAdapters {
#BindingAdapter("app:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Code B
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginTop="24dp"
android:contentDescription="#string/profile_avatar_cd"
android:minHeight="48dp"
android:minWidth="48dp"
app:layout_constraintBottom_toTopOf="#+id/likes_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed"
app:popularityIcon="#{viewmodel.popularity}"/>
Code C
object BindingAdapters {
#BindingAdapter("myok:popularityIcon")
#JvmStatic fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
...
}
Databinding ignores namespaces. So it removes app: or myok: or anything else. Also, if you put both adapters with the same name but different namespaces, you would get an error telling you that there are more than one adapter for popularityIcon.
You can check the docs for more information.
Note: The Data Binding Library ignores custom namespaces for matching purposes.
you need to update your namespace in your XML were you using this binding.
like below
xmlns:myok="http://schemas.android.com/apk/res-auto"
check below code
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myok="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</androidx.constraintlayout.widget.ConstraintLayout>
I've tried to apply EmojiCompatibility at Notification's RemoteView.
The app crashed when using EmojiTextView at RemoteView(Notification).
<android.support.text.emoji.widget.EmojiTextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
And I also tried another(java code)
EmojiCompat.get().registerInitCallback(new EmojiCompat.InitCallback() {
#Override
public void onInitialized() {
final EmojiCompat compat = EmojiCompat.get();
remoteViews.setTextViewText(R.id.tv_name,
compat.process("item.getEmoticon()");
}
});
How can I use it at RemoteView?
Error code (when applying EmojiTextView at Layout.)
couldn’t inflate view for notification
android.view.InflateException: Binary XML file line #39: Error
inflating class android.support.text.emoji.widget.EmojiTextView
Couldn't expand RemoteViews for: StatusBarNotification
You cannot use emojicompat for remoteviews.
I have this layout test, in my layout menu_item_layout.xml there is an IconTextView with text "{fa-times}". When I try to run the test I get android.view.InflateException.
But if I remove the text "{fa-times}" from IconTextView, the test passed successfully.
MenuItemTest.kt
#RunWith(RobolectricTestRunner::class)
#Config(constants = BuildConfig::class)
class MenuItemLayoutTest {
#Test
fun shouldDisplayCorrectTextViews() {
val layout = RoboLayoutInflater.from(RuntimeEnvironment.application)
.inflate(R.layout.menu_item_layout, MenuItemLayout(RuntimeEnvironment.application, null), true) as MenuItemLayout
assertEquals(layout.itemNameTextView.text,"Item 001")
}
}
menu_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp">
<com.joanzapata.iconify.widget.IconButton
android:id="#+id/minusButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:text="{fa-minus-circle}"
android:textColor="#color/minus_button"
android:textSize="24sp"/>
</RelativeLayout>
My assumption is that the RuntimeEnvironment.application needs to call Iconify.with(FontAwesomeModule()) to load. But I have no clue how to do that. Is it possible to extend RuntimeEnvironment.application of Robolectric?
I'm using robolectric:3.1.2
Notes
The test failed when I run ./gradlew test, but if I run a test on a single file (right clicking the file MenuItemTest.kt and Run) it passed.