Java File
Application -> ADD -> Provider
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="DB정보가 셋팅되었습니다." />
</LinearLayout>
main activity
package dr.android.contents;
import android.app.Activity;
import android.os.Bundle;
public class ConstantsOne extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Provider
package dr.android.contents;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.hardware.SensorManager;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;
public class Provider extends ContentProvider{
//DB명
private static final String DATABASE_NAME ="constants.db";
//테이블 명
private static final String TABLE_NAME = "constants";
//URI중 고유이름 지정
private static final String AUTHORITY = "dr.android.contents.Provider";
//집합데이터와 개별 데이터 구별을 위한 상수 지정
private static final int CONSTANTS =1;
private static final int CONSTANT_ID=2;
//URI 정보를 갖는 객체 선언
private static final UriMatcher MATCHER;
//마임타입 지정 (집합데이터/개별데이터)
private static final String COLLECTION_TYPE =
"vnd.android.cursor.dir/vnd.commonsware.constant";
private static final String SINGLE_TYPE =
"vnd.android.cursor.item/vnd.commonsware.constant";
//컬럼 명세 갖는 객체 선언
private static HashMap<string,string> CONSTANTS_LIST_PROJECTION;
//SQLite 연동을 위한 db선언
private SQLiteDatabase db;
public static final class Constants implements BaseColumns{
public static final Uri CONTENT_URI =Uri.parse("content://"+AUTHORITY+"/constants");
public static final String TITLE="title";
public static final String VALUE="value";
}
static {
//UriMatcher 객체 생성
//전달되는 Uri가 집합데이터를 의미하는지 개별데이터를 의미하는지 여부 판결
MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
MATCHER.addURI(AUTHORITY, "constants", CONSTANTS);
MATCHER.addURI(AUTHORITY, "constants/#", CONSTANT_ID);
//컬럼 명세를 보관하는 객체
CONSTANTS_LIST_PROJECTION = new HashMap<string,string>();
CONSTANTS_LIST_PROJECTION.put(Provider.Constants._ID, Provider.Constants._ID);
CONSTANTS_LIST_PROJECTION.put(Provider.Constants.TITLE, Provider.Constants.TITLE);
CONSTANTS_LIST_PROJECTION.put(Provider.Constants.VALUE, Provider.Constants.VALUE);
}
@Override
public boolean onCreate(){
db=(new DatabaseHelper (getContext())).getWritableDatabase();
return (db ==null)?false:true;
}
//전달된 URI를 통해서
//집합데이터 / 개별데이터 요청 요부를 확인
private boolean isCollectionUri(Uri url) {
return(MATCHER.match(url)==CONSTANTS);
}
//기본 컬럼 명세를 갖고있는 객체 반환
private HashMap<string, string=""> getDefaultProjection() {
return(CONSTANTS_LIST_PROJECTION);
}
@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
SQLiteQueryBuilder qb=new SQLiteQueryBuilder();
qb.setTables(TABLE_NAME);
if (isCollectionUri(url)) {
//집합 데이터
qb.setProjectionMap(getDefaultProjection());
}
else {
//개별 데이터
qb.appendWhere(Provider.Constants._ID+"="+url.getPathSegments().get(1));
}
String orderBy;
if (TextUtils.isEmpty(sort)) {
//전달되는 정렬 정보가 없을 경우
orderBy=Provider.Constants.TITLE;
} else {
//전달되는 정렬 정보가 있을 경우
orderBy=sort;
}
Cursor c=qb.query(db, projection, selection, selectionArgs,
null, null, orderBy);
//URI 원본자료가 변하면 그 사실을 Cursor 객체에 통보하는 역할
//예)update후 query될 때 update시 변경된 자료 반영
c.setNotificationUri(getContext().getContentResolver(), url);
return c;
}
@Override
public String getType(Uri url) {
if (isCollectionUri(url)) {
return(COLLECTION_TYPE);
}
return(SINGLE_TYPE);
}
@Override
public Uri insert(Uri url, ContentValues initialValues) {
long rowID;
ContentValues values;
if (initialValues!=null) {
values=new ContentValues(initialValues);
} else {
values=new ContentValues();
}
if (!isCollectionUri(url)) {
throw new IllegalArgumentException("Unknown URL " + url);
}
rowID=db.insert(TABLE_NAME, Provider.Constants.TITLE, values);
if (rowID > 0) {
Uri uri=ContentUris.withAppendedId(Provider.Constants.CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
throw new SQLException("Failed to insert row into " + url);
}
@Override
public int delete(Uri url, String where, String[] whereArgs) {
int count;
long rowId=0;
if (isCollectionUri(url)) {
count=db.delete(TABLE_NAME, where, whereArgs);
}
else {
String segment=url.getPathSegments().get(1);
rowId=Long.parseLong(segment);
count=db
.delete(TABLE_NAME, Provider.Constants._ID+"="
+ segment
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
}
getContext().getContentResolver().notifyChange(url, null);
return count;
}
@Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
int count;
if (isCollectionUri(url)) {
count=db.update(TABLE_NAME, values, where, whereArgs);
}
else {
String segment=url.getPathSegments().get(1);
count=db
.update(TABLE_NAME, values, Provider.Constants._ID+"="
+ segment
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
}
getContext().getContentResolver().notifyChange(url, null);
return count;
}
private class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(
"CREATE TABLE constants (_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, value REAL);");
ContentValues cv=new ContentValues();
cv.put(Constants.TITLE, "Gravity, Death Star I");
cv.put(Constants.VALUE, SensorManager.GRAVITY_DEATH_STAR_I);
db.insert("constants", Provider.Constants.TITLE, cv);
cv.put(Constants.TITLE, "Gravity, Earth");
cv.put(Constants.VALUE, SensorManager.GRAVITY_EARTH);
db.insert("constants", Provider.Constants.TITLE, cv);
cv.put(Constants.TITLE, "Gravity, Jupiter");
cv.put(Constants.VALUE, SensorManager.GRAVITY_JUPITER);
db.insert("constants", Provider.Constants.TITLE, cv);
cv.put(Constants.TITLE, "Gravity, Mars");
cv.put(Constants.VALUE, SensorManager.GRAVITY_MARS);
db.insert("constants", Provider.Constants.TITLE, cv);
}catch(SQLException e){
Log.e("Provider",e.toString());
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w("Constants", "Upgrading database, which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS constants");
onCreate(db);
}
}
}
res/ layout/ add_edit.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="이름:" />
<EditText
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="값:" />
<EditText
android:id="@+id/value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</LinearLayout>
</LinearLayout>
res/ layout/ main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ConstantsBrowser" />
</LinearLayout>
res/ layout/ row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</RelativeLayout>
res/ values/ strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">77ConstantsTwo</string>
<string name="ok">확인</string>
<string name="cancel">취소</string>
<string name="add_title">상수 추가</string>
<string name="delete_title">상수 데이터를 제거하시겠습니까?</string>
</resources>
src/ dr.android.contents2/ ConstantsTwo
package dr.android.contents2;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;
public class ConstantsTwo extends ListActivity {
private static final String TITLE="title";
private static final String VALUE="value";
private static final String CONTENT_URI =
"content://dr.android.contents.Provider/constants";
private static final String[] PROJECTION = new String[] {
BaseColumns._ID, TITLE, VALUE};
private Cursor constantsCursor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//manageQuery()와 getContentResolver().query() 둘다 사용가능
constantsCursor=managedQuery(
Uri.parse(CONTENT_URI),PROJECTION, null, null, null);
ListAdapter adapter=new SimpleCursorAdapter(this,
R.layout.row, constantsCursor,
new String[] {TITLE,VALUE},
new int[] {R.id.title, R.id.value});
setListAdapter(adapter);
registerForContextMenu(getListView());
}
@Override
public void onDestroy() {
super.onDestroy();
constantsCursor.close();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, 1, Menu.NONE, "추가")
.setIcon(R.drawable.add)
.setAlphabeticShortcut('a');
menu.add(Menu.NONE, 2, Menu.NONE, "종료")
.setIcon(R.drawable.eject)
.setAlphabeticShortcut('c');
return(super.onCreateOptionsMenu(menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
add();
return(true);
case 3:
finish();
return(true);
}
return(super.onOptionsItemSelected(item));
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
menu.add(Menu.NONE, 2, Menu.NONE, "삭제")
.setIcon(R.drawable.delete)
.setAlphabeticShortcut('d');
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 2:
AdapterView.AdapterContextMenuInfo info=
(AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
delete(info.id);
return(true);
}
return(super.onOptionsItemSelected(item));
}
private void add() {
LayoutInflater inflater=LayoutInflater.from(this);
View addView=inflater.inflate(R.layout.add_edit, null);
final DialogWrapper wrapper=new DialogWrapper(addView);
new AlertDialog.Builder(this)
.setTitle(R.string.add_title)
.setView(addView)
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
processAdd(wrapper);
}
})
.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// ignore, just dismiss
}
})
.show();
}
private void delete(final long rowId) {
if (rowId>0) {
new AlertDialog.Builder(this)
.setTitle(R.string.delete_title)
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
processDelete(rowId);
}
})
.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// ignore, just dismiss
}
})
.show();
}
}
private void processAdd(DialogWrapper wrapper) {
ContentValues values=new ContentValues(2);
values.put(TITLE, wrapper.getTitle());
values.put(VALUE, wrapper.getValue());
getContentResolver().insert(Uri.parse(CONTENT_URI),values);
constantsCursor.requery();
}
private void processDelete(long rowId) {
Uri uri=ContentUris.withAppendedId(Uri.parse(CONTENT_URI),rowId);
getContentResolver().delete(uri, null, null);
constantsCursor.requery();
}
class DialogWrapper {
EditText titleField=null;
EditText valueField=null;
View base=null;
DialogWrapper(View base) {
this.base=base;
valueField=(EditText)base.findViewById(R.id.value);
}
String getTitle() {
return(getTitleField().getText().toString());
}
float getValue() {
return(new Float(getValueField().getText().toString()).floatValue());
}
private EditText getTitleField() {
if (titleField==null) {
titleField=(EditText)base.findViewById(R.id.title);
}
return(titleField);
}
private EditText getValueField() {
if (valueField==null) {
valueField=(EditText)base.findViewById(R.id.value);
}
return(valueField);
}
}
}