简单梳理一下流程(链接可能需要Over the wall)
Google GCM的集成
国内大部分手机不支持google play服务,无法使用GCM 推送,针对的是支持Google Play 服务的移动设备
GCM过时了,迁移到FCM
Android FCM详情配置请参考:
在 Android 上设置 Firebase 云消息传递客户端应用
下面是简述流程:
- 将 Firebase 添加到您的 Android 项目
需要登录Firebase 控制台创建项目
2.添加项目成功以后,配置Firebase
具体配置信息就不贴了 参考github firebase FCM: quickstart-android/messaging/
github GCM:google-services/android/gcm/
对于无法知道设备是否拥有兼容的 Google Play 服务,需要检查 Google Play 服务,通过GoogleApiAvailability.makeGooglePlayServicesAvailable()方法,这个方法在com.google.android.gms.common下如果用的FCM需要另导入相关API,这是我当前使用的版本
implementation 'com.google.firebase:firebase-messaging:17.3.4'//app/gradle
implementation 'com.google.android.gms:play-services-base:16.0.1' //app/gradle
classpath 'com.google.gms:google-services:4.0.1' //project gradle
若发生错误,需要注意版本问题
如果继续使用GCM,
compile "com.google.android.gms:play-services-gcm:16.0.0"
就不用再导入其他API
亚马逊服务配置
Amazon Simple Notification Service
吐槽一下,亚马逊把开发文档放在资源里面,一点都不好找
直接打开开发指南,推送概括
1.向 AWS 注册您的移动应用
参考:使用Amazon SNS向Android设备发送推送通知(日语的,用Google浏览器翻译一下)
所需要的GCM API Key 看第2步
2.Google Cloud Messaging for Android 入门
这一步有用的一点就是在 Google API 控制台网站上,创建 Google API 项目并启用 GCM 服务,获取服务器 API 密钥
3.使用 Amazon SNS 移动推送
链接中的 1,2步 ,已经完成,其中令牌就是FCM返回的token,注册 ID参考第二步
要使用 Amazon SNS 将通知推送到应用程序,必须先通过调用创建平台终端节点操作,将该应用程序的设备令牌注册到 Amazon SNS。此操作以参数的形式获取平台应用程序的 Amazon 资源名称 (ARN) 以及设备令牌,并返回所创建平台终端节点的 ARN
网页中有一部分Java示例,给他补全了下,
implementation 'com.amazonaws:aws-android-sdk-sns:2.6.10'
public class AmazonRegister {
private String token;
private String applicationArn = "";//Amazon 资源名称 (ARN)
private String amazonkeyid="";//amazon keyid
private String serverKey="";//服务key
private String arnStorage;
AmazonSNSClient client;
public AmazonRegister(String token){
this.token = token;
}
public void registerWithSNS() {
String endpointArn = retrieveEndpointArn();
// String token = "Retrieved from the mobile operating system";
AWSCredentials credentials = new BasicAWSCredentials(amazonkeyid,serverKey); //aws 验证
client = new AmazonSNSClient(credentials); //provide credentials here
boolean updateNeeded = false;
boolean createNeeded = (null == endpointArn);
if (createNeeded) {
// No platform endpoint ARN is stored; need to call createEndpoint.
endpointArn = createEndpoint();
createNeeded = false;
}
System.out.println("Retrieving platform endpoint data...");
// Look up the platform endpoint and make sure the data in it is current, even if
// it was just created.
try {
GetEndpointAttributesRequest geaReq =
new GetEndpointAttributesRequest()
.withEndpointArn(endpointArn);
GetEndpointAttributesResult geaRes =
client.getEndpointAttributes(geaReq);
updateNeeded = !geaRes.getAttributes().get("Token").equals(token)
|| !geaRes.getAttributes().get("Enabled").equalsIgnoreCase("true");
} catch (NotFoundException nfe) {
// We had a stored ARN, but the platform endpoint associated with it
// disappeared. Recreate it.
createNeeded = true;
}
if (createNeeded) {
createEndpoint();
}
System.out.println("updateNeeded = " + updateNeeded);
if (updateNeeded) {
// The platform endpoint is out of sync with the current data;
// update the token and enable it.
System.out.println("Updating platform endpoint " + endpointArn);
Map attribs = new HashMap();
attribs.put("Token", token);
attribs.put("Enabled", "true");
SetEndpointAttributesRequest saeReq =
new SetEndpointAttributesRequest()
.withEndpointArn(endpointArn)
.withAttributes(attribs);
client.setEndpointAttributes(saeReq);
}
}
/**
* @return never null
* */
private String createEndpoint() {
String endpointArn = null;
try {
System.out.println("Creating platform endpoint with token " + token);
CreatePlatformEndpointRequest cpeReq =
new CreatePlatformEndpointRequest()
.withPlatformApplicationArn(applicationArn)
.withToken(token);
client.setRegion(Region.getRegion(Regions.US_WEST_2));
CreatePlatformEndpointResult cpeRes = client
.createPlatformEndpoint(cpeReq);
endpointArn = cpeRes.getEndpointArn();
} catch (InvalidParameterException ipe) {
String message = ipe.getErrorMessage();
System.out.println("Exception message: " + message);
Pattern p = Pattern
.compile(".*Endpoint (arn:aws:sns[^ ]+) already exists " +
"with the same token.*");
Matcher m = p.matcher(message);
if (m.matches()) {
// The platform endpoint already exists for this token, but with
// additional custom data that
// createEndpoint doesn't want to overwrite. Just use the
// existing platform endpoint.
endpointArn = m.group(1);
} else {
// Rethrow the exception, the input is actually bad.
throw ipe;
}
}
storeEndpointArn(endpointArn);
return endpointArn;
}
/**
* @return the ARN the app was registered under previously, or null if no
* platform endpoint ARN is stored.
*/
private String retrieveEndpointArn() {
// Retrieve the platform endpoint ARN from permanent storage,
// or return null if null is stored.
return arnStorage;
}
/**
* Stores the platform endpoint ARN in permanent storage for lookup next time.
* */
private void storeEndpointArn(String endpointArn) {
// Write the platform endpoint ARN to permanent storage.
arnStorage = endpointArn;
}
}
可以传入applicationArn ,amazonkeyid,serverKey在Amazon sns 控制台创建节点,然后
向移动设备发送直送消息
终于写完了—
资料:
snsmobilepush.zip
sns 示例(master主支上没有相关demo)
sns 源码
由于我们使用FCM获取的token(令牌)传入后台,后台向Amazon 发送令牌,Amazon SNS 使用该设备令牌来创建移动终端节点,再传递到FCM平台向设备发送通知,客户端来接收消息,就不需要接入amazon sns sdk了
相关资料:
日语环境
https://qiita.com/miyatay/items/b122ca1c019c985c78eb
https://qiita.com/papettoTV/items/f45f75ce00157f87e41a
http://kurochan-note.hatenablog.jp/entry/2014/02/14/235824
https://qiita.com/MJeeeey/items/3068f1e39ca074fa8e6e