Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 팁&트릭
Delphi Programming Tip&Tricks
[328] 델파이와 안드로이드 통신
첫눈 [hadugo] 4469 읽음    2015-01-09 18:29
질문을 너무 자주해서 죄송한데 짜증 한 번 없이 꼬박 꼬박 답변 해주시는 분들께 감사합니다.

저도 뭔가 도움을 드려야 하는데 제가 아는게 없어서 드릴것은 없고
이번에 안드로이드와 델파이 통신을 하면서 새로 알게 된 것이라도 올려봅니다.

여기 계신 분들에게 무슨 도움이 되겠느냐만 제가 할 수 있는게 이것 뿐이네요.




델파이XE2를 사용하고 있습니다.

정품구매한지 얼마 안된것 같은데 벌써 몇 년이 지나고 이제 XE6네요.

개발이 전문이라면 다시 구매하겠지만 자잘한 프로그램들 개인적으로 개발해서 사용하는터라 또 비용을 들일 수가 없어
안드로이드 개발을 위해 자바와 이클립스를 설치했는데요.

이놈의 이클립스와 자바 무슨 에러가 그렇게 많은지 프로젝트 하나 딸랑 생성하는데만 몇개월이 걸렸는지 생각도 안나네요.

이번에 개발한 것은 안드로이드(자바)에서 서버(델파이)로 데이터 요청을 하면
서버에서 필요한 자료를 전송해서 안드로이드 폰에 데이터를 보여주는 간단한 프로그램입니다.

서버쪽에서는 idTCPServer을 이용했구요.

클라이언트에서는 socket라이브러리를 이용했습니다.

문제는 안드로이드에서 데이터를 요청하면 서버에서 여러개의 레코드를 어떻게 전송하느냐인데
특히 integer형의 경우 델파이와 안드로이드에서 integer형 데이터의 크기가 다르고 변수에 저장될때 바이트 순서가 다른건지
데이터를 읽지 못합니다.

그리고 델파이쪽에서 데이터를 레코드형식으로 담아서
여러개의 레코드를 스트림에 담아서 전송하려고 했는데
문제는 제가 개발자가 아니고 단지 남들이 만들어 놓은 소스코드 수정해가며 짜집기 하는 정도이다 보니
스트림으로 데이터를 보냈을때 안드로이드(자바)쪽에서 어떤 형식의 데이터로 받아야 하는지도 모르겠고
게다가 자바에는 레코드형 데이터가 없기 때문에 어떻게 해야 할지 몰라 질문을 하니
고맙게도 조대현님께서 힌트를 주셧습니다.

하지만 힌트를 얻고 나서도 여러개의 레코드를 전송할때 루프로 돌리면서 하나씩 전송하는 예제는 인터넷에 많이 올라와 있는데
여러개의 레코드를 한 번에 자바쪽으로 전송하는 소스코드를 구할 수가 없어 고민을 했습니다.


게다가 개발을 전문으로 하는 분들에게는
서버가 자바이고 클라이언트가 델파이인 경우와
서버가 델파이이고 클라이언트가 자바이거나 관계가 없겠지만
인터넷을 뒤져보면 모두 자바가 서버인 예제만 있고 전 그와 반대로 해야하니
전 이걸 어떻게 고쳐야 하는지 조차 모르니 이것 때문에 한참을 고생했네요.^^



하여간 데이터 호완성 문제는 결국은 XML로 해결했습니다.


델파이쪽에서는 데이터를 XML형식으로 담아 언어간의 호환성이 좋은 XML형식의 스트링으로 전송하고
안드로이드쪽에서는 그 스트링을 받아서 파싱합니다.

그리고 수치형데이터의 경우 문제가 있기 때문에 모두 intToString를 이용해 모두 스트링형으로 바꿔서 전송하니
모든 문제가 해결되네요.




하지만 여전히 이해가 안되는 것은 델파이쪽에서는 String을 UTF-8로 변환해서 보냈는데
안드로이드 쪽에서는 받은 그대로 읽히더라는 겁니다.

JAVA가 웹이라는게 나오면서 나와서 UTF-8을 기반으로 하는지도 모르겠네요.




먼저 델파이쪽입니다.

idTCPServer에서 스트링형을 전송하는 방법은 모두 아실테니 별도로 설명드리지는 않겠습니다.
다만 XML형식으로 변환하는 부분만 보여드리겠습니다.
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
...
...
Begin
	IF AContext.Connection.Connected Then
	Begin
		....
		....
		SendStr := '';
		SendStr := SendStr + '';
		For i := 0 To count do
		Begin
			name     := ....;
			value     := ....;
			SendStr := SendStr + '' + name  + '';
			SendStr := SendStr + '' + value   + '';
		End;	
		SendStr := SendStr + '';
		....
		....
		AContext.Connection.IOHandler.Writeln(SendStr, TIdTextEncoding.UTF8);
	End;
End;



이렇게 전송하면
다음은 안드로이드쪽에서 수신하는 부분입니다.



public class MainActivity extends FragmentActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		.....
		.....
		.....
		Button startButton = (Button)findViewById(R.id.button1);
		startButton.setOnClickListener(new View.OnClickListener() {			
			@Override
			public void onClick(View v) {
				//안드로이드에서는 통신을 할때 쓰레드처리를 해야 에러가 안납니다.
				TCPclient	tcpThread	= new TCPclient("데이터 좀 보내줘");
				Thread		thread		= new Thread(tcpThread);
				thread.start();
				//일단 쓰레드에서 데이터를 전송했으니 이제 데이터가 오기를 기다리면 됩니다.
				//하지만 데이터가 언제 올지 몰라서 루프로 돌렸네요.
                                //루프는 1분(60000)을 기다려도 안오면  그냥 포기합니다.
				// 만일 응답이 없으면 에러처리는 별도로 해야 합니다.
				String	ReceiveString	= "";
				long	TimeStemp1		= System.currentTimeMillis();
				while (ReceiveString.equals("")) {
					ReceiveString	= tcpThread.GetTCPclient();  //쓰레드 안에서 데이터를 받아옵니다.	
					long TimeStemp2	= System.currentTimeMillis();
					if((TimeStemp2 - TimeStemp1) > 60000){     // 1분동안 응답이 없으면 포기
						break;
					}
				}
			// 이제 데이터가 들어왔으니 XML파싱을 합니다.
			// XML파싱은 XmlPullParser를 이용하는데요. 
			// XmlPullParser는 저같은 사람들도 쉽게 이해할 수 있고 인터넷을 뒤져보면 아주 쉽게 자료를 구할 수 있습니다.
                              ......
                              ......
			} // public void onClick(View v)
		}); // startButton.setOnClickListener(new View.OnClickListener() 
	} //protected void onCreate(Bundle savedInstanceState) 

	//서버에 데이터요청하는 모듈 (자바에서는 모듈이라고 안하고 클래스라고 하더군요.^^)
	private class TCPclient implements Runnable {
		private	Socket	inetSocket	= null;    // 이놈이 델파이의 idTCPClient에 해당하는 놈인가 봅니다.
		private	String	sendString	= "";
		private	String	receiveString	= "";
		private	String	ipAddr		= 서버IP주소
		private	int		portNo		= 통신포트

		public TCPclient(String _sendString) {
			this.sendString = _sendString;
	    	} //public TCPclient(String _sendString)

		public String GetTCPclient() {
			return this.receiveString;
		} //public String GetTCPclient()


		public void run() {
			try {
	    			inetSocket = new Socket(ipAddr ,portNo );
		    		try {
					OutputStream		outputStream= inetSocket.getOutputStream();
					WriteroutputStream	Writer		= new OutputStreamWriter(outputStream);
					Writer			bufferWriter	= new BufferedWriter(outputStreamWriter);
					PrintWriter		out				= new PrintWriter(bufferWriter, true);
					out.println(sendString);  //여기서 서버로 데이토요청신호가 전송됩니다.

					InputStream		inputStream		= inetSocket.getInputStream();
					Reader			bufferReader	= new InputStreamReader(inputStream);
					BufferedReader	in				= new BufferedReader(bufferReader);

					Long 			timeStemp1 		= System.currentTimeMillis();
					while (receiveString.equals("")) {
						receiveString		= in.readLine();   // 서버에서 응답한 데이터를 읽는 부분
						Long timeStemp2	= System.currentTimeMillis();
						if((timeStemp2 - timeStemp1) > 60000){ break; } // 1분을 기다려도 응답이 없으면 포기해요.
					} //while (receiveString.equals(""))
				} catch (Exception e) {
					Toast.makeText(MainActivity.this, "전송에러", Toast.LENGTH_SHORT).show();
				} finally {
					inetSocket.close();
				} 
			} catch (Exception e) {
				Toast.makeText(MainActivity.this, "접속에러", Toast.LENGTH_SHORT).show();
			}
	    } // public void run() 
       } //private class TCPclient implements Runnable
} //public class MainActivity extends FragmentActivity




참고로 전 자바를 모르기 때문에 위 코드대로 입력하면 데이터형이 잘못됬다는 에러가 발생할지도 모릅니다.
데이터형은 다른 자료를 참고하여 수정하시기 바랍니다.

+ -

관련 글 리스트
328 델파이와 안드로이드 통신 첫눈 4469 2015/01/09
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.