Создание уведомления от InstrumentationTestCase

Я хочу протестировать из единичного теста, может ли уведомление воспроизводить пользовательский звук из активов. Тест не предназначен для проверки чего-либо, я написал его как быстрый способ продемонстрировать функцию без загромождения основного кода приложения.

Итак, в тестовом проекте я добавил wav-файл внутри /res/raw . Я буду использовать этот URL-адрес с создателем уведомлений:

 Uri path = Uri.parse("android.resource://<main app package name>/testsound.wav"); 

Этот URL должен работать в соответствии с вопросами, которые я читал в SO. Предположим, что это работает.

Теперь, поскольку я не хотел включать тестовый wav-файл в основную папку проекта /res/raw но в тестовом проекте один, я вынужден сделать мой модульный тест расширенным с InstrumentationTestCase чтобы я мог получить доступ к ресурсам в Тестовый проект.

Вот код:

  NotificationCompat.Builder builder = new NotificationCompat.Builder(getInstrumentation().getContext()); ... builder.setSound(path, AudioManager.STREAM_NOTIFICATION); ... NotificationManager notificationManager = (NotificationManager) getInstrumentation().getContext().getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(NOTIFICATION_ID, builder.build()); 

Вызов notify вызывает следующее исключение:

  java.lang.SecurityException: Calling uid 10198 gave package <main app package name> which is owned by uid 10199 at android.os.Parcel.readException(Parcel.java:1540) at android.os.Parcel.readException(Parcel.java:1493) at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:611) at android.app.NotificationManager.notify(NotificationManager.java:187) at android.app.NotificationManager.notify(NotificationManager.java:140) ... at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1873) 

Я отслеживал это исключение до класса NotificationManagerService :

  void checkCallerIsSystemOrSameApp(String pkg) { int uid = Binder.getCallingUid(); if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) { return; } try { ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo( pkg, 0, UserHandle.getCallingUserId()); if (!UserHandle.isSameApp(ai.uid, uid)) { throw new SecurityException("Calling uid " + uid + " gave package" + pkg + " which is owned by uid " + ai.uid); } } catch (RemoteException re) { throw new SecurityException("Unknown package " + pkg + "\n" + re); } } 

Очевидно, что исключение не имеет никакого отношения к настраиваемому звуку, но с тем фактом, что мы создаем уведомление от InstrumentationTestCase .

Есть ли способ проверить это? Я помню, что создавал уведомления от AndroidTestCase в прошлом, но если я это сделаю, то я не смогу получить доступ к тестовому wav-файлу. Я мог бы создать банку с wav и удалить банку в папке lib тестового проекта, но это будет скрывать файл, а другим программистам может быть трудно найти его, если им нужно будет заменить его в будущем.

На самом деле, я был немного озадачен вопросом. Поэтому я написал небольшой контрольно-измерительный тест.

Для утверждения я пометил тест для работы только с API 23 ( getActiveNotifications недоступен), но он отлично getActiveNotifications для старых API.

Хитрость заключается в использовании getTargetContext() вместо getContext() :

 public final class MainActivityTest extends ActivityUnitTestCase<MainActivity> { public MainActivityTest() { super(MainActivity.class); } @TargetApi(Build.VERSION_CODES.M) public void testSendNotification() { final NotificationManager manager = (NotificationManager) getInstrumentation().getTargetContext().getSystemService(Context.NOTIFICATION_SERVICE); manager.cancel(42); assertEquals(0, manager.getActiveNotifications().length); final NotificationCompat.Builder builder = new NotificationCompat.Builder(getInstrumentation().getTargetContext()); builder.setContentTitle("Notification test") .setAutoCancel(true) .setContentText("Hello, Mister Smith") .setSmallIcon(R.drawable.ic_launcher_notification); manager.notify(42, builder.build()); assertEquals(1, manager.getActiveNotifications().length); } } 

Отлично работает:

Введите описание изображения здесь

Надеюсь, поможет.

Я решил, как заставить звук работать с AndroidTestCase . WAV-файл был добавлен в исходную папку тестового проекта и не был включен в основной проект, как предполагалось.

URL-адрес уведомления был следующим:

 Uri path = Uri.parse("android.resource://<test project package name>/" + R.raw.air_horn); 

И строитель был получен следующим образом:

 NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext());