2015年12月22日 星期二

Android手機上GCM的設定方法

【注意!如果是在找iPhone,或純網頁版的GCM功能,建議別在我這篇文章裡浪費時間了,除非你搞不懂Key和SenderID之間的關係,弄不懂自己到底哪裡出錯。】

所謂的GCM,就是Android會時不時從網路上收到由「Google系統」所發出「針對你這支手機、要給你的資訊。」

它的結構並不難!只是有些資訊因為版本不停更換,不管是API說明,或是Console端介面,所以說明變得越來越模糊籠統,對新人來說越來越不友善。

但GCM只是種「如何實現非Google系統也能針對特定手機發送針對這支手機所發出的資訊」的機制,它的具體應用內容目前並沒有太多規範與限制!

所以要試著把「自己想做的事情和應用」給排除、專注在理解「發送GCM」上,反而會容易理解GCM的機制與應用方法



雖然網頁教學強調「Server Key」和「SenderID」是應用的基礎,但......

「Google Developer Console端設定」才是這項功能的核心!

(官網上的教學完全假設使用者已經對Console端運作的邏輯和每個欄位每個值得意義滾瓜爛熟......)

每一支GCM功能都要在Console端設定一項專案!

意思是說...一支網頁如果有發送GCM功能,它是否只能針對一項GCM功能?一支手機APP一次是否只能囊括一項GCM功能?...以上答案都是「不」!

理論上來說,一支APP裡面同時可以應用到很多個GCM功能。

比如A購物應用和B購物應用都有自己的GCM內容,能否做一支APP同時把兩支應用的GCM都改由同一支APP接收?(「我不想要購物,但我想要知道廣告消息?」)...

理論上來說,可以!

(2015/12/23:我自己是有測試過,成功了。但未來是否會針對這項特性做出限制?...不保證!)



GCM服務在Google Console上可以獨立成為一項專案嗎?

理論上來說可以,只是不知道為何,我連測試它的動力都沒有。可能是因為我是使用GAE平台來施作Service,而我的GCM服務就直接附屬GAE專案在裏頭。但對不使用GAE的使用者來說,這樣做可能反而很合理。

這是Google Console設定的邏輯。一項專案可以單純的只是一串Google API應用權限的集合,設定完之後任何網頁APP或手機APP都能使用這項專案的權限設定。

再講精準一點、講的懶人一點,一支手機APP中,可以使用兩組以上的Google API專案?...答案當然也是「可以」。(關鍵點在這組專案的這項功能是否讓特定APP使用。如果不行?那就是沒有權限!如果將特定APP的權限加入後,自然就可以使用了。)



這是很多菜鳥在思維跟管理上會犯的錯。(對!我是菜鳥!)

GCM服務並不屬於任何Web Service或是APP,而是Web Service或APP需要使用特定GCM專案時,需要將自己的權限加入GCM服務專案中。

將Web Service加入GCM服務專案後,就會產生一組Server Key。這組Key就是Authorization欄位中所要帶入的參數值。(我不會用XMPP,所以那段怎麼做,請自行研究一下。)

至於APP端需要的SenderID,其實就是這個GCM服務專案的專案ID!

(2015/12/23:不知道為何,中文版的Console上,每個專案都有兩組專案ID,一組是文字,另一組則是編號。這地方要取用編號。)

如果Service Key跟SenderID來自不同的GCM專案,就會產生「MismatchSenderID」的結果!

如果為了方便開發,APP端跟WebService可能會分頭進行,為了測試就用GAE設置了測試用的簡單WebService,這時候就很容易忽略了這個步驟.......

因為是GAE,所以一定會在Console上設置一組Google API專案。就很順手的把GCM服務也歸屬在這項專案中,也從中取得ServiceKey和加入APP權限......但不知道為何,使用的SenderID還是正式WebService的專案ID。



對.......

其實這整篇文只是想解釋MismatchSenderID造成的原因。

2015年12月7日 星期一

檢查參數內容是否是同一個物件實體?

假設物件A內有兩個參數,分別是字串B和長整數C。

物件A生成兩個實體參數,分別是實體一和實體二......

可以將實體一和實體二的B和C都設為同樣的數值內容,但如果用if(實體一 == 實體二)來檢查結果...

在Java中一定會得到false。

除非逐一針對B和C參數比對,不然永遠都會是false,──但這不是重點!



只要善用這個特性,可以輕鬆地完成「資料是否有更新」的比對。



最近碰到一個功能,(我保留了細節,只講大概,)要在Activity A中用網路去查詢資料,查詢完後將資料在Activity B鐘用列表(ListView)顯示,並且用彈出式視窗告知使用者「現在有幾筆資料」,然後在Activity C中可以看各筆資料的詳細內容.......並且重新設定查詢條件後再次查詢、查詢完後退回「上一頁(也就是Activity B)」。


用彈出式視窗告知使用者「現在有幾筆資料」是後來追加的功能,所以我設計的簡單,就是在Activity B的onResume中把列表的資料數顯示出來就是...

但問題是在Activity C中,使用者大部分只是單純的看完細節就退回Activity B,並不會重新設定查詢。

所以「判斷是否有重新設定查詢」仍是有必要的一件事。



方法很簡單。

資料要能跨三個Activity間傳遞並操作,方法就是使用一個static型態的ArrayList參數。

(在同一個APP中只要這樣做即可,Intent是很多餘的東西。)

每次只要有「查詢」,就會將這個static ArrayList參數重新產生一個實體。

然後在Activity B中設置一個物件類別專屬的ArrayList參數三,並在onResume中做if(實體一 == 實體二)的檢查,就可以快速精準地知道「使用者是否重新使用過查詢功能」。

(怕有人不知道:通常,將static ArrayList設為實體一,可以省去檢查實體二是否為null的動作。)



但如果ListView的Adapter直接使用參數三,這個方法「可能」會導致APP當機。

怕有人不知道......

安全的程序應該是再產生ArrayList參數四,然後用addAll()的方式將參數三內的資料全部倒進參數四中,然後再使用參數四來產生ListView的Adapter。

(資料量不要太誇張...一般來說這個動作是不吃什麼效能的。如果資料量很誇張,擔心記憶體,不要擔心效能。)