검색결과 리스트
분류 전체보기에 해당되는 글 253건
- 2012.03.02 [Android] SQL
- 2012.03.02 [Android] PreferenceActivity
- 2012.03.02 [Android] Preference
- 2012.02.29 [Android] 파일 관리
- 2012.02.29 [Android] ScrollView 와 WebView
- 2012.02.27 [C#] InvokeRequired
- 2012.02.23 [Design] 상속관계의 업/다운 캐스팅
- 2012.02.23 [Java] Socket 2
- 2012.02.23 [C#] Socket
- 2012.02.23 [C#] Delegate와 Event 1
글
안드로이드에서 데이터 베이스는 SQLite를 이용한다.
여기에서 SQLiteOpenHelper를 이용하여서 적용시키는데 간단히 코드로 구현을 하면 다음과 같다.
class DBHelper extends SQLiteOpenHelper{
public DBHelper(Context context){
super(context,"test.db",null,1);
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE data(id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "first TEXT, second TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS data");
onCreate(db);
}
}
다음은 해당하는 내용의 메서드들의 설명이다.
메서드 | 내용 |
onCreat | DB가 처음 만들어 질 때 호출 되며 테이블 생성 및 초기 레코드 입력 |
onUpgrade | DB를 업그레이드 할 경우 호출. 기존 테이블을 삭제하고 새로 생성하거나 ALTER를 이용하여 DB를 수정 |
onOpen | DB를 열 때 이용 |
getReadableDatabase | 데이터를 읽기 위해 DB 열기 |
getWriteableDatabase | 읽고 쓰기 위한 DB 열기 |
close | DB 닫기 |
위 내용을 적용하여 CRUD 구문을 구현해보면 다음과 같다.
import android.app.Activity;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Button;
import android.widget.TextView;
public class ImageViewActivity extends Activity{
DBHelper m_dbhelper;
EditText m_txt;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
m_dbhelper = new DBHelper(this);
m_txt = (EditText)findViewById(R.id.txt);
findViewById(R.id.insert).setOnClickListener(b_listener);
findViewById(R.id.delete).setOnClickListener(b_listener);
findViewById(R.id.update).setOnClickListener(b_listener);
findViewById(R.id.select).setOnClickListener(b_listener);
}
Button.OnClickListener b_listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
SQLiteDatabase db;
ContentValues row;
switch(v.getId()){
case R.id.insert :
db = m_dbhelper.getWritableDatabase();
row = new ContentValues();
row.put("1", "2");
row.put("3", "4");
db.insert("data", null, row);
db.execSQL("INSERT INTO data VALUES (null,'5','6');");
db.close();
m_txt.setText("successed insert");
break;
case R.id.delete :
db = m_dbhelper.getWritableDatabase();
row = new ContentValues();
db.delete("data", null, null);
//db.execSQL("DELETE FROM data;");
db.close();
m_txt.setText("successed delete");
break;
case R.id.update :
db = m_dbhelper.getWritableDatabase();
row = new ContentValues();
row.put("first", "8");
db.update("data", row, "first='1'", null);
//db.execSQL("UPDATE data SET first = '8' WHERE first = '1';");
db.close();
m_txt.setText("successed update");
break;
case R.id.select :
db = m_dbhelper.getWritableDatabase();
Cursor cursor;
//cursor = db.query("data", new String[]{"first","second"},null,null,null,null,null);
cursor = db.rawQuery("SELECT first, second FROM data", null);
String result = "";
while(cursor.moveToNext()){
String first = cursor.getString(0);
String second = cursor.getString(1);
result+=(first+"="+second+"\n");
}
if(result.length()==0){
m_txt.setText("No Data");
}
else{
m_txt.setText(result);
}
cursor.close();
db.close();
break;
}
}
};
}
설정
트랙백
댓글
글
이 내용은 프리퍼런스에 의존하여 데이터를 가지고 있을 수 있는 UI 이다.
단 제약이 있다면 PreferenceScreen 영역 안에 레이아웃을 작성해야한다.
다음이 그 xml 내용이다.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
android:key="age"
android:title="나이"
android:summary="몇 살"
android:defaultValue="19"
/>
<CheckBoxPreference
android:key="male"
android:title="성별"
android:summary="남자?"
android:defaultValue="true"
/>
</PreferenceScreen>
여기 내용은 데이터가 변동 되더라도 자동으로 프리퍼런스에 접근하여 그때 그때 마다 내용을 기억 시킨다.
다음은 그 자바 코드이다.
package imageview.test;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
import java.io.*;
public class ImageViewActivity extends PreferenceActivity{
TextView v_key, v_value;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.main);
}
}
설정
트랙백
댓글
글
프리퍼런스는 일종의 환경 설정 파일과 동일한 형태라 생각하면 된다.
우리는 CS 프로그램을 만들다 보면 ini 와 같은 설정용 파일을 만드는데 안드로이드는 다음과 같이 하면 그런 형태를 만들어 낼 수 있다.
package imageview.test;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
import java.io.*;
public class ImageViewActivity extends Activity{
TextView v_key, v_value;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
v_key = (TextView)findViewById(R.id.key);
v_value = (TextView)findViewById(R.id.value);
SharedPreferences ref = getSharedPreferences("ImageViewActivity",Service.MODE_PRIVATE);
String key = ref.getString("key", "3");
v_key.setText(key);
int value = ref.getInt("value", 4);
v_value.setText("" + value);
}
public void onPause(){
super.onPause();
SharedPreferences ref = getSharedPreferences("ImageViewActivity",Service.MODE_PRIVATE);
SharedPreferences.Editor edit = ref.edit();
String key = v_key.getText().toString();
int value = 0;
try{
value = Integer.parseInt(v_value.getText().toString());
}catch(Exception ex){}
edit.putString("key", key);
edit.putInt("value", value);
edit.commit();
}
}
위에 내용에서 보면 getSharedPreferences 을 이용하여 첫번째 인자 내용의 xml 파일엥서 그 내용을 편집하기 위해 지정한다.
이는 DDMS 에서 패키지 명을 찾아 그 아래 폴더를 찾아보면 나와 있다.
또한 반드시 해야 할 것은 commit 처리이다. 저것을 하지 않으면 저장이 되지 않는다.
설정
트랙백
댓글
글
안드로이드 상에서 파일 관리는 자바 코드와 동일한 형식이다.
단 리소스에 추가 한 것만 좀 다른데 아무래도 리소스에 포함해서 하는 것이 좋지 않나 싶다.
실제 배포 경우 파일을 누락하고 하면 문제가 크니까 말이다.
다음은 그 코드 내역이다.
package imageview.test;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
import java.io.*;
public class ImageViewActivity extends Activity{
EditText txt;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt = (EditText)findViewById(R.id.txt);
findViewById(R.id.save).setOnClickListener(clicklistener);
findViewById(R.id.load).setOnClickListener(clicklistener);
findViewById(R.id.res).setOnClickListener(clicklistener);
findViewById(R.id.delete).setOnClickListener(clicklistener);
}
Button.OnClickListener clicklistener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.save :
try{
FileOutputStream fos = openFileOutput("text.txt",Context.MODE_WORLD_READABLE);
String str = "file save test";
fos.write(str.getBytes());
fos.close();
txt.setText("Success");
}
catch(Exception btn1ex){}
break;
case R.id.load :
try{
FileInputStream fis = openFileInput("text.txt");
byte[] data = new byte[fis.available()];
while(fis.read(data)!=-1){}
fis.close();
txt.setText(new String(data));
}
catch(FileNotFoundException btn2ex){txt.setText("File Not Fount");}
catch(Exception btn2ex){}
break;
case R.id.res :
try{
InputStream res = getResources().openRawResource(R.raw.test);
byte[] data = new byte[res.available()];
while(res.read(data)!=-1){}
res.close();
txt.setText(new String(data));
}
catch(Exception btn3ex){}
break;
case R.id.delete :
try{
if(deleteFile("text.txt")){
txt.setText("Delete");
}
else{
txt.setText("Delete Failed");
}
}
catch(Exception btn4ex){}
break;
}
}
};
}
설정
트랙백
댓글
글
스크롤 뷰는 프레임 레이아웃의 하위 클래스이다.
말 그대로 이는 한 화면에 나타내지 못하는 내용들을 보여주기 위해서 이용하는 뷰이다.
예제 코드는 다음과 같다.
XML
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scr"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ScrollView>
Java
package imageview.test;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
public class ImageViewActivity extends Activity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ScrollView svw = (ScrollView)findViewById(R.id.scr);
svw.addView(new ColorView(this));
}
}
class ColorView extends View{
String m_Text="";
public ColorView(Context context){
super(context);
}
public void onDraw(Canvas canvas){
Paint pnt = new Paint();
for(int i=0;i<1024;i+=4){
pnt.setARGB(255, 255-i/4, 255-i/4, 255);
canvas.drawRect(0, i,500,i+4,pnt);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
setMeasuredDimension(500,1024);
}
}
다음은 웹뷰이다.
웹뷰는 C#으로 친다면 WebBrowser 와 같은 역할이다.
간단한 테스트 코드를 보자면 다음과 같다.
XML
<?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">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="go"
/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="back"
/>
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="forward"
/>
<Button
android:id="@+id/btn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="local"
/>
</LinearLayout>
<FrameLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" >
<WebView
android:id="@+id/web"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible">
</WebView>
</LinearLayout>
</FrameLayout>
</LinearLayout>
다음은 자바 코드이다.
package imageview.test;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
public class ImageViewActivity extends Activity{
WebView web;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
web = (WebView)findViewById(R.id.web);
web.setWebViewClient(new webClient());
WebSettings set = web.getSettings();
set.setJavaScriptEnabled(true);
set.setBuiltInZoomControls(true);
web.loadUrl("http://www.google.com");
}
class webClient extends WebViewClient{
public boolean shouldOverriderUrlLoading(WebView view, String url){
view.loadUrl(url);
return true;
}
}
}
설정
트랙백
댓글
글
true의 경우에는 서로 다른 Thread 환경에서 나타나고 false 경우에는 같은 Thread 환경시 일어난다.
이는 보통 Thread 환경에서 다른 Control에 접근하여 쓰는 경우에 많이 있다.
대표적인 예로 Progress의 경우이다.
어떤 작업 비지니스 로직에서 이를 호출한 메인 Instance에서 그 내용을 변경 시 나타내는데 단순히 된다고 넘어 갈게 아니라
명심해 둬야 해서 이렇게 포스팅을 해 본다.
설정
트랙백
댓글
글
부모를 두고 자식이 부모 = 자식, 부모 = 부모, 자식 = (자식)부모 캐스팅 가능하나 자식 = 부모 캐스팅은 안된다.
이것은 OOP를 해 본 사람이라면 당연히 알 것이다.
이 글을 쓴 것도 훈스에 놀러 갔다가 퇴근5분전 님이 올린 댓글을 보고 그냥 생각나서 끄적여 본다.
흔히들 패턴에 맞춰서 코드를 생성하다 보면 함정에 빠진다.
당연히 1번과 2번의 관계면 생성 되서 다형성 형태로 만들 수 있겠지 하는 그런 생각.
그렇다고 함정에 빠지는 사람이 많다고 생각하지 않는다. 상속 관계를 어느정도 이해를 하는 사람들은...
하지만 다형성을 구현하고 할 경우에는 항상 숙지 해 둬야한다고 생각한다.
설정
트랙백
댓글
글
C#과 그냥 동일한 형태이다. 단 다음 예제는 객체를 던진다.
즉, Sirializable 된 데이터를 넘겨준다. 물론 C#에도 있다. 메모리 스트림을 이용하여 넘겼었던가 그럴 것이다.
서버 측 코드는 다음과 같다.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_Object
{
public static void main(String[] args) throws IOException
{
ServerSocket ServerSocket = null;
Socket AcceptSocket = null;
try
{
ServerSocket = new ServerSocket( 8520, 2000 );
while(true)
{
AcceptSocket = ServerSocket.accept();
ThreadClass service = new ThreadClass(AcceptSocket);
service.run();
}
}
catch(Exception ex)
{
System.out.println("error" + ex.getMessage());
}
finally
{
ServerSocket.close();
}
}
}
class ThreadClass extends Thread
{
private Socket s_socket;
public ThreadClass(Socket Sock)
{
s_socket = Sock;
}
public void run()
{
try
{
ObjectInputStream in = new ObjectInputStream(s_socket.getInputStream());
Student data = (Student)in.readObject();
out.writeObject(data);
}
catch(Exception e)
{
System.out.println("error" + e.getMessage());
}
finally
{
try
{
s_socket.close();
}
catch(IOException ioex)
{
}
}
}
}
크게 다른 것은 없다
소켓을 생성하여 거기에 대한 접근 소켓을 따로 처리 해 주면서 Stream을 통하여 처리를 한다. 문자열을 보내고 싶다면
BufferedWriter와 BufferedReader, StreamReader 쪽을 찾아서 처리를 하면 된다.
스트림을 받을 땐 명시적으로 반드시 해당하는 형에 따른 변환을 하여서 처리를 해야한다.
그리고 서버 소켓 쪽에 살펴보면 2000 이라고 명시 된 부분이 있는데 이는 C#에서 Listen 과 같은 역할을 한다.
클라이언트 쪽은 다음과 같다.
import java.net.*;
import java.io.*;
public class Client_Object {
public static void main(String[] Args) throws IOException
{
Socket c_socket = null;
try
{
c_socket = new Socket("127.0.0.1",5425);
ObjectOutputStream out = new ObjectOutputStream(c_socket.getOutputStream()
Student data = new Student();
data.setName("홍길동");
data.setAdd("경북");
out.writeObject(data);
}
catch(Exception ex)
{
System.out.println("error" + ex.getMessage());
}
finally
{
c_socket.close();
}
}
}
역시나 마찮가지로 소켓을 하나 생성한 후 ObjectOutputStream을 이용하여 날려 보내면 된다.
바이트로 데잍를 전송 시킬 경우는 다음과 같다.
일단 먼저 서버이다.
try
{
byte[] buff = new byte[1024];
in.read(buff);
String sData= new String(buff);
System.out.println(sData);
out.write("S->C".getBytes());
}
catch(Exception e)
{
System.out.println("error" + e.getMessage());
s_socket.close();
break;
}
finally
{
}
InputStream을 이용하여 buffer에 쌓인 데이터를 받아 원하는 형태로 바꿔주고
전송 할 경우 getBytes()를 이용한다. 이는 C#에 Encoding.Defalt.GetBytes() 와 동일한 역할을 한다.
클라이언트 측도 위 내용과 동일한 형태이다. InputStream과 OutputStream을 이용하면 손쉽게 작성 가능하다.
설정
트랙백
댓글
글
문득 생각나서 한번 작성해 본 코드이다.
.NET 에서 제공하는 리스너가 아닌 소켓만으로 작성한 예이다.
일반적으로 코드 내용은 같다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace Server
{
public partial class Form1 : Form
{
IPEndPoint _ip_end_point;
Socket _server;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
this._ip_end_point = new IPEndPoint(IPAddress.Any, 10000);
this._server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this._server.Bind(this._ip_end_point);
this._server.Listen(100);
while (true)
{
Application.DoEvents();
Socket client = this._server.Accept();
int recv_total = 0;
int recv_size = 0;
int left_data = 0;
int recv_data = 0;
byte[] size = new byte[4];
recv_data = client.Receive(size, 0, 4, SocketFlags.None);
recv_size = BitConverter.ToInt32(size, 0);
left_data = recv_size;
byte[] data = new byte[recv_size];
while (recv_total < recv_size)
{
Application.DoEvents();
recv_data = client.Receive(data, recv_total, left_data, 0);
if (recv_data == 0)
{
this.Text = "Zero Data";
break;
}
else
{
this.Text = "No Zero Data";
recv_total += recv_data;
left_data -= recv_data;
}
}
client.Close();
MessageBox.Show(Encoding.Default.GetString(data, 0, recv_size));
}
}
catch
{
}
finally
{
this._server.Close();
}
}
}
}
코드에서 보면 알겠지만 엔드 포인트를 잡아주고 그것을 바인드 한 형태이다.
하나 의문인게 Listen 처리를 하지 않으면 안될까.. 고민 하다가 한번 빼 보고 했는데 바로 오류가 났다.
한 소켓에 접근하는 수를 제어하는 것인데 여러 수천, 수만명이 접근 할 때는 어떻게 되는 것인가 의문이 든다.
한번 연구 해 볼 만한 가치는 있는 듯 하다.(경력에 비해 해 본 것이 없는 것 같아 슬프다.)
나머지는 대략 접속한 소켓을 생성하고 그 내용을 바이트 처리 하여 하는 것이다. 여기까지가 서버 코드이다.
다음은 클라이언트 코드이다.
try
{
IPEndPoint ip_end_point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10000);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Connect(ip_end_point);
int send_total = 0;
int data_size = 0;
int left_data = 0;
int send_data = 0;
EventHandler();
byte[] data = new byte[data_size];
data = Encoding.Default.GetBytes("TCP/IP Connect Test");
data_size = data.Length;
left_data = data_size;
byte[] size = new byte[4];
size = BitConverter.GetBytes(data_size);
server.Send(size);
while (send_total < data_size)
{
send_data = server.Send(data, send_total, left_data, SocketFlags.None);
send_total += send_data;
left_data -= send_data;
}
}
catch
{
}
finally
{
server.Close();
}
최초의 작업은 서버 측과 동일하다. 엔드 포인트를 잡아주고 소켓을 생성해서 서버와 접속을 한다.
물론 데이터 처리는 서버와 동일하게 하기 위해서 바이트 처리를 하게 해봤다.
이것 말고도 네트워크 스트림을 이용하여 스트림을 이용해서 문자열들을 보내는 통신 또한 가능하다.
각기 해당하는 스트림을 생성하여 Flash() 처리를 해 주면 된다.
그렇게 작업 할 경우 반드시 스트림 처리엔 Flash() 처리를 해 줘야한다. 아닐 경우 버퍼에 쌓인 데이터 문제도 있을 뿐더러
통신 결과가 원할하지 않거나 문제가 발생하는 것을 확인 할 수가 있을 것이다.
설정
트랙백
댓글
글
대리자와 이벤트는 종종 많이 쓰인다.
보통 부모와 자식의 관계를 맺고 있거나, 쓰레드를 이용할 경우 필자는 종종 썼다.
예전에 좀 무식하게 부모창으로 넘길 때는 this 키워드를 이용해서 Invoke 하는 방식으로 했는데
혼자서 좀 생각을 해 보니 다음과 같이 해도 될 것 같아 해 보니 동작은 한다.
일단 자식 측에 아래와 같이 코드를 작성해 본다.
public delegate void m_delegate(string msg);
public event m_delegate m_event;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
m_event("Test");
}
그리고 부모 측의 코드는 다음과 같다.
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2();
form.m_event += new Form2.m_delegate(event_test);
form.ShowDialog();
}
private void event_test(string msg)
{
MessageBox.Show(msg);
}
부모 측에 보면 자식에 접근하여 그곳의 이벤트를 생성한 것을 알 수가 있다.
그러나 테스트 코드를 짜다보니 결과가 원하는 대로 나오지 않았다.
왜냐.. 자식 측에 어떤 특정한 이벤트가 일어나지 않으면
m_event("Test"); 부분은 작성 할 수가 없었다.(아니면 누군가 보시다 지적 바랍니다.)
혹시나 싶어서 버튼 이벤트를 주고 해 보니 동작했다.
사용 방법마다 조금씩 다르겠지만.. 이 역시 숙지 해 둔다면 좋을 법 하다.
그리고 대리자와 이벤트의 관계를 잘 보면 이벤트는 대리자의 선언 명으로 형식을 지정하는데
이는 이벤트가 대리자를 캡슐화 한다고 생각해도 무방 할 듯 하다.
RECENT COMMENT