Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inflating TextView throwing noSuchMethodException on method addFontWeightStyle() during inflate process

Update: I've changed the title to remove the indication that ExoPlayer has anything to do with what is going on as I've managed to duplicate this without it being used at all.

I decided to try and isolate this error on API levels:

I obtained an older Samsung tablet (Tab S2) running Android 7.0 (Api 24), and the error does not occur there.

I am not able to duplicate this problem on a Nexus 6 emulator using API 25

I also tried on a newer Samsung tablet (Tab S3) running Android 8.0.0 (Api 26), the same version as on the Samsung S7 Edge phone. I got the same error.

I then created a new emulator (Pixel 2 XL) running Api 26 (Oreo 8.0.0) and ran the software and got the same error.

I then created a new emulator (Pixel XL) running Api 27 (Oreo 8.1) and ran the software and got the same error.

Lost of frustration trying to verify this on Android 9 - got errors on download of the bundle, Googled to find out many people had to run as Administrator in order to solve this, did that, copied the downloads over to the SDK location I'm using with my normal login, re-started Android under my normal login, patched the SDK per prompt from Studio, and defined an emulator using 9. Got the same error.

Interestingly, in the stack trace using Pie, I got a different line number for where the fail happens in TypefaceCompat - line 47 this time which is at least on the instancing of the relevant class (TypefaceCompatApi28Impl). However then stacktrace is still showing Api21Impl throwing the error. Examining Api28Impl shows me it extends Api26Impl which extends Api21Impl. So it looks like this is simply a matter of the tag not getting reported correctly. Api21Impl is the base class and so that's what is getting reported out.

It still doesn't explain why the error is happening nor what to do about it.

So it would appear at least from this limited testing that there is some issue introduced with Oreo 8.0 that also exists in all SDK's thereafter.

What to do about it?

Update: Some other odd things - my Samsung is API 26 (8.0.0), yet the stack trace below shows Android is attempting to utilize TypefaceCompatApi21Impl:

at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)

That line of code in TypefaceCompatApi21Impl looks like this:

        try {
            fontFamilyClass = Class.forName(FONT_FAMILY_CLASS);
            fontFamilyCtor = fontFamilyClass.getConstructor();
error here--->            addFontMethod = fontFamilyClass.getMethod(ADD_FONT_WEIGHT_STYLE_METHOD,
                     String.class, Integer.TYPE, Boolean.TYPE);

What's odd about this is that further down the stacktrace we see how the *Impl class gets initialized:

The AppCompatTextView.setTypeface() method is called (line 576) This in turn causes a typeface to get created:

finalTypeface = TypefaceCompat.create(getContext(), tf, style);

When the static method create() is called, this in turn causes a static initializer to be run:

public class TypefaceCompat {
    private static final TypefaceCompatBaseImpl sTypefaceCompatImpl;
    static {
        if (Build.VERSION.SDK_INT >= 28) {
            sTypefaceCompatImpl = new TypefaceCompatApi28Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            sTypefaceCompatImpl = new TypefaceCompatApi26Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
                && TypefaceCompatApi24Impl.isUsable()) {
            sTypefaceCompatImpl = new TypefaceCompatApi24Impl();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            sTypefaceCompatImpl = new TypefaceCompatApi21Impl();
        } else {
            sTypefaceCompatImpl = new TypefaceCompatBaseImpl();
        }
    }

This line in the stacktrace:

at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)

is actually the line initializing TypefaceCompatApi26Impl(), which would suggest that TypefaceCompatApi26Impl should be used (which makes sense given the API level of my Samsung hardware) and yet the stacktrace shows TypefaceCompatApi21Impl() throwing the error!

How is that possible?

The other clue in here is that a static initializer only runs once. Since I am getting this only after I launch the detail layout (but there are other layouts that also have TextView components on them that appear prior to this), there has to be something associated with this layout that is somehow different. Here are the first few components (up to the first definition of a TextView component) in the layout:

<?xml version="1.0" encoding="utf-8"?>
<!-- This layout is used by PlaylistDetailFragment -->
<androidx.constraintlayout.widget.ConstraintLayout
    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:id="@+id/item_listitem_constraint_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Layout related to Playlist 'Header' -->
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.25"
        android:orientation="vertical" />

    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.80"
        android:orientation="vertical" />

    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.90"
        android:orientation="vertical" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/item_list_content_image"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:layout_marginStart="16dp"
        android:layout_marginTop="4dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/playlist"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/guideline1"
        app:layout_constraintBottom_toBottomOf="@+id/playlist_detail_description"/>

    <TextView
        android:id="@+id/playlist_detail_list_content_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:text="@string/playlist_title_label"
        android:textAppearance="@android:style/TextAppearance.Material.Small"
        app:layout_constraintTop_toTopOf="@+id/playlist_detail_title"
        app:layout_constraintBottom_toBottomOf="@+id/playlist_detail_title"
        app:layout_constraintRight_toRightOf="@+id/playlist_detail_list_content_description"/>

I thought perhaps the android:textAppearance="@android:style/TextAppearance.Material.Small" line in the TextView definition was causing an issue for some reason, but removing it had no effect - same error is happening.

Update 2/15/19: This just happened again, this time on the same Samsung device where it didn't happen previously, with a completely different layout which doesn't use ExoPlayer at all and in fact just uses stock widgets. In the stack trace below, this line:

at com.reddragon.cloudframe.PlaylistDetailFragment.onCreateView(PlaylistDetailFragment.java:309)

is where I'm inflating a layout:

final View rootView = inflater.inflate(R.layout.playlist_detail, container, false);

The layout includes very standard items (TextView, RecyclerView, Guidelines) etc. Here is the full stack trace:

2019-02-15 06:31:12.287 10895-10895/com.reddragon.cloudframe E/TypefaceCompatApi21Impl: java.lang.NoSuchMethodException
    java.lang.NoSuchMethodException: addFontWeightStyle [class java.lang.String, int, boolean]
        at java.lang.Class.getMethod(Class.java:2068)
        at java.lang.Class.getMethod(Class.java:1690)
        at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)
        at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)
        at androidx.core.graphics.TypefaceCompat.create(TypefaceCompat.java:190)
        at androidx.appcompat.widget.AppCompatTextView.setTypeface(AppCompatTextView.java:576)
        at androidx.appcompat.widget.AppCompatTextHelper.loadFromAttributes(AppCompatTextHelper.java:217)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:93)
        at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:182)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1267)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1317)
        at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:189)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at com.reddragon.cloudframe.PlaylistDetailFragment.onCreateView(PlaylistDetailFragment.java:309)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2530)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:887)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1233)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1299)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:688)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2069)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1859)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1814)
        at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1691)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:537)
        at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:170)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
        at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:23297)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6928)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:733)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:95)
        at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1556)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:803)
        at android.view.View.measure(View.java:23297)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6928)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)

Any ideas at all? This is very strange, and extremely frustrating!

It seems that it fails on the first TextView that it tries to inflate, but I can't figure out why this error is occurring. I'm using the same TextView widgets in other layouts of this app, they inflate just fine!

Update 2/13/19: when Googling around for similar issues I found this post. Because it mentioned different behavior on emulator vs. physical, I tested my issue on a physical device (Samsung 7 Edge, Android 8.0.0) and voila - no problem.

EDIT 2/16/19 - but now see comments at the top of this post. I don't know why it didn't happen on my initial test that I describe here I did on 2/13, but the issue is "back" on the Samsung 7 Edge running API 26.

I deleted the previous emulator (Nexus 5, API 27), and created a new one (Nexus 6, API 25) and....no error! Strange, but somehow the emulator got confused I suppose... Still would be good to understand how to troubleshoot these kinds of things faster.

=================================

I have been working on an app (MediaPlayerActivity) using the latest Exoplayer (2.9.5), and have just recently started getting errors when trying to inflate the stock views:

2019-02-12 21:36:43.339 25761-25761/E/TypefaceCompatApi21Impl: java.lang.NoSuchMethodException
    java.lang.NoSuchMethodException: addFontWeightStyle [class java.lang.String, int, boolean]
        at java.lang.Class.getMethod(Class.java:2068)
        at java.lang.Class.getMethod(Class.java:1690)
        at androidx.core.graphics.TypefaceCompatApi21Impl.<clinit>(TypefaceCompatApi21Impl.java:74)
        at androidx.core.graphics.TypefaceCompat.<clinit>(TypefaceCompat.java:49)
        at androidx.core.graphics.TypefaceCompat.create(TypefaceCompat.java:190)
        at androidx.appcompat.widget.AppCompatTextView.setTypeface(AppCompatTextView.java:576)
        at androidx.appcompat.widget.AppCompatTextHelper.loadFromAttributes(AppCompatTextHelper.java:217)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
        at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:93)
        at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:182)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1267)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1317)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.parseInclude(LayoutInflater.java:995)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:859)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at com.google.android.exoplayer2.ui.PlayerControlView.<init>(PlayerControlView.java:296)
        at com.google.android.exoplayer2.ui.PlayerView.<init>(PlayerView.java:452)
        at com.google.android.exoplayer2.ui.PlayerView.<init>(PlayerView.java:304)
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at android.view.LayoutInflater.createView(LayoutInflater.java:647)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at MediaPlayerActivity$MediaPagerAdapter.instantiateItem(MediaPlayerActivity.java:676)

I'm using the standard stock ExoPlayer views - nothing custom:

Layout from pager_video_item.xml:

<!-- Video Player  -->
<com.google.android.exoplayer2.ui.PlayerView
    android:id="@+id/video_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"/>

Code from which the error begins, which is in a PagerAdapter instance:

        case Media.MEDIA_TYPE_VIDEO:
            itemView = mLayoutInflater.inflate(R.layout.pager_video_item, container, false);

mLayoutInflater is initialized in the PagerAdapter constructor:

class MediaPagerAdapter extends PagerAdapter {

    final Context mContext;
    final LayoutInflater mLayoutInflater;

    MediaPagerAdapter(Context context) {
        mContext = context;
        mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

The context passed is from my MediaPlayerActivity class, which extends androidx.appcompat.app.AppCompatActivity (CFViewPager extends ViewPager, and just adds some logic to handle dispatching touch events appropriately.):

mViewPagerView = findViewById(R.id.activity_media_player_viewpager);
((CFViewPager) mViewPagerView).setAdapter(new MediaPagerAdapter(this));

I can build and run the ExoPlayer demo on my same machine and it works. So clearly I've changed some setting in my app that is confusing the runtime. Again, this used to work perfectly a couple days back.

I've poured over the version control diffs and can't see anything I've introduced that might cause this behavior.

From the stack trace, it looks like it is failing when trying to inflate a TextView in the PlayerControlView. But I don't know how to troubleshoot.

What would cause runtime to think "all of a sudden" that it can't use reflection to find the addFontWeightStyle() method in TypefaceCompatApi21Impl.java?

Android Studio is the latest stable release (3.3.1) I believe my gradle files are up to date:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

compileSdkVersion 28
defaultConfig {
    applicationId "mycoolapp.com"
    minSdkVersion 21
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"

Build tools is set to 28.0.3

I have invalidated caches and restarted, rebuilt, etc.

Thanks for any thoughts about where to look to troubleshoot.

like image 415
tfrysinger Avatar asked Feb 13 '19 05:02

tfrysinger


People also ask

What is a nosuchmethodexception?

And What About NoSuchMethodException? NoSuchMethodException is related to NoSuchMethodError, but occurs in another context. While a NoSuchMethodError occurs when some JAR file has a different version at runtime that it had at compile time, a NoSuchMethodException occurs during reflection when we try to access a method that does not exist.

What is inflate in Android Studio?

Android - Inflate (a layout XML to a view UI object) 1 About. In this context, Inflate means reading a layout XML (often given as parameter) to translate them in Java code. 2 Articles Related 3 Inflate. setContentView method of an activity. The inflate method inflates the View hierarchy and binds to it all it one step. 4 Documentation / Reference

What is the use of the inflate method?

The inflate method inflates the View hierarchy and binds to it all it one step. The layout file activity_main.xml:

Are You misusing layoutinflater’s inflate () method?

Upon looking for clarification in Google documentation and discussion on the rest of the web, I noticed that many others were not only unsure of the specifics of LayoutInflater’s inflate () method, but were completely misusing it.


1 Answers

This is a bug already reported to the Android team, and seems to be a fix in place ready for a future release:

https://issuetracker.google.com/issues/124274577

I'm guessing they are referring to a future release of the AndroidX library.

like image 55
PerracoLabs Avatar answered Nov 07 '22 10:11

PerracoLabs