谷歌GCM 接入笔记2

最近事多,到今天接着上一篇接着写,左边是  上一篇的地址  <a target=_blank href="http://blog.csdn.net/taiyouxian/article/details/51993258" style="font-family: Arial, Helvetica, sans-serif;">点击打开链接</a>

上一篇我们已经做好了前期工作了,再总结一下,前期工作有 确认翻墙,确认能接受谷歌GCM服务,下载好了jar包,得到了谷歌GCM服务所需参数

下载好了demo了,打开demo来看看什么样子吧


工程很简单就四个文件,值得看的还有 配置文件AndroidManifest.XML文件,res/values/strings.xml文件

简单介绍一下上述文件,

工程文件  DemoActivity 看名字就知道是入口  Activity,功能就是  确认你本地有没有RegistrationId,没有就发送send_id 去谷歌服务器要。

还有在你activicty结束的时候 调用一下  GCMRegistrar.onDestroy(this); 方法

值得一提的是demo里面有为  连接Http发送RegistrationId的部分,由于我的工程并不是从网页端发通知,所以这里就不再介绍了。

工程文件 CommonUtilities 这个看名字也知道啦,是公用的参数文件,另外还有一个广播方法,来从后台通知到UI。

工程文件 GCMIntentService 这个文件就是重头戏了,谷歌发回来的数据,就是通过这个类的方法来接受的,里面还提供了一个现成的显示通知的方法

generateNotification。

工程文件 ServerUtilities  这个文件是专门为给http传递参数写的,因为我的项目并没有用到这个类,就不介绍了。

然后就是配置文件了,从简单的开始介绍

res/values/strings.xml文件 里面有APP名字,还有一些通知要用到的提示字,之所以放在xml文件里,看网上介绍是说,方法出各种语言,有需求只要改XML文件就好,不用东换西换。


AndroidManifest.XML文件大家也都知道

    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/>

    <!-- GCM connects to Google Services. -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- GCM requires a Google account. -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <!-- Keeps the processor from sleeping when a message is received. -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <!--
     Creates a custom permission so only this app can receive its messages.

     NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
           where PACKAGE is the application's package name.
    -->
    <permission
        android:name="com.google.android.gcm.demo.app.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission
        android:name="com.google.android.gcm.demo.app.permission.C2D_MESSAGE" />

    <!-- This app has permission to register and receive data message. -->
    <uses-permission
        android:name="com.google.android.c2dm.permission.RECEIVE" />

上面最低版本8要注意,你的工程的最低版本一定要大于等于8,目标版本倒是可以不设置

然后就是设置接收Intent的服务了

        <!--
          BroadcastReceiver that will receive intents from GCM
          services and handle them to the custom IntentService.

          The com.google.android.c2dm.permission.SEND permission is necessary
          so only GCM services can send data messages for the app.
        -->
        <receiver
            android:name="com.google.android.gcm.GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <!-- Receives the actual messages. -->
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <!-- Receives the registration id. -->
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <span style="color:#006600;"><category android:name="com.google.android.gcm.demo.app" /></span>
            </intent-filter>
        </receiver>

        <!--
          Application-specific subclass of GCMBaseIntentService that will
          handle received messages.

          By default, it must be named .GCMIntentService, unless the
          application uses a custom BroadcastReceiver that redefines its name.
        -->
        <span style="color:#006600;"><service android:name=".GCMIntentService" /></span>

有两个地方要注意

<category android:name="com.google.android.gcm.demo.app" />
<pre name="code" class="java" style="font-size: 11px;"><service android:name=".GCMIntentService" />

 

用到你工程里面,com.google.android.gcm.demo.app要换成你自己的包名,

比如你的包名是 com.test,就要换成<category android:name="com.test" />   

GCMIntentService文件的位置一定要在你的包名下  比如上面的 com.test.GCMIntentService.

这个是jar包里面定好的,如果你的工程得因为需求,得出好几个不同的包名(如com.google.xxx,com.xiaomi.xxx)。

那你就在那些包名下面都创建一个GCMIntentService,亲测,不会冲突的。   com.google.xxx.GCMIntentService,com.xiaomi.xxx.GCMIntentService。

下面开始贴代码了,第一个入口activity

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		GCMRegistrar.checkDevice(this);
		GCMRegistrar.checkManifest(this);
		final String regId = GCMRegistrar.getRegistrationId(this);
		//这里本来是判断没有才发,为了保证每次都是最新的reg_id,我改成了每次都发
		GCMRegistrar.register(this, GCMIntentService.SENDERID);
	}
	
    @Override
    protected void onDestroy() {
    	//APP被杀死的时候调用一下这个方法
        GCMRegistrar.onDestroy(this);
        super.onDestroy();
    }

因为项目没有使用 Http,CommonUtilities我就不写了,直接写在GCMIntentService

(下面这个是在别人的博客里面找到的准确的解释,http://blog.csdn.net/u011589986/article/details/50948101)

以下包含的是GCM返回会调用到的方法:

onRegistered(Context context, String regId): 收到注册Intent后此方法会被调用,GCM分配的注册ID会做为参数传递到设备/应用程序对。通常,你应该发送regid到你的服务器,这样服务器就可以根据这个regid发消息到设备上。 

onUnregistered(Context context, String regId): 当设备从GCM注销时会被调用。通常你应该发送regid到服务器,这样就可以注销这个设备了。

onMessage(Context context, Intent intent): 当你的服务器发送了一个消息到GCM后会被调用,并且GCM会把这个消息传送到相应的设备。如果这个消息包含有效负载数据,它们的内容会作为Intent的extras被传送。

onError(Context context, String errorId): 当设备试图注册或注销时,但是GCM返回错误时此方法会被调用。通常此方法就是分析错误并修复问题而不会做别的事情。 

onRecoverableError(Context context, String errorId): 当设备试图注册或注销时,但是GCM服务器无效时。GCM库会使用应急方案重试操作,除非这个方式被重写并返回false。这个方法是可选的并且只有当你想显示信息给用户或想取消重试操作的时候才会被重写。

public class GCMIntentService extends GCMBaseIntentService {
	public static final String SENDERID = "474522007985";
	
	public GCMIntentService(){
		super(SENDERID);
	}

	@Override
	protected void onError(Context context, String errorId) {
		Log.v("GCMIntentService", "如果有错误推过来  就是进的这个方法");
	}

	@Override
	protected void onMessage(Context context, Intent intent) {
		//Intent 功能太强大了,比较常用的就是Activity (Service)之间的数据传递。举个简单例子,在当前Activity1使用startActvity(intent)或者startActivityForResult(intent, code)方法跳转到另一个Activity2之前,
		//如果要传递某些String类型数据给Activity2,则会执行intent.putExtra(String str, String Key),将String数据打包到Intent中,并给它一个Key标识。在Activity2当中,getIntent()方法获得这个intent,然后再getStringExtra(Key),就可以获得你之前打包的那个数据了。这种机制非常简单,也比较好用。
		//这里的mine 就是key的意思
		//可以先获得Intent中的Bundle对象,所有值都保存在这个对象里,intent.getBundle(),而Bundle对象自身可以当作一个Map理解,
		//而且Bundle有一个方法:keySet,返回所有的键,这样就可以打印出所有的值了。		

		Bundle	bundle = intent.getExtras();
		Set<String> key_all = bundle.keySet();
		//打印这个key_all 就能知道所有的key
		String score = bundle.getString("score");
		String time = bundle.getString("time");
		String collapse_key = bundle.getString("collapse_key");
		String from = bundle.getString("from");

		Log.v("GCMIntentService", "intent key_all"+key_all);
		Log.v("GCMIntentService", "intent score"+score);
		Log.v("GCMIntentService", "intent time"+time);
		Log.v("GCMIntentService", "intent collapse_key"+collapse_key);
		Log.v("GCMIntentService", "intent from"+from);
		Log.v("GCMIntentService", "context 里面是什么数据"+context);
		Log.v("GCMIntentService", "intent 看看能打印出来不"+intent);
		Log.v("GCMIntentService", "intent 这个东西貌似就是字典的作用"+intent.getStringExtra("data"));
		//比如这里我和服务端  约定好,要在notify里面显示的数据都放在 message里面
		String message = intent.getStringExtra("message");
		
		//这个方法其实是在demo里面的CommonUtilities里面的,这里为了方便,可以直接提取出来,就是一个广播方法
		Intent intent_2 = new Intent("xxxx.DISPLAY_MESSAGE");
		intent_2.putExtra("message", message);
        context.sendBroadcast(intent_2);
        
        // notifies user  这里的message就是你和你的服务器端约定好上面intent中的那个key ,所对应的value
        generateNotification(context, message);
	}

	@Override 
	protected void onRegistered(Context context, String registrationId) {
		Log.v("GCM-TEST","谷歌提供这个方法能拿到registrationId------" + registrationId);
		//这里就该自己写方法  把registrationId 传给你的APP服务器了,你的APP服务器是通过registrationId来发送通知的
	}

	@Override   //, 
	protected void onUnregistered(Context arg0, String arg1) {
		Log.v("GCM-TEST", "这个方法因为我项目里 没有用到,所以没仔细测,不过貌似是下次registrationId会变的时候,这个方法就会被调用,有兴趣的大兄弟可以自己多试试");
	}
	
    /**
     * Issues a notification to inform the user that server has sent a message.
     */
    private static void generateNotification(Context context, String message) {
        //这里的ic_stat_gcm 就是你的APP的图标
    	int icon = R.drawable.ic_stat_gcm;
        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager)
                context.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(icon, message, when);
        String title = context.getString(R.string.app_name);
        //设置了 <category android:name="android.intent.category.LAUNCHER"/>的入口Activity
        Intent notificationIntent = new Intent(context, MainActivity.class);
        // set intent so it does not start a new activity
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent intent =
                PendingIntent.getActivity(context, 0, notificationIntent, 0);
        notification.setLatestEventInfo(context, title, message, intent);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        //这里为了简单 设置notify_id 一直设置的都是0,notify_id一直一样的话,当有多条通知,最新的会覆盖掉上一条
        //你要保证有多条通知,最简单的  就是设置初始是0 然后一直进行 ++操作就好
        notificationManager.notify(0, notification);
    }
}


(顺便说一句,如果你的APP已经接了其他平台的推送,而那个推送也是用到了GCM的,你就得去那个平台找找有多个推送的解决方法了,用我第一个入口activity 里面的方法,可能发布出去通知,那个推送可能会拦截掉



GCM笔记到这里就结束了,如果想知道notification更多设置,可以看看我另外一篇博客,里面有介绍  点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值