有关从C2DM切换到GCM的问题

时间:2015-07-16 21:08:03

标签: android google-cloud-messaging

我将我的应用从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");
      }

     }
}

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

checkPlayServices()确保安装了Android 2.3或更高版本并安装了Google Play服务,因为这些是使用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或String token)?

AFAIK,GCM会在适当时向我发送新令牌。我所要做的就是随时准备接受它并存储它。是吗?

如上所示使用RegistrationIntentService允许我随时接受/存储令牌。是吗?

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

同样的"后续的电话是本地的" ?是否要求获取我在此处收到并存储在设备上的令牌?

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将导致RegistrationIntentService运行并获取新的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发送消息告诉它"将此消息发送给具有此令牌的人#34;它在上面的代码中到达我的应用程序。这是对的吗?

这是将AndroidManifest放在一起的AndroidManifest:

    <!-- [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中显式启动RegistrationIntentService:

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

但不是其他服务?

1 个答案:

答案 0 :(得分:0)

if (this.checkPlayServices()) {
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
}
     

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

没有。 IntentService只有在完成onHandleIntent

中的代码之后才会存在
  

checkPlayServices()确保安装了Android 2.3或更高版本并安装了Google Play服务,因为这些是使用GCM的唯一要求。这是对的吗?

呀。和不。您还需要网络连接。我想在检查Play服务之前检查网络。

  

什么“注册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中显式启动RegistrationIntentService:

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

但不是其他服务?

您在清单中声明InstanceIDListenerServiceGcmListenerService因为它们需要一直运行。如果你没有注册,那么他们什么都不做。清单中未调用RegistrationService,因为您可能不希望它立即启动。例如,如果您想让您的用户注册您的应用程序,那么一旦通过身份验证,您就可以通过启动此服务注册gcm。