rekire
rekire

Reputation: 47945

Unit testing: NoSuchMethodError while calling Notification.setLatestEventInfo()

Feel free to improve the title I'm a little uncreative in this special case.

I am implementing a unit test for checking notifications, this is hardly possible I know, but I want to check how far I can automatism it.

I cannot test this simple line of code:

Notification test = new NotificationCompat.Builder(context).build();

The reason is stupid and simple in one. This code here will been executed internally:

public Notification build(Builder b, BuilderExtender extender) {
    Notification result = b.mNotification;
    result.setLatestEventInfo(b.mContext, b.mContentTitle,
            b.mContentText, b.mContentIntent);
    [...]

I'm getting this exception:

Caused by: java.lang.NoSuchMethodError: android.app.Notification.setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V
    at android.support.v4.app.NotificationCompat$NotificationCompatImplBase.build(NotificationCompat.java:479)
    at android.support.v4.app.NotificationCompat$Builder.build(NotificationCompat.java:1561)

It is not hard to guess that the Google guys call here a method which was removed (or more properly annotated with @hide) in the Android Marshmallow SDK. I have verified it that call is missing the the newest documentation, but it was introduced in API 1 AFIK.

How can I work around that?

Things I tried and got stuck:

Upvotes: 2

Views: 754

Answers (1)

rekire
rekire

Reputation: 47945

The solution is easier than expected. I missed that by default Build.VERSION.SDK_INT has the value 0 since it cannot read the real value. So that support library calls it on just that platforms where this method exists.

With the help of this answer. I just had to add this code:

setFinalStatic(Build.VERSION.class.getDeclaredField("SDK_INT"), 23);

And my the codes works.
Well it still crashes somewhere else, but the notification is created. Wohoo!

And the actual function:

public static void setFinalStatic(Field field, Object newValue) throws IllegalAccessException, NoSuchFieldException
{
    field.setAccessible(true);
    // remove final modifier from field
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}

Upvotes: 3

Related Questions