728x90

안드로이드와 PHP 연동하여 MySQL DB에서 결과를 회신받아 안드로이드에서 보는 방법이다.

안드로이드 폰에서 검색어를 입력하면 서버에서 해당 검색어에 대한 결과를 돌려주는 방식이다.

인터넷에 올라온 자료들은 참조하여 테스트를 하다보니 결과가 나오질 않는다.
뭐가 잘못된 것인지 찾기 위해 각종 게시글을 참조하면서 하나 하나 잘못된 점을 찾아나갔다.
틀린 점이 하나 발견되었다.
conn.setDoInput(true); // 서버로부터 응답 헤더와 메시지를 읽어들이겠다는 옵션
이 코드가 추가되면 결과값이 없는지 화면에 아무것도 없다. 이 한줄의 쓰임새는 아직 파악을 못한 상태다.


==== get_json.php ======

<?php
    include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
    require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
    require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/xmlClass.php';

    $conn = new MySQLDbClass(); // DB 함수
    $DB_CONNECT = $conn->isConnectDb($DB);

    // 화면에 출력할 칼럼 발췌
    $sql = "select uid,name,mobile from Person ";
    $result = mysql_query($sql);

    // 1. JSON 데이터 생성방법
    $c = new jsonClass();
    echo $c->JSONEncode($result,'result');
?>


참고

class jsonClass {
    function JSONEncode($result,$varname){
        $R = array(); // 결과 담을 변수 생성
        while($row = mysql_fetch_object($result)) { 
            array_push($R, $row);
        }
       
        return json_encode(array($varname=>$R)); //배열-문자열등을 json형식의 '문자열'로 변환
    }
// end of Class


이제 검색 기능을 추가했다.

안드로이드에서 검색 명령어를 입력하면 PHP에서 검색명령어를 인식해야 한다.

GET 방식과 POST 방식 모두 입력값을 인식하도록 $_REQUEST['search'] 를 적어줬다.

Where 조건절에 쿼리문은 인덱스를 타지 않는 LIKE 를 적용했다.

값이 제대로 넘어오는지만 확인하기 위한 목적이기 때문에....


<?php

if(!isset($_REQUEST['search']) || empty($_REQUEST['search'])){

echo '비정상접속';

exit;

}


$query = $_REQUEST['search'];

include_once $_SERVER['DOCUMENT_ROOT'].'/db.info.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/xmlClass.php';

$conn = new MySQLDbClass(); // DB 함수
$DB_CONNECT = $conn->isConnectDb($DB);

// 화면에 출력할 칼럼 발췌
$sql = "select uid,name,mobile from Person ";
if(!empty($query)) {
    $sql .= "where name LIKE '%".$query."%' or mobile LIKE '%".$query."%'";
}
$result = mysql_query($sql);

// 1. JSON 데이터 생성방법
$c = new jsonClass();
echo $c->JSONEncode($result,'result');
?>


안드로이드 코드 부문

===== MainActivity.java 추가 사항 =====

TextView searchView = (TextView) findViewById(R.id.SearchView);
searchView.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(), "검색화면으로 이동합니다", Toast.LENGTH_LONG).show();
        Intent intent = new Intent(MainActivity.this, Search_Item.class);
        startActivity(intent);
    }           
});


===== Search_Item.java =====

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class Search_Item extends Activity {
   
    static String getEdit;
    EditText inputSearch;
    Button btnSearch;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_search);
       
        final Button btn = (Button) findViewById(R.id.back_btn);
        btn.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                finish();
            }
        });

        Button homeBtn = (Button) findViewById(R.id.home_btn);
        homeBtn.setOnClickListener(new Button.OnClickListener() {

            public void onClick(View v) {
                Intent mn = new Intent(Search_Item.this, MainActivity.class);
                mn.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mn);
            }
        });

        // title set
        TextView title = (TextView) this.findViewById(R.id.navibar_text); // title
        title.setText("연락처 검색");

        inputSearch = (EditText) findViewById(R.id.list_search_edit);       
        btnSearch = (Button) findViewById(R.id.list_search_btn);
        btnSearch.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View v) {
                searchData();               
            }           
           
        });
    }
   
    private void searchData() {
        getEdit = inputSearch.getText().toString().trim();
        if(getEdit.equals("") ){
            Toast.makeText(Search_Item.this, "검색어를 입력하세요!", Toast.LENGTH_SHORT).show();
        } else {
            // 검색어 값을 전달
            Intent intent = new Intent(Search_Item.this, SearchActivity.class);
            intent.putExtra("search", getEdit);
            startActivity(intent);
            finish();
        }
       
    }
}


===== SearchActivity.java =====

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class SearchActivity extends Activity {
   
    private ListView sListView = null;
    private ListViewAdapter sAdapter = null;

    // 서버 정보를 파싱하기 위한 변수 선언
    String searchJSON; 
    private static final String TAG_RESULTS="result"; 
    private static final String TAG_UID = "uid"; 
    private static final String TAG_NAME = "name"; 
    private static final String TAG_Mobile ="mobile"; 
 
    JSONArray peoples = null; 
    String squery = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search_result);
       
        // ActionBar 제거하기  --> AnroidManifest.xml 파일을 수정했음. 화면이 까맣게 나오는 현상 때문에
        ActionBar actionbar = getActionBar();
        actionbar.hide();

        final Button btn = (Button) findViewById(R.id.back_btn);
        btn.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                finish();
            }
        });

        Button homeBtn = (Button) findViewById(R.id.home_btn);
        homeBtn.setOnClickListener(new Button.OnClickListener() {

            public void onClick(View v) {
                Intent mn = new Intent(SearchActivity.this, MainActivity.class);
                mn.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mn);
            }
        });

        // title set
        TextView title = (TextView) this.findViewById(R.id.navibar_text); // title
        title.setText("검색 결과");
       
        sListView = (ListView) findViewById(R.id.list_search); 
        sAdapter = new ListViewAdapter(this);       

        // 이전 Activity에서 전달한 값 받기
        Intent intent = getIntent();
        squery = intent.getExtras().getString("search");

        // 서버에 있는 정보를 읽어다가 mAdapter.addItem 에 추가하는 과정
        String url ="http://IP주소/mobile/get_json.php";
        getDbData(url);
       
        sListView.setAdapter(sAdapter);

    }
   
    private void getDbData(String string) {
        class GetDataJSON extends AsyncTask<String, Void, String>{ 

            @Override 
            protected String doInBackground(String... params) { 
 
                String uri = params[0];
 
                BufferedReader bufferedReader = null; 
                try { 
                    URL url = new URL(uri); 
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    String post_data = "search=" + Uri.encode(squery);

                    StringBuilder sb = new StringBuilder(); 
 
                    if(conn != null){ // 연결되었으면
                        conn.setConnectTimeout(10000); // milliseconds 연결 타임아웃시간

                        //add request header
                        conn.setUseCaches(false);
                        conn.setDefaultUseCaches(false);
                        //conn.setDoInput(true); // 서버로부터 응답 헤더와 메시지를 읽어들이겠다는 옵션
                        // 이 코드를 활성화하면 응답된 내용이 전혀 없다. 비활성화하면 정상이다.
                        conn.setDoOutput(true); // POST 로 데이터를 넘겨주겠다는 옵션

                        conn.setRequestMethod("POST");

                        // 서버에게 웹에서 <Form>으로 값이 넘어온 것과 같은 방식으로 처리하라고 알려준다

                        conn.setRequestProperty("USER-AGENT", "Mozilla/5.0");
                        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
 
                        // Send POST request (서버로 값 전송)
                        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
                        wr.writeBytes(
post_data);
                        wr.flush();
                        wr.close();
                       
                        int responseCode = conn.getResponseCode();
                        System.out.println("GET Response Code : " + responseCode); //
200 : 정상연결                      
                        if(responseCode == HttpURLConnection.HTTP_OK){ // 연결 코드가 리턴되면
                            bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                            String json;
                            while((json = bufferedReader.readLine())!= null){ 
// 라인단위로 읽는다

                               sb.append(json + "\n"); // View에 표시하기 위해 라인 구분자 추가

                            }     
                        }
                        bufferedReader.close();
                    }
                    return sb.toString().trim(); 
 
                } catch(Exception e){ 
                    return new String("Exception: " + e.getMessage());
                }  
 
            } 
 
            protected void onPostExecute(String result){ 
                searchJSON=result; 
                showList(); 
            }           
        } 
       
        GetDataJSON g = new GetDataJSON(); 
        g.execute(string);                
       
    }
   
    protected void showList() {
        // 서버에서 읽어온 정보를 sAdapter 에 저장하고 화면에 출력
        try { 
            JSONObject jsonObj = new JSONObject(searchJSON); 
            peoples = jsonObj.getJSONArray(TAG_RESULTS);
           
            for(int i=0;i<peoples.length();i++){ 
                JSONObject c = peoples.getJSONObject(i); 
                String uid = c.getString(TAG_UID); 
                String name = c.getString(TAG_NAME); 
                String mobile = c.getString(TAG_Mobile); 
                Drawable myIcon = getResources().getDrawable( R.drawable.ic_launcher );
               
                sAdapter.addItem(myIcon,uid,name,mobile);
            }         


            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    sAdapter.notifyDataSetChanged();
                }
            });
           
        } catch (JSONException e) { 
            e.printStackTrace(); 
        }

    } 

    class ViewHolder {
         public LinearLayout child_slayout;
         public ImageView mImage;     
         public Button ListBtn;     
         public TextView name;
         public TextView mobile;
    }

    private class ListViewAdapter extends BaseAdapter {

        private Context sContext = null;
        private ArrayList<ListData> sListData = new ArrayList<ListData>();
       
        public ListViewAdapter(Context mContext) {
            super();
            this.sContext = mContext;
        }
       
        @Override
        public int getCount() {       
            return sListData.size();
        }

        @Override
        public Object getItem(int position) {       
            return sListData.get(position);
        }

        @Override
        public long getItemId(int position) {       
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            View view = convertView;
            if (view == null) {
                viewHolder = new ViewHolder();
         
                LayoutInflater inflater = (LayoutInflater) sContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.search_item, parent, false);
               
                view.setBackgroundColor(0x00FFFFFF);
                view.invalidate();
         
                viewHolder.child_slayout = (LinearLayout) view.findViewById(R.id.child_searchlayout);
                viewHolder.mImage = (ImageView) view.findViewById(R.id.mImage);
                viewHolder.ListBtn = (Button ) view.findViewById(R.id.search_ListBtn);
                viewHolder.name = (TextView) view.findViewById(R.id.search_name);
                viewHolder.mobile = (TextView) view.findViewById(R.id.search_mobile);
         
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }
           
            final ListData sData = sListData.get(position);
           
            if (sData.mImage != null) {
                viewHolder.mImage.setVisibility(View.VISIBLE);
                viewHolder.mImage.setImageDrawable(sData.mImage);
            } else {
                viewHolder.mImage.setVisibility(View.GONE);
            }
           
            viewHolder.ListBtn.setText(sData.uid);
            viewHolder.name.setText(sData.name);
            viewHolder.mobile.setText(sData.mobile);
           
            viewHolder.ListBtn.setOnClickListener(new Button.OnClickListener(){

                @Override
                public void onClick(View v) {
                   
                    Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                    vibe.vibrate(50);
                   
                    AlertDialog showdialog = new AlertDialog.Builder(SearchActivity.this)
                            .setTitle(sData.name)
                            .setMessage(sData.mobile + " 통화하시겠습니까?")
                            .setPositiveButton("예",
                                    new DialogInterface.OnClickListener() {

                                        public void onClick(DialogInterface dialog,int which) {

                                            Intent i = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+ sData.mobile));
                                            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                            startActivity(i);
                                        }

                                    })
                            .setNegativeButton(
                                    "아니오",
                                    new DialogInterface.OnClickListener() {

                                        public void onClick(DialogInterface dialog,int which) {
                                            dialog.dismiss();
                                        }
                                    }).create();
                    showdialog.show();
                }
               
            });
           
            return view;
        }

        public void addItem(Drawable icon, String uid, String name, String mobile){
            ListData addInfo = null;
            addInfo = new ListData();
            addInfo.mImage = icon;
            addInfo.uid = uid;
            addInfo.name = name;
            addInfo.mobile = mobile;
                    
            sListData.add(addInfo);
        }
   
    }

}


===== AndroidManifest.xml =====

아래 순서는 Login.java --> MainActivity.java --> Search_Item.java  --> SearchActivity.java 파일 순으로 실행된다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.phpmysqljson"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="23" />
   
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
 
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.MODIFY_PHONE_READ"/>
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.VIBRATE" />
       
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".Login"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustPan" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" />
       
        <activity
            android:name=".Search_Item"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.NoTitleBar" />

        <activity
            android:name=".SearchActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:launchMode="singleTop" />
       
    </application>

</manifest>

블로그 이미지

Link2Me

,