Friday, December 9, 2011

Python으로 c2dm server 만들기

1. http://code.google.com/intl/ko-KR/android/c2dm/ 에서 c2dm 서비스에 sign-up
(gmail account를 새로 만들어서 가입하는 것이 좋다. - 실제로 이 account정보를 클라이언트 및 서버에 모두 넣어야 하고 더구나 서버에는 패스워드정보도 필요하기 때문)

2. 가입하면 E-mail로 가입한 Account로 서비스가 Enable되었다는 내용의 메일이 옮(보통 하루안에 오고 늦어도 몇일 사이에는 오는 듯)

여기까지 준비 완료! 아래는 실제 파이썬 코드 시작!!

import urllib, urllib2

class ClientLoginTokenFactory(): 
    _token = None 
    
    def __init__(self):
        self.url = 'https://www.google.com/accounts/ClientLogin'
        self.accountType = 'GOOGLE'
        self.email = 'c2dm에 가입한 메일주소'
        self.password = 'c2dm에 가입한 메일주소의 패스워드'
        self.source = 'replstory-replstory-0'
        self.service = 'ac2dm'
    
    def getToken(self):    
        if self._token is None:
            
            # Build payload
            values = {'accountType' : self.accountType,
                      'Email' : self.email,
                      'Passwd' : self.password, 
                      'source' : self.source, 
                      'service' : self.service}
            
            # Build request
            data = urllib.urlencode(values)
            request = urllib2.Request(self.url, data)
            
            # Post
            response = urllib2.urlopen(request)
            responseAsString = response.read()
            
            # Format response
            responseAsList = responseAsString.split('\n')
            
            self._token = responseAsList[2].split('=')[1]
            
        return self._token
    
class C2DM():
    
    def __init__(self):
        self.url = 'https://android.apis.google.com/c2dm/send'
        self.clientAuth = None
        self.registrationId = None
        self.collapseKey = None
        self.data = {}
        
    def sendMessage(self):
        if self.registrationId == None or self.collapseKey == None:
            return False
        
        clientAuthFactory = ClientLoginTokenFactory()
        self.clientAuth = clientAuthFactory.getToken()
        
        # Build payload
        values = {'registration_id' : self.registrationId,
                  'collapse_key' : self.collapseKey}     
        
        # Loop over any data we want to send
        for k, v in self.data.iteritems():            
            values['data.' + k] = v
        
        # Build request
        headers = {'Authorization': 'GoogleLogin auth=' + self.clientAuth}        
        data = urllib.urlencode(values)
        request = urllib2.Request(self.url, data, headers)
        
        # Post
        try:
            response = urllib2.urlopen(request)
            responseAsString = response.read()
            
            return responseAsString
        except urllib2.HTTPError, e:
            print 'HTTPError ' + str(e)
            
            
sender = C2DM()
sender.registrationId = 'Android단말기에서 c2dm서버로 부터 받은 고유번호'
sender.collapseKey = 1
sender.data = {'msg':'test'}
response = sender.sendMessage()
print response

9,10,79 라인의 정보만 바꾸고 실행하면 c2dm등록된 단말기로 test라는 푸시 메세지가 날아간다.
http://blog.boxedice.com/2010/10/07/android-push-notifications-tutorial/ 에 있는 예제코드인데 제대로 돌지 않아서 약간의 수정만 했음.

이미 눈치 채셨겠지만 실제 사용시에는 78라인부터만 따로 가져가서 원하는 곳에 사용하면 된다. collapseKey를 1로 고정해두고 사용하면 c2dm메세지가 동일한 단말에 동일한 메세지를 계속 적으로 보낼 경우 중간중간 빼먹는 경우가 생긴다. 구글에서 중복된 메세지 전송을 방지하게 넣어둔 코드임. 중복으로 보내는 메세지라도 단말에 꼭 전송이 되어야 하는 메세지라면 collapseKey를 increase하면서 보내는 것이 상책!

3 comments:

  1. 파이썬 코드에서 한글을 사용하기 위해서는 가장 위에
    # -*- coding: utf-8 -*-
    를 추가하시면 됩니다.(Tweet에서 문의주신 분이 계셔서...)

    ReplyDelete
  2. 좋은 내용 감사합니다.
    위 내용에서 'msg':'test'를 사용할 경우 메시지를 못받고 'payload':'test'를 사용할 경우 받을 수 있었습니다.

    ReplyDelete
  3. 'Android단말기에서 c2dm서버로 부터 받은 고유번호'는 어떻게 알 수 있나요?

    ReplyDelete