Android GCM (Google Cloud Messaging):Server Side

01 July 2013

GCM (Google Cloud Messaging)其實就是C2DM 的前身,
先前就有寫過四篇文章來講解C2DM,
分別有:
第一篇在講參數說明 (舊版C2DM)
第二篇在講流程說明 (舊版C2DM)
第三篇在講server端的實作 (舊版C2DM)
第四篇在講android端的實作 (舊版C2DM)



其實新版的GCM和C2DM只有些微的差別,因此在migrate時只需要小小變化,

甚至更為方便!
除了方便以外,而GCM多了一項新功能,
就是讓你的server可以與Google Server建立一個persistent TCP connection,
其目的就是為了讓你使用XMPP,而此Server稱作Cloud Connection Server(CCS)


當然我們也可以用傳統的HTTP Server,而這兩者個差異,可以看這篇文章


而本篇文章主要是告訴大家如何implement server side,
以及怎麼和Google Server做溝通!
這裡語言主要會以Python為主!
然後web-framework是使用flask,
web server是nginx+uwsgi

如果要看Android Client Side,請至(http://blog.kenyang.net/2013/07/android-gcm-google-cloud_1.html


在開始之前,還要告訴大家GCM有個最方便的地方,
還記得C2DM在傳資料給Google Server時,需要帶一個header
而這個header必須儲存Google Client Login的auth token.
我一直覺得這非常非常之愚蠢!!
等於我如果要做到automation,我還要有一套機制去使用Google Client Login API去login google,實在太不方便!
但現在不用了!!!
取而代之的是用API Key!(這才是根本之道啊)

至於怎麼申請API Key呢?
  1. 請先來到Google API Console
  2. 點選左邊的Services
  3. 找到Google Cloud Messaging for Android
  4. 把它打開
  5. 接著點選左邊API Access
  6. 點選按鈕『Create new Server Key』
  7. 點選按鈕『Create』
  8. 接著就會看到下圖中的API key,請記起來!





接著要開始寫Server Side
Server Side分為兩個角色!
  1. Android Device會傳送自己本身的registration id上來給Server,此時Server必須儲存此id
  2. 把data和id一併送到Google Server去,這時候Google Server就會自動push data至對應到該id的device上


首先是接收registration id的部分!因為我偷懶,我收到id以後就寫到一個file裡面去
正規做法應該是存在database之類的,但我這邊為了方便,所以先存在一個file裡去!

@app.route("/storeRegId",methods=['GET'])
def storeRegId():
id = request.args.get('id')

with open("regIdList","w") as f:
f.write("%s" % id)

return 'id %s' % id

接著就是傳送data給Google Server的部分!
請注意把下面的API_KEY換成您自己的!
這個範例傳送的資料會有兩筆,分別是last name以及first name!
當然你可以增加或者減少!反正就是JSON format!

@app.route("/send")                                                                                                        
def send():

# remember place your API Key
API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

params = {}

# put the data you want to send to device
params['data']={ 'last name': 'yang','first name': 'ken'}

# get registration id, this registration id will be mapped to a device.
f = open ("regIdList","r")
regId = f.read()
f.close()

params['registration_ids']=[regId]
params = json.JSONEncoder().encode(params)


headers = { "Content-type": "application/json",
"Authorization": "key="+API_KEY}

conn = httplib.HTTPSConnection("android.googleapis.com")

# method,url,body,header
conn.request('POST','/gcm/send', params,headers)
res = conn.getresponse()

conn.close()
result = {'msg':res.status}
return jsonify(result)




這樣就完成了Server side的部分!
將在下一篇教大家怎麼implement Android part!














read more »


Android DatePicker scroll problem.

18 June 2013

在Android 4.0.4機器上的 DatePicker一定會發生scroll的小問題,
(但是4.2.3不會發生!而我推測或許3.x以上~4.0.4以下的device都會發生)


如下圖,
你會發現經過scrolling以後,在年/月/日的三個欄位,位置都怪怪的
原因是因為在做position時,那個event是被parent截取到!
但理應上應該是DatePicker截取到才對!



所以workaround就是,自己定義一個class,以及extend DatePicker!
然後去取消parent截取event!

public class CustomDatePicker extends DatePicker {

public CustomDatePicker(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CustomDatePicker(Context context) {
super(context);
}

@SuppressLint("NewApi")
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* Prevent parent component intercept touch event.
* because only happened on Android 3.x ~ 4.0.4, so we need to check the current os version.
*/
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
ViewParent p = getParent();
if (p != null){
// disallow its parent intercept touch event.
p.requestDisallowInterceptTouchEvent(true);
}
}
}

return false;
}

}


而使用方式就是在你的layout.xml中指定我們上方定義的class,
<view android:id="@+id/share_expires" 
android:layout_width="fill_parent"
android:visibility="gone"
android:layout_height="wrap_content"
class="net.kenyang.util.CustomDatePicker" >
</view>


這樣就能解決scrolling的問題!

read more »


Android remove dedicated menu icon.

04 June 2013

If you want to remove Action overflow button on newest apps (above 3.0),
please set your targetSdkVersion as 14.

<uses-sdk android:minSdkVersion="7" 
android:targetSdkVersion="14" />




Cause Android decides whether to show the overflow button on the bottom bar based on which API level you used.









read more »