전체 예제 코드를 http://bunhere.tistory.com/205 에 추가했습니다.
약간 복잡한 기초 데이터를 위해 초기 실행시 Create Table 도 하고 insert도 할 수 있겠지만, 별도의 db 파일을 만들어 관리하고 싶다면 아래와 같은 방법을 쓰는 것도 한가지 방법입니다.


1. db 파일을 assets에 넣습니다.


 2. 아래 함수를 적당한 위치에 넣습니다.
풀 코드가 아니라 크게 도움은 안되지만 컨셉을 이해하실 수 있을 것이라고 생각됩니다.ROOT_DIR은 아래와 같이 선언되어 있습니다. 경로는 자기 패키지 경로로 수정해주시면 됩니다.

[2010-09-30] 간단히 설명 추가합니다.
4번 라인에서 mkdirs를 통해 폴더를 생성하고자 노력합니다. 일단 만들어져있으면 이 함수를 실패할 것입니다.
그러나 이미 원하는 목적(폴더생성)은 되어 있을 것이므로 문제가 되지 않습니다.
중요한 점 하나는 /data/data/ 아래에는 자기 패키지가 있는 곳 외에는 수정이 불가능합니다.
따라서 ROOT_DIR이 이상할 경우 mkdirs는 폴더가 없더라도 실패합니다.

5번라인에서 해당 폴더 아래 DATABASE_NAME 변수가 가르키는 이름을 가진 파일이 있는지 체크합니다.
이 파일의 이름은 반드시 assets에 복사해놓은 파일명과 동일해야 합니다.
(테이블 명이 아닙니다!)
왜냐하면 9번 라인에서 assetManager를 오픈할 때 이 DATABASE_NAME을 쓰기 때문입니다.



DATABASE_NAME은 assets에 복사해놓은 파일명(첫번째 그림 참조)입니다 이 경우 lecture.db가 되겠네요.저는 폴더를 따로 만들었습니다. 이를 위해 먼저 3,4번 라인에서 패키지 경로 밑에 database란 폴더를 생성합니다.mkdirs는 이미 폴더가 있으면 실패하게 됩니다.
5번 라인에서 파일을 읽어드립니다.
6번 라인과 같이 파일의 길이가 0보다 작다는 것은 파일이 없다는 의미라고 생각했습니다. 따라서 파일을 복사하는 그 아래 코드(7번~18번)를 실행하게 됩니다.asset의 파일을 읽어오기 위해 7번 라인과 같이 assetManager를 이용해서 파일을 오픈합니다.나머지 내용들은 자바이므로 생략합니다.혹시 이해가 안되는 부분이나 더 나은 방법이 있다면 답글 주세요.


허접한 글이지만, 도움이 되셨다면 아래 손가락 꾹 눌러주세요.



Posted by 소혼


최종 바이너리를 만들면서 확인하다가 큰 실수를 했다는 것을 알았습니다. density에 관한 것입니다.
에고 덕분에 완빵 고생을 하고 이 글을 적습니다. 혹시 이 글을 보시는 분은 배포 전에 꼭 resolution 독립적인지 확인하셔서 저같은 실수를 안하시길 빕니다.

일단 density를 위해 아래와 같은 점을 고려하면 될 것 같습니다.

1. 프로젝트를 만들 때, 반드시 min-sdk를 지정합시다.
프로젝트를 만들 때, min-sdk에 기본값이 없어도 프로젝트가 생성이 되지만 이렇게 만들어진 프로젝트는 hdpi 해상도에 대해 제대로 처리할 수 없습니다. 에뮬레이터가 큰 값을 갖더라도 그렇습니다.


2. px를 쓰지 말고 dp를 씁시다
최대한 레이아웃에 좌표계를 쓰지 않는 것이 좋지만 꼭 써야 한다면, dp를 쓰도록 합시다. dp는 해상도의 변경에 자유롭습니다.

3. 만약 소스코드에서 고쳐야 한다면 아래 코드처럼 DisplayMetric을 이용해 변환합니다.
DisplayMetrics metrics = new DisplayMetrics();
          getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.density의 값은 hdpi 타겟의 경우 1.5 mdpi의 경우 1.0이 반환됩니다.
원하는 좌표계에 이 값을 곱하면 적당한 위치에 그려지는 것을 알 수 있습니다.

4. 이미지 크기에 주의합시다
이미지가 용량이 크면 메모리 오류가 발생할 수 있습니다.


허접한 글이지만, 도움이 되신다면 아래 손가락 꾹 눌러주세요.
Posted by 소혼
마무리 작업을 하고 있다.
타겟에 올려보니 실제와 다른 부분이 몇가지 있다.

특히 SDCARD부분이 다소 달랐다.
만약, SDCARD가 컴퓨터에 연결이 되어 있다면 디바이스에 인스톨된 어플리케이션은 SDCARD에 접근을 하지 못하는 것 같다.

곰곰히 생각해보니, 만약 어플 사용자가 선을 연결해놓고 실행하려 하는 경우 동일한 문제가 발생할 수 있다는 생각이 들었다.

따라서 SDCARD를 사용하려면 반드시 사용하기 전에 SDCARD의 상태가 정상적인지 확인하는 것이 필요하다.

SDCARD의 상태를 확인하는 것은 getExternalStorageState() 를 사용하면 된다.
android.os.Environment.getExternalStorageState()
아래는 안드로이드 Developer 자료
Constants
String MEDIA_BAD_REMOVAL getExternalStorageState() returns MEDIA_BAD_REMOVAL if the media was removed before it was unmounted.
String MEDIA_CHECKING getExternalStorageState() returns MEDIA_CHECKING if the media is present and being disk-checked
String MEDIA_MOUNTED getExternalStorageState() returns MEDIA_MOUNTED if the media is present and mounted at its mount point with read/write access.
String MEDIA_MOUNTED_READ_ONLY getExternalStorageState() returns MEDIA_MOUNTED_READ_ONLY if the media is present and mounted at its mount point with read only access.
String MEDIA_NOFS getExternalStorageState() returns MEDIA_NOFS if the media is present but is blank or is using an unsupported filesystem
String MEDIA_REMOVED getExternalStorageState() returns MEDIA_REMOVED if the media is not present.
String MEDIA_SHARED getExternalStorageState() returns MEDIA_SHARED if the media is present not mounted, and shared via USB mass storage.
String MEDIA_UNMOUNTABLE getExternalStorageState() returns MEDIA_UNMOUNTABLE if the media is present but cannot be mounted.
String MEDIA_UNMOUNTED getExternalStorageState() returns MEDIA_UNMOUNTED if the media is present but not mounted.

최소한 MEDIA_SHARED 상태인지 확인하는 것이 필요하다고 여겨진다.

허접한 글이지만, 도움이 되셨다면 아래 손가락 꾹 눌러주세요.
Posted by 소혼
SimpleCursorAdaptor와 ListView의 사용예
Activity를 MyList.java로 만들고 아래 코드들을 추가
DB는 단순하게 사용하였음


### 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"
    >
<ListView android:id="@+id/IndexList"
        android:layout_width="fill_parent" android:layout_height="fill_parent"/>
</LinearLayout>

main.xml

### java

package com.yesum.listDBSample;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.AdapterView.OnItemClickListener;

public class MyList extends Activity {
    private static final String DATABASE_NAME = "sample.db";
    public static final String TABLE_NAME = "mytable";
    private static final String COLUMN_KEY_ID = "_id";
    private static final String COLUMN_NAME = "name";

    private ListView m_listIndex;
    private SQLiteDatabase mDatabase;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        m_listIndex = (ListView) this.findViewById(R.id.IndexList);
        m_listIndex.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
            }
        });
        //createDB();
        //insert("ryuan");
        //insert("yesum");
        //insert("dongsik");
        setAdaptor();
    }

    private long insert(String name) {
        if (mDatabase == null) {
            mDatabase = openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
        }
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_NAME, name);
        return mDatabase.insert(TABLE_NAME, null, cv);
    }

    private void createDB() {
        // create sample DB
        if (mDatabase == null) {
            mDatabase = openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
        }
        String createSQL = "CREATE TABLE " + TABLE_NAME + " (_id integer primary key, " +
            "name)";
        mDatabase.execSQL(createSQL);

    }

    private void setAdaptor() {
        if (mDatabase == null) {
            mDatabase = openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
        }
        Cursor cursor = null;
        final CursorAdapter adaptor;
        String[] columns = new String[] {COLUMN_KEY_ID, COLUMN_NAME};

        cursor = mDatabase.query(TABLE_NAME, columns, null, null, null, null, null);
        adaptor = new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1,
                cursor,
                new String[] {COLUMN_NAME},
                new int[] {android.R.id.text1}
                );
       
        m_listIndex.setAdapter(adaptor);
    }
}

MyList.java

Posted by 소혼
에뮬레이터를 만들 때, 혹은 추후에 가상의 SDCARD를 만들었다면 그 안에 데이터를 넣을 수 있다.

1. 먼저 에뮬레이터를 실행시킨다.
    - 안드로이드 SDK 설치하기 참조
2. DDMS를 실행한다.
    우측 상단에 DDMS를 클릭한다. 만약 DDMS가 보이지 않는다면 아래 그림과 같이 Window에 Show View > Other를 선택하고 안드로이드의 DDMS를 선택하면 우측 상단에 DDMS가 나타난다.

3. sdcard를 선택하고 파일을 업로드한다.
   
DDMS를 선택하면 위와 같은 화면이 뜬다. File Explore에서 sdcard를 선택하고 우측 상단의 두 아이콘중 휴대폰 모양의 아이콘을 클릭한다.

반대로 sdcard의 파일을 꺼내려고 하면 디스켓 모양을 클릭하면 된다.

그러나 이방법을 사용하면 큰 파일을 올리기에 부적합하다. 올라가는 중간에 잘 끊어진다.
따라서, 어쩔수 없이 콘솔을 통해 업로드하는 방법을 썼다.

1. 먼저 [Window의 경우] 시작의 실행을 선택하고 cmd를 입력한다.
2. 안드로이드 sdk를 설치한 폴더로 이동한다. 정확히는 tools라는 폴더를 찾아야 한다.
3. 아래 명령을 실행한다.
    adb push [로컬파일 위치] /sdcard/[적절한 폴더 및 파일 명]

100메가 정도 업로드하는데 몇분 걸리는 것 같다.
경로는 /sdcard가 아니라 /mnt/sdcard 일 수도 있다. 정확한 경로는 DDMS의 File Explore가 보여주는 위치를 사용하도록 한다.
허접한 글이지만, 도움이 되신다면 아래 손가락 꾹 눌러주세요.
Posted by 소혼
1. 설치 준비(Preparing for Installation)
    JDK와 이클립스를 다운로드한다.

    1. Download java sdk (JDK)
        http://java.sun.com/javase/downloads/index.jsp

    2. Download Eclipse with the Android Development Tools (ADT) Plugin
        http://www.eclipse.org/downloads/

2. SDK를 설치한다.(Installing the SDK)
    1. After downloading the SDK, unpack the .zip archive to a suitable location on your machine
        http://developer.android.com

3. 이클립스를 실행한다.
    workspace는 적당히 자신이 개발할 곳을 지정한다.
4. 이클립스에 안드로이드 플러그인을 설치한다.
    아래 그림과 같이 이클립스의 헬프를 클릭하여 새로운소프트웨어 설치를 클릭한다.

    아래와 같은 창이 뜬다. 여기서 Add를 눌러준다.
안드로이드 플러그인을 설치하려면 아래 그림과 같이 사이트( http://dl-ssl.google.com/android/eclipse )를 추가해야 한다.
해당 주소를 입력하고 OK를 누르면, 원래 떠 있던 창에 아래 그림과 같이 새로운 정보가 나타난다.
모두 설치한다. 라이선스 이슈같은 창에서 적당하 Next와 Finish를 클릭한다.(중간에 라이선스는 Yes(였나?)로 선택해야 함)
5. Preference에 안드로이드 SDK를 지정해준다.
메뉴에서 Window의 Preference를 선택하면 위 화면이 뜬다. 위 화면의 Android 탭을 선택하고 미리 구해놓은 (이미 압축은 해제된) 안드로이드 SDK 폴더를 지정한다. OK를 누른다.

설치하고 나면 화살표 아래 모양의 그림이 화면에 나오게 된다.(툴바 왼쪽에서 4번째)
이 아이콘을 클릭하면 위의 그림처럼 AVD Manager가 뜨게 된다.
지금 하나의 가상 디바이스가 이미 만들어져있다.
먼저 SDK 설치를 위해 Available Packages를 선택한다.
설치하고자 하는 SDK를 설치한다. 최근 SDK와 플랫폼은 2.2 API 8 버전이다.
API에 체크박스를 체크하고 설치한다.
설치가 완료되면 Virtual Devices를선택하고 New를 클릭하여 새로운 디바이스를 생성한다.
디바이스를 생성할 때 이름과 타겟을 지정하고 그냥 누르면 기본 형태의 디바이스가 생긴다. SDCARD를 주거나 해상도를 변경할 수도 있다.

생성한 Virtual Device를 선택하면 Start버튼이 활성화된다.
Start를 누러 안드로이드 에뮬레이터의 동작을 볼 수 있다.


허접한 글이지만, 도움이 되신다면 아래 손가락 꾹 눌러주세요.
글에 질문 있으시면 답글 주시면 아는 노력해서 댓글 드립니다.
Posted by 소혼
안드로이드 에서 검색 버튼을 누르면 searchbox 가 뜬다.


이 searchbox가 뜨는 것을 막으려면

Activity에 아래와 같이 onKeyDown을 오버라이드 하면 된다.
모든 Activity에 넣어야 하는게 문제인데 혹시 다른 방법이 있다면 조언 부탁드립니다.

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.w("ENGLISH1", "KEYCODE : " + keyCode + " vs " + KeyEvent.KEYCODE_SEARCH);
        if (keyCode == KeyEvent.KEYCODE_SEARCH)
            return true;
        return super.onKeyDown(keyCode, event);
    }

허접한 글이지만, 도움이 되신다면 손가락 꾹 눌러주세요.

'<안드로이드>개발 > 안드로이드/App' 카테고리의 다른 글

[팁] SDCARD의 상태 확인  (0) 2010.06.26
[Widget][예제]ListView with CursorAdaptor  (3) 2010.06.24
[팁] Quick Search Box 막기(안뜨게 하기)  (0) 2010.06.19
MediaPlayer  (0) 2010.06.17
[공부] Thread  (2) 2010.06.17
[Widget 스터디] Seekbar  (4) 2010.06.16
Posted by 소혼
MediaPlayer mediaPlayer = new MediaPlayer ( );
mediaPlayer.setDataSource("/sdcard/test.3gp");
mediaPlayer.prepare();



# Activity 가 Media volume만 조절하게 하기.
setVolumeControlStream(AudioManager.STREAM_MUSIC);


오류 관련 TIP


1. prepare failed status 0xFFFFFFFC

prepare() 수행중에 해당 에러가 나는 경우가 있다.(IOException의 e.getMessage() 를 출력한 결과)

여러가지 이유때문인 것으로 추정된다.

의심해야 할 항목은 setDataSource가 읽어드린 데이터에 대해 player가 판단하지 못한 경우이다.

1) header가 잘못된 파일을 읽었을 경우

2) 읽어드린 범위가 잘못된 경우 (예컨데 - setDataSource(fd, 0, 0); )

3) 다운로드 파일을 재생하려고 application 폴더 영역을 datasource로 사용한 경우.


나의 경우 2번에 해당했다. 사이즈가 0인걸 뻔히 로그로 찍으면서 원인을 찾느라고 2시간 삽질 ㅠㅠ


Posted by 소혼
<계속 업데이트 합니다 질문 환영>

자바를 해본지가 워낙 오래되어 놓으니 Thread도 제대로 못 만들어 헉헉된다.

안드로이드에서 Thread를 쓰려면 두개의 Runnable이 기본으로 생성되어야 하는 것 같다.

1. Thread 생성
    자바의 Thread를 만드는 것과 같다. 하지만 대부분 UI와 통신을 하기 위해서는 두개의 Runnable을 만드는게 일반적이다.
    private final Handler h = new Handler();
    private final Runnable uiProcess = new Runnable() {
        public void run() {
// UI와 통신을 담당, 버튼을 바꾸거나 seekbar를 수정하는 등
        }
    };
    private Runnable mythread = new Runnable() {// Child Thread
        public void run() {
            while (threadFlag) {
    h.post(uiProcess);
    try {
        Thread.sleep(300);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
        }
    };

쓰레드를 만들고 싶은 곳에서 mythread 를 만들어 start 시키면 된다.
Thread mMythread = new Thread(null, mythread, "mythread");
mMythread.start();
Child thread에서 threadFlag를 하나 넣은 이유는 자바가 stop 메소드가 deprecated 된 듯 하다.
thread를 종료시키는 제대로 된 루틴이 필요할 것 같다.
일단 심플하게 threadFlag를 넣는 걸로 처리했다.
Posted by 소혼
< 계속 업데이트 합니다. 질문 환영 >
10-06-16 초기 문서, style 설정 등 작성
- Seekbar


Progress바와 유사하나, thumb를 옮겨 사용자가 원하는 위치로 이동하는 것이 가능하다.

1) 만드는 법
   -
2) Seekbar 변경에 반응하기

3) style 바꾸는 법
   - thumb 바꾸는 법
     thumb를 바꾸는 법은 쉽다. 함수를 사용할 경우,
     drawable.setBounds(new Rect(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()));
     mSeekbar.setThumb(drawable);
     layout을 사용할 경우 아래 속성을 Seekbar 태그에 포함시킨다.
     android:thumb="@drawable/pb_slider_thumb1"
   - thumb 없애기
     mSeekbar.setThumb(null);
     layout을 사용해서는 어떻게 해야 하는지 모르겠다.
     ( thumb을 통해서 없애는 방법을 쓰느니 progressbar를 쓰는게 낫다.
     아이스크림 샌드위치에서는 crash가 발생한다. 버그인듯; ) 

   - background, foregound 바꾸는 법
     xml로 이루어진 drawable을 추가한다.
     (이 때, 이미지들이 9patch가 안되어 있다면 동일한 이미지가 반복적으로 나타난다.)
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:id="@android:id/background"
              android:drawable="@drawable/pb_slider_normal" />
        <item android:id="@android:id/secondaryProgress">
              <clip android:drawable="@drawable/pb_slider_normal"/>
        </item>
        <item android:id="@android:id/progress">
              <clip android:drawable="@drawable/pb_slider_highlight"/>
        </item>
</layer-list>
      seekbar 레이아웃에 이 xml 파일을 설정한다.
<SeekBar android:id="@+id/seek"
         android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="50"
        android:secondaryProgress="75" android:thumb="@drawable/pb_slider_thumb1"
        android:progressDrawable="@drawable/seekbar_drawable"/>


4) seekbar에 대한 이벤트 감지
        mSeekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            public void onProgressChanged(SeekBar seekBar, int progress,
                    boolean fromUser) {
                mplayer.seekTo(progress);
            }
       });

5) seekbar 위치 변경
       position / maxvalue 의 위치로 설정
       sk.setMax(maxvalue);
       sk.setProgress(position);

참고
source에서 id로 Drawable 만드는 법
Drawable d = getResources().getDrawable(drawable id)

참고 자료
http://blog.naver.com/ween8/50082179209
http://www.codeweblog.com/android-modify-seekbar-style/
http://www.helloandroid.com/tutorials/musicdroid-audio-player-part-i


Posted by 소혼
이전버튼 1 2 3 4 5 6 이전버튼

티스토리 툴바