2012.06.27 12:40

방학하고나서 레퍼런스폰에만 돌아가던것을 고치기 위해 파싱을 이용한 방법을 공부했다.

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로 정했다.

소스는 이렇다.


\n"; //xml파일에 출력할 코드
$xmlcode .= "$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로 정했다.

소스는 아래와 같다.


\n"; //xml파일에 출력할 코드

while($obj = mysql_fetch_object($result))
{
	$name = $obj->name;
	$price = $obj->price;

	$xmlcode .= "\n";
	$xmlcode .= "$name\n";
	$xmlcode .= "$price\n";
	$xmlcode .= "\n"; //DB쿼리로 받아낸 name과 price값을 xml파일에 출력하기 위한 코드
}

$dir = "C:/APM_Setup/htdocs/Books"; //searchresult.xml 파일을 저장할 경로
$filename = $dir."/searchresult.xml";

file_put_contents($filename, $xmlcode); //xmlcode의 내용을 xml파일로 출력
?>

이제 마지막으로 안드로이드를 작성할 차례이다.

먼저 통신을 해야하기 때문에 매니페스트 파일을 만져줘야 한다.

인터넷 퍼미션을 등록해야하기 때문이다.


매니페스트 파일 소스는 이렇다.





    
    

    
        
            
                

                
            
        
    


다음은 레이아웃을 손대겠다.

레이아웃은 main.xml 하나밖에 없고 소스는 대락 이렇다.





    

    

        
    

    

        

        

마지막으로 자바파일을 손대야 한다.

자바파일 소스는 밑에 있다.


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 data;
	ArrayAdapter 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();
        adapter = new ArrayAdapter(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 namelist = getXmlDataList("searchresult.xml", "name");//name 태그값을 읽어 namelist 리스트에 저장
									ArrayList 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 getXmlDataList(String filename, String str) { //태그값 여러개를 받아오기위한 ArrayList형 변수
		String rss = SERVER_ADDRESS + "/";
		ArrayList ret = new ArrayList();
		
		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;
	}
}

이렇게 하면 웹서버의 Mysql과 안드로이드가 잘 연동될 것이다.

이렇게 쉬울줄 몰랐는데

직접 해보니 할만했다 ㅋ

저번학기때 프로젝트 했던것을 공모전에 내기로 했는데

이것으로 싹 고쳐야했다.

그래도 SQLite를 쓰는것보단 간단한 소스라 금방 고칠수 있었다.

이제 버그 테스트를 하고 버그수정 하는 일밖에 남지 않았다.

다음은 뭘 올려야할지 모르겠지만

공부하다가 도움될만한 것 찾게되면 올려야겠다.


P.S

DB에 한글이 깨지는것을 막기 위해서 utf-8로 인코딩 했는데도 안된다면 PHP파일에 HTML 명령어를 넣어야 한다.

<head>

<meta http-equiv = "content-Type" content = "text/html" charset = "utf-8">

</head>

이 명령어를 넣어야 하는데 PHP파일 맨 앞에다가 넣어주면 된다.


요렇게 ㅋ

Posted by 특례 받고싶은 공대생