1. 程式人生 > >Amazon AWS使用Google GCM/FCM推送

Amazon AWS使用Google GCM/FCM推送

簡單梳理一下流程(連結可能需要VPN)

Google GCM的整合
國內大部分手機不支援google play服務,無法使用GCM 推送,針對的是支援Google Play 服務的移動裝置
GCM過時了,遷移到FCM
在這裡插入圖片描述
Android FCM詳情配置請參考:
在 Android 上設定 Firebase 雲訊息傳遞客戶端應用

下面是簡述流程:

  1. 將 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了