Android + Web Service 建國科技大學 資管系 饒瑞佶 2017/3 V1.

Slides:



Advertisements
Similar presentations
JAVA 编 程 技 术 主编 贾振华 2010年1月.
Advertisements

第13章 繪圖與多媒體 13-1 顯示圖檔-行動相簿 13-2 音樂播放-音樂播放器 13-3 影片播放-視訊播放器
MVC Servlet与MVC设计模式.
實驗五:多媒體播放器選單介面.
Part 2 開發Android應用程式的流程
位置與地圖應用 此投影片為講解Android如何取得定位經緯度和使用Google Map地圖.
第二章 JAVA语言基础.
類別與物件 Class & Object.
ArrayAdapter & Spinner
厦门大学数据库实验室 报告人:谢荣东 导师:林子雨 2014年8月30日
實驗四:單位轉換程式.
Chapter 13 Android 實戰演練.
Android + JUnit 單元測試 建國科技大學資管系 饒瑞佶 2012/8/19V4.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
實驗十三:顯示目前經緯度位置.
Ch06 再談選單元件 物件導向系統實務.
使用Android控制Arduino 史先强
第10章 App微信分享的实现 倚动实验室.
Android資料庫處理 Android智慧型手機程式設計 程式設計與應用班 建國科技大學 資管系 饒瑞佶 2012/4 V1
第一个Android程序 本讲大纲: 1、创建Android应用程序 2、Android项目结构说明 3、运行Android应用程序
第8章 Android内容提供者(ContentProvider)应用
Chapter 6 Advanced UI Design.
Android智慧型手機程式設計實務應用班
Ch5 Android應用程式的主要組成.
Chapter 7 Android應用元件 Android應用元件可以幫助我們獲得系統資源訊息(ActivityManager)、提供系統服務(Service)、搜尋系統服務(SearchManager)、監聽Intent訊息(Broadcast Receiver)以及資料共享(ContentProvider和ContentResolver)。
Android介面設計 Android智慧型手機程式設計 建國科技大學 資管系 饒瑞佶 2012/4 V1 2012/8 V2
本單元介紹何謂變數,及說明變數的宣告方式。
Chapter 6 進階UI設計.
第4章 Android生命周期.
第9章 使用意圖啟動活動與內建應用程式 9-1 意圖的基礎 9-2 使用意圖啟動活動
ANDROID PROGRAMMING2.
程式設計實作.
CH7 佈局、按鈕與文字編輯元件.
Android + Service 建國科技大學 資管系 饒瑞佶.
實驗十四:顯示與控制地圖.
第2讲 移动应用开发基础知识(二) 宋婕
第6章 建立Android使用介面 6-1 介面元件的基礎 6-2 Android的事件處理 6-3 按鈕元件 6-4 文字元件
Java程序设计 第2章 基本数据类型及操作.
生活智慧王 樹德科技大學 資訊工程系 指導教授 : 陳毓璋 教授 小組成員: 劉上緯 翁維廷 洪文財.
實驗十一:待辦事項程式 (儲存在手機上).
主编:钟元生 赵圣鲁.
Android Studio介面設計 建國科技大學資管系 饒瑞佶 2016/3 V1.
透過YouTuBe API取得資料 建國科技大學 資管系 饒瑞佶 2018/1 V1.
Android Application Component
Chapter 5 Basic UI Design.
實驗九:延續實驗八, 製作一個完整音樂播放器
Location Based Services - LBS
Android WebService Android智慧型手機程式設計 建國科技大學 資管系 饒瑞佶 2012/4 V1 2012/8 V2
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
第二章 Java基本语法 讲师:复凡.
第二章 Java语法基础.
Broadcasts (廣播) 靜宜大學資管系 楊子青
Android WebService Android智慧型手機程式設計 程式設計與應用班 建國科技大學 資管系 饒瑞佶 2012/4 V1
Review 1~3.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
第16章 天气预报 --Web Service调用
進階UI元件:ListView元件以及複選 靜宜大學資管系 楊子青
RecyclerView and CardView
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
Android Speech To Text(STT)
用Intent啟動程式中的其他Activity、運用WebView顯示網頁 靜宜大學資管系 楊子青
第2章 Java语言基础.
第9章 BroadcastReceiver的使用
讀取網路資料及JSON開放資料 靜宜大學資管系 楊子青
加速感測器 靜宜大學資管系 楊子青.
第二章 Java基础语法 北京传智播客教育
Part 8 Broadcast Receiver、Service和App Widget
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
Summary
Presentation transcript:

Android + Web Service 建國科技大學 資管系 饒瑞佶 2017/3 V1

呼叫 OpenData Web Service http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire& rid=e7c46724-3517-4ce5-844f-5a4404897b7d

http://data. taipei/opendata/datalist/apiAccess http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=e7c46724-3517-4ce5-844f-5a4404897b7d

Notepad++ 解析JSON https://sourceforge.net/projects/nppjsonviewer/?source=typ_redirect

JSON JavaScript Object Notation 一種用於資料傳輸與交換的輕量級資料結構 目前網路資料傳輸或OPEN DATA都支援此格式,也使用此 格式 以文字為主 從JavaScript的陣列子集所演變而來(JS用[]來表示陣列) 並非程式語言

JSON sample { } "fullname" : "Sam Kelly", "telephones" : [ {"type" : "work" , "value" : "123-4567"}, {"type" : "home" , "value" : "987-6543"}, ], "addresses" : [ {"type" : "work" , "value" : "11 1st Ave"}, {"type" : "home" , "value" : "22 Main St"}, ] } 最簡單樣式(單純的文字資料) 3組資料 資料是一個陣列 陣列中每個元素又是一個集合

JSON中的幾個符號 :  用以分隔名稱與資料(資料對) { } 用來表示資料集(物件) [] 用來表示陣列 ,  用來分割每段「資料對」

JSON格式 物件 (object) 一個物件以「{」開始,並以「}」結束。 一個物件包含一系列非排序的名稱:值組成(資料對) 每個名稱/值對之間使用「,」分割 名稱/值(collection) 名稱和值之間使用「:」隔開 名稱為一字串 值為字串、數值、物件、布林值、陣列或是null {name:value} 資料對使用「,」分隔 陣列(Array) 使用中括弧「[ ]」將資料收集 多筆資料使用「,」分隔 [collection, collection, collection]

使用JSON 嚴格說是解析JSON 多數程式語言都具備有解析JSON的語法或函式庫 這裡使用jQuery、PHP、ASP.NET三種語法分別示範

Android vs. JSON

JSON解析 Google提供org.json.JSONObject類別 JSONObject(要解析的原字串) get(name) getJSONArray(name) 透過getJSONObject(index)取得JSONObject物件 getXXX(name), 如Int, Double, String…等 取得name對應的資料(依據資料格式)

解析範例 http://data.taipei/opendata/datalist/apiAccess?scope=resourc eAquire&rid=e7c46724-3517-4ce5-844f-5a4404897b7d

新增專案

新增上網權限 <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

layout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <TextView android:id="@+id/main_textView1" android:layout_height="wrap_content" android:text="@string/app_name" android:textAppearance="?android:attr/textAppearanceLarge" /> <LinearLayout android:orientation="horizontal">

layout <Button android:id="@+id/main_button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="重新設定" /> android:id="@+id/main_button1" android:text="解析JSON" /> </LinearLayout> <ListView android:id="@+id/main_listView1" android:layout_width="match_parent" android:layout_height="wrap_content" />

layout

strings.xml <resources> <string name="app_name">AndroidWebService</string> <string name="str_parsing">查詢API中,請稍候</string> <string name="connection_error">無法找到可用連線,請檢查網路連線</string> <string name="lost_connection">失去網路連線</string> <string name="wifi_connected">Wi-Fi已連線</string> <string name="str_parsing_ok">解析成功</string> <string name="str_user_choose">您選擇的是:</string> </resources>

加入畫面對應物件與按鈕程式

public class MainActivity extends AppCompatActivity { private TextView mTextView01; //標題 private Button mButton01, mButton02; private ListView mListView01; // 顯示資料 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView01 = (TextView) findViewById(R.id.main_textView1); //標題 mButton01 = (Button) findViewById(R.id.main_button1); //解析JSON mButton02 = (Button) findViewById(R.id.main_button2); //重新設定 mListView01 = (ListView) findViewById(R.id.main_listView1); // 顯示資料 // 開始透過WebService取得資料 mButton01.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { if (refreshDisplay) { // 如果有網路連線 mTextView01.setText(getString(R.string.str_parsing)); // 呼叫DownloadTask連線WebService進行資料取得與解析,傳入URL new DownloadTask().execute("http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=e7c46724-3517-4ce5-844f-5a4404897b7d"); } else { mTextView01.setText(getString(R.string.connection_error)); } }); // 重新設定,清除listview上的資料 mButton02.setOnClickListener(new Button.OnClickListener() { // 清除 ListView 與 重新設定上方TextView文字 mTextView01.setText(getString(R.string.app_name)); mListView01.setAdapter(null);

檢查網路是否連線? 相關變數宣告 // 網路 public static String sPref = null; private static boolean wifiConnected = false; private static boolean mobileConnected = false; // 檢查網路狀態,並設定是 wifiConnected 或 mobileConnected // 依據網路狀態改變變數wifiConnected或mobileConnected @Override protected void onStart() { super.onStart(); ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeInfo = connMgr.getActiveNetworkInfo(); if (activeInfo != null && activeInfo.isConnected()) { wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI; mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE; } else { wifiConnected = false; mobileConnected = false; }

註冊BroadcastReceiver偵測網路狀態 // onResume()時,註冊一BroadcastReceiver (receiver物件),捕捉兩個事件 // 1.ConnectivityManager.CONNECTIVITY_ACTION與2.android.net.conn.CONNECTIVITY_CHANGE // 當發生網路連線事件或網路連線改變事件時,被自訂的NetworkReceiver()接收 @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); filter.addAction("android.net.wifi.STATE_CHANGE"); receiver = new NetworkReceiver(); this.registerReceiver(receiver, filter); } protected void onPause() { super.onPause(); // 離開程式呼叫onPause(),解除receiver物件註冊 this.unregisterReceiver(receiver);

BroadcastReceiver接收系統廣播訊息 // 偵測網路狀態 public class NetworkReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.isConnected()) { wifiConnected = networkInfo.getType() == ConnectivityManager.TYPE_WIFI; mobileConnected = networkInfo.getType() == ConnectivityManager.TYPE_MOBILE; } else { wifiConnected = false; mobileConnected = false; } // 網路狀態改變時,以Toast顯示連線狀態 if (wifiConnected || mobileConnected) { refreshDisplay = true; Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show(); refreshDisplay = false; Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show(); // 失去連線,清除ListView內容 mListView01.setAdapter(null); 相關變數宣告 private NetworkReceiver receiver = new NetworkReceiver(); public static boolean refreshDisplay = true;

連線WebService進行資料取得與解析 Android規定與網路連線相關動作屬於可能耗時與會影響 UI操作的行為 需要透過並行的執行序或非同步(AsyncTask)方式進行 非同步(AsyncTask)方式是透過執行前(onPreExecute)、執 行(doInBackground)與執行後(onPostExecute)三步驟完成動 作

連線WebService進行資料取得與解析 private class DownloadTask extends AsyncTask<String, Void, String> { // 背景中執行下載資料的動作 @Override protected String doInBackground(String... urls) { return downloadUrl(urls[0]); // urls[0]為Web Service URL } // 下載完成後,開始解析JSON protected void onPostExecute(String result) { mTextView01.setText(getString(R.string.str_parsing_ok)); mList = new ArrayList<String>(); // 解析JSON try { // result為原始JSON字串 JSONObject json = new JSONObject(result); // 取得原始資料中的result區段物件 JSONObject json2 = json.getJSONObject("result"); // 取得result區段物件內名稱為results的資料(一個陣列) String data = json2.getString("results"); 相關變數宣告 private ArrayList<String> mList = new ArrayList<String>(); private ArrayAdapter<String> adapter;

// 將上面data陣列分割成可操作 JSONArray dataArray = new JSONArray(data); // 宣告陣列name,用來儲存dataArray內分割出的資料 String[] name = new String[dataArray.length()]; for (int i = 0; i < dataArray.length(); i++) { // 依序取出陣列中名稱為name與addr的資料 // 放入mList陣列表中 mList.add(dataArray.getJSONObject(i).getString("name") + "\n" + dataArray.getJSONObject(i).getString("addr")); } // MainActivity為Activity的名稱 adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, mList); // 將資料顯示到ListView mListView01.setAdapter(adapter); mListView01.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, getString(R.string.str_user_choose) + mList.get(position), Toast.LENGTH_SHORT).show(); }); } catch (Exception e) { e.printStackTrace();

連線WEBSERVICE下載資料 private String downloadUrl(String urlString) { String strHTML = ""; try { URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(10000); // milliseconds conn.setConnectTimeout(15000); conn.setRequestMethod("GET"); conn.setDoInput(true); conn.connect(); InputStream stream = conn.getInputStream();

if (stream != null) { int leng = 0; byte[] Data = new byte[100]; byte[] totalData = new byte[0]; int totalLeg = 0; do { leng = stream.read(Data); if (leng > 0) { totalLeg += leng; byte[] temp = new byte[totalLeg]; System.arraycopy(totalData, 0, temp, 0, totalData.length); System.arraycopy(Data, 0, temp, totalData.length, leng); totalData = temp; } while (leng > 0); strHTML = new String(totalData, "UTF-8"); } catch (Exception e) { e.printStackTrace(); return strHTML;

執行

透過SOAP存取

SOAP 這節的內容針對的是MS的Web Service或是使用 SOAP(Simple Object Access Protocol)標準建立的 Web Service 針對其它資料庫或是data provider,可以採用 HTTPPost或是HttpGet (前面OPEN DATA的作法)

透過Ksoap函式庫

加入Soap.java 直接從MainActivity複製 修改AndroidManifest.xml

修改WS呼叫

修改downloadUrl // 執行連線WEBSERVICE下載資料的動作 private String downloadUrl(String urlString) { WSClass ws1 = new WSClass(); // 呼叫WEB SERVICE //依據SQL選擇 String ALLNews = ws1.toWS(urlString); // 第1個參數=SQL指令 Log.i("DEBUG", "allnews=" + ALLNews); return ALLNews; // 回傳整個JSON字串 }

WSClass public class WSClass { private static final String NAMESPACE = "http://tempuri.org/"; private String URL = "http://120.109.34.168/ProjectWS/ProjectWS.asmx"; private static final String METHOD_NAME = "GetData"; private static final String SOAP_ACTION = "http://tempuri.org/GetData"; // 回傳的資料 String receivedString; public String toWS(String sqlstr) { try { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); PropertyInfo celsiusPI = new PropertyInfo(); celsiusPI.setName("SqlStr"); // Set Value celsiusPI.setValue(sqlstr); // 要執行的SQL指令,透過參數傳入 // Set dataType celsiusPI.setType(double.class); // Add the property to request object request.addProperty(celsiusPI);

WSClass SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); envelope.setOutputSoapObject(request); envelope.dotNet = true; HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.call(SOAP_ACTION, envelope); SoapPrimitive Result = (SoapPrimitive) envelope.getResponse(); receivedString = Result.toString(); if (androidHttpTransport != null) { androidHttpTransport.reset(); } } catch (Exception e) { receivedString = "not work"; return receivedString;

result

存取網路既有的WS

SOAP WebService 現有可以被呼叫的WebService 攝氏與華氏轉換 http://www.webservicex.net/ConvertTemperature.asmx

加入CelsiusToFahrenheit.java

<LinearLayout xmlns:android="http://schemas. android android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/main_textView1" android:layout_height="wrap_content" android:text="請輸入攝氏溫度" android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:id="@+id/inputC" android:ems="10" android:inputType="textPersonName" android:text="" /> <Button android:id="@+id/CtoF" android:text="轉換" /> android:id="@+id/finalresult" android:text="結果" /> </LinearLayout> layout

修改CelsiusToFahrenheit.java

修改CelsiusToFahrenheit.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ctof); mTextView01 = (TextView) findViewById(R.id.finalresult); //結果 CtoF = (Button) findViewById(R.id.CtoF); //解析JSON pramater =(EditText) findViewById(R.id.inputC); // 輸入華氏溫度 // 開始透過WebService取得資料 CtoF.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { if (refreshDisplay) { // 如果有網路連線 mTextView01.setText(getString(R.string.str_parsing)); // 呼叫DownloadTask連線WebService進行資料取得與解析,傳入URL new DownloadTask().execute(pramater.getText().toString()); } else { mTextView01.setText(getString(R.string.connection_error)); } });

修改DownloadTask與downloadUrl // 連線WebService進行資料取得與解析 private class DownloadTask extends AsyncTask<String, Void, String> { // 背景中執行下載資料的動作 @Override protected String doInBackground(String... urls) { return downloadUrl(urls[0]); // urls[0]為Web Service URL } // 下載完成後,開始解析JSON protected void onPostExecute(String result) { mTextView01.setText("轉換後華氏溫度=" + result); // 執行連線WEBSERVICE下載資料的動作 private String downloadUrl(String urlString) { WSCelsiusToFahrenheit ws1 = new WSCelsiusToFahrenheit(); // 呼叫WEB SERVICE String ALLNews = ws1.tempconvert(urlString); // 第1個參數=攝氏溫度 return ALLNews; // 回傳結果

加入WSCelsiusToFahrenheit.java public class WSCelsiusToFahrenheit { private static final String NAMESPACE = "http://www.webserviceX.NET/" ; private static final String URL="http://www.webserviceX.NET/ConvertTemperature.asmx"; private static final String METHOD_NAME = "ConvertTemp"; private static final String SOAP_ACTION = "http://www.webserviceX.NET/ConvertTemp"; // 回傳的資料 String receivedString; public String tempconvert(String temp){ String receivedString="not work"; //預設回傳值 try { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); request.addProperty("Temperature", temp); //傳入攝氏溫度 request.addProperty("FromUnit", "degreeCelsius"); //傳入被轉換單位 request.addProperty("ToUnit", "degreeFahrenheit"); //傳入轉換單位 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.setOutputSoapObject(request); envelope.dotNet = true; HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

result