在Android应用程序中伪造GCM消息

3

背景:

我希望在我的安卓应用程序中轻松模拟接收推送通知的方法。

我使用SNS和GCM发送推送通知,但我不想每次测试接收器处理时都发送真正的通知。

我在主活动中创建了一个“开发菜单”,其中包含“清除缓存”、“伪造服务器错误”等项目,因此我添加了一个“伪造推送通知”项目到该列表中。(仅出现在调试版本中)

这个想法是,当选择菜单项时,我会以编程方式调用onMessageReceived方法来实现GcmListenerService,从而伪造接收到推送通知。

问题

为了访问onMessageReceived方法,我需要访问GcmListenerService,该服务在我的清单文件中定义如下(根据文档):
<service
    android:name=".service.MyGcmListenerService"
    android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
</service>

我尝试使用现有的Dagger2设置将一个实例注入到活动中,但我不知道如何向dagger“提供”正确的实例。
显然,新建一个新的MyGcmListenerService会调用onMessageReceived方法,但是没有应用程序上下文,因此在创建Intent时会出现NPE:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:132)
at android.content.ComponentName.<init>(ComponentName.java:128)at android.content.Intent.<init>(Intent.java:4868)
at uk.co.blah.blah.service.MyGcmListenerService.onMessageReceived(MyGcmListenerService.java:30)
at uk.co.blah.blah.DashboardActivity.onOptionsItemSelected(DashboardActivity.java:297)
at android.app.Activity.onMenuItemSelected(Activity.java:3203)

Dagger提供者:(我不希望它能够工作,因为它不是正确的GcmListenerService)

@Provides
@Singleton
MyGcmListenerService provideMyGcmListenerService() {
    return new MyGcmListenerService();
}

菜单项处理程序:

if (id == R.id.fake_notification) {
        Bundle bundle = new Bundle();
        bundle.putString("message", "Test notification");
        gcmListenerService.onMessageReceived("fakeNotification", bundle);
}

我的GcmListenerService的实现:

public class MyGcmListenerService extends GcmListenerService {

@Override
public void onMessageReceived(String from, Bundle data) {
    String message = data.getString("message");
    Timber.d("From: %s", from);
    Timber.d("Message: %s", message);

    // FIXME Fails here
    Intent notificationAction = new Intent(this, DashboardActivity.class); 

    ... do some other stuff to create the notification

}

}

我认为我可能一直在走错路,因此对于任何其他技术都持开放态度。但请不要建议涉及应用程序外部的选项(如某些虚假服务器之类),因为整个重点是使用仅在应用程序中可用的操作来欺骗应用程序内的通知... 这也很有用,可以向利益相关者演示通知。

在您的主活动中创建一个名为fakeNotification的方法,并将通知构建器代码复制粘贴到onMessageReceived中。然后,在菜单项上点击时调用此方法。 - Deepak John
我可以这样做,但我不是一个热衷于到处复制粘贴代码的人,但是是的,这个建议可行 - 谢谢你的建议 :) - OliverDeLange
2个回答

2

最简单的方法可能是让你的MyGcmListenerService.onMessageReceived调用某个方法,然后你的测试也调用同样的方法。

但如果你真的想要实例化你的MyGcmListenerService,那么你需要遵循启动和连接到Android服务的常规步骤


谢谢John,根据你的第一条建议,我正在重构实际创建通知的部分,将其放入一些辅助类中,并通过onMessageReceived进行调用。 - OliverDeLange

0

为什么这么复杂?你可以保存自己的 registrationId,然后使用它发送通知来测试推送通知是否正常工作。


1
是的,这也可以工作,假设您的意思是从应用程序本身使用GCM API... 但是,我需要设置一个调试HTTP客户端来调用GCM端点,这意味着将主代码库与非生产代码混合在一起。这是我不愿意外部访问应用程序的原因之一。 - OliverDeLange

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接