httpclient 를 사용해서 웹페이지에서 리턴값을 받아오려는데, 그것도 POST 방식으로~ 잘 되지않는다. 온갖 예제를 다 해봤지만 되지 않았었다. 이유는 무엇이었을까나...
말도 안되게 시뮬레이터 문제였다.
android:permission=INTERNET 도 주고 했건만 안되다가...
프로젝트 생성시에 SDK 버전을 8로 주고 만들었었는데, 그것이 화근이었을까?
LOG 를 보니 SDK 8 어쩌고 에러가 있더라.
새로 프로젝트를 생성하며 생성창 제일 아래의 SDK 버전 정보를 입력하지 않고 생성.
그리고, 기존 소스를 입력한 후 실행했더니 왠걸~
바로 실행되버렸다. 어이없음.

디버그 스킬을 익힐 필요를 느끼면, 이클립스는 참 놀라운 툴이지만 쓸줄 모르면 에디트플러스만 못하구나라는걸 새삼.
소스에만 문제가 있을거라는 이 안이한 생각은 어디서 나온 것일까? 요즘  웹브라우저의 다양성으로 인해 웹프로그램 납품에 비상이 걸린지 오래이다.
예전엔 잘 되던 소스들이 이젠 브라우저마다 다르게 보인다는 문제가 생겨버린 것이다.

스마트폰 개발을 해보며 느끼는것도 비슷한 부류다. 디바이스 기준이기 때문에 디바이스의 성격을 잘 알아야 문제없이 만들어 갈수 있다. 이제 문제는 동일 소스가 적용되지 않는다는 것이지. 존재하지 않는 소수는 없지만, 디바이스에 대한 무지가 빗어내는 버그들.

전체를 봐야 할 것이야~
크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/23 18:35 2010/11/23 18:35
, ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5670

[Android] 인텐트(Intent) 의 기본

인텐트(Intent)

한 액티비티에서 다른 액티비티를 실행하려면 액티비티 실행을 요청하는 도구가 필요하다. 안드로이드는 브로드캐스팅과 인텐트(Intent)를 제공하는데, 브로드캐스팅은 모든 객체에게 뿌리는 방송과 같은 것이며 인텐트는 이 방송에 실려 전달되는 메시지에 해당된다.

인텐트는 명시적 인텐트와 묵시적 인텐트가 있다.
실행할 액티비티를 직접적으로 정확하게 가리키는 것을 명시적 인텐트라고 하고,
필요한 기능만 설명한 채 직접적으로 액티비티를 가리키지 않는 것을 암시적 인텐트라고 한다.

명시적 인텐트가 가장 빈번히 사용되는 경우는 하나의 패키지 안의 한 액티비티가 또 다른 액티비티를 호출할 때이다. 이것이 가능한 이유는 너무나도 당연한 일이지만 호출하는 쪽에서 호출할 액티비티를 임포트할 수 있기때문이다.
명시적 인텐트를 사용하는 법은 어렵지 않다. 현재 액티비티의 컨텍스트와 실행할 액티비티 클래스를 인텐트 생성자의 인자로 사용하여 인텐트 인스턴스 하나를 생성한 후에 startActivy() 메서드에 생성한 인텐트를 인자로 넘겨서 호출하면 된다.
... (생략)...
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
... (생략)...
만일 액티비티의 실행 결과를 받아서 추가적인 일을 수행하려면 startActivity() 메서드 대신
startActivityForResult() 메서드를 사용하면 된다.
... (생략)...
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 0);
... (생략)...
startActivityForResult() 메서드가 실행되고 지정한 액티비티가 실행된 후에 실행된 액티비티가 다시 종료되면 액티비티의 onActionResult() 메서드가 호출될 것이다.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
      // 실행한 액티비티가 종료된 후에 필요한 코드를 이곳에 추가합니다.
}
Intent 클래스 생성자의 첫 번째 인자는 현재 액티비티의 컨텍스트이고 두 번째 인자는 실행할 액티비티의 클래스이다.

암시적 인텐트는 앞에서 설명한 것처럼 실행 주제를 정확하게 서술하지 않고 자신의 목적만으로 적합한 액티비티를 실행하는 것이다.  암시적 인텐트를 사용하기 위해서는 두 가지가 필요하다. 하나는 실행하고자 하는 기능을 나타내는 액션(action)이며, 다른 하나는 액션과 함께 액티비티에 넘겨줄 데이터(data)입니다. 액션은 String 객체로 표현되며 데이터는 Uri 클래스의 인스턴스 이다. 예를 들어 가장 많이 사용되는 전화의 경우 액션으로 Intent.ACTION_CALL을, 데이터로 Uri.parse("tel:01012345678") 과 같은 Uri 값을 사용한다. 이를 코드로 구현하면 아래와 같다.
...(생략)...
/* 전화를 걸기 위한 인텐트를 생성합니다. */
Intent intent = new Intent(Intent.ACTION_CALL);
/* 전화를 Uri 인스턴스로 변환합니다.  */
intent.setData(Uri.parse("tel:01012345678"));
/* 생성된 인텐트를 사용해 액티비티를 실행합니다.  */
startActivity(intent);
...(생략)...
전화를 거는 액티비티를 실행하기 위해 Intent.ACTION_CALL 액션을 사용하고 전화번호를 인자로 넘겨줘야 한다는 사실을 어떻게 알 수 있을까? 암시적 인텐트를 사용하기 위해서는 실행될 대상이 어떤 조건의 인텐트를 받는지 문서상으로 알고 있어야 한다. 안드로이드의 기본 애플리케이션 가운데 전화, 브라우저, 맵 등은 액티비티 공유를 위해 필요한 액션과 데이터를 문서로 공유하고 있다.

구글의 개발자 사이트의 http://developer.android.com/guide/appendix/g-app-intents.html 로 들어가서 Intents List : Invoking Google Applications on Android Devices(인텐트 목록: 안드로이드 기기에서 구글의 애플리케이션 호출하기)를 읽어보면 액션과 필요한 데이터를 확인할 수 있다.



크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/09 16:42 2010/11/09 16:42
, , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5633



Unparsed aapt error(s)! Check the console for output. 발생 시

이클립스에서 위의 에러 발생 시

메뉴에서 [Project] > [clean] 으로 처리하시오.

크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/08 18:27 2010/11/08 18:27
, , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5630

액티비티 생명주기(Activity Life Cycle) 는 총 6단계를 거치며, 상황에 따라 1단계가 더 추가될 수 있다.
6단계는 시간의 순서에 따라 생성, 시작, 활성화, 비활성화, 중비, 소멸이며,
애플리케이션이 비활성화되었다가 활성화되는 순간 재시작을 거치게 되어 사실상 7단계로 구성된다. (재시작되지 않은채 소멸될수 있다. )

처음 실행시 OnCreate(), onStart(), onResume()순으로 빠르게 호출이 실행된다.
이것은 액티비티가 처음으로 실행될 때이며 테스크가 백그라운드로 숨었다가 다시 실행될 때에는 onStart() onResume() 메서드를 호출하고, onCreate()는 생략된다.
onPause()는 액티비티가 비활성화되어 화면에서 사라지기 직전을 나타낸다.
onStop() 은 액티비티가 화면상에서 완전히 사라져버릴때 호출된다. onPause() 뒤에 불리며 시스템메모리가 부족한 경우 onStop()은 호출되지 않는다.

대부분의 경우 액티비티가 화면상에서 사라지는 순간 onPause(), onStop()순으로 연속 호출되어 두 메서드 사이의 경계를 구분하기가 어려울 수 있는데, onStop()의 호출없이 onPause() 메서드만 호출되었다가 활성화되었을때 onResume()으로 돌아가는 경우는 현재 액티비티 앞에 반투명 액티비티가 존재하는 경우이다.

* 일반적인 실행 종료 주기


#  두개의 액티비티가 존재할 경우
* 최초 실행
사용자 삽입 이미지사용자 삽입 이미지
*  A액티비티 택스트 클릭시 B 액티비티 실행
사용자 삽입 이미지사용자 삽입 이미지
* 취소 버튼으로 B 액티비티 취소
사용자 삽입 이미지사용자 삽입 이미지
* A 액티비티 까지 전부 종료
사용자 삽입 이미지사용자 삽입 이미지

* ActivityLifeCycle.java
package com.froglamb.activity_life_cycle;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class ActivityLifeCycle extends Activity {
   
    private String TAG = "ActivityLifeCycle";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.i(TAG, "onCreate()");   
       
        //SecondaryActivity 추가
        TextView text_view = (TextView) findViewById(R.id.text_view);
        text_view.setOnClickListener(
                new OnClickListener() {
                    public void onClick(View v) {
                        Intent intent = new Intent(ActivityLifeCycle.this,
                                SecondActivity.class);
                        startActivity(intent);
                    }
                });
    }
   
    @Override
    public void onStart(){
        super.onStart();
       
        Log.i(TAG, "onStart()");
    }
   
    @Override
    public void onStop(){
        super.onStop();
       
        Log.i(TAG, "onStop()");
    }
   
    @Override
    public void onResume(){
        super.onResume();
       
        Log.i(TAG, "onResume()");
    }
   
    @Override
    public void onRestart(){
        super.onRestart();
       
        Log.i(TAG, "onRestart()");
    }
   
    @Override
    public void onDestroy(){
        super.onDestroy();
       
        Log.i(TAG, "onDestroy()");
    }
   
    @Override
    public void onPause(){
        super.onPause();
       
        Log.i(TAG, "onPause()");
    }
       
}

* SecondActivity.java
package com.froglamb.activity_life_cycle;

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

public class SecondActivity extends Activity{
    private String TAG = "ActivityLifeCycle";
   
    @Override
    public void onCreate(Bundle savedInstanceBundle){
        super.onCreate(savedInstanceBundle);
        Log.i(TAG, "SecondActivity/onCreate()");
       
        TextView textview = new TextView(this);
        textview.setText("SecondActivity !!!");
        setContentView(textview);
    }
}


* Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.froglamb.activity_life_cycle"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ActivityLifeCycle"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="SecondActivity" android:theme="@android:style/Theme.Translucent" />

    </application>
    <uses-sdk android:minSdkVersion="8" />

</manifest>

* main.xml - Layout
<?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:id="@+id/text_view"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
</LinearLayout>


크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/08 12:10 2010/11/08 12:10
, , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5629

DroidDraw 는 안드로이드 화면 구성 코드를 보다 손쉽게 작성할 수 있도록 GUI 를 구현해둔 것이다. 감탄이 절로 나오는걸~
홈페이지에 들어가면 메인에서 바로 적용해볼 수 있어서 접근성을 엄청 높였다.

DroidDraw - Graphical User Interface (UI) designer/editor for programming the Android Cell Phone Platform

URL : http://www.droiddraw.org/

사용자 삽입 이미지
Android Draw : http://www.droiddraw.org/androiddraw.html
사용자 삽입 이미지사용자 삽입 이미지


Tutorial : http://www.droiddraw.org/tutorial.html

사용자 삽입 이미지
Widget Guide : http://www.droiddraw.org/widgetguide.html

사용자 삽입 이미지



크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/04 20:10 2010/11/04 20:10
, , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5619

SQLite
(1)  데이터베이스의 정의
 : Android에서 데이터베이스로 접근하려면, SQLiteOpenHelper 클래스를 상속한 데이터베이스 헬퍼를 정의하고 이것을 이용한다.  이 헬퍼는 데이터베이스의 생성 및 업그레이드를 관리한다.
 SQLiteOpeHelper 클래스를 상혹한 클래느는 다음의 메소드를 오버라이드한다.
오버라이드하는 메소드 메소드의 호출
onCreate() 메소드
onUpgrade() 메소드
데이터베이스 생성 시 호출.
데이터베이스 업그레이드 시 호출.

(2) 데이터베이스 헬퍼 생성자

   SQLiteOpenHepler 클래스

SQLiteOpenHelper(Context context, String fileName, SQLiteDatabase.CursorFactory factory, int version)
기능 : SQLiteOpenHelper 클래스의 생성자
인수 : context     컨텍스트
           fileName 데이터베이스 파일명
          factory      팩토리
          version     버전
  데이터베이스 이름에는 저장할 곳의 파일명을 지정합니다.
  /data/data/패키지명/databases/데이터베이스 파일명 ( test.db) 에 저장됩니다.
  팩토리는 사용하지 않으면 null을 지정하고, 버전은 1을 지정.

(3) 데이터베이스의 생성 : onCreate() 메소드를 호출
   SQLiteOpenHelper 클래스

void onCreate(SQLiteDatabase db)
기능 : 데이터베이스 생성 시 호출
인수 : db 데이터베이스 객체
  onCreate() 메소드 내에서는 SQL명령으로 테이블을 생성하고 있습니다. test 라는 테이블명에서 id 와 info 라는 컬럼을 갖고 있는 테이블을 생성하는 SQL 명령은 아래와 같습니다. 컬럼의 형은 문자열이므로 컬럼명 뒤에 text라고 기술하고, id 는 다른 ID 와 중복되지 않는 기본키이므로 primary key 라고 추가합니다.
create table id not exists text(id text primary key, info text)                                                       

SQL명령을 실행하려면 SQLtestDatabase 클래스의 execSQL()을 사용합니다.
   SQLiteDatabase 클래스

void execSQL(String Sql)
기능 : SQL 명령의 실행
인수 : sql   SQL명령

(4) 데이터베이스의 업그레이드
  : 데이터베이스는 버전업 시 데이터베이스 구조를 변환하지 않으면 업그레이드가 안 되는 경우가 있습니다. 필요로 하는 버전에 이상이 있을 경우 이 onUpdate() 메소드가 불리므로, 이 메소드 내에서 구버전 번호와 신버전 번호의 정보로부터 데이터베이스 구조의 변환을 실행합니다.
  SQLiteOpenHelper 클래스

void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
기능 : 데이터베이스를 업그레이드한 때
인수 : db                 데이터베이스 객체
           oldVersion 구버전 번호
          newVersion 신버전 번호
  다음으로, SQL명령으로 테이블을 삭제한 후 onCreate() 메소드를 호출하여 테이블을 생성합니다. test 라는 이름의 테이블을 삭제할 SQL명령은 다음과 같습니다.
 drop    table   if    exists   test                                                                                                

(5) 데이터베이스 객체의 취득
  : 메인이 되는 SQLiteEx 클래스의 개체에서는 먼저 정의한 데이터베이스 헬퍼를 이용하는 SQLiteDatabase 형 데이터베이스객체를 구합니다. 프로그램 내에서는 이 객체를 사용해서 데이터베이스의 조작을 실행합니다. 데이터베이스 객체를 구하려면 DBHelper 객첼르 생성한 후 getWritableDatabase() 메소드를 호출합니다.
    SQLiteOpenHelper 클래스

SQLiteDatabase getWritableDatabase()
기능 : 데이터베이스 객체의 취득
인수 :데이터베이스 객체

(6) 데이터베이스의 쓰기
   : 데이터베이스의 쓰기를 실행하려면 Content Values 클래스로 갱신하는 레코드 정보를 작성합니다. Content Values 객체를 생성한 후 put() 메소드로 컬럼명과 값을 세트로 추가합니다.
   ContentValues 클래스

void put(String colName, String value)
기능 : 레코드 정보에 컬럼명과 값 추가
인수 : colName   컬럼명
           value         값
이 프로그램에서는 다음의 칼럼을 추가하고 있습니다.
컬러명   
    값                                                       
id
info
0
텍스트 박스의 문자열
데이터 객체의 update() 메소드에 이 레코드 정보를 건네주는 것에 의해서, id[0]을 갖는 레코드의 info가 텍스트 박스의 문자로 덧쓰게 됩니다.
   SQLiteDatabase 클래스

int update(String tableName, ContentValues values, String where, String[] whereArgs)
기능 : 테이블 레코드의 갱신
인수 : tableName   테이블명
           values           레코드 정보
          where           where 파라미터
          whereArgs  where 파라미터
반환값 : 갱신한 레코드 수
  반환값 레코드 수가 0이 될 때는 id[0] 이 존재하지 않는다고 간주하고, insert() 메소드로 테이블에 레코드를 삽입한다.
  SQLiteDatabase 클래스

long insert(String tableName, String nullColumnHack, ContentValues values)
기능 : 테이블의 레코드 추가
인수 : tableName   테이블명
           nullColumnHack   NULL값
          values           레코드 정보
반환값 : 레코드 ID

(7) 데이터베이스로부터 읽기
    : 데이터베이스로부터 읽기를 실행하려면 데이터베이스 객체의 query() 메소드를 사용합니다.
  SQLiteDatabase 클래스

Cursor query(String tableName, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
기능 : 데이터베이스로부터 읽기
인수 : tableName   테이블명
           columns        컬럼명의 배열
           selection       selection parameter
           selectArgs    selection parameter factor
           groupBy        groupBy parameter
           having           having parameter
           orderBy         orderBy parameter
           limit                limit parameter
반환값 : Cursor 객체
    selection, groupBy, having, orderBy, limit 파라미터는 SQLite의 query 명령 파라미터입니다. 이번에는 id가 0 인것만을 취득하고 싶기 때문에 selection 파라미터에 "id=0" 을 지정하고 있습니다.
  반환값은 Cursor 객체로 구해지는데, Cursor 객체는 내부적으로 다수의 레코드를 저장하고 있습니다.  getCount() 메소드로 레코드 수, getColumnCount() 메소드로 컬럼 수를 구할 수 있습니다.

  Cursor 클래스

int getCount()              
기능 : 레코드 수 구하기
반환값 : 레코드 수
Cursor 클래스

int getColumnCount()                  
기능 : 컬럼 수 구하기
반환값 :컬럼 수
    Cursor 객체는, 자장하는 레코드 안의 조작대상을 지시하는 정보(커서)를 갖습니다.
     커서에서 선두의 레코드를 지시하는 때에는 moveToFirst() 메소드를 부릅니다.
Cursor 클래스

boolean moveToFirst()                  
기능 : 커서에서 선두 레코드를 지시한다.
반환값 : 성공 또는 실패
 그리고 나서, getString() 메소드 등을 부르는 것으로 레코드 내의 컬럼이 지시하는 값을 수하는 것이 가능합니다.
Cursor 클래스

String getString(int colIdx)                     
기능 : String 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : String 형의 값

double getDouble(int colIdx)                 
기능 : double 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : double 형의 값

float getFloat(int colIdx)               
기능 : float 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : float 형의 값

int getInt(int colIdx)               
기능 : int 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : int 형의 값

long getLong(int colIdx)               
기능 : long 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : long 형의 값

short getShort(int colIdx)               
기능 : short 형 값 구하기
인수 : colIdx 컬럼의 위치
반환값 : short 형의 값

여기에서는 컬럼1(0부터 시작하므로 2열 째) 값을 String 형으로 얻고 있습니다.
마지막으로, Cursor 객체의 close() 메소드를 호출하여 Cursor 를 종료합니다.

------------- SQLiteEx.java ------------------------
package com.froglamb.sqliteex;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

public class SQLiteEx extends Activity implements View.OnClickListener{
   
    private final static String DB_NAME = "test.db"; // DB name
    private final static String DB_TABLE = "test";   // table name
    private final static int    DB_VERSION = 1;      // Version
   
    private EditText        editText;
    private Button            btnWrite;
    private Button            btnRead;
    private SQLiteDatabase     db;

    // 초기화
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
       
        // 레이아웃의 생성
        LinearLayout layout = new LinearLayout(this);
        layout.setBackgroundColor(Color.rgb(255, 255, 255));
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);
       
        // 텍스트 박스의 생성
        editText = new EditText(this);
        editText.setText("", EditText.BufferType.NORMAL);
        setLLParams(editText, 240, 50);
        layout.addView(editText);
       
        // 쓰기 버튼의 생성
        btnWrite = new Button(this);
        btnWrite.setText("쓰기");
        btnWrite.setOnClickListener(this);
        setLLParams(btnWrite);
        layout.addView(btnWrite);
       
        // 일기 버튼의 생성
        btnRead = new Button(this);
        btnRead.setText("읽 기");
        btnRead.setOnClickListener(this);
        setLLParams(btnRead);
        layout.addView(btnRead);
       
        // 데이터베이스 객체 구하기 (5)
        DBHelper dbHelper = new DBHelper(this);
        db = dbHelper.getWritableDatabase();
    }
   
    // 버튼 클릭 이벤트 처리
    public void onClick(View v){
        if ( v == btnWrite) {
            try {
                String str = editText.getText().toString();
                writeDB(str);
            } catch (Exception e) {
                showDialog(this, "Error", "Write Error");
            }
        } else if ( v == btnRead) {
            try {
                String str = readDB();
                editText.setText(str);
            } catch (Exception e) {
                showDialog(this, "Error", "Read Error");
            }
        }
    }

    // 데이터베이스의 쓰기 (6)
    private void writeDB(String str) throws Exception{
        ContentValues values = new ContentValues();
        values.put("id", "0");
        values.put("info", "info");
        int colNum = db.update(DB_TABLE, values, null, null);
        if( colNum == 0 ) db.insert(DB_TABLE, "", values);
    }
   
    private String readDB() throws Exception{
        Cursor c = db.query(DB_TABLE, new String[] {"id","info"}, "id='0'", null, null, null, null);
        if ( c.getCount() == 0 ) {
            throw new Exception();
        }
        c.moveToFirst();
        String str = c.getString(1);
        c.close();
        return str;
    }

   
    // 데이터베이스 헬퍼 정의 (1)
    private static class DBHelper extends SQLiteOpenHelper{
        // 데이터베이스 헬퍼 생성자 (2)
        public DBHelper(Context context){
            super(context, DB_NAME, null, DB_VERSION);
        }
       
        // 데이터베이스의 생성 (3)
        @Override
        public void onCreate(SQLiteDatabase db){
            db.execSQL(
                    "create table if not exists " +
                    DB_TABLE + " (id text primary key, info text)"
            );           
        }
       
        // 데이터베이스의 업그레이드 (4)
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
            db.execSQL(
                    "drop table if exists " + DB_NAME
            );
            onCreate(db);
        }
    }
   
   
    // 대화상자 표시
    private static void showDialog(final Activity activity, String title, String text){
        AlertDialog.Builder ad = new AlertDialog.Builder(activity);
        ad.setTitle(title);
        ad.setMessage(text);
        ad.setPositiveButton("OK", new  DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int whichButton){
                activity.setResult(Activity.RESULT_OK);
            }
        });
        ad.create();
        ad.show();
    }
   
    // 리니어 레이아웃의 파라미터 지정
    private static void setLLParams(View view){
        view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
    }
   
    // 리니어 레이아웃의 파라미터 지정
    private static void setLLParams(View view, int w, int h){
        view.setLayoutParams(new LinearLayout.LayoutParams(w, h));
    }
   
   
}









크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/03 18:00 2010/11/03 18:00
, , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5614

SOA 시대와 웹 프로그래밍 모델

SOA 시대와 웹 프로그래밍 모델
유비쿼터스 컴퓨팅이나 SOA 같은 개념을 현실과 그대로 비교해 보면 거창하게 느껴지기도 하고, 이론적이라고 치부할 수도 있다.
하지만 누군가 상상하고 그린 모습이 미래를 만드는 후보가 되고 끈길지고 열정적인 사람이 매달린 꿈은 곧 현실이 된다.

WOA = REST?
WOA가 곧 REST(Representational State Transfer)는 아니지만, 둘은 구분하기 어려울 정도로 꽤나 닮아 있다. 다음은 위키피디아에서 찾은 WOA 정의다.
Web Oriented Architecture(WOA) is a style of software architecture that extends service-oriented architecture(SOA) to web based applications, and is sometimes considered to be a light-weight wersion of SOA. WOA is also aimed at maximizing the browser and server interactions by use of technologies such as REST and POX(Plain Old XML).
REST는 WOA 를 위해 쓰이는 기술중의 하나일 뿐임을 알 수 있다.

SOFEA(Service-Oriented Front-End Architecture)
SOFEA가 기준으로 삼는 5가지 원칙은 아래와 같다.
1. 표현 층에서 서로 직교하는 세 가지 다른 처리인 애플리케이션 내려받기와 표현흐름, 데이터 교환은 서로 구분해야 한다.
2. 클라이언트 유형을 고려해 내려 받는 방법을 다양하게 해야 한다.
3. 표현 흐름은 서버 개입 없이 클라리언트가 처리한다. 대부분의 웹 프레임워크가 사용하는 프론트 컨트롤러 패턴은 바람직 하지 않다.
4. 표현 층도 반드시 복잡한 데이터 구조와 타입, 데이터 제약을 지원해야 한다. 이상적인 모습은 클라이언트/서버 모델이 아니라  P2P모델을 통한 자연스런 이벤트 통지다.
5. MVC는 표현 층 개발에는 좋은 패턴이지만 프론트 컨트롤러를 사용하는 MVC 구현은 잘못된 방식이다. MVC 컨트롤러는 표현흐름과 데이터교환을 주도하는 핵심 구성요소로 클라이언트 상태 변화를 관장한다.

아래의 그림 1, 이는 전통적인 MVC 와 SOFEA가 제시한 MVC 차이를 잘 표현하는 그림이 다.
1. 전통적인 MVC 모델
Figure 1. Classic MVC
2. 웹 2.0의 새로운 아키텍처
Figure 2. Modern Web 2.0 architecture

현재의 문제점은 지금까지의 작업에 묻혀서 생각의 전환이 쉽지않는다는 것과 좀더 나은 프로그램을 하려는 마음이 생기지 않는데에 있다. 작업일정에 쫓기다 보면 계속 동일한 방법만 반복되는게 현실이니까.
방법론이나 프로세스를 꾸준히 발전시켜서 적용하는건 일단은 리더의 문제라고 담아 짊어지려 한다.

크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/11/02 21:30 2010/11/02 21:30
, , , , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5609

[Android] 파일의 읽고 쓰기

파일의 읽고 쓰기.

1. 문자열 바이트 배열 변환
: 문자열을 파일로 저장할 때에는 바이트 배열로 변환한 후 저장해야 하고,
문자열을 바이트 배열로 변환하려면 String 클래스의 getByte() 메소드를 사용해야 한다.
byte[] getBytes()
기능 : 바이트 배열로 변환
변환값 : 바이트 배열

2. 바이트 배열의 문자열 변환
: 바이트 배열을 파일로부터 읽은 후 문자열로 번달하려면 String 클래스의 생성자를 사용한다.
String(byte[] data)
기능 : String  클래스의 생성자
인수 : data 바이트 배열

String(byte[] data, String encoding)
기능 : String 클래스 생성자
인수 : data        바이트 배열
            encoding 인코딩
- 인코딩은 [UTF-8]을 지정.

3. 파일 출력 스트림의 개방
: 스트림의 바이트 배열을 파일로 쓰려면, 파일 출력 스트림을 열고 쓰기 처리를 한 후 마지막으로 닫는다.
파일 출력 스트림을 열려면 Context 클래스의 openFileOutput()메소드를 사용한다.
OutputStream openFileOutput(String fileName, int mode)
기능 : 파일의 열기
인수 : fileName 파일명
           mode        모드
반환값 : 출력 스트림
: 파일명으로는 저장할 파일명을 지정한다. 절대경로는 /data/data/패키지명/files/파일명 이 된다.  모드는 다음의 정수를 지정한다. 여기서는 Contenxt.MODE_PRIVATE 로 파일 생성을 했다.
모드기능
Context.MODE_APPEND기존 파일 단말기로부터 추가 쓰기
Context.MODE_PRIVATE다른 어플리케이션으로부터는 접근불가
Context.MODE_WORLD_READABLE다른 어플리케이션으로부터 읽기 가능
Context.MODE_WORLD_WRITEABLE다른 어플리케이션으로부터 쓰기 가능

4. 바이트 배열의 쓰기
 : 바이트 배열을 출력 스트림에 쓰려면 OutputStream 클래스의 write() 메소드를 사용한다.
void write(byte[] data, int off, int len)
기능 : 바이트 데이터 data의 off 번째부터 len 만큼 쓰기
인수 : data     바이트 데이터
           off         데이터의 시작 위치
           len        쓰기 바이트 수
void write(byte[] data)
기능 : 바이트 데이터 data의 모든 데이터 쓰기
인수 : data     바이트 데이터
void write(int data)
기능 : 1 바이트의 바이트 데이터 쓰기
인수 : data     바이트 데이터( 0 ~ 255 )

: 인수는 int 형이지만, 0 ~ 255 값만을 지정한다.

5. 파일 출력 스트림의 닫기
 : 파일 출력 스트림을 닫으려면 OutputStream 클래스의 close() 메소드를 사용한다.
void close()
기능 : 출력 스트림 닫음

6. 파일 입력 스트림의 개방
 : 스트림의 개방 파일로부터 바이트 배열을 읽으려면 파일 입력 스틀미을 열고 읽기 처리를 실행한 후 마지막으로 닫는다. 파일입력 스트림을 열려면 Context 클래스의 openFileInput() 메소드를 사용한다.
OutputStream openFileInput(String fileName, int mode)
기능 : 파일 입력 스트림의 열기
인수 : fileName    파일명
           mode          모드

7. 바이트 배열의 읽기
 : 바이트 배열의 읽기를 실행하려면 InputStream 클래스의 read() 메소드를 사용한다.
int read(byte[] data)
기능 : 바이트 배열의 읽기
인수 : data     바이트 배열
반환값 : 읽은 바이트 크기
 : 인수로 전달한 바이트 배열에 읽은 데이터가 저장되고, 반환값에는 읽은 바이트 크기가 전달된다. 단, 바이트 배열보다 큰 바이트 데이터는 읽을 수 없다. 거기에서 읽은 바이트크기가 0이 될 때까지 read() 메소드를 반복하여 호출하면서 가변 길이 바이트 배열 ByteArrayOutputStream 클래스에 쓰고 있다.

8. 파일 입력 스트림의 닫기
 : 파일 입력 스트림을 닫기 위해서는 Input Stream 클래스의 close() 메소드를 사용한다.
void close()
기능 : 파일 입력 스트림의 닫기

9. ByteArrayOutputStream 객체의 바이트 배열화
 : ByteArrayOutputStream 객체에서 갖고 있는 바이트 데이터를 byte[] 형의 값으로 얻으려면 ByteArrayOutputStream 클래스의 toByteArray() 메소드를 사용한다.
byte[] toByteArray()
기능 : 바이트 배열 구하기
반환값 : 바이트 배열
사용자 삽입 이미지사용자 삽입 이미지

* DDMS 의 File Explorer
   : DDMS의 File Explorer 를 사용하면, 저장되어 있는 파일을 확인 할 수 있다.
     1. Eclipse  메뉴중 [Window]-[Open Perspective]-[DDMS] 를 선택.
     2. Devices 에서 단말기를 선택한다(에뮬레이터의 경우는 emulator-XXXX).
     3. File Explorer 에서 [data]-[data]-[패키지명]-[files]-[파일명] 을 선택.
     4. 우측 위의 [Pull a file from the device] 버튼을 통해 파일 대화상자를 열고 파일을 컴퓨터에 저장할수 있다. [Put File on Device] 버튼을 통해 컴퓨터로부터 파일을 추가할 수 있고, [삭제] 버튼을 통해 파일 삭제도 가능하다.

 
[SOURCE]
package com.froglamb.fileex;

more..


크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/10/26 13:39 2010/10/26 13:39
, ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5588

옵션 프로그램은 단발기의 메뉴버튼을 누르는 것에 의해서 표시되는 메뉴로, 어플리케이션의 보조적인 작업에 이용한다.

import android.view.Menu;
import android.view.MenuItem;

//옵션 메뉴 생성 (1)
    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
       
        //메뉴 항목0 추가 (2)
        MenuItem item0=menu.add(0,MENU_ITEM0,
            0,R.string.menu_item0);
        item0.setIcon(android.R.drawable.ic_menu_add);
       
        //메뉴 항목1 추가
        MenuItem item1=menu.add(0,MENU_ITEM1,
            0,R.string.menu_item1);
        item1.setIcon(android.R.drawable.ic_menu_call);
       
        //메뉴 항목2 추가
        MenuItem item2=menu.add(0,MENU_ITEM2,
            0,R.string.menu_item2);
        item2.setIcon(android.R.drawable.ic_menu_save);
        return true;
    }


//메뉴 항목 선택 이벤트 처리 (3)
    @Override
        public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case MENU_ITEM0:
            showDialog(this,"","항목0이 눌렸음");
            return true;
        case MENU_ITEM1:
            showDialog(this,"","항목1이 눌렸음");
            return true;
        case MENU_ITEM2:
            showDialog(this,"","항목2가 눌렸음");
            return true;
        }
        return true;
    }


   
    //대화상자 표시
    private static void showDialog(final Activity activity,
        String title,String text) {
        AlertDialog.Builder ad=new AlertDialog.Builder(activity);
        ad.setTitle(title);
        ad.setMessage(text);
        ad.setPositiveButton("OK",new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int whichButton) {
                activity.setResult(Activity.RESULT_OK);
            }
        });
        ad.create();
        ad.show();
    }
}


사용자 삽입 이미지사용자 삽입 이미지


크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/10/26 10:33 2010/10/26 10:33
, ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5587


네트워크 상에 있는 HTML 파일을 읽으려면 WebView 클래스에 있는 loadUrl() 메소드의 인수에 HTML의 URL을 전달합니다. 예를 들어, http://www.ngio.co.kr/tc/ 를 열려면, 다음과 같이 작성합니다.

webView.loadUrl("http://ngio.co.kr/tc/index.php") ;

또한 통신이 필요하므로 AndroidManifest.xml 의 manifest 태그 안에 android.permission.INTERNET의 권한을 설정할 필요가 있습니다.

<uses-permission android:name="android.permission.INTERNET" />
크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by 홍반장

2010/10/25 18:16 2010/10/25 18:16
, , , ,
Response
No Trackback , No Comment
RSS :
http://tcbs17.cafe24.com/tc/rss/response/5583


블로그 이미지

- 홍반장

Archives

Recent Trackbacks

Calendar

«   2018/10   »
  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      
Statistics Graph

Site Stats

Total hits:
107250
Today:
1
Yesterday:
5