DB연동 - XML 파싱을 이용한 Mysql 연동
방학하고나서 레퍼런스폰에만 돌아가던것을 고치기 위해 파싱을 이용한 방법을 공부했다.
JSP로 할까 PHP로 할까 고민했었는데
내컴엔 APM이 깔려있어서 그냥 PHP로 했다.(사실 간단한거라면 PHP가 JSP보다 쉬운거 같으니까 PHP로 했다.)
이렇게 이름과 가격을 입력하고 입력버튼을 누르면 웹서버에 있는 Mysql DB에 저장이 된다.
그러고 나서 찾기를 누르면 DB에 저장되어있던 값이 나온다.
인터넷에 있는 방식은 어려워보였지만
PHP를 할줄 아는사람에게는 어렵지 않다.(PHP를 기본밖에 모르는 나도 했으니 ㅋ)
일단 SQLite 방식은 내 아트릭스에서 안돌아갔지만
이 파싱방식은 내 아트릭스에서 돌아가는것을 확인할 수 있었다.
안드로이드와 Mysql을 연동시키는 방법은 이렇다.
안드로이드가 서버에 있는 php나 jsp 파일을 넘길 인자값을 넣어 실행한다.
실행된 php나 jsp 파일은 받은 인자값을 이용해 DB에 접근하고 쿼리 결과를 xml 파일에 저장한다.
안드로이드는 다시 서버에 있는 xml파일을 열고 xml파서를 이용해 쿼리 결과를 받는다.
좀 복잡해 보일 수도 있겠지만
직접 해보면 어려운건 아니다.
일단 내 소스는
PHP는 내가 스스로 공부한것을 바탕으로 했고
XML 파싱하는 방법은
단계별 예제로 배우는 안드로이드 프로그래밍
이 책을 참고하였다.
쨌든 본론 들어가겠다.
아파치 서버에 DB와 테이블을 만든다.
난 DB 이름을 bookdb로 했고
테이블 이름은 books로 했다.
테이블 모양은 이렇다.
이제 코딩을 하겠다.
먼저 DB에 입력하기 위한 과정이다.
일단 PHP파일을 작성한다.
PHP파일 이름은 대충 insert.php로 정했다.
소스는 이렇다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <!--? $connect = mysql_connect( "127.0.0.1" , "root" , "0000" ); //DB가 있는 주소(이것은 웹서버로 직접 접속하는 것이기 때문에 루프백 주소를 써도 됨) mysql_selectdb( "bookdb" ); //DB 선택 mysql_query( "set names utf8" ); //이것 또한 한글(utf8)을 지원하기 위한 것 $name = $_REQUEST [name]; //주소에 있는 name값을 받아 name 변수에 저장 $price = $_REQUEST [price]; //주소에 있는 price값을 받아 prica 변수에 저장 $qry = "insert into books(name, price) values('$name', $price);" ; $result = mysql_query( $qry ); $xmlcode = "<?xml version = \"1.0\" encoding = \"utf-8\"?-->\n" ; //xml파일에 출력할 코드 $xmlcode .= "<result>$result</result>\n" ; //DB insert가 성공적으로 됐는지 여부를 확인하기 위해 result값을 xml로 출력시킴 $dir = "C:/APM_Setup/htdocs/Books" ; //insertresult.xml 파일을 저장할 경로 $filename = $dir . "/insertresult.xml" ; file_put_contents ( $filename , $xmlcode ); //xmlcode의 내용을 xml파일로 출력 ?> |
다음은 검색버튼을 눌렀을때 검색 결과가 나오게 할 PHP파일이다.
이름은 대충 search.php로 정했다.
소스는 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <!--? $connect = mysql_connect( "127.0.0.1" , "root" , "0000" ); //DB가 있는 주소(이것은 웹서버로 직접 접속하는 것이기 때문에 루프백 주소를 써도 됨) mysql_selectdb( "bookdb" ); //DB 선택 mysql_query( "set names utf8" ); //이것 또한 한글(utf8)을 지원하기 위한 것 $qry = "select * from books;" ; $result = mysql_query( $qry ); $xmlcode = "<?xml version = \"1.0\" encoding = \"utf-8\"?-->\n" ; //xml파일에 출력할 코드 while ( $obj = mysql_fetch_object( $result )) { $name = $obj ->name; $price = $obj ->price; $xmlcode .= "<node>\n" ; $xmlcode .= "<name>$name</name>\n" ; $xmlcode .= "<price>$price</price>\n" ; $xmlcode .= "</node>\n" ; //DB쿼리로 받아낸 name과 price값을 xml파일에 출력하기 위한 코드 } $dir = "C:/APM_Setup/htdocs/Books" ; //searchresult.xml 파일을 저장할 경로 $filename = $dir . "/searchresult.xml" ; file_put_contents ( $filename , $xmlcode ); //xmlcode의 내용을 xml파일로 출력 ?> |
이제 마지막으로 안드로이드를 작성할 차례이다.
먼저 통신을 해야하기 때문에 매니페스트 파일을 만져줘야 한다.
인터넷 퍼미션을 등록해야하기 때문이다.
매니페스트 파일 소스는 이렇다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!--?xml version="1.0" encoding="utf-8"?--> < manifest xmlns:android = "http://schemas.android.com/apk/res/android" package = "gong.mille.books" android:versioncode = "1" android:versionname = "1.0" > < uses-sdk android:minsdkversion = "8" > < uses-permission android:name = "android.permission.INTERNET" > < application android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" > < activity android:name = ".Android_BookActivity" android:label = "@string/app_name" > < intent-filter > < action android:name = "android.intent.action.MAIN" > < category android:name = "android.intent.category.LAUNCHER" > </ category ></ action ></ intent-filter > </ activity > </ application > </ uses-permission ></ uses-sdk ></ manifest > |
다음은 레이아웃을 손대겠다.
레이아웃은 main.xml 하나밖에 없고 소스는 대락 이렇다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <!--?xml version="1.0" encoding="utf-8"?--> < linearlayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "fill_parent" android:layout_height = "fill_parent" android:orientation = "vertical" > < textview android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:text = "@string/hello" > < edittext android:id = "@+id/editText1" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:ems = "10" > < requestfocus > </ requestfocus ></ edittext > < linearlayout android:layout_width = "match_parent" android:layout_height = "wrap_content" > < edittext android:id = "@+id/editText2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_weight = "1" android:ems = "10" android:inputtype = "number" > < button android:id = "@+id/button1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_weight = "1" android:text = "입력" > </ button >< button android:id = "@+id/button2" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "찾기" > < listview android:id = "@+id/listView1" android:layout_width = "match_parent" android:layout_height = "wrap_content" > </ listview > </ button ></ edittext ></ linearlayout ></ textview ></ linearlayout > |
마지막으로 자바파일을 손대야 한다.
자바파일 소스는 밑에 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | package gong.mille.books; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; public class Android_BookActivity extends Activity { private final String SERVER_ADDRESS = "http://127.0.0.1/Books" ; //서버 주소(php파일이 저장되어있는 경로까지, 절대로 127.0 . 0.1 이나 localhost를 쓰면 안된다!! 그러므로 아이피는 자기 아이피로.....) EditText edtname; EditText edtprice; Button btninsert; Button btnsearch; ListView list; ArrayList<string> data; ArrayAdapter<string> adapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); edtname = (EditText )findViewById(R.id.editText1); edtprice = (EditText )findViewById(R.id.editText2); btninsert = (Button )findViewById(R.id.button1); btnsearch = (Button )findViewById(R.id.button2); list = (ListView )findViewById(R.id.listView1); data = new ArrayList<string>(); adapter = new ArrayAdapter<string>( this , android.R.layout.simple_list_item_1, data); list.setAdapter(adapter); btninsert.setOnClickListener( new View.OnClickListener() { //입력 버튼을 눌렀을 때 public void onClick(View v) { // TODO Auto-generated method stub if ( edtname.getText().toString().equals( "" ) || edtprice.getText().toString().equals( "" ) ) { //이름이나 가격중에 하나라도 입력이 안돼있을때 Toast.makeText(Android_BookActivity. this , "이름이나 가격을 입력하세요" , Toast.LENGTH_SHORT).show(); return ; } runOnUiThread( new Runnable() { public void run() { // TODO Auto-generated method stub String name = edtname.getText().toString(); String price = edtprice.getText().toString(); try { URL url = new URL(SERVER_ADDRESS + "/insert.php?" + "name=" + URLEncoder.encode(name, "UTF-8" ) + "&price=" + URLEncoder.encode(price, "UTF-8" )); //변수값을 UTF-8로 인코딩하기 위해 URLEncoder를 이용하여 인코딩함 url.openStream(); //서버의 DB에 입력하기 위해 웹서버의 insert.php파일에 입력된 이름과 가격을 넘김 String result = getXmlData( "insertresult.xml" , "result" ); //입력 성공여부 if (result.equals( "1" )) { //result 태그값이 1일때 성공 Toast.makeText(Android_BookActivity. this , "DB insert 성공" , Toast.LENGTH_SHORT).show(); edtname.setText( "" ); edtprice.setText( "" ); } else //result 태그값이 1이 아닐때 실패 Toast.makeText(Android_BookActivity. this , "DB insert 실패" , Toast.LENGTH_SHORT).show(); } catch (Exception e) { Log.e( "Error" , e.getMessage()); } } }); } }); btnsearch.setOnClickListener( new View.OnClickListener() { public void onClick(View arg0) { // TODO Auto-generated method stub final Handler handler = new Handler(); runOnUiThread( new Runnable() { public void run() { // TODO Auto-generated method stub final ProgressDialog dialog = ProgressDialog.show( Android_BookActivity. this , "불러오는중....." , "잠시만 기다려주세요." ); handler.post( new Runnable() { public void run() { // TODO Auto-generated method stub try { data.clear(); //반복적으로 누를경우 똑같은 값이 나오는 것을 방지하기 위해 data를 클리어함 URL url = new URL(SERVER_ADDRESS + "/search.php" ); url.openStream(); //서버의 serarch.php파일을 실행함 ArrayList<string> namelist = getXmlDataList( "searchresult.xml" , "name" ); //name 태그값을 읽어 namelist 리스트에 저장 ArrayList<string> pricelist = getXmlDataList( "searchresult.xml" , "price" ); //price 태그값을 읽어 prica 리스트에 저장 if (namelist.isEmpty()) data.add( "아무것도 검색되지 않았습니다." ); else { for ( int i = 0 ; i < namelist.size(); i++) { String str = namelist.get(i) + " - " + pricelist.get(i); data.add(str); } } } catch (Exception e) { Log.e( "Error" , e.getMessage()); } finally { dialog.dismiss(); adapter.notifyDataSetChanged(); } } }); } }); } }); } private String getXmlData(String filename, String str) { //태그값 하나를 받아오기위한 String형 함수 String rss = SERVER_ADDRESS + "/" ; String ret = "" ; try { //XML 파싱을 위한 과정 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware( true ); XmlPullParser xpp = factory.newPullParser(); URL server = new URL(rss + filename); InputStream is = server.openStream(); xpp.setInput(is, "UTF-8" ); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { if (xpp.getName().equals(str)) { //태그 이름이 str 인자값과 같은 경우 ret = xpp.nextText(); } } eventType = xpp.next(); } } catch (Exception e) { Log.e( "Error" , e.getMessage()); } return ret; } private ArrayList<string> getXmlDataList(String filename, String str) { //태그값 여러개를 받아오기위한 ArrayList<string>형 변수 String rss = SERVER_ADDRESS + "/" ; ArrayList<string> ret = new ArrayList<string>(); try { //XML 파싱을 위한 과정 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware( true ); XmlPullParser xpp = factory.newPullParser(); URL server = new URL(rss + filename); InputStream is = server.openStream(); xpp.setInput(is, "UTF-8" ); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { if (xpp.getName().equals(str)) { //태그 이름이 str 인자값과 같은 경우 ret.add(xpp.nextText()); } } eventType = xpp.next(); } } catch (Exception e) { Log.e( "Error" , e.getMessage()); } return ret; } } </string></string></string></string></string></string></string></string></string></string> |
이렇게 하면 웹서버의 Mysql과 안드로이드가 잘 연동될 것이다.
이렇게 쉬울줄 몰랐는데
직접 해보니 할만했다 ㅋ
저번학기때 프로젝트 했던것을 공모전에 내기로 했는데
이것으로 싹 고쳐야했다.
그래도 SQLite를 쓰는것보단 간단한 소스라 금방 고칠수 있었다.
이제 버그 테스트를 하고 버그수정 하는 일밖에 남지 않았다.
다음은 뭘 올려야할지 모르겠지만
공부하다가 도움될만한 것 찾게되면 올려야겠다.
P.S
DB에 한글이 깨지는것을 막기 위해서 utf-8로 인코딩 했는데도 안된다면 PHP파일에 HTML 명령어를 넣어야 한다.
<head>
<meta http-equiv = "content-Type" content = "text/html" charset = "utf-8">
</head>
이 명령어를 넣어야 하는데 PHP파일 맨 앞에다가 넣어주면 된다.
요렇게 ㅋ
[출처] [안드]phpMyAdmin(MySQL)서버와 데이터 주고받기|작성자 세뮤렐
[출처] http://gongmille.tistory.com/5
[소스] http://gongmille.tistory.com/6
[출처] [안드로이드]phpMyAdmin(MySQL)서버와 데이터 주고받기|작성자 세뮤렐
'프로그래밍 > Android (Java)' 카테고리의 다른 글
Activity 를 Dialog 처럼 띄우기 (0) | 2015.10.14 |
---|---|
XML 파싱 ( DOM Parser ) ( AsyncTask 클래스 사용 ) (0) | 2015.10.14 |
videoview streaming android example (0) | 2015.10.06 |
어플에서 SMS(문자) 전송 하기 (0) | 2015.06.18 |
Preferences 를 이용한 자동 로그인 (0) | 2015.05.27 |