這裡則是介紹,如何在原本的 Android APP 開發環境,開發使用 PhoneGap 的 Andriod APP。
步驟:
- 到 http://phonegap.com/download/ 下載 PhoneGap,我下載的是 phonegap-2.5.0.zip
- 解縮壓備用,例如解壓縮到 D:\phonegap-2.5.0
- 在 Eclipse 新開一個 android 專案。此時目錄結構如下圖。
- 複製 D:\phonegap-2.5.0\lib\android\cordova-2.5.0.jar 到 android 專案的 libs 資料夾底下。
在 libs 資料夾上按右鍵,選「Build Path」->「Configure Build Path...」開啟設定視窗。按「Add JARs」,選擇 cordova-2.5.0.jar 加進去。 - 在andriod 專案的 assets 目錄底下,建立 www 目錄,此目錄即是用來放網頁的地方,
複製 D:\phonegap-2.5.0\lib\android\cordova-2.5.0.js 到 assets\www 目錄底下。 - 複製 D:\phonegap-2.5.0\lib\android\xml 資料夾 到 android 專案的 res 資料夾底下。
進行到這裡,此時目錄結構應該如下圖。 - 修改 AndroidManifest.xml 檔。可比較 D:\phonegap-2.5.0\lib\android\example\AndroidManifest.xml 和 andriod 專案產生的 AndroidManifest.xml 檔案,進行以下修改。
(註:19~34 行的 APP 權限設定,若開發的 APP 沒使用這麼多功能,沒用到的權限設定可以刪除)<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.mytest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_VIDEO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.mytest.MainActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
- 修改 MainActivity.java,讓程式執行時,是經由 PhoneGap 去執行 assets/www/ 底下的網頁。
package com.example.mytest; import android.os.Bundle; import org.apache.cordova.*;//新增此行 public class MainActivity extends DroidGap {// extends Activity 改成 extends DroidGap @Override public void onCreate(Bundle savedInstanceState) {// protected void 改成 public void super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main);//沒用到,註解 super.loadUrl("file:///android_asset/www/index.html");// 新增此行 } }
- 此時,設定的部份已經告一段落。
下面的範例,是用網頁寫一個簡單的彈出訊息視窗。
在 android_asset/www/ 資料夾底下新增一個 index.html 檔,內容如下:
第 7 行:引入 PhoneGap 的 JS 檔
第 9 行:確保 PhoneGap 已準備就緒,才執行 function onDeviceReady(){} 的程式碼,不過此例中,沒用到。
第 15~20 行:使用 PhoneGap API,彈出 Notification.alert 視窗。
http://docs.phonegap.com/en/2.5.0/cordova_notification_notification.md.html#notification.alert
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"/> <title>test</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script type="text/javascript" charset="utf-8" src="cordova-2.5.0.js"></script> <script type="text/javascript"> document.addEventListener("deviceready", onDeviceReady, false); function onDeviceReady() { } function showAlert() { navigator.notification.alert( '訊息...', function(){}, '標題', '按鈕' ); } </script> </head> <body> <p><a href="#" onclick="showAlert(); return false;">訊息視窗</a></p> </body> </html>
- 執行結果
備註:
- 如果要畫面看起來更像一般的手機 APP,可以使用 jQuery Mobile 來做網頁,預設的一些樣式、效果, 看起來更符合手機。
- 雖然用 PhoneGap 可以將網頁包成 APP,但 PhoneGap API 沒提供的手機功能,便要看有無其他人寫的 Plugin,不然就要自己寫了。
- 某些情況,可能用HTML和JS達不到。例如我為了使用 GCM 推播訊息,找了Plugin https://github.com/marknutter/GCM-Cordova。我想在訊息來時有響鈴和震動,所以在 JS 寫了"navigator.notification.beep(2);" 和 "navigator.notification.vibrate(2000);",一般情況都正常,但重開機後,雖然有收到通知訊息(通知訊息我另外寫在JAVA裡),卻沒音效和震動。
後來發現是掛在 GCMPlugin:sendJavascript javascript:null 這裡,原來是,推播訊息來了,雖然Plugin的JAVA部份有正常執行,但要送給JS部份執行"navigator.notification.beep(2);" 和 "navigator.notification.vibrate(2000);"時,就失敗了。原因是,重開機後,APP沒有開啟,當然JS沒辦法執行。後來我的震動、響鈴,就都改寫到 JAVA 了。 - PhoneGap 1.9 之後,可以使用 CordovaWebView 方式,取代 DroidGap 方式執行。
但我看官方的CordovaWebView說明文件,似乎有點簡略,例如官方寫前前兩個步驟
「1.Usebin/create
to fetch the commons-codec-1.6.jar」
「2.cd
into/framework
and runant jar
to build the cordova jar (it will create the .jar file in the formcordova-x.x.x.jar
in the/framework
folder)」
看不到framework資料夾在哪,後來才發現是要到 http://cordova.apache.org/ 下載source code。
而執行bin/create.bat 要安裝 JDK、Android SDK、Apache ant,JDK、Android SDK應該都有裝好了。Apache ant也不難裝,解壓縮,設環境變數即可。
怪的是bin/create.bat 少什麼東西,它不會詳細跟你說
,每次都說少了 JDK、Android SDK、Apache ant 其中之一。但我明明都裝了,還是不行
知道這兩個步驟只是要產生 cordova-2.5.0.jar、cordova-2.5.0.js、example...這些東西。。只好
看 bin/create.bat怎麼寫,原來是判斷有沒有 JAVA_HOME 環境變數,有沒有java.exe javac.exe ant.bat android.bat 4個指令。把這些執行檔路徑、環境變數設好,就可以編譯了。
編譯完,才
後來又遇到一些怪問題,官網找不到,google後,雖然一一解決,簡單的APP也可跑,但看LogCat有出現一些錯誤訊息,暫時沒時間研究,所以目前我還是先用 DroidGap 的方式。
針對備註所提到的GCMPlugin:sendJavascript javascript:null我也有遇過 發生的時機在已註冊後沒有執行window.GCM.register,造成gECB這個值是null,所以我增加一個方法window.GCM.foo,同時更新GCMPlugin.java,在已註冊時去執行另一個方法GCMPlugin.java execute foo,讓"gECB"這個值不會是null,所以當收到通知時,就不會有javascript:null的問題, PS: 也是使用phonegap 2.5
回覆刪除您好,我沒看到 window.GCM.register 說
刪除是指 window.plugins.GCM.register 嗎 ?
如果是指 window.plugins.GCM.register
我研究的結果,似乎先執行 JS 的 window.plugins.GCM.register 後
然後才會去執行 GCMPlugin.java 裡面的 GCMRegistrar.register,進行註冊。
忽然想到,官網提供的 JS 範例裡面的 unregister,
寫 window.GCM.unregister(GCM_Success, GCM_Fail);
我之前測試,應該是錯的,沒辦法運作,應該改成
window.plugins.GCM.unregister(GCM_Success, GCM_Fail);
另外我正式使用時,phonegap 是使用跟官網一樣的版本 2.1
對 是我打錯了:P
回覆刪除我補充說明我的做法,在已註冊的情況時,
if (!CheckDeviceRegistered()) //檢查是否已註冊
{
window.plugins.GCM.register(appID, "GCM_Event", GCM_Success, GCM_Fail);
}
else {
window.plugins.GCM.GetReadyformessage("GCM_Event", GCM_Success, GCM_Fail); //自己加進去的程式
}
GCMPlugin.js
GCM.prototype.getreadyformessage = function (eventCallback, successCallback, failureCallback) {
return cordova.exec(successCallback, //Callback which will be called when directory listing is successful
failureCallback, //Callback which will be called when directory listing encounters an error
'GCMPlugin', //Telling Cordova that we want to run "DirectoryListing" Plugin
'getreadyformessage', //Telling the plugin, which action we want to perform
[{ ecb: eventCallback }]); //Passing a list of arguments to the plugin,
};
在GCMPlugin.java
加入
public static final String GETREADYFORMESSAGE="getreadyformessage";
在execute中加入以下的判斷,由javascript呼叫時on起來
else if (GETREADYFORMESSAGE.equals(action)) {
try{
JSONObject jsonObj=new JSONObject(data.toString().substring(1, data.toString().length()-1));
gwebView = this.webView;
gECB = (String)jsonObj.get("ecb"); //gECB就不會是null,也就不會造成 sendJavascript javascript:null
result = true;
}
catch(JSONException e){
}
}
依以下版本改寫
https://github.com/marknutter/GCM-Cordova
感謝分享,遇到類似情況時,就可以參考了。
刪除我也是有記錄目前是否已註冊(用html5 localStorage),
判斷已註冊就不執行 window.plugins.GCM.register
(不過我還另外做了藉由 server 返回的訊息,可以強制再重新執行 window.plugins.GCM.register)
因為我不想使用者每次開啟 APP,就執行 window.plugins.GCM.register,感覺會多耗一點資源
但我之前測試時,已註冊後,還是可以正常執行 window.plugins.GCM.register
,重覆註冊
另外您第一篇提到"收到通知,javascript:null"的問題
之前研究的結果,收到通知時,
訊息的處理,似乎是執行 GCMIntentService.java 的 protected void onMessage
處理成 json 後,
再丟給 GCMPlugin.java 的 public static void sendJavascript
好像跟目前有無註冊較無關聯
可能我們的主程式細節有些差異,造成不同的結果。
請問xyz版大,何時能造福
回覆刪除寫個phonegap GCM推播教學呢?
您好,
刪除其實當初有想要寫,但東西有點多、我有點懶 :p...就沒寫了
我之前主要是參考這個網站
http://devgirl.org/2012/10/25/tutorial-android-push-notifications-with-phonegap/
您可以試看看,如果有問題,再討論囉
再次請問一下
回覆刪除我有個phonegap的專案 怎結合eclipse開啟的gcm 專案呢?
gcm專案我是用google提出的範例 現在想把兩個結合在一起 請問版大xyz
我該如何做呢?卡好幾天了=ˇ=
您好,因內容蠻多的,我先大概分成三個部分,簡單說明如下,您先看看是哪部分卡住。
刪除1.在 google developers console 新增專案,並記下專案的數字ID「sender ID」(Project Number)
APIS & AUTH->APIS,開啟 Google Cloud Messaging for Android
APIS & AUTH->Credentials->Create new key->取得Key for server applications裡面的「API key」
「sender ID」用在手機端程式,可用來註冊這隻手機已經安裝此APP
「API key」用在server端程式,用來將訊息發給有註冊的手機
http://developer.android.com/google/gcm/gs.html
2.手機程式(client端、APP)
因為用PhoneGap,所以要用 PhoneGap 的 GCM plugin
PhoneGap plugin for Google C2DM (GCM-Cordova)
https://github.com/marknutter/GCM-Cordova
第一步驟的「sender ID」,填在 assets\www\CORDOVA_GCM_script.js (第36行)
window.plugins.GCM.register("sender ID", "GCM_Event", GCM_Success, GCM_Fail );
這步驟正常的話,應該可以送出這隻手機的「registration ID」,
「registration ID」要送到 server 端。
3.server端程式
將接收到的「registration ID」,記錄下來(例如存到資料庫),這樣就可以知道哪些手機有安裝此APP。
要推播訊息的時候,就撈出存在資料庫的所有「registration ID」發送(我自己怕有容量限制,所以是分批發送)。
正常的話,手機上面的 APP 就可以接收到訊息。
xyz版大 我下載了https://github.com/marknutter/GCM-Cordova
刪除用eclipse 匯入
發現src 的 com.plugin.GCM 內的 GCMPlugin.java 內的 import有錯
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
我改成
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
或
import org.apache.cordova.*;
import org.apache.cordova.api.*;
底下繼承的public class GCMPlugin extends CordovaPlugin 都有錯
如圖~
刪除https://drive.google.com/file/d/0B0_P7nGYhft_RW1SdzhEWkRjVUE/edit?usp=sharing
您好,圖片的分享權限沒開,看不到喔
刪除抱歉XYZ大
回覆刪除因為高雄氣爆比較晚回(剛好住附近=ˇ=)
以上的問題已經解決的 Client端已經處理完畢
非常感謝
另外請問一下
關於Server端
我用 gcm-demo-appengine 去發送消息
有辦法可以更改預設的訊息嗎
都收到From GCM:you got message!
沒關係,安全比較重要。
刪除gcm-demo-appengine 我沒用過,不過我看 "From GCM: you got message" 出現在
https://code.google.com/p/gcm/source/browse/samples/gcm-demo-client/res/values/strings.xml
但這好像是 client 端,感覺不像是 server 送出的訊息內容,不過我沒很確定。
我之前是使用 GCM HTTP Connection Server
http://developer.android.com/google/gcm/http.html
server 端依照規定的資料格式 POST 給 https://android.googleapis.com/gcm/send 即可。
PHP 的範例,大概如下
----------
define("GOOGLE_API_KEY", "專案的API KEY"); //API KEY
//registration ID
$registrationIDs = array();
$registrationIDs[] = '要接收訊息的手機 registration ID 1';
$registrationIDs[] = '要接收訊息的手機 registration ID 2';
//要推播的訊息
$payload = array('title' => '標題', 'msg' => '推播訊息內容');
//titile、msg 這兩個名稱可以隨便設,因為是 client 自己要解析的
//像 PhoneGap plugin for Google C2DM (GCM-Cordova) 是用 message、msgcnt
//https://github.com/marknutter/GCM-Cordova/blob/master/src/com/cordova2/gcm/GCMIntentService.java
//https://github.com/marknutter/GCM-Cordova/blob/master/assets/www/CORDOVA_GCM_script.js
//要 POST 給 https://android.googleapis.com/gcm/send 的資料
$headers = array('Authorization: key=' . GOOGLE_API_KEY, 'Content-Type: application/json'); //HTTP header
$fields = array('registration_ids' => $registrationIDs, 'data' => $payload); // HTTP body
//使用 curl POST 資料
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //HTTP header
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields)); //HTTP body 傳送時轉成 JSON 格式
$result = curl_exec($ch);
curl_close($ch);
----------
POST 到 https://android.googleapis.com/gcm/send 後
google 那邊也會將每一個Registration ID 的發送結果,以 JSON 格式回傳
http://developer.android.com/google/gcm/http.html#response
然後便可以視需要做處理
例如回傳訊息中,某一個 Registration ID 是 NotRegistered,
表示手機未註冊,可能使用者移除 APP 了,那我會把這個 Registration ID 在 server 端移除。
感謝XYZ版大 已經都解決嚕
刪除除了震動和鈴聲外....
還有點擊推播訊息要打開該應用程式 也還沒完成XD
請問xyz大大 不好意思又來麻煩您
回覆刪除安裝app後的regIds gcm demo都存在 local的gae 只要重新啟動server 裡面的DB就會被清空
請問您怎解決的呢?
您好,我沒用過 GAE (Google App Engine?)
刪除如果是指 Registration ID 儲存的問題,我是在 APP 向 Google GCM 註冊成功後,再將 Registration ID 傳送到其他 Server 儲存,Server 上則是用 MySQL 儲存 (不知這不是您要問的問題)。
另外,Server 將 Registration ID 儲存成功後,我會在 APP 記錄已完成註冊,因為是用 PhoneGap,所以我直接用 HTML5 的 localStorage 記錄。或是也可以用 Android 的 SharedPreferences 來記錄。下次啟動 APP 時,如果記錄中,是尚未註冊成功,我才會再執行一次註冊的程序。
非常感謝您 那我試試看 用jdbc寫到mssql好了 :D
回覆刪除目前都成功了 非常感謝:D
回覆刪除只是現在一個頭兩個大
用phonegap 點了推播訊息不知道該怎樣打開那樣消息
只知道該點了要執行哪個class..
我是用 android 的 Notification 接收訊息,上方狀態列出現 Notification 後,往下滑就直接顯示訊息內容。點擊訊息內容,就開 APP。
刪除可參考 http://nkeegamedev.blogspot.tw/2013/02/gcm-gcm2.html 裡面的第4點。
xyz大大
回覆刪除我一樣用eclipse 匯入
發現src 的 com.plugin.GCM 內的 GCMPlugin.java 內的 import有錯
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
請問大大該如何解決!?
可能是沒加入 cordova-2.5.0.jar,可先檢查 cordova-2.5.0.jar 是否有加到 libs 裡
刪除XYZ版大,你好
回覆刪除我是PhoneGap的初學者,對於整合推播的元件,一直測不出來
比如說我依DEMO的方式,在index.html
也有載入了 CORDOVA_GCM_script.js
可是在addEventListener中,似乎沒有執行到
就如您文中所提到的navigator.notification.alert
也是沒有反應,我實在沒有其它的資源可以詢問
我可以提供我目前測試的文件,
可否麻煩你指點迷津呢
打擾之處,還請見諒
謝謝
您好,因為我已許久未碰PhoneGap,所以不確定是否跟版本差異有關,先提供幾點您先測試看看,若依然不能解決,歡迎再討論。
刪除1.本文的demo,僅是單純使用PhoneGap顯示一個navigator.notification.alert訊息,並未整合推播功能。所以您若navigator.notification.alert亦有問題,可以先不要整合推播的功能,測試最單純navigator.notification.alert是否能正常執行。以釐清是哪部分有問題。
2.如果第一點的PhoneGap基本執行沒問題,再測試推播的部分。
下載整合的PhoneGap推播元件測試
https://github.com/marknutter/GCM-Cordova
直接用 eclipse 開啟下載後的專案,然後改 CORDOVA_GCM_script.js,
將裡面 window.plugins.GCM.register(...) 第一個 senderId 參數,改成您申請的 GCM senderId。
再來要找出你手機的 registration id,
可以參考
http://devgirl.org/2012/10/25/tutorial-android-push-notifications-with-phonegap/
裡面 "You should also see the following trace in your console",底下那一段,
在 eclipse 觀察執行過程輸出的訊息,找到手機的 registration id 複製下來。
再來測試推播功能前,
您要先另外用您會的server端語言,寫一個發送訊息的程式(之後要放在server端),
寫好 server 端發訊息的程式後,將訊息發送到剛剛的手機 registration id,沒問題的話,該手機即能收到推播訊息。如果手機沒收到,這時可觀察server 端程式發送訊息後,接收到的返回訊息,裡面應該會有發送失敗之類的原因,便可針對失敗原因加以排除。
謝謝,我再試試,如有問題,再向您請教
刪除