【问题标题】:Is it possible to simulate a GCM receive from the adb shell / am command line? I'm getting an error是否可以从 adb shell / am 命令行模拟 GCM 接收?我收到一个错误
【发布时间】:2014-11-13 22:18:28
【问题描述】:

我正在尝试使用 adb 和命令行来模拟设备正在接收 GCM 推送消息。我试过这个命令来广播 GCM 意图:

adb shell am broadcast -c com.myapp -a com.google.android.c2dm.intent.RECEIVE -e data "SomeData"

这会触发“权限拒绝”日志行:

09-19 12:23:34.820      725-787/? W/BroadcastQueue﹕ Permission Denial: broadcasting Intent { act=com.google.android.c2dm.intent.RECEIVE cat=[com.myapp] flg=0x10 (has extras) } from null (pid=21244, uid=2000) requires com.google.android.c2dm.permission.SEND due to receiver com.myapp/com.google.android.gcm.GCMBroadcastReceiver

我的清单的相关部分:

<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application>
<receiver
    android:name="com.google.android.gcm.GCMBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="com.myapp" />
    </intent-filter>
</receiver>
</application>

有什么想法吗?

编辑/澄清:推送/GCM接收生产中的作品。我正在寻找一种更简单的方法来测试更改。

【问题讨论】:

  • 如何添加多个键值或一个意图

标签: android


【解决方案1】:

您需要删除接收者定义中的 permission 属性,如下所示:

<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application>
<receiver
    android:name="com.google.android.gcm.GCMBroadcastReceiver" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="com.myapp" />
    </intent-filter>
</receiver>
</application>

【讨论】:

  • 有效!我误解了那个许可。有了那个参数,我们只想要来自具有 SEND 权限的活动的消息 - 命令行工具没有。不确定我是否希望在生产中使用它,但也许我可以只为 Debug 构建定制清单
【解决方案2】:

比暂时编辑 AndroidManifest.xml 删除权限检查,并记得稍后恢复它,您可以在调试版本中自动禁用权限检查。

为此,请通过Manifest Merger 占位符设置属性:

<receiver
  android:name="com.google.android.gcm.GCMBroadcastReceiver"
  android:permission="${gcmPermissionRequired}">

然后在build.gradle中设置占位符:

buildTypes {
    debug {
        ...
        manifestPlaceholders = [gcmPermissionRequired: ""] // "" => let the GCM BroadcastReceiver accept Intents from 'adb shell am broadcast'
    }
    release {
        ...
        manifestPlaceholders = [gcmPermissionRequired: "com.google.android.c2dm.permission.SEND"]
    }
}

(注意:之前我使用debug & release字符串资源。事实证明,如果应用定义了使用字符串资源的intent filter权限,Play商店会拒绝该应用。)

【讨论】:

  • 如果负载数据是 JSON 格式,那么在 adb shell am broadcast 命令中正确引用它是一个难题。请参阅stackoverflow.com/a/29428061/1682419 以获得解决方案。
  • 由于 Play 商店不接受字符串资源技术,我将其更改为使用 Manifest Merger 占位符。
【解决方案3】:

我建议使用命令行 curl,因为发送 GCM 推送就像调用一些 REST API 一样简单。请参阅下面的示例 shell 脚本:

#!/bin/bash

REGISTRATION_ID=YOUR_GCM_REGISTRATION_ID

SERVER_KEY=YOUR_SERVER_KEY_FROM_GOOGLE_API_CONSOLE

curl --header "Authorization: key=$SERVER_KEY" --header  Content-Type:"application/json"  https://android.googleapis.com/gcm/send  -d  "{ \"data\" : {\"foo\": \"bar\"}, \"registration_ids\":[\"$REGISTRATION_ID\"]  }"

【讨论】:

  • 很棒的提示!一个小补充,您从“GoogleCloudMessaging.getInstance(context).register(...)”获取应用程序中的 YOUR_GCM_REGISTRATION_ID
  • 我决定再写几句话,适用于 iOS 和 Android:codingfingers.com/testing-push-notifications-on-ios-and-android
  • 这是一个很好的解决方案,但不是最优的。如果您离线怎么办?或者,如果您希望它在构建服务器上作为集成测试运行并且不希望服务器密钥存储在那里怎么办?
  • 我明白你的意思,但我没有看到更好的解决方案 - 但是,你可以尝试添加第二个接收器(可能仅在某些 gradle 构建变体中公开)并使用它来向 GCMIntentService 传递消息。仍然 - 不完美,但只允许您测试如何处理推送。
【解决方案4】:
  1. 先安装adb。

sudo apt-get install adb

  1. 从 manifest.xml 中删除 SEND 权限。

android:permission="com.google.android.c2dm.permission.SEND" >

  1. 从 shell 推送通知的命令

adb shell am 广播 -c com.myapp -a com.google.android.c2dm.intent.RECEIVE -e 数据“SomeData”

  1. 根据需要更改包名称 (com.myapp) 和“SomeData”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-01
    • 2022-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多