亚马逊AWS使用GCM推送

阎麒
2023-12-01

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

https://developers.google.com/cloud-messaging/android/start

http://aws.amazon.com/cn/mobile/sdk/

https://github.com/aws/aws-sdk-android

https://github.com/awslabs/aws-sdk-android-samples/tree/v1    一定要下亚马逊在github上分支的demo,当时不知道master分支上根本就没有亚马逊sns的使用demo

https://console.aws.amazon.com

https://console.developers.google.com/

google-play-service集成指南  https://developers.google.com/android/guides/setup

google-play-service.jar瘦身  https://gist.github.com/dmarcato/d7c91b94214acd936e42

android studio   

compile 'com.google.android.gms:play-services:8.4.0'

或者

complie 'com.google.android.gms:play-services-gcm:8.4.0'

可我是用的Eclipse 下载了谷歌类项目以后引进发现Unable to execute dex: method ID not in [0, 0xffff]: 65536

所以需要一个瘦身后的google-play-services.jar还有下面这个也很关键

<meta-data android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

 <integer name="google_play_services_version">8487000</integer>
注意这个version数字要匹配,也可以将 google-play-service类项目中的version.xml拷贝过来

亚马逊是个大傻逼,集成GCM的例子中竟然没有将注册的谷歌token向亚马逊注册部分

添加亚马逊引用 aws-android-sdk-core-2.2.7.jar 和 aws-android-sdk-sns-2.2.7.jar

亚马逊控制台  https://console.aws.amazon.com/sns/v2/home?region=us-east-1#/applications

谷歌  https://developers.google.com/cloud-messaging/       https://console.developers.google.com/

下面的函数用来检验google play service是否可用,可以用来检查不能使用谷歌play服务的原因

/**
	 * Method to verify google play services on the device
	 * */
	private boolean checkPlayServices() {
		int resultCode = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(this);
		if (resultCode != ConnectionResult.SUCCESS) {
			Log.d(TAG,"google service error");
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				GooglePlayServicesUtil.getErrorDialog(resultCode, this, 1)
						.show();
			} else {
				Toast.makeText(getApplicationContext(),
						"This device is not supported.", Toast.LENGTH_LONG)
						.show();
			}
			return false;
		}
		Log.d(TAG,"google service true");
		return true;
	}
从网上抄来的代码,至于取消向亚马逊注册就不贴了,因为我没这个需求
public class GCMRegisterTask extends AsyncTask<String, Void, Boolean> {
		private Context context;
		private GoogleCloudMessaging gcm;

		public GCMRegisterTask(Context context, GoogleCloudMessaging gcm) {
			super();
			this.context = context;
			this.gcm = gcm;
		}

		@Override
		protected Boolean doInBackground(String... params) {
			String token;
			try {
				token = gcm.register(context
						.getString(R.string.gcm_project_number));
				SharedPreferences sp = PreferenceManager
						.getDefaultSharedPreferences(context);
				sp.edit()
						.putString(context.getString(R.string.gcm_pref_token),
								token).apply();
				return true;
			} catch (IOException e) {
				e.printStackTrace();
				Log.e("Registration Error", e.getMessage());
			}
			return false;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			String token = PreferenceManager.getDefaultSharedPreferences(
					context)
					.getString(getString(R.string.gcm_pref_token), null);
			if (!TextUtils.isEmpty(token)) {
				new AWSCreateEndpointTask(context)
						.execute(
								"arn:aws:sns:us-east-1:1206...:app/GCM/Android",//亚马逊的arn
								token, UserUtil.getemail(context));
			}
		}
	}

	public class AWSCreateEndpointTask extends
			AsyncTask<String, Void, CreatePlatformEndpointResult> {
		Context context;

		public AWSCreateEndpointTask(Context context) {
			super();
			this.context = context;
		}

		@Override
		protected CreatePlatformEndpointResult doInBackground(String[] params) {
			if (params.length < 3) {
				return null;
			}
			String arn = params[0];
			String gcmToken = params[1];
			String userData = params[2];
			try {
				CreatePlatformEndpointRequest request = new CreatePlatformEndpointRequest();
				request.setCustomUserData(userData);
				request.setToken(gcmToken);
				request.setPlatformApplicationArn(arn);
				return AWSManager.getSNSClient()
						.createPlatformEndpoint(request);
			} catch (Exception ex) {
				ex.printStackTrace();
				return null;
			}
		}

		@Override
		protected void onPostExecute(CreatePlatformEndpointResult result) {
			if (result != null) {
				SharedPreferences prefs = PreferenceManager
						.getDefaultSharedPreferences(context); // context.getSharedPreferences(
				// "my_prefs", Context.MODE_PRIVATE);
				String endpointArn = result.getEndpointArn();
				Log.e(TAG, "endpointArt=" + endpointArn);
				prefs.edit()
						.putString(
								context.getString(R.string.aws_endpoint_arn),
								endpointArn).apply();
			}
		}
	}
使用

GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getBaseContext());
new GCMRegisterTask(this, gcm).execute("");

前期的时候出现  GCM SERVICE_NOT_AVAILABLE这个问题,网上说在GCMBroadcastReceiver中会得到registration_id

GCMBroadcastReceiver.class  消息

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class GCMBroadcastReceiver extends BroadcastReceiver {

	public void onReceive(Context context, Intent intent) {
		if (intent != null) {
			Bundle extras = intent.getExtras();
			// if(!AndroidMobilePushApp.inBackground){
			//MessageReceivingService.sendToApp(extras, context);
			// }
			// else{
			Log.d("GCMBroacastReceiver","registration_id="+extras.getString("registration_id"));
			MessageReceivingService.saveToLog(extras, context);
			// }
		}
	}
}

 <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="com.google.android.c2dm.permission.REGISTER" />
    <uses-permission android:name="包名.permission.C2D_MESSAGE" />

 <receiver
            android:name=".GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <action android:name="com.google.android.c2dm.intent.REGISTER" />

                <category android:name="包名" />
            </intent-filter>
        </receiver>


又出现了AUTHENTICATION_FAILED错误,所有的错误都让我碰到了无语 http://stackoverflow.com/questions/18911996/gcm-authentication-failed-error-while-getting-registration-id

出现的原因是谷歌商店没有安装好,安装好谷歌商店以后,将谷歌商店用Root Explorer文件管理器将/data/app/com.android.vending-1.apk拷贝到/system/app中,登陆好谷歌账号以后问题就会解决。

出现故障:The security token included in the request is invalid. (Service: AmazonSNS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: 774075ca-08c5-52d3-8354-3add0234abc8)

这是因为签名的亚马逊注册代码没有创建证书,可以照着下面的代码修改

private void register() {
new AsyncTask(){
    protected Object doInBackground(final Object... params) {
        String token;
        try {
            token = gcm.register(getString(R.string.project_number));//GCM project number
            Log.i("registrationId", token);
            String platformApplicationArn = "arn:aws:sns:usxxxxxxxxx";
            AWSCredentials awsCredentials = new BasicAWSCredentials("自己的Access Key ID", "自己的Secret Access Key");//容易被人反编译得到
            AmazonSNSClient pushClient = new AmazonSNSClient(awsCredentials); 
            CreatePlatformEndpointRequest platformEndpointRequest = new CreatePlatformEndpointRequest();

            platformEndpointRequest.setCustomUserData(customPushData);
            platformEndpointRequest.setToken(token);
            platformEndpointRequest.setPlatformApplicationArn(platformApplicationArn);
            pushClient.setRegion(Region.getRegion(Regions.US_WEST_1));

            CreatePlatformEndpointResult result = pushClient.createPlatformEndpoint(platformEndpointRequest);
            Log.e("Registration result",result.toString());
        } 
        catch (IOException e) {
            Log.i("Registration Error", e.getMessage());
        }
        return true;
    }
}.execute(null, null, null);
}
又出现了Invalid parameter: PlatformApplicationArn Reason: Region from ARN (us-east-1) is different than SNS endpoint region (us-west-1). (Service: AmazonSNS; Status Code: 400; Error Code: InvalidParameter; Request ID: 41f2a3ca-7966-5295-852d-ecdd59352de0)
原来亚马逊还分东部,西部1和西部2,我的项目是创建在东部,所以把Regions.US_WEST_1改为US_EAST_1。

总结:整个搞下来花了我太多时间。

彻底放弃eclipse吧,用起来真心的不方便了。

一定要按照官网最新的API做,还是安心的照着https://github.com/googlesamples/google-services上重新来过吧。

不要想着免费的翻墙了,还是老实的花上20元买一个月的VPN,被这个墙的问题搞了一天,最后还是放弃了免费的。


eclipse中对google-play-services.jar进行瘦身操作,很简单,用压缩软件打开删除所有无用的文件夹,最后只保留common gcm iid internal 4个文件夹


 类似资料: