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.
可我是用的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)
总结:整个搞下来花了我太多时间。
彻底放弃eclipse吧,用起来真心的不方便了。
一定要按照官网最新的API做,还是安心的照着https://github.com/googlesamples/google-services上重新来过吧。
不要想着免费的翻墙了,还是老实的花上20元买一个月的VPN,被这个墙的问题搞了一天,最后还是放弃了免费的。
eclipse中对google-play-services.jar进行瘦身操作,很简单,用压缩软件打开删除所有无用的文件夹,最后只保留common gcm iid internal 4个文件夹