본문 바로가기
옛날

안드로이드에서 웹서버에 post로 글쓰기 [Android]

by 차가운게 조아 2015. 12. 11.


출처 블랙독의 프로그래밍 블로그 | 블랙독
원문 http://blog.naver.com/wono77/140114232168

 

안드로이드에서 웹서버에 post로 글쓰기(by wono77)

 

최초문서작성: 2010년 10월 4일

글공개 : 2012년 4월 6일

 

미투데이처럼 안드로이드에서 글을 쓰면,

웹서버는 어떻게 그 내용을 받아내서 db에 올려야 할까?

꽤 오래전부터 궁금했었는데, 계획만 있을뿐 제대로 공부해보지를 못하고 있었다.

드디어 시간이 나서 그 방법을 찾아보고 개발을 해보았다.

 

코드설명:

 

안드로이드 코드상에서 간단히 id, pass를 post 방식으로 쓰고,

웹서버는 php를 사용하였다.

php에서 받은 글을 txt로 저장한 후, echo로 결과를 쓴다.

그러면, 안드로이드는 그 웹서버의 echo를 받아서 에뮬 화면에 작성하는 코드이다.

 

실행화면:



  

안드로이드에서 올린 글을 받아내서 반응하는 php 코드:

 

php가 안드로이드의 글을 받았는지 서버단에서의 확인을 하기 위해,

db에 연결하지 않고 일단 간단히 반응이 오면 파일을 작성해보았다.

 

<?

$id=$_REQUEST[id];
//echo("id: ".$id);
$pass=$_REQUEST[pass];
//echo("pass: ".$pass);

 

$imgpath = "/home/hosting_users/radstyle/www";

$fp=fopen($xmlpath."./test.txt",'w');

fwrite($fp,$id);
fwrite($fp,"\n");
fwrite($fp,$pass);

fclose($fp);

echo("id is $id, pass is $pass");
if(file_exists($fp)){
    if(sizeof($fp)>0){
        echo("id is $id, pass is $pass");
    }else{
        echo("file size is zero");
    }
}

?> 

 

위 코드가 잘 반응하는지 웹에서 확인하기 위한 코드는 아래와 같다.

get 방식으로 테스트하려면,

http://radstyle.net/loginTest.php?id=aaaa&pass=1111 만으로 될 것이다. 

(추가로 php 파일 업로드 폼도 작성해볼 것)

 

<?

echo("loginTest");


?>

<form action="loginTest.php" method="post" >
<input type=text name=id>
<input type=submit>
</form>


 

안드로이드 코드(파일첨부함):

 


package com.bbs.www;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class bbs extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  TextView resultField = ( TextView ) findViewById( R.id.result ) ;
  
  // try {
  // downloadUrl("http://radstyle.net/sexfa.php", "최원효");
  // } catch (UnsupportedEncodingException e) {
  // // TODO Auto-generated catch block
  // e.printStackTrace();
  // }

  try {
   resultField.setText(sendData("wono77", "하얀별"));
  } catch (UnsupportedEncodingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (ClientProtocolException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 private String sendData(String id, String pwd)
   throws ClientProtocolException, IOException {
  // TODO Auto-generated method stub
  HttpPost request = makeHttpPost(id, pwd,
    "http://radstyle.net/loginTest.php");
  // Get 방식일경우
  // HttpPost request = makeHttpGet( id, pwd,
  // "http://www.shop-wiz.com/android_post.php" ) ;
  HttpClient client = new DefaultHttpClient();
  ResponseHandler<String> reshandler = new BasicResponseHandler();
  String result = client.execute(request, reshandler);
  return result;
 }

 // Post 방식일경우
 private HttpPost makeHttpPost(String user_id, String user_pwd, String url) {
  // TODO Auto-generated method stub
  HttpPost post = new HttpPost(url);
  Vector<NameValuePair> params = new Vector<NameValuePair>();
  params.add(new BasicNameValuePair("id", user_id));
  params.add(new BasicNameValuePair("pass", user_pwd));
  post.setEntity(makeEntity(params));
  return post;
 }
 
 private HttpEntity makeEntity(Vector<NameValuePair> params) {
  HttpEntity result = null;
  try {
   //result = new UrlEncodedFormEntity( params ) ;
   result = new UrlEncodedFormEntity(params, HTTP.UTF_8);
  } catch (UnsupportedEncodingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return result;
 }
 
 //다른 방식
 private void downloadUrl(String postURL, String input)
   throws UnsupportedEncodingException {
  try {
   HttpClient client = new DefaultHttpClient();
   HttpPost post = new HttpPost(postURL);
   List<NameValuePair> params = new ArrayList<NameValuePair>();
   params.add(new BasicNameValuePair("name", input));
   UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,
     HTTP.UTF_8);
   post.setEntity(ent);
   HttpResponse responsePOST = client.execute(post);
   HttpEntity resEntity = responsePOST.getEntity();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

}

 

 

 

 

 

* 남은 문제:

 

encoding UTF8을 하여 서버에 한글을 제대로 전송되었지만, 결과를 받아보니 한글이 깨졌음.

이 문제 해결을 위해서는 아래처럼 하면 된다고 한다.

 

참조:

http://www.androidpub.com/?_filter=search&mid=android_dev_qna&search_target=title_content&search_keyword=euc-kr&document_srl=549232

 

   text를 네트워크를 통해서 쓸 때 EUC-KR로 변환해서 쏘아주고,

 

   OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream(), "EUC-KR"));
   writer.write(text);
 
   받을때도 아래처럼...
      
   BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "EUC-KR")));
   String text = reader.readLine();

 

일반적으로 웹의 글을 가져올때는 테스트로 작성한 코드처럼 httpPost로 글을 가져오지 않고,

isStream으로 아래처럼 가져오므로, 이 때는 한글 변환에 문제가 없으리라 생각된다.

url에서 stream을 가져온후, post 방식으로 redirected된 url을 가져오던 소스의 bufferRead하던 부분과

조합해서 위의 인코딩을 잘 넣어보면 한글도 읽혀지지 않을까 싶다.

아래에서 싸이주소값을 가져올때는 한글이 깨졌었다.

 

/**
  * url에서 이미지를 가져와서 sdcard에 저장하는 함수
  * fullPath=urlPrefix + fileName
  * 
  * @author wono77(2010.04.11)
  * @param urlPrefix : "http://radstyle.net/images/cp/"
  * @param fileName : a.jpg
  */
 public void imageSaveFromURL(String urlPrefix, String fileName) {
  String fullImageUrl = urlPrefix + fileName;
  // String sdcardPath =
  // Environment.getExternalStorageDirectory().toString();//+ "/sdcard/";
  String sdcardFullPath = sdcardPath + fileName;

  // url을 파일에 저장
  InputStream is = null;
  try {
   is = getUrlStream(fullImageUrl);
  } catch (Exception e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }

  // directory 존재여부 체크 한번
  File dir = new File(sdcardPath);
  if (!dir.exists()) {
   dir.mkdir();
  }

  if (is != null) {
   try {
    BufferedInputStream bis = new BufferedInputStream(is);
    FileOutputStream fos = new FileOutputStream(new File(sdcardFullPath));
    int n = 0;
    try {
     while ((n = bis.read()) != -1) {
      fos.write(n);
     }
    } catch (IOException e) {
     Log.v("a", "write fail");
    } finally {
     fos.close();
     bis.close();
    }
   } catch (IOException e) {
    Log.v("a", "fail");
   }
  }
 }

 

/**
  * url에서 inputStream을 받아오는 함수
  * 
  * @author wono77(2010.04.11)
  * @param path
  * @return
  * @throws Exception
  */ 

 public InputStream getUrlStream(String path) throws Exception {
  InputStream is = null;
  try {
   // 20100222 최원효 : timeout 셋팅
   int desiredValue = 3000;
   URL sourceImageUrl = new URL(path);
   URLConnection t_connection = sourceImageUrl.openConnection();
   t_connection.setConnectTimeout(desiredValue);
   t_connection.setReadTimeout(desiredValue);
   is = t_connection.getInputStream();

  } catch (Exception e) {
   if (is != null) {
    is.close();
   }
   is = null;
  }
  return is;
 }

 

/**
  * url을 입력받아 direct 되는 url의 내용을 가져오는 함수
  * 
  * @author wono77(2010.08.24)
  * @param inputUrl
  * @return
  * @throws IOException
  */
 public String getRedirectedUrlStream(String inputUrl) {
  URL url = null;
  String inputLine = "";
  String response = "";
  URLConnection conn = null;
  try {
   url = new URL(inputUrl);
   conn = url.openConnection();
  } catch (MalformedURLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  if (conn instanceof HttpURLConnection) {
   HttpURLConnection httpConn = (HttpURLConnection) conn;
   try {
    httpConn.setRequestMethod("POST");
    httpConn.setRequestProperty("Content-type", "text/xml");
    httpConn.setUseCaches(false);
    httpConn.setDoInput(true);
    httpConn.setDoOutput(true);
    String testxml = null;
    DataOutputStream out;
    out = new DataOutputStream(httpConn.getOutputStream());
    out.flush();
    out.close();

    // This next line throws an IOException if response code is not
    // 200 <<======<<
    BufferedReader in = null;
    in = new BufferedReader(new InputStreamReader(
      httpConn.getInputStream()));
    while ((inputLine = in.readLine()) != null) {
     response = response + inputLine;
    }
    in.close();

   } catch (ProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   return response;
  } else {
   return null;
  }
 }
 

 

 

* 더 해볼 내용: 이미지 업로드

 

참고할것 :

http://www.androidpub.com/?_filter=search&mid=android_dev_qna&search_target=title_content&search_keyword=post&page=4&division=-841993&last_division=-513271&document_srl=664496

 

* 참조한글:

 

1. 안드로이드 글쓰기 (외국글)

http://blog.dahanne.net/2009/08/16/how-to-access-http-resources-from-android/

2. 안드로이드 이미지 업로드 with php

http://blog.inculab.net/28

3. 초록돼지의 글 모음

http://absenteye.blog.me/100110049502

4. 가장많이 참조한글

http://www.shop-wiz.com/document/android/execise_linkage_web

 

 


[설명]
이번장에서는 웹과의 데이타 교환에 대해 연속적으로 다루어 보겠습니다.
그 첫번째로 post/get 방식으로 웹에 데이타를 전달하고 결과치를 다시 받는 것을 처리하겠습니다.
일단 어플에서 불러올 php 파일을 작성하겠습니다.
이 php파일은 변수를 받아서 출력해주는 프로그램입니다.
android_post.php
1
2
3
4
5
6
<?php  
$id $_POST["user_id"] ; 
$pwd $_POST["user_pwd"] ;  
echo "your id is ".$id." and your passwd is ".$pwd;  
?>
    
[설명]
이제는 AndroidManifest.xml에서 인터넷에 대한 권한이 줍니다.
<uses-permission android:name="android.permission.INTERNET" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
      package="com.ProjectLinkageWeb"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ProjectLinkageWeb"
                  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>
    <uses-permission android:name="android.permission.INTERNET" />
</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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<TextView    
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    android:text="Input Your Id"  
    />  
<EditText   
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"  
    android:id="@+id/user_id"   
/>  
<TextView    
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    android:text="Input Your password"  
    />  
<EditText   
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"  
    android:id="@+id/user_pwd"   
/>  
<TextView   
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"  
    android:id="@+id/get_result"  
    android:text="Result Field"  
/>  
<Button   
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"  
    android:id="@+id/submitBtn"  
    android:text="Submit"  
/>      
</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
package com.ProjectLinkageWeb;
  
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Vector;
  
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
  
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
  
public class ProjectLinkageWeb extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
          
        Button button = (Button) findViewById( R.id.submitBtn ) ;  
        button.setOnClickListener(new View.OnClickListener() {   
            public void onClick(View v) {   
                String user_id = ((EditText) findViewById(R.id.user_id)).getText().toString() ;  
                String user_pwd = ((EditText) findViewById(R.id.user_pwd)).getText().toString() ;  
                TextView resultField = ( TextView ) findViewById( R.id.get_result ) ;  
  
                try {  
                //데이터를 웹서버에 보내고 받아온 결과를 출력합니다.  
                    resultField.setText( sendData( user_id, user_pwd ) ) ;  
                catch (ClientProtocolException e) {  
                // TODO Auto-generated catch block  
                    e.printStackTrace();  
                catch (IOException e) {  
                // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
            }   
         });         
    }
      
    private String sendData(String id, String pwd) throws ClientProtocolException, IOException {  
        // TODO Auto-generated method stub  
        HttpPost request = makeHttpPost( id, pwd, "http://www.shop-wiz.com/android_post.php" ) ;  
        // Get 방식일경우
        //HttpPost request = makeHttpGet( id, pwd, "http://www.shop-wiz.com/android_post.php" ) ; 
        HttpClient client = new DefaultHttpClient() ;  
        ResponseHandler<STRING> reshandler = new BasicResponseHandler() ;
        String result = client.execute( request, reshandler ) ;  
        return result ;  
    }  
  
    //Post 방식일경우
    private HttpPost makeHttpPost(String user_id, String user_pwd, String url) {  
        // TODO Auto-generated method stub  
        HttpPost request = new HttpPost( url ) ;  
        Vector<NAMEVALUEPAIR> nameValue = new Vector<NAMEVALUEPAIR>() ;  
        nameValue.add( new BasicNameValuePair( "user_id", user_id ) ) ;  
        nameValue.add( new BasicNameValuePair( "user_pwd", user_pwd ) ) ;  
        request.setEntity( makeEntity(nameValue) ) ;  
        return request ;  
    }  
      
    //Get 방식일경우
    private HttpGet makeHttpGet(String user_id, String user_pwd, String url) {  
        // TODO Auto-generated method stub  
        Vector<NAMEVALUEPAIR> nameValue = new Vector<NAMEVALUEPAIR>() ;  
        nameValue.add( new BasicNameValuePair( "user_id", user_id ) ) ;  
        nameValue.add( new BasicNameValuePair( "user_pwd", user_pwd ) ) ;
            
        String my_url = url + "?" + URLEncodedUtils.format( nameValue, null) ;  
        HttpGet request = new HttpGet( my_url ) ;  
        return request ;  
    }
      
    private HttpEntity makeEntity( Vector<NAMEVALUEPAIR> nameValue ) {  
        HttpEntity result = null ;  
        try {  
        result = new UrlEncodedFormEntity( nameValue ) ;  
        catch (UnsupportedEncodingException e) {  
        // TODO Auto-generated catch block  
        e.printStackTrace();  
        }  
        return result ;  
    }     
}
    
[설명]

이 프로그램을 실행할때는 반드시 이클립스상에서 인터넷이 되는지 확인해야 합니다.
저의 경우는 아래와 같이 환경을 처리했습니다.
 

 

업로드 관련 추가글들: (파일로도 첨부합니다.)

 

http://blog.naver.com/legendx/40132716891 (여기가 젤 깔끔하게 정리 잘 된듯)

 

http://www.androidpub.com/?_filter=search&mid=android_dev_qna&search_target=title_content&search_keyword=post&page=4&division=-841993&last_division=-513271&document_srl=664496


'옛날' 카테고리의 다른 글

Coach mark View [Android]  (0) 2015.12.11
Webview 소스 [Android]  (0) 2015.12.11
네트워크 상태 [Android]  (0) 2015.12.11
Tabhost custom [Android]  (0) 2015.12.11
TabActivity back key Event [Android]  (0) 2015.12.11