Исключение «Попытка чтения из поля int android.content.pm.ApplicationInfo.targetSdkVersion 'для ссылки на пустой объект» - PullRequest
0 голосов
/ 06 ноября 2018

Во время выполнения тестов эспрессо с использованием Mockito, у меня в настоящее время есть проблема, что исключение "Attempt to read from the field 'int android.content.pm.ApplicationInfo.targetSdkVersion' on a null object reference" появляется случайным образом после инициации основного действия.

Это часть инициализации для основного задания:

private MainActivity subject;
SingleActivityFactory<MainActivity> activityFactory =
    new SingleActivityFactory<MainActivity>(MainActivity.class) {
        @Override
        protected MainActivity create(Intent intent) {
            subject = spy(getActivityClassToIntercept());
            return subject;
        }
    };

@Rule public ActivityTestRule<MainActivity> mainActivityRule =
    new ActivityTestRule<>(activityFactory, true, false);

@Before
public void init() {
    mainActivityRule.launchActivity(null);
}

Это исключение:

java.lang.NullPointerException: Attempt to read from field 'int 
android.content.pm.ApplicationInfo.targetSdkVersion' on a null object 
reference
at android.view.View.getLayoutDirection(View.java:10277)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:446)
at android.view.View.measure(View.java:23169)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
at android.view.View.measure(View.java:23169)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
at android.view.View.measure(View.java:23169)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535
Test running failed: Instrumentation run failed due to 'Process crashed.'

Кроме того, logcat аварии:

2018-11-06 15:34:50.391 3299-3299/com.application.android E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.application.android, PID: 3299
java.lang.NullPointerException: Attempt to read from field 'int android.content.pm.ApplicationInfo.targetSdkVersion' on a null object reference
    at android.view.View.getLayoutDirection(View.java:10277)
    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:446)
    at android.view.View.measure(View.java:23169)
    at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)

Проблема здесь в том, что эта проблема не является последовательной - доля отказов составляет около 40%. У кого-нибудь есть идеи по этому вопросу? Кроме того, я должен отметить, что эта проблема не появляется, если активность запускается без шпионажа Activity с использованием Mockito.

Обновление:

Проблема была исправлена ​​путем внесения изменений в класс View.java:

@ResolvedLayoutDir
public int getLayoutDirection() {
    //added check if ApplicationInfo is not null
    if(getContext().getApplicationInfo() == null){
            View v = this;
            Log.i("View id: ", getContext().getString(v.getId()));
            Log.e("Main error", "Bug catched");
    }
    else {
        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
        }
    }
    return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
            PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
}

Можно ли достичь аналогичного результата без изменения системного класса?

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

скорее всего, Context настроен неправильно ...

метод в android.view.View на самом деле выглядит так:

public int getLayoutDirection() {
    return mViewFlags & LAYOUT_DIRECTION_MASK;
}

нет ничего, что использовало бы targetSdkVersion, кроме одного случая:

case R.styleable.View_fadingEdge:
    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
        break;
    }

слишком плохой код теста в неполном - скорее всего, ActivityTestRule неверен; new ActivityTestRule<> выглядит странно без <T> и, скорее всего, должно выглядеть примерно так:

new ActivityTestRule<MainActivity>(getActivityFactory(), true, false);

также mainActivityRule.launchActivity(null); кажется бесполезным.

см. InterceptingActivitySampleTest.java для функционального примера.

только что нашел другой пример, который почти совпадает с примером в вопросе:

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    MainActivity subject;

    SingleActivityFactory<MainActivity> activityFactory = new SingleActivityFactory<MainActivity>(MainActivity.class) {
        @Override
        protected MainActivity create(Intent intent) {
            subject = spy(getActivityClassToIntercept());
            return subject;
        }
    };

    @Rule
    public ActivityTestRule<MainActivity> testRule = new ActivityTestRule<>(activityFactory, true, true);

    @Test
    public void activity_isBeingSpied() {
        verify(subject).setContentView(R.layout.layout_main);
    }
}
0 голосов
/ 12 ноября 2018

Я думаю, что ваша проблема связана с предыдущей проблемой ,

, которые производят похожее поведение при использовании метода getFragmentManager(),

Решение:

используйте взамен getSupportFragmentManager() и расширяйте класс v4.app.Fragment

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...