我将我的应用从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);
但不是其他服务?
答案 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);
但不是其他服务?
您在清单中声明InstanceIDListenerService
和GcmListenerService
因为它们需要一直运行。如果你没有注册,那么他们什么都不做。清单中未调用RegistrationService
,因为您可能不希望它立即启动。例如,如果您想让您的用户注册您的应用程序,那么一旦通过身份验证,您就可以通过启动此服务注册gcm。