Location Based Services - LBS 系統實例 – 天災救援
Outline 系統簡介 系統規劃 系統環境建置 天災救援建置
Chapter1. 系統簡介
系統簡介 1. 創作動機 近年台灣地區各種天災所帶來的災害不容小覷,以八八水災重創南台灣為例,因災區無法向外界即時求援,而造成災情持續擴大。
系統簡介 1. 創作動機 附近有間全家 在有隻小貓 旁邊 有更明確 的目標嗎? 報案地點在哪邊?
系統簡介 1. 創作動機 天災救援因應而生
系統簡介 Mobile Device 2. 系統功能 災情定位 災情回報 物資需求 災情監控 物資管理 災情管理 Web
系統簡介 2. 系統架構 Client Web Server Web Service Database Internet
系統簡介 3. 系統操作流程 天災資訊網 (開放一般民眾查詢) 發送求救 災情回報 天災管理 資訊系統 救援管理系統 (救難人員使用)
系統簡介 3. 系統操作流程 一般民眾
系統簡介 3. 系統操作流程 救援人員
系統簡介 3. 系統操作流程 緊急登入
系統簡介 3. 系統操作流程 一般民眾天災管理系統 提供一般民眾透過網頁方式來查詢目前發佈災害的位置,並可掌握即時最新消息,亦可以在平台上發佈尋人啟事。
系統簡介 3. 系統操作流程 救難人員天災救援管理系統 救難人員可以掌握目前災害的詳細資訊(詳細地點與照片),並可以即時作物資的配送與救難人員的調度。
Chapter2. 系統規劃
系統規劃 1. 系統功能介面規劃 Android Web 天災管理系統 ID Picture Type Require Position Simid Check # 災害照片 災害類型 需求或描述 位置座標 傳送人 確認按鈕
系統規劃 2.ER-Model alarmType ad_id simID Name Notify check User Alarm_Detail simid lat lng location alarmDetail
帳號登入(若沒帳號則會註冊,若有帳號則會更新姓名) 系統規劃 3. Web Service 規劃 Service Http 功能描述 需求參數 返回格式 返回參數 備註 login.php get 帳號登入(若沒帳號則會註冊,若有帳號則會更新姓名) simid json response name alarmDetail.php post 新增災難相關資訊 (文字&照片) alarmType alarmDetail location photo alarmStatus.php 查詢發佈災難的狀態 (0:未確認,1:已確認) String 0 or 1 ad_id
系統規劃 4.天災救援 Use Case Diagram 天災救援系統(Android) 使用者 天災救援系統(Web) 救災人員 地圖打點 <<include>> 地圖打點 災情通報 <<include>> 通報 等待回覆 使用者 會員登入 天災救援系統(Web) <<include>> 災情確認 通報災情管理 救災人員
系統規劃 5.天災救援 Class Diagram <<persistent>> User - simid : String - name : String - lat : Double - lng : Double + getName(simid): String + addUser(simid,name) <<persistent>> Alarm_Detail - ad_id : Int - simid : String - alarmType : String - alarmDetail : String - location : Double - check : Int + addAlarm (simid,alarmType,alarmDetail,location) + getAlarmList(aid): List + getStatus(simid,ad_id): String 1 0…*
系統規劃 6.天災救援 Sequence Diagram :會員 :報警 Web Android Service login(simid,name):boolean checkUser(simid,name):json return return addAlarm (alarmType,alarmDetail,location,simid,photo) addAlarm (alarmType,alarmDetail,location,simid,photo): json return return getStatus(simid,ad_id) getStatus(simid,ad_id): json return return getAlarmList(): List getAlarmList(): json return return
Chapter3. 系統環境建置
系統環境建置 1.建置資料庫 點擊Admin,啟動MySQL管理介面
系統環境建置 2.建置資料庫 alarm utf8_general_ci 1 2 3 4
系統環境建置 3.建置資料庫欄位 user 2 3 user 2 1 2
系統環境建置 3.建置資料庫欄位 建立user相關欄位
系統環境建置 3.建置資料庫欄位 alarm_detail 6 3 alarm_detail 6 1 2
系統環境建置 3.建置資料庫欄位 建立alarm_detail相關欄位
Chapter4. 天災救援建置
天災救援建置 3. 權限說明 Uses Permission INTERNET 網路存取權限 ACCESS_FINE_LOCATION GPS定位權限 ACCESS_COARSE_LOCATION 無線網路定位 ACCESS_NETWORK_STATE 允許應用程序訪問有關GSM網絡信息 WRITE_EXTERNAL_STORAGE 允許應用程序寫入外部存儲器
天災救援建置 3. 權限說明 Uses Permission Permission MAPS_RECEIVE 允許下載圖資 READ_PHONE_STATE 允許存取 SIM Card 資訊 READ_GSERVICES 允許 API 訪問 Google Web 的服務 Permission MAPS_RECEIVE 允許下載圖資
在其他user-permission底下貼上READ_GSERVICES權限 天災救援建置 在其他user-permission底下貼上READ_GSERVICES權限 只有READ_GSERVICES的權限需要透過手動的方式加入到AndroidManifest.xml程式碼當中 2 1 <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
天災救援建置 4. 物件參數設定 value.java 1 2 3 4 5 6 7 8 9 而 service 參數要設定成自己的位置 /* package com.stu.alarm; 2 public final class value { 3 public static String simid = ""; 4 public static String name = ""; 5 public static String service = 6 "http://localhost/service/alarm/"; 7 /* 每個頁面可能會用到的參數, 8 都會先宣告在 value 物件當中 9 而 service 參數要設定成自己的位置 /* 10 11 } 打開 value.java
天災救援建置 5. 登入功能描述 Android Web Service 1 MainActivity.java Require 將 SIMID 與 NAME 傳送給 Service 後,便可直接登入到功能頁面 Require response simid Web Service name JSON login.php GET 第一次登入會透過SIM CARD ID 當作帳號與輸入姓名來新增一筆帳號,再次登入僅會更新姓名資料 Response
天災救援建置 5-1. 登入功能 Service login.php 1 2 3 4 5 6 7 8 9 10 11 if (isset($_GET['simid']) && isset($_GET['name'])) 2 { 3 $simid = mysql_real_escape_string($_GET['simid']); 4 $name = mysql_real_escape_string($_GET['name']); 5 //透過 GET 代入 simid (SIM Card ID) 與 name (名稱) 參數 6 include("../connect.php"); 7 $sql = "SELECT * FROM user WHERE simid = '$simid'"; 8 $result = mysql_query($sql, $link) or die("oops"); 9 //指定查詢 $simid 是否有註冊紀錄,若回傳資料筆數為 0 則表示未註冊 1 則已註冊 10 if(mysql_num_rows($result) != 0) { 11 $sql = "Update user SET name = '$name' WHERE simid = '$simid'";
天災救援建置 12 // 若已註冊則更新這個 $simid 的 name 欄位,更改名稱 13 $result = mysql_query($sql, $link) or die("oops"); 14 }else{ 15 $sql = "INSERT INTO user(simid,name,lat,lng) VALUES('$simid','$name','0','0')"; 16 //若未註冊則新增一筆使用者紀錄,預設 lat 與 lng 經緯度位置為 0 17 18 } 19 if($result) { 20 $data['responese'] = 'success'; 21 echo json_encode($data); 22 23 24
天災救援建置 5-2. 登入功能 Layout activity_main.xml 1 2 3 4 5 6 7 8 9 10 11 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 <Button 11 android:id="@+id/button1"
天災救援建置 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_alignParentBottom="true" 15 android:layout_centerHorizontal="true" 16 android:layout_marginBottom="78dp" 17 android:text="登入" /> 18 <EditText 19 android:id="@+id/editText1" 20 21 22 android:layout_alignParentTop="true" 23 24 android:layout_marginTop="95dp"
天災救援建置 25 android:ems="10" 26 android:inputType="textMultiLine" > 27 <requestFocus /> 28 </EditText> 29 <TextView 30 android:id="@+id/textView1" 31 android:layout_width="wrap_content" 32 android:layout_height="wrap_content" 33 android:layout_alignBottom="@+id/editText1" 34 android:layout_centerHorizontal="true" 35 android:layout_marginBottom="51dp" 36 android:text="名稱" 37 android:textAppearance="?android:attr/textAppearanceLarge" /> 38 </RelativeLayout>
天災救援建置 5-3. 登入功能 MainActivity.java 1 2 3 4 5 6 7 8 9 import org.apache.http.HttpEntity; 3 import org.apache.http.HttpResponse; 4 import org.apache.http.client.HttpClient; 5 import org.apache.http.client.methods.HttpGet; 6 import org.apache.http.impl.client.DefaultHttpClient; 7 import org.apache.http.util.EntityUtils; 8 import android.app.Activity; 9 import android.content.Context; 10 import android.content.Intent; 11 import android.os.Bundle; Android:MainActivity.java 打開 MainActivity.java
天災救援建置 12 import android.telephony.TelephonyManager; 13 import android.util.Log; 14 import android.view.View; 15 import android.view.View.OnClickListener; 16 import android.widget.Button; 17 import android.widget.EditText; 18 19 public class MainActivity extends Activity { 20 EditText name; 21 Button login; 22 23 protected void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState);
天災救援建置 25 setContentView(R.layout.activity_main); 26 findViwe(); 27 //前置先與 Layout 元件作連結 28 simid(); 29 //取得 SIM Card ID 30 initListener(); 31 32 } 33 public void findViwe() { 34 name = (EditText) findViewById(R.id.editText1); 35 login = (Button) findViewById(R.id.button1); 36 //連結 EditText 與 Button 元件,並給定到參數中 37
天災救援建置 38 39 40 41 42 43 44 45 46 47 48 49 50 public void simid() { TelephonyManager manager = 40 (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 41 value.simid = manager.getDeviceId(); 42 //透過 TelephonyManager 取得 SimCard ID,存放到 value.simid 43 } 44 45 public void initListener() { 46 login.setOnClickListener(new OnClickListener() { 47 public void onClick(View v) { 48 value.name = name.getText().toString(); 49 login Login = new login(); 50 Login.start();
天災救援建置 51 52 53 54 55 並在執行 Login 執行緒後,轉跳功能選擇頁 /* 56 } 57 }); 58 59 60 Intent intent = new Intent(); 52 intent.setClass(MainActivity.this, Map.class); 53 startActivity(intent); 54 /* 將 name 當中輸入的字串設定給 value 物件, 55 並在執行 Login 執行緒後,轉跳功能選擇頁 /* 56 } 57 }); 58 59 60 61 62 63
天災救援建置 64 class login extends Thread { 65 66 public void run() { 67 super.run(); 68 try { 69 HttpClient client = new DefaultHttpClient(); 70 String url = value.service + "login.php?simid=" + value.simid 71 + "&name=" + value.name; 72 //將 value 物件中的 service 與 simid 與 name 透過 GET 呼叫 login.php 73 HttpGet get = new HttpGet(url); 74 HttpResponse response = client.execute(get); 75 //執行 url 設定的 Login Service 76
天災救援建置 77 HttpEntity resEntity = response.getEntity(); 78 String result = EntityUtils.toString(resEntity); 79 //回傳執行的結果並存放在 result 當中 80 } catch (Exception e) { 81 e.printStackTrace(); 82 } 83 84 85 86 87 88 89
天災救援建置 6. 災害通報功能描述 Android Web Service 2 Map.java DetailActivity.java 3 Bundle(lat,lng) Map.java DetailActivity.java Require 在地圖上打點(災害位置)後 Bundle座標位置到災情回報頁面,並填寫災害類型與需求與拍攝現場照片 alarmType alarmDetail response location Web Service JSON simid alarmDetail.php photo 處理上傳相片並建立一筆新的災難紀錄 POST Response
天災救援建置 6-1. 災害通報功能 Service alarmDetail.php 1 @header("Content-Type:text/html; charset=utf-8"); 2 3 if (isset($_POST['alarmType']) && isset($_POST['alarmDetail']) && 4 isset($_POST['location']) && isset($_POST['simid']) && isset($_FILES['photo'])) { 5 6 $alarmType = mysql_real_escape_string($_POST['alarmType']); 7 $alarmDetail = mysql_real_escape_string($_POST['alarmDetail']); 8 $location = mysql_real_escape_string($_POST['location']); 9 $simid = mysql_real_escape_string($_POST['simid']); 10 /* 11 * 透過 Http Post 方式傳入
天災救援建置 12 * alarmDetail: 災害敘述或需求 13 * location: 災害位置(經緯度) 14 * simid: 使用者ID 15 * photo: 上傳檔案(照片) 16 */ 17 include("connect.php"); 18 $sql = "INSERT INTO alarm_detail(alarmDetail,alarmType,location,simid) 19 VALUES('$alarmDetail','$alarmType','$location','$simid')"; 20 $result = mysql_query($sql, $link) or die("oops"); 21 $last_id = mysql_insert_id(); 22 //加入一筆新的災害通報,並把自動產生的ID記錄到$last_id當中 23 if($result) 24 {
天災救援建置 25 if ($_FILES["photo"]["error"] > 0){ 26 echo "Error: " . $_FILES["photo"]["error"]; 27 //判斷上傳檔案是否有錯誤 28 }else{ 29 move_uploaded_file($_FILES["photo"]["tmp_name"],"upload/".$last_id.".jpg"); 30 echo 'OK:'.$last_id; 31 //若檔案上傳正常則將檔案從暫存位置移動到指定的目錄位置 32 } 33 }else 34 { 35 echo "Error"; 36 } 37
天災救援建置 6-2. 災害通報地圖打點功能 Layout map.xml 1 2 3 4 5 6 7 8 9 10 11 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="fill_parent" 3 android:layout_height="fill_parent"> 4 5 <Button 6 android:id="@+id/button01" 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:layout_centerHorizontal="true" 10 android:layout_alignParentBottom="true" 11 android:text="下一步"/>
天災救援建置 12 <fragment 13 android:id="@+id/map" 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" 16 android:layout_alignParentTop="true" 17 android:layout_above="@id/button01" 18 class="com.google.android.gms.maps.MapFragment"/> 19 </RelativeLayout> 20 21 22 23 24
天災救援建置 6-3. 災害通報功能 Layout activity_detail.xml 1 2 3 4 5 6 7 8 9 10 11 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 <TextView 11 android:id="@+id/textView1"
天災救援建置 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_marginTop="10dp" 15 android:text="災害類型:"/> 16 <Spinner 17 android:id="@+id/spinner1" 18 19 20 android:layout_below="@id/textView1" 21 /> 22 <EditText 23 android:id="@+id/editText1" 24 android:layout_width="match_parent"
天災救援建置 25 android:layout_height="wrap_content" 26 android:layout_below="@id/spinner1" 27 android:layout_marginTop="10dp" 28 android:hint="災害需求" 29 /> 30 <ImageButton 31 android:id="@+id/imageButton1" 32 android:layout_width="100dp" 33 android:layout_height="100dp" 34 android:layout_below="@id/editText1" 35 android:layout_centerHorizontal="true" 36 android:layout_marginTop="10dp"/> 37
天災救援建置 38 <Button 39 android:id="@+id/button1" 40 android:layout_width="wrap_content" 41 android:layout_height="wrap_content" 42 android:layout_below="@id/imageButton1" 43 android:layout_centerHorizontal="true" 44 android:layout_marginTop="10dp" 45 android:text="Send" 46 /> 47 </RelativeLayout> 48 49 50
天災救援建置 6-4. 災害通報地圖打點功能 Map.java 打開 Map.java 1 import android.app.Activity; 2 import android.content.Intent; 3 import android.os.Bundle; 4 import android.view.View; 5 import android.widget.Button; 6 import android.view.View.OnClickListener; 7 import com.google.android.gms.maps.GoogleMap; 8 import com.google.android.gms.maps.MapFragment; 9 import com.google.android.gms.maps.model.LatLng; 10 import com.google.android.gms.maps.model.Marker; 11 import com.google.android.gms.maps.CameraUpdateFactory; 打開 Map.java
天災救援建置 12 import com.google.android.gms.maps.model.MarkerOptions; 13 import com.google.android.gms.maps.GoogleMap.OnMapClickListener; 14 import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; 15 16 public class Map extends Activity implements OnMarkerClickListener,OnMapClickListener 17 { 18 //實作 OnMarkerClickListener 與 OnMapClickListener 19 static LatLng AlarmLocation = null; 20 GoogleMap mMap; 21 Button button01; 22 LatLng latlng = new LatLng(22.764702, 120.371935); 23 Marker myMarker; 24
天災救援建置 25 @Override 26 protected void onCreate(Bundle savedInstanceState) { 27 super.onCreate(savedInstanceState); 28 setContentView(R.layout.map); 29 findViwe(); 30 //前置先與 Layout 元件作連結 31 initListener(); 32 //初始化相關監聽物件 33 setMap(); 34 //地圖初始設定 35 } 36 37 public void findViwe() {
天災救援建置 38 button01=(Button)findViewById(R.id.button01); 39 mMap = ((MapFragment) getFragmentManager() 40 .findFragmentById(R.id.map)) 41 .getMap(); 42 } 43 44 public void initListener() { 45 button01.setOnClickListener(new OnClickListener() { 46 @Override 47 public void onClick(View v) { 48 // TODO Auto-generated method stub 49 if(AlarmLocation != null) 50 {
天災救援建置 51 Intent intent = new Intent(); 52 intent.setClass(Map.this, DetailActivity.class); 53 intent.putExtra("location", 54 AlarmLocation.latitude + "," + 55 AlarmLocation.longitude); 56 startActivity(intent); 57 /* 58 * 按下按鈕後先判斷 AlarmLocation 是否有值 59 * 再傳值 Location 至下一個 Activity 60 */ 61 } 62 } 63 });
天災救援建置 64 } 65 66 public void setMap(){ 67 } 65 66 public void setMap(){ 67 mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); 68 mMap.moveCamera(CameraUpdateFactory. 69 newLatLngZoom(latlng, 15.0f)); 70 mMap.setOnMapClickListener(this); 71 //設置地圖 72 73 74 @Override 75 public boolean onMarkerClick(Marker marker) { 76 // TODO Auto-generated method stub
天災救援建置 77 if (marker.equals(myMarker)) { 78 // handle click here 79 } } 80 return false; 81 } 82 83 @Override 84 public void onMapClick(LatLng point) { 85 86 if(myMarker == null) 87 { 88 MarkerOptions markerOptions = new MarkerOptions(); 89 markerOptions.position(point);
天災救援建置 90 markerOptions.title("災害地點"); 91 myMarker = mMap.addMarker(markerOptions); 92 //點擊地圖後,即會在地圖上新增災害標記位置 93 }else 94 { 95 myMarker.setPosition(point); 96 //如果已經新增過標記,即作災害標記位置的移動 97 } 98 AlarmLocation = point; 99 //觸發點擊地圖即紀錄座標位置於 AlarmLocation 100 } 101 102 }
打開 DetailActivity.java 天災救援建置 6-5. 災害通報功能 DetailActivity.java 1 import java.io.ByteArrayOutputStream; 2 import java.io.FileNotFoundException; 3 import java.nio.charset.Charset; 4 import org.apache.http.HttpResponse; 5 import org.apache.http.client.HttpClient; 6 import org.apache.http.client.methods.HttpPost; 7 import org.apache.http.entity.ContentType; 8 import org.apache.http.entity.mime.HttpMultipartMode; 9 import org.apache.http.entity.mime.MultipartEntityBuilder; 10 import org.apache.http.entity.mime.content.ByteArrayBody; 11 import org.apache.http.impl.client.DefaultHttpClient; 打開 DetailActivity.java
天災救援建置 12 import org.apache.http.protocol.BasicHttpContext; 13 14 import org.apache.http.protocol.HttpContext; 15 import org.apache.http.util.EntityUtils; 16 import android.app.Activity; 17 import android.content.ContentResolver; 18 import android.content.Intent; 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapFactory; 21 import android.net.Uri; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.os.Message;
天災救援建置 25 import android.util.Log; 26 import android.view.View; 27 import android.view.View.OnClickListener; 28 import android.widget.AdapterView; 29 import android.widget.AdapterView.OnItemSelectedListener; 30 import android.widget.ArrayAdapter; 31 import android.widget.Button; 32 import android.widget.EditText; 33 import android.widget.ImageButton; 34 import android.widget.Spinner; 35 36 public class DetailActivity extends Activity { 37
天災救援建置 38 Spinner spinner1; 39 EditText editText1; 40 ImageButton imageButton1; 41 Button button1; 42 String[] SpinnerList = new 43 String[]{"火災","水災","地震", 44 "土石流","報案","物資","其他"}; 45 String location = ""; 46 String alarmType = ""; 47 String alarmDetail = ""; 48 String ad_id = ""; 49 Bitmap photo = null; 50
天災救援建置 51 @Override 52 protected void onCreate(Bundle savedInstanceState) { 53 super.onCreate(savedInstanceState); 54 setContentView(R.layout.activity_detail); 55 findViwe(); 56 //前置先與 Layout 元件作連結 57 getValue(); 58 //取得前一個Activity傳遞資料 59 init(); 60 //初始化物件 61 initListener(); 62 //初始化相關監聽物件 63 }
天災救援建置 64 65 public void findViwe() { 66 65 public void findViwe() { 66 spinner1=(Spinner)findViewById(R.id.spinner1); 67 editText1=(EditText)findViewById(R.id.editText1); 68 imageButton1=(ImageButton)findViewById(R.id.imageButton1); 69 button1=(Button)findViewById(R.id.button1); 70 } 71 72 public void getValue() 73 { 74 Intent intent1=getIntent(); 75 location = intent1.getStringExtra("location"); 76 //取得Map Activity 傳遞的 location 值
天災救援建置 77 } 78 79 public void init() 80 { 81 } 78 79 public void init() 80 { 81 ArrayAdapter ListAD = new ArrayAdapter 82 (this,android.R.layout.simple_spinner_item,SpinnerList); 83 spinner1.setAdapter(ListAD); 84 //初始化下拉式選單 85 86 87 public void initListener() { 88 89 spinner1.setOnItemSelectedListener(new OnItemSelectedListener(){
天災救援建置 90 91 @Override 92 public void onItemSelected(AdapterView arg0, View arg1, 93 int position, long arg3) { 94 // TODO Auto-generated method stub 95 alarmType = SpinnerList[position]; 96 //將所選擇的 position 對應給 Spinner String Array 並存放在 alarmType 97 } 98 99 100 public void onNothingSelected(AdapterView arg0) { 101 102
天災救援建置 103 } 104 105 }); 106 107 imageButton1.setOnClickListener(new OnClickListener() { 108 @Override 109 public void onClick(View arg0) { 110 // TODO Auto-generated method stub 111 Intent intent = new Intent( 112 android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 113 startActivityForResult(intent, 1); 114 /* 透過 startActivityForResult 啟動拍照功能 115 * 並透過 intent 轉跳到攝影畫面再返回相關照片路徑資料
天災救援建置 116 */ 117 } 118 119 }); 120 button1.setOnClickListener(new OnClickListener() { 121 @Override 122 public void onClick(View v) { 123 AlarmUpload alarmUpload = new AlarmUpload(); 124 alarmUpload.start(); 125 //當按下按鈕後便啟動 AlarmUpload 執行序 126 127 128 }
天災救援建置 129 130 class AlarmUpload extends Thread { 131 @Override 132 130 class AlarmUpload extends Thread { 131 @Override 132 public void run() { 133 // TODO Auto-generated method stub 134 super.run(); 135 alarmDetail = editText1.getText().toString(); 136 //取得 textview 輸入之內容 137 if(location.isEmpty()||alarmType.isEmpty()|| 138 alarmDetail.isEmpty()||photo==null) 139 { 140 return; 141 //判斷是否有資料不齊全,若不齊全則跳出
天災救援建置 142 } 143 144 try { 145 HttpClient httpClient = new DefaultHttpClient(); 146 HttpContext localContext = new BasicHttpContext(); 147 HttpPost httpPost = new HttpPost( 148 value.service + "alarmDetail.php" ); 149 //透過 HttpPost 將 Service URL 位置設定好 150 MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create(); 151 meBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 152 meBuilder.setCharset(Charset.forName(HTTP.UTF_8)); 153 photo = Bitmap.createScaledBitmap(photo, photo.getWidth()/2, 154 photo.getHeight()/2, true);
天災救援建置 155 ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); 156 byte [] data = baoStream.toByteArray(); 157 //將photo調整長寬比例後並將其轉置存放在 ByteArray 158 159 meBuilder.addPart("photo",new ByteArrayBody(data, "test.jpg")); 160 meBuilder.addTextBody("alarmType", alarmType, ContentType 161 .create( "text/plain" , Charset.forName( HTTP.UTF_8))); 162 meBuilder.addTextBody("alarmDetail", alarmDetail,ContentType 163 164 meBuilder.addTextBody("location", location); 165 meBuilder.addTextBody("simid", value.simid); 166 //透過 MultipartEntityBuilder來建立 Post 傳遞相關資訊 167 httpPost.setEntity(meBuilder.build()); 168 HttpResponse response = httpClient.execute(httpPost, localContext);
天災救援建置 169 String Response = EntityUtils.toString(response.getEntity()); 170 171 if(Response.startsWith("OK")) 172 { 173 ad_id = Response.split(":")[1]; 174 //取出 Web Service 新建立災情自動編號的回傳 ID 值 175 Message msg = new Message(); 176 msg.what=1; 177 mHandler.sendMessage(msg); 178 //此 Web Service 回傳資訊是以":"作間隔,例: OK;2,故透過 split 來作分割 179 } 180 } catch (Exception e) { 181 e.printStackTrace();
天災救援建置 182 } 183 } 184 } 185 186 protected void onActivityResult(int requestCode, int resultCode, Intent data) 187 { 188 if (requestCode==1&&resultCode == RESULT_OK) 189 { 190 Uri uri=data.getData(); 191 ContentResolver CR=getContentResolver(); 192 try { 193 //由抽象資料接口轉換圖檔路徑為 Bitmap 194 photo= BitmapFactory.decodeStream(CR.openInputStream(uri));
天災救援建置 195 imageButton1.setImageBitmap(photo); 196 } catch (FileNotFoundException e) { 197 Log.e("Exception", e.getMessage(),e); 198 } 199 } 200 super.onActivityResult(requestCode, resultCode, data); 201 } 202 203 private Handler mHandler = new Handler() { 204 public void handleMessage(Message msg) { 205 super.handleMessage(msg); 206 207 if(msg.what==1)
天災救援建置 208 { 209 Intent intent = new Intent(); 210 { 209 Intent intent = new Intent(); 210 intent.setClass(DetailActivity.this, StatusActivity.class); 211 intent.putExtra("ad_id", ad_id); 212 startActivity(intent); 213 } 214 /* 215 透過 handler 來請 main thread 處理 setList 216 sub thread 不能值接對 UI 作控制,必須透過 handler 來請主程序作 217 */ 218 } 219 }; 220 }
天災救援建置 7. 災害通報遠端回覆功能描述 Android Web Service 4 StatusActivity.java Require 在將災害資料上傳後,便等待遠端救難人員的確認訊息 simid 0 or 1 ad_id String Web Service GET alarmStatus.php 查詢災害狀態是否已被確認
天災救援建置 7-1. 災害通報功能 Service alarmStatus.php 1 @header("Content-Type:text/html; charset=utf-8"); 2 if (isset($_GET['simid'])&&isset($_GET['ad_id'])) { 3 $simid = mysql_real_escape_string($_GET['simid']); 4 $ad_id = mysql_real_escape_string($_GET['ad_id']); 5 6 include("connect.php"); 7 8 $sql = "SELECT `check` FROM alarm_detail 9 WHERE simid = '$simid' AND ad_id = '$ad_id'"; 10 $result = mysql_query($sql, $link) or die("oops"); 11 //指定查詢 $simid 與$ad_id 條件,察看災情處理人員是否確認收到這筆資訊
天災救援建置 12 if(mysql_num_rows($result) != 0) 13 { 14 { 14 while($row = mysql_fetch_array($result)) { 15 echo $row['check']; 16 //show 出災難通報是否已確認(check -> 已確認:1, 未確認:0 ) 17 break; 18 } 19 } 20 } 21 22 23 24
天災救援建置 7-2.災害通報功能 Layout activity_status.xml 1 2 3 4 5 6 7 8 9 10 11 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 <TextView 11 android:id="@+id/textView1"
天災救援建置 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_centerHorizontal="true" 15 android:layout_marginBottom="51dp" 16 android:text="災情處理中心未確認" 17 android:textAppearance="?android:attr/textAppearanceLarge" /> 18 19 </RelativeLayout> 20 21 22 23 24
打開 StatusActivity.java 天災救援建置 7-3.災害通報功能 StatusActivity.java 1 import org.apache.http.HttpEntity; 2 import org.apache.http.HttpResponse; 3 import org.apache.http.client.HttpClient; 4 import org.apache.http.client.methods.HttpGet; 5 import org.apache.http.impl.client.DefaultHttpClient; 6 import org.apache.http.util.EntityUtils; 7 import android.app.Activity; 8 import android.content.Intent; 9 import android.os.Bundle; 10 import android.os.Handler; 11 import android.os.Message; 打開 StatusActivity.java
天災救援建置 12 import android.widget.TextView; 13 14 14 public class StatusActivity extends Activity { 15 TextView textView; 16 String ad_id = ""; 17 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_status); 21 getValue(); 22 //取出前一個 Activity 傳遞的值 23 findViwe(); 24
天災救援建置 25 //前置先與 Layout 元件作連結 26 AlarmStatus AS = new AlarmStatus(); 27 AS.start(); 28 //執行 AlarmStatus 執行序 29 } 30 31 public void getValue() 32 { 33 Intent intent1 = getIntent(); 34 ad_id = intent1.getStringExtra("ad_id"); 35 36 37 public void findViwe() {
天災救援建置 38 textView = (TextView) findViewById(R.id.textView1); 39 //連結 EditText 與 Button 元件,並給定到參數中 40 } 41 42 // 登入的執行序 43 class AlarmStatus extends Thread { 44 @Override 45 public void run() { 46 // TODO Auto-generated method stub 47 super.run(); 48 try { 49 HttpClient client = new DefaultHttpClient(); 50 String url = value.service + "alarmStatus.php?simid="
天災救援建置 51 + value.simid+"&ad_id=" + ad_id; 52 //將 value 物件中的 service 與 simid 與 name 透過 GET 呼叫 login.php 53 HttpGet get = new HttpGet(url); 54 HttpResponse response = client.execute(get); 55 //執行 url 設定的 Login Service 56 HttpEntity resEntity = response.getEntity(); 57 String result = EntityUtils.toString(resEntity); 58 if(result.equals("1")) 59 { 60 Message msg = new Message(); 61 msg.what=1; 62 mHandler.sendMessage(msg); 63 //若回傳訊息值為 1,則執行畫面更新為已確認
天災救援建置 64 }else 65 { 66 Thread.sleep(5000); 67 { 66 Thread.sleep(5000); 67 AlarmStatus AS = new AlarmStatus(); 68 AS.start(); 69 //若回傳訊息為 0,則休眠 5s 在重複執行確認動作 70 } 71 } catch (Exception e) { 72 e.printStackTrace(); 73 } 74 } 75 } 76
天災救援建置 } 77 private Handler mHandler = new Handler() { 78 public void handleMessage(Message msg) { 79 super.handleMessage(msg); 80 if(msg.what == 1) 81 { 82 textView.setText("災情處理中心已確認"); 83 } 84 /* 透過 handler 來請 main thread 處理 setList 85 * sub thread 不能值接對 UI 作控制,必須透過 handler 來請主程序作 86 */ 87 } 88 }; 89 }
天災救援建置 8. 天災後端確認功能描述 Web alarm.php 天災管理系統 Require 顯示全部天災通報相關資訊,並且在即時確認後更新通報狀態,讓手機端可以接收確認訊息 response ad_id POST 天災管理系統 ID Picture Type Require Position Simid Check # 災害照片 災害類型 需求或描述 位置座標 傳送人 確認按鈕
天災救援建置 8-1. 天災後端確認 Web alarm.php 1 <!-- Latest compiled and minified CSS Bootstrap --> 2 <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> 3 <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"> 4 <style type="text/css"> 5 td{ 6 vertical-align: middle !important; 7 text-align: center !important; 8 } 9 </style> 10 <body> 11 <div class="container">
天災救援建置 12 <table frame="box" rules="all" class="center-block table table-striped table-hover"> 13 <th colspan="7" class="text-center">天災管理系統</th> 14 <tr class="text-center"> 15 <td>ID</td> 16 <td>Picture</td> 17 <td>Type</td> 18 <td>Require</td> 19 <td>Position</td> 20 <td>Simid</td> 21 <td>Check</td> 22 <tr> 23 <?php 24 @header("Content-Type:text/html; charset=utf-8");
天災救援建置 25 include("connect.php"); 26 if(isset($_POST['ad_id'])) 27 { 28 $ad_id = mysql_real_escape_string($_POST['ad_id']); 29 $sql = "Update alarm_detail SET `check` = '1' WHERE ad_id = '$ad_id'"; 30 $result = mysql_query($sql, $link) or die("oops"); 31 //如果$_POST['ad_id']有取得值,則進行更新該 ad_id 的 check 狀態為1 32 } 33 $sql = "SELECT * FROM alarm_detail"; 34 35 //查詢所有天災通報的資訊 36 if(mysql_num_rows($result) != 0) 37
天災救援建置 38 while($row = mysql_fetch_array($result)) { 39 echo '<tr><td>'.$row['ad_id'].'</td><td>' 40 .'<img src="upload/'.$row['ad_id'] 41 .'.jpg" alt="photo" width="100" class' 42 .'="img-thumbnail center-block"></td><td>' 43 .$row['alarmType'].'</td><td>' 44 .$row['alarmDetail'].'</td><td>' 45 .$row['location'].'</td><td>' 46 .$row['simid'].'</td><td>'; 47 //使用迴圈將資料逐筆取出,並且寫至html的表格當中 48 if($row['check']=='0') 49 { 50 echo '<form name="form1" method="post" action="">'
天災救援建置 51 .'<input type="submit" name="submit" value="確認"' 52 .' class="btn btn-primary center-block">'; 53 echo '<input type="hidden" name="ad_id" value="' 54 .$row['ad_id'].'" ></form>'; 55 //檢查check欄位目前狀態, 值為 0:則秀出按鈕 1:不顯示按鈕 56 } 57 echo '</td></tr>'; 58 59 60 ?> 61 </table> 62 </div> 63 </body>
天災救援建置 8-1. 天災後端確認 Web 天災後端頁面展示