Please Enable JavaScript!
Gon[ Enable JavaScript ]

안드로이드(Andriod) 에서 다양한 네트워크 연결 및 데이터 받기

안드로이드 개발
반응형

안드로이드(Andriod) 에서 다양한 네트워크 연결 및 데이터 받기

 

개발환경 : window 7 64bit, Eclipse Kepler, Android 4.2.2

 

안드로이드에서 소켓통신을 하기 위한 샘플 예제이다.

테스트를 하기 위해 java 서버프로세스를 준비하였다. 그 서버 프로세스를

띄운 상태에서 안드로이드 프로그램을 실행한다. 그리고 연결후에 서버로

부터 받은 데이터를 안드로이드 프로그램에서 표현한다.

 

1. 소켓연결을 위해 서버 프로그램 띄우기

 

테스트를 위해서 간단하게 서버역활을 할수 있는 프로그램을 하나 만든다.

이 프로그램은 서버소켓을 하나 만들고 대기 하고 있다가 Client 프로그램(안드로이드)

에서 요청이 들어 오면 OutputStream 를 이용해 데이터를 보낸다.

OutputStream 통해서 보낸 데이터는 안드로이드 Client 프로그램에서 받아 표현할 것이다.

프로그램은 스레드를 사용해서 만들지 않았기 때문에 한번 실행하고 대기 하고 있다가

요청에 응답하면 끝나는 형태의 아주 단순한 프로그램이다.

 

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;


public class Main {

	public static void main(String[] args) {
		try{
            ServerSocket serverSocket = new ServerSocket(0);
            System.out.println("I'm waiting here: " + serverSocket.getLocalPort());            
                                
            Socket socket = serverSocket.accept();
            System.out.println("from " + 
                socket.getInetAddress() + ":" + socket.getPort());
            
            OutputStream outputStream = socket.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.print("Server Send data ~~ ");
            printStream.close();
            
            socket.close();
        }catch(IOException e){
            System.out.println(e.toString());
        }
	}
}

 

2. 안드로이드 소켓통신을 하기 위한 준비

 

안드로이드에서 소켓통신을 하기위한 퍼미션 설정을 해야한다. 하지 않으면

아래와 같이 Permission denied 에러가 날수 있다.

java.net.SocketException: socket failed: EACCES (Permission denied)

 

AndroidManifest.xml 에 퍼미션 설정을 한다. Permissions 탭으로 들어가

User Permission 에 해당하는 android.permission.INTERNET 추가한다.

 

 

3. MainActivity 구성하기

 

메인화면은 간단하게 IP, PORT 입력란만 만들고 연결이벤트가 발생할수 있도록 하였다.

필요한 정보를 입력하고 버튼만 클릭하면 미리 띄워둔 서버 프로그램에 접속해

데이터를 받고 TextView 에 결과값을 출력하는 것이다.

 

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	edtTextAddress = (EditText) findViewById(R.id.address);
	edtTextPort = (EditText) findViewById(R.id.port);
	btnConnect = (Button) findViewById(R.id.connect);
	btnClear = (Button) findViewById(R.id.clear);
	txtResponse = (TextView) findViewById(R.id.response);

	btnConnect.setOnClickListener(buttonConnectOnClickListener);
	btnClear.setOnClickListener(new OnClickListener() {
		public void onClick(View v) {
			txtResponse.setText("");
		}
	});
}
	
// 클릭이벤트 리스너 
OnClickListener buttonConnectOnClickListener = new OnClickListener() {
	public void onClick(View arg0) {
		NetworkTask myClientTask = new NetworkTask(
				edtTextAddress.getText().toString(), 
				Integer.parseInt(edtTextPort.getText().toString())
		);
		myClientTask.execute();
	}
};

 

4. 네트워크 통신을 위한 AsyncTask 클래스 만들기

 

네트워크 통신을 위한 프로그램들은 비동기로 만들어져야 한다. 왜냐하면 프로그램

응답이 올때까지 기다릴수 없기 때문이다. 응답이 올때까지 먹통이 되면 안되기 때문이다.

Java 에서는 Thread 를 사용하겠지만 안드로이드에서는 AsyncTask 클래스를 제공해 준다.

이것을 상속받아 만드는데 시작할 때 수행하는 doInBackground() 함수와 onPostExecute()

만 구현하면된다.

그림에서 처럼 기본적으로 5개의 내부 Thread 가 생성되서 돌아가게 된다.

 

 

생성자에서 IP, PORT 정보를 넘긴다. 그리고 doInBackground() 에서는 Socket 객체를

생성한후 InputStream 을 통해 데이터를 받는다. onPostExecute() 에서는 받은 데이터를

표시하게 된다. 이곳에 표현하는 이유는 UI 스레드가 종료될 때 발생하는 함수 이기

때문이다. UI 가 다 표현 되지 않았는데 표현할려고 한다던지 UI스레드와 충돌을

방지 하기 위함이다.

 

public class NetworkTask extends AsyncTask {

	String dstAddress;
	int dstPort;
	String response;

	NetworkTask(String addr, int port) {
		dstAddress = addr;
		dstPort = port;
	}

	@Override
	protected Void doInBackground(Void... arg0) {

		try {
			Socket socket = new Socket(dstAddress, dstPort);
			InputStream inputStream = socket.getInputStream();
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
					1024);
			byte[] buffer = new byte[1024];

			int bytesRead;
			while ((bytesRead = inputStream.read(buffer)) != -1) {
				byteArrayOutputStream.write(buffer, 0, bytesRead);
			}

			socket.close();
			response = byteArrayOutputStream.toString("UTF-8");

		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	protected void onPostExecute(Void result) {
		txtResponse.setText(response);
		super.onPostExecute(result);
	}

}

 

5. 전체 소스와 실행화면

 

실행안드로이드 소스 :   SampleConnector.zip

서버 소스 :   ServerSocket.zip

 

 

package com.example.sampleconnector;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

	private TextView txtResponse;
	private EditText edtTextAddress, edtTextPort;
	private Button btnConnect, btnClear;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		edtTextAddress = (EditText) findViewById(R.id.address);
		edtTextPort = (EditText) findViewById(R.id.port);
		btnConnect = (Button) findViewById(R.id.connect);
		btnClear = (Button) findViewById(R.id.clear);
		txtResponse = (TextView) findViewById(R.id.response);

		btnConnect.setOnClickListener(buttonConnectOnClickListener);
		btnClear.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				txtResponse.setText("");
			}
		});
	}
	
	// 클릭이벤트 리스너 
	OnClickListener buttonConnectOnClickListener = new OnClickListener() {

		public void onClick(View arg0) {
			NetworkTask myClientTask = new NetworkTask(
					edtTextAddress.getText().toString(), 
					Integer.parseInt(edtTextPort.getText().toString())
			);
			myClientTask.execute();
		}
	};

	public class NetworkTask extends AsyncTask<Void, Void, Void> {

		String dstAddress;
		int dstPort;
		String response;

		NetworkTask(String addr, int port) {
			dstAddress = addr;
			dstPort = port;
		}

		@Override
		protected Void doInBackground(Void... arg0) {

			try {
				Socket socket = new Socket(dstAddress, dstPort);
				InputStream inputStream = socket.getInputStream();
				ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
						1024);
				byte[] buffer = new byte[1024];

				int bytesRead;
				while ((bytesRead = inputStream.read(buffer)) != -1) {
					byteArrayOutputStream.write(buffer, 0, bytesRead);
				}

				socket.close();
				response = byteArrayOutputStream.toString("UTF-8");

			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			txtResponse.setText(response);
			super.onPostExecute(result);
		}

	}
}

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <EditText 
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Address" />
    <EditText 
        android:id="@+id/port"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Port" />
    <Button 
        android:id="@+id/connect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Connect..."/>
    <Button 
        android:id="@+id/clear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Clear"/>
    <TextView
        android:id="@+id/response"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
반응형
Posted by 녹두장군1
,