从InstrumentationTestCase创建通知

我想从unit testing中测试通知是否能够从资产中播放自定义声音。 测试并不是为了validation任何东西,我把它写成一种快速的方式来演示一个function而不会混淆主应用程序代码。

所以在测试项目中,我在/res/raw添加了一个wav文件。 我将在通知构建器中使用此URL:

 Uri path = Uri.parse("android.resource:///testsound.wav"); 

该URL应该根据我在SO中阅读的问题工作。 我们假设它有效。

现在因为我不想在主项目的/res/raw文件夹中包含测试wav文件,但是在测试项目中,我不得不从InstrumentationTestCase扩展我的unit testing,以便我可以访问测试项目。

这是代码:

  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调用抛出以下exception:

  java.lang.SecurityException: Calling uid 10198 gave package  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) 

我已将此exception跟踪到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); } } 

显然,exception与自定义声音没有任何关系,但事实是我们正在从InstrumentationTestCase创建通知。

有没有办法测试这个? 我记得过去曾经从AndroidTestCase创建过通知,但如果我这样做,那么我将无法访问测试wav文件。 我可以使用wav创建一个jar并将jar放在测试项目的lib文件夹中,但这会隐藏文件,如果将来需要替换它,其他程序员可能很难find它。

实际上,我对这个问题感到有些困惑。 所以我写了一个小仪器测试。

为了断言,我将测试标记为仅在API 23上运行( getActiveNotifications之前似乎不可用),但它也适用于较旧的API。

诀窍是使用getTargetContext()而不是getContext()

 public final class MainActivityTest extends ActivityUnitTestCase { 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:///" + R.raw.air_horn); 

建造者获得如下:

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