当前位置: 首页 > 知识库问答 >
问题:

关于从C2DM转换为GCM的问题

拓拔玺
2023-03-14

我正在将我的应用程序从C2DM转换为GCM,我有一些问题。

我修改了这里的gcmquickstart示例:

git clone https://github.com/googlesamples/google-services.git

在我的类,扩展应用程序,我有:

public class MyApp extends Application {
    @Override
    public void onCreate() {
          super.onCreate();

      if (this.checkPlayServices()) {
            Intent intent = new Intent(this, RegistrationIntentService.class);
            startService(intent);
      }
      else{             
        Log.e(TAG,"Failed checkforGCM");
      }

     }
}

好的,这将启动服务,并且它将永远运行,或者如果操作系统关闭它,那么操作系统将重新启动它。对吗?

CheckPlayServices()确保这是Android 2.3或更高版本,并且安装了Google Play Services,因为这些是使用GCM的唯一要求。那是正确的吗?

public class RegistrationIntentService  extends IntentService{

private static final String TAG = "RegIntentService";

    public RegistrationIntentService() {
      super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

      try {
        // In the (unlikely) event that multiple refresh operations 
        // occur simultaneously,
        // ensure that they are processed sequentially.

        synchronized (TAG) {
            // [START register_for_gcm]
            // Initially this call goes out to the network to 
            // retrieve the token, 
            // subsequent calls are local.
            // [START get_token]
            InstanceID instanceID = InstanceID.getInstance(this);
            String token = instanceID.getToken(getString(R.string.googleProjectId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

            Log.d(TAG, "GCM Registration Token: " + token);

            /* Store the token */

            // [END register_for_gcm]
        }
      } catch (Exception e) {
        Log.e(TAG, "Failed to complete token refresh", e);
      }
}

}

什么是“GCM注册”?是这样吗

InstanceID instanceID = InstanceID.getInstance(this);

什么“得到代币”?是这样吗

 String token = instanceID.getToken(getString(R.string.googleProjectId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

关于刷新操作的讨论让我有点不安。具体来说,我是否必须定期刷新令牌?如果是,那么在哪里、如何以及哪一个(InstanceID InstanceID或字符串标记)?

好的,GCM会在适当的时候给我发一个新的代币。我所要做的就是随时准备接受并存储它。是这样吗?

如上所示,使用注册意图服务允许我随时接受/存储令牌。那是对的吗?

同步也有点麻烦。这似乎意味着谷歌可以向我发送多个注册令牌。有没有办法触发它,让我看到它对我的应用程序产生更大的影响?

还有什么“后续电话是本地的”?打电话来获取我在这里收到并存储在设备上的令牌?

public class MyInstanceIDListenerService extends InstanceIDListenerService {

    private static final String TAG = "MyInstanceIDLS";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. This call is initiated by the
     * InstanceID provider.
     */
    // [START refresh_token]

    @Override
    public void onTokenRefresh() {
        // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]
}

这是我最困惑的地方。基于阅读代码,我认为这个想法是,如果GCM服务器决定我需要另一个instanceID,那么它将把必要性传达给MyInstanceIDListenerService。此时,MyInstanceIDListenerService将导致注册意图服务运行并获取新的instanceID和令牌。那是正确的吗?

/** Intent Service to handle each incoming GCM message */
public class MyGcmListenerService extends GcmListenerService {  
final static String TAG = "GcmService";

   /**
     * Called when message is received.
     *
     * @param from SenderID of the sender.
     * @param data Data bundle containing message data as key/value pairs.
     *             For Set of keys use data.keySet().
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(String from, Bundle data) {

          //do stuff with data communicated from my server to this app
          //via the GCM registration token received in 
          //RegistrationIntentService. onHandleIntent(Intent intent)
    }
    // [END receive_message]
}

这项服务对我来说是最容易理解的。本练习的全部要点是让GCM为我的应用程序分配一个令牌,我的应用程序将令牌传递给我们的一台服务器,我们的服务器向GCM发送一条消息,告诉它“将此令牌发送给使用此令牌的家伙”,然后按照上述代码到达我的应用程序。对吗?

这是把这一切放在一起的Android清单:

    <!-- [START gcm_receiver] -->
    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="my.package" />
        </intent-filter>
    </receiver>
    <!-- [END gcm_receiver] -->

    <!-- [START gcm_listener] -->
    <service
        android:name="my.package.MyGcmListenerService"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>
    <!-- [END gcm_listener] -->

    <service
        android:name="my.package.MyInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>

    <service
        android:name="my.package.RegistrationIntentService"
        android:exported="false">
    </service>

为什么我必须在MyApp中显式启动注册意图服务:

Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);

而不是其他服务?

共有1个答案

欧阳勇
2023-03-14
if (this.checkPlayServices()) {
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
}

这将启动服务,并且它将永远运行,或者如果操作系统关闭它,那么操作系统将重新启动它。对吗?

不可以。IntentService只有在其在OnHandleContent

确保这是Android 2.3或更高版本,并且安装了Google Play Services,因为这些是使用GCM的唯一要求。那是正确的吗?

是 啊不,你还需要一个网络连接。我喜欢在检查播放服务之前检查网络。

什么是“GCM注册”?是这样吗

InstanceID instanceID = InstanceID.getInstance(this);

什么“得到代币”?是这样吗

 String token = instanceID.getToken(getString(R.string.googleProjectId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

是的。getInstance()将向GCM注册。getToken将向您提供注册到此用户的令牌。

这项服务对我来说是最容易理解的。本练习的全部要点是让GCM为我的应用程序分配一个令牌,我的应用程序将令牌传递给我们的一台服务器,我们的服务器向GCM发送一条消息,告诉它“将此令牌发送给使用此令牌的家伙”,然后按照上述代码到达我的应用程序。对吗?

是啊。差不多吧。

为什么我必须在MyApp中显式启动注册意图服务:

Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);

而不是其他服务?

您在清单中声明了InstanceIDListenerService和GcmListenerService,因为它们需要一直运行。如果你没有注册,那么他们什么也不会做。清单中没有调用注册服务,因为您可能不希望它立即启动。例如,如果你想让你的用户注册你的应用程序,那么一旦认证,你就可以通过启动这项服务来注册gcm。

 类似资料:
  • 场景: 如下图, 红框中的数据是后台传过来的时间, 因为是一串字符串, 在 ts 中我就没办法对这个时间做处理 (例如转成数字、获取年月日等) 对应的 ts 代码 问题简述1: 我在model中定义的 createTime 和 updateTime, 都是 number 类型, 并且我在接收 res 时候已经指定接收对象是一个 Icon 类型的数组了, 但为什么我最终 res.icons[0].c

  • 问题内容: 我想转换为,所以我写了一个const ,并尝试使用它进行转换。但是,代码会引发错误: 但是,如果我在分配后推迟类型转换,则代码可以解决。 我的问题: 这两个代码之间有什么区别吗? 为什么第一个会引发编译错误? 问题答案: 请参阅:https://golang.org/ref/spec#Constant_expressions 类型化常数的值必须始终可以由常数类型的值准确表示。以下常量表

  • 我正在用以下代码生成以毫秒为单位的历元时间戳,它可以工作(通过https://www.epochconverter.com/验证)。但是,当我们使用JVM选项-duser.timezone=america/toronto设置时区时,对于某些历史日期,时间偏移量会相差一小时。即日期=1950-11-19(yyyy-MM-dd)正确的历元毫秒-603313200000(星期日,1950年11月19日1

  • 我打算用projectreactor库编写一个process()方法 process()方法将字节数组作为参数,并执行以下步骤。假设每个步骤的所有其他方法都已编写并准备好使用。 将字节数组反序列化为消息对象 从消息对象提取用户ID、用户状态和用户地址 从数据库中按用户ID检索记录 如果从消息对象提取的这两个值不为Null,则使用userStatus和userAddress更新记录 将记录保存到数据

  • 例外情况: java.lang.ClassCastException:com.interconnect.library.gcm.util.checkplayServices(util.java:96),com.interconnect.library.gcm.regiseter.handleRegister(regiseter.java:53),com.interconnect.library.g

  • 结果: 问题: 1.lis,ele=>ele.textContent中我把ele.textContent换成了lis.textContent结果出来的是一个undefine的集合,是为什么? 2.lis,ele=>ele.textContent我是否可以理解为Array.from(arr,function),然后返回元素的文本内容? 3.该怎么理解lis和ele之间的关系呢?(因为看到很多案例都是