Copyright 2010, 2011, 2012, 2013 Lars Vogel 19.08.
2013
vogella.com
Tutorials
Training
Books
Shop
Contact us
TEXT REAL
INTEGER
DATA/data /APP_NAME/databases/FILENAME DATA Environment.getDataDirectory() APP_NAME FILENAME
android.database android.database.sqlite
SQLiteOpenHelper
super()
vogella.com
Tutorials
Training
Books
Shop
Contact us
onCreate() onUpgrade()
onCreate() SQLiteDatabase
SQLiteOpenHelper
getReadableDatabase() SQLiteDatabase _id
getWriteableDatabase()
onCreate()
onUpgrade() SQLiteOpenHelper
SQLiteOpenHelper
SQLiteDatabase
SQLiteDatabase execSQL() ContentValues value
insert() update()
delete()
key ContentValues
rawQuery() rawQuery() query() SQLiteQueryBuilder
query()
SQLiteQueryBuilder
rawQuery()
Cursor cursor = getReadableDatabase(). rawQuery("select * from todo where _id = ?", new String[] { id });
query()
return database.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY, KEY_DESCRIPTION }, null, null, null, null, null);
query()
vogella.com
Tutorials
Training
Books
Shop
Contact us
null
Cursor
getCount() moveToFirst() isAfterLast() Cursor get*() getLong(columnIndex) getString(columnIndex) moveToNext()
Cursor
getColumnIndexOrThrow(String)
Cursor
close()
ListViews
Views ListViews ListViews SimpleCursorAdapter ListViews
ListActivities
SimpleCursorAdapter
Views SimpleCursorAdapter Cursor Loader Views Cursor
Get Free Trial Software
clustrix.com/free-trial Promo license ClustrixDB Leading Scale out SQL DB
vogella.com
Tutorials
Training
Books
Shop
Contact us
ContentProvider
Loader
Cursor
de.vogella.android.sqlite.first
MySQLiteHelper
onUpgrade()
package de.vogella.android.sqlite.first; import import import import android.content.Context; android.database.sqlite.SQLiteDatabase; android.database.sqlite.SQLiteOpenHelper; android.util.Log;
public class MySQLiteHelper extends SQLiteOpenHelper { public static final String TABLE_COMMENTS = "comments"; public static final String COLUMN_ID = "_id"; public static final String COLUMN_COMMENT = "comment"; private static final String DATABASE_NAME = "commments.db"; private static final int DATABASE_VERSION = 1;
// Database creation sql statement private static final String DATABASE_CREATE = "create table " + TABLE_COMMENTS + "(" + COLUMN_ID + " integer primary key autoincrement, " + COLUMN_COMMENT + " text not null);";
public MySQLiteHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION);
vogella.com
Tutorials
Training
Books
Shop
Contact us
@Override public void onCreate(SQLiteDatabase database) { database.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(MySQLiteHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS); onCreate(db); }
}
Comment
package de.vogella.android.sqlite.first; public class Comment { private long id; private String comment; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; }
// Will be used by the ArrayAdapter in the ListView @Override public String toString() { return comment; }
}
CommentsDataSource
package de.vogella.android.sqlite.first; import java.util.ArrayList; import java.util.List; import import import import import android.content.ContentValues; android.content.Context; android.database.Cursor; android.database.SQLException; android.database.sqlite.SQLiteDatabase;
public class CommentsDataSource {
// Database fields private SQLiteDatabase database; private MySQLiteHelper dbHelper; private String[] allColumns = { MySQLiteHelper.COLUMN_ID, MySQLiteHelper.COLUMN_COMMENT };
public CommentsDataSource(Context context) { dbHelper = new MySQLiteHelper(context); } public void open() throws SQLException { database = dbHelper.getWritableDatabase(); } public void close() { dbHelper.close(); } public Comment createComment(String comment) { ContentValues values = new ContentValues(); values.put(MySQLiteHelper.COLUMN_COMMENT, comment); long insertId = database.insert(MySQLiteHelper.TABLE_COMMENTS, null, values); Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS, allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null, null, null, null); cursor.moveToFirst();
vogella.com
}
Tutorials Training return newComment;
Books
Shop
Contact us
public void deleteComment(Comment comment) { long id = comment.getId(); System.out.println("Comment deleted with id: " + id); database.delete(MySQLiteHelper.TABLE_COMMENTS, MySQLiteHelper.COLUMN_ID + " = " + id, null); } public List<Comment> getAllComments() { List<Comment> comments = new ArrayList<Comment>(); Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS, allColumns, null, null, null, null, null); cursor.moveToFirst(); while (!cursor.isAfterLast()) { Comment comment = cursorToComment(cursor); comments.add(comment); cursor.moveToNext(); } // make sure to close the cursor cursor.close(); return comments; } private Comment cursorToComment(Cursor cursor) { Comment comment = new Comment(); comment.setId(cursor.getLong(0)); comment.setComment(cursor.getString(1)); return comment; } }
main.xml
res/layout ListView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add New" android:onClick="onClick"/> <Button android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Delete First" android:onClick="onClick"/> </LinearLayout> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
TestDatabaseActivity
package de.vogella.android.sqlite.first; import java.util.List; import java.util.Random; import import import import android.app.ListActivity; android.os.Bundle; android.view.View; android.widget.ArrayAdapter;
vogella.com
Tutorials
Training
Books
Shop
Contact us
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
datasource = new CommentsDataSource(this); datasource.open(); List<Comment> values = datasource.getAllComments();
// use the SimpleCursorAdapter to show the // elements in a ListView ArrayAdapter<Comment> adapter = new ArrayAdapter<Comment>(this, android.R.layout.simple_list_item_1, values); setListAdapter(adapter);
}
// Will be called via the onClick attribute // of the buttons in main.xml public void onClick(View view) { @SuppressWarnings("unchecked") ArrayAdapter<Comment> adapter = (ArrayAdapter<Comment>) getListAdapter(); Comment comment = null; switch (view.getId()) { case R.id.add: String[] comments = new String[] { "Cool", "Very nice", "Hate it" }; int nextInt = new Random().nextInt(3); // save the new comment to the database comment = datasource.createComment(comments[nextInt]); adapter.add(comment); break; case R.id.delete: if (getListAdapter().getCount() > 0) { comment = (Comment) getListAdapter().getItem(0); datasource.deleteComment(comment); adapter.remove(comment); } break; } adapter.notifyDataSetChanged(); } @Override protected void onResume() { datasource.open(); super.onResume(); } @Override protected void onPause() { datasource.close(); super.onPause(); }
}
AndroidManifest.xml
ContentProvider
AndroidManifest.xml
android:authorities
vogella.com
Tutorials
Training
Books
Shop
Contact us
content providers
content providers
ContentProvider android.content.ContentProvider android:authorities ContentProvider ContentProvider AndroidManifest.xml
<provider android:authorities="de.vogella.android.todos.contentprovider" android:name=".contentprovider.MyTodoContentProvider" > </provider>
query() insert() update() delete() getType() onCreate()
UnsupportedOperationException()
android:exported=false|true AndroidManifest.xml
android:exported
ContentProvider synchronized ContentProvider ContentProvider android:multiprocess=true AndroidManifest.xml
ContentProvider
vogella.com
Tutorials
Training
Books
Shop
Contact us
vogella.com
Tutorials
Training
Books
Shop
Contact us
res/layout contactview
TextView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/contactview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
ContentProvider AndroidManifest.xml
android.permission.READ_CONTACTS
package de.vogella.android.contentprovider; import import import import import import android.app.Activity; android.database.Cursor; android.net.Uri; android.os.Bundle; android.provider.ContactsContract; android.widget.TextView;
public class ContactsActivity extends Activity { /** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contacts); TextView contactView = (TextView) findViewById(R.id.contactview);
Cursor cursor = getContacts();
vogella.com
Tutorials Training Books Shop Contact us String displayName = cursor.getString(cursor .getColumnIndex(ContactsContract.Data.DISPLAY_NAME)); contactView.append("Name: "); contactView.append(displayName); contactView.append("\n");
} } private Cursor getContacts() { // Run query Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME }; String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + ("1") + "'"; String[] selectionArgs = null; String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs, sortOrder); } }
ContentProvider TextView ListView
Loader
Loader
AsyncTaskLoader LoaderManager Loader
# start a new loader or re-connect to existing one getLoaderManager().initLoader(0, null, this);
initLoader() LoaderManager.LoaderCallbacks
LoaderManager.LoaderCallbacks Loader getLoaderManager().initLoader() onCreateLoader() Loader onLoadFinished()
Loader CursorLoader CursorLoader
vogella.com
Tutorials
Training
Books
Shop
Contact us
CursorLoader Cursor onLoaderReset()
managedQuery() Loader ContentProvider SimpleCursorAdapter Cursor CursorLoader Cursor ListViews onLoadFinished() swapCursor()
OptionMenu
ContentProvider
Cursor
Loader
vogella.com
Tutorials
Training
Books
Shop
Contact us
de.vogella.android.todos TodoDetailActivity
TodosOverviewActivity
de.vogella.android.todos.database
package de.vogella.android.todos.database; import android.database.sqlite.SQLiteDatabase; import android.util.Log;
vogella.com
Tutorials
Training
Books
Shop
Contact us
// Database table public static final public static final public static final public static final public static final
String String String String String
TABLE_TODO = "todo"; COLUMN_ID = "_id"; COLUMN_CATEGORY = "category"; COLUMN_SUMMARY = "summary"; COLUMN_DESCRIPTION = "description";
// Database creation SQL statement private static final String DATABASE_CREATE = "create table " + TABLE_TODO + "(" + COLUMN_ID + " integer primary key autoincrement, " + COLUMN_CATEGORY + " text not null, " + COLUMN_SUMMARY + " text not null," + COLUMN_DESCRIPTION + " text not null" + ");";
public static void onCreate(SQLiteDatabase database) { database.execSQL(DATABASE_CREATE); } public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { Log.w(TodoTable.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); database.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO); onCreate(database); } }
TodoDatabaseHelper TodoTable
SQLiteOpenHelper
package de.vogella.android.todos.database; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class TodoDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "todotable.db"; private static final int DATABASE_VERSION = 1; public TodoDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); }
// Method is called during creation of the database @Override public void onCreate(SQLiteDatabase database) { TodoTable.onCreate(database); } // Method is called during an upgrade of the database, // e.g. if you increase the database version @Override public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { TodoTable.onUpgrade(database, oldVersion, newVersion); }
}
ContentProvider
de.vogella.android.todos.contentprovider MyTodoContentProvider ContentProvider
package de.vogella.android.todos.contentprovider; import java.util.Arrays; import java.util.HashSet; import import import import import import import import android.content.ContentProvider; android.content.ContentResolver; android.content.ContentValues; android.content.UriMatcher; android.database.Cursor; android.database.sqlite.SQLiteDatabase; android.database.sqlite.SQLiteQueryBuilder; android.net.Uri;
vogella.com
Tutorials Training Books Shop Contact us import de.vogella.android.todos.database.TodoTable;
public class MyTodoContentProvider extends ContentProvider {
// database private TodoDatabaseHelper database; // used for the UriMacher private static final int TODOS = 10; private static final int TODO_ID = 20;
private static final String AUTHORITY = "de.vogella.android.todos.contentprovider"; private static final String BASE_PATH = "todos"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH); public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/todos"; public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/todo"; private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, BASE_PATH, TODOS); sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", TODO_ID); }
@Override public boolean onCreate() { database = new TodoDatabaseHelper(getContext()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists checkColumns(projection); // Set the table queryBuilder.setTables(TodoTable.TABLE_TODO);
int uriType = sURIMatcher.match(uri); switch (uriType) { case TODOS: break; case TODO_ID: // adding the ID to the original query queryBuilder.appendWhere(TodoTable.COLUMN_ID + "=" + uri.getLastPathSegment()); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } SQLiteDatabase db = database.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners are getting notified cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; }
@Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = database.getWritableDatabase(); int rowsDeleted = 0; long id = 0; switch (uriType) { case TODOS: id = sqlDB.insert(TodoTable.TABLE_TODO, null, values); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(BASE_PATH + "/" + id); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = database.getWritableDatabase(); int rowsDeleted = 0;
vogella.com
Tutorials Training Books Shop Contact us rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO, selection, selectionArgs); break; case TODO_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO, TodoTable.COLUMN_ID + "=" + id, null); } else { rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO, TodoTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsDeleted;
@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB = database.getWritableDatabase(); int rowsUpdated = 0; switch (uriType) { case TODOS: rowsUpdated = sqlDB.update(TodoTable.TABLE_TODO, values, selection, selectionArgs); break; case TODO_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsUpdated = sqlDB.update(TodoTable.TABLE_TODO, values, TodoTable.COLUMN_ID + "=" + id, null); } else { rowsUpdated = sqlDB.update(TodoTable.TABLE_TODO, values, TodoTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsUpdated; } private void checkColumns(String[] projection) { String[] available = { TodoTable.COLUMN_CATEGORY, TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_DESCRIPTION, TodoTable.COLUMN_ID }; if (projection != null) { HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection)); HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available)); // check if all columns which are requested are available if (!availableColumns.containsAll(requestedColumns)) { throw new IllegalArgumentException("Unknown columns in projection"); } } } }
MyTodoContentProvider
update() insert() delete() SQLiteDatabase
query()
checkColumns() ContentProvider
<application <!-- Place the following after the Activity Definition --> <provider android:name=".contentprovider.MyTodoContentProvider" android:authorities="de.vogella.android.todos.contentprovider" > </provider> </application>
vogella.com
Tutorials
Training
Books
Shop
Contact us
listmenu.xml
res/menu
android:showAsAction="always"
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/insert" android:showAsAction="always" android:title="Insert"> </item> </menu>
priority.xml
res/values
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="priorities"> <item>Urgent</item> <item>Reminder</item> </string-array> </resources>
strings.xml
res/values
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, Todo!</string> <string name="app_name">Todo</string> <string name="no_todos">Currently there are no Todo items maintained</string> <string name="menu_insert">Add Item</string> <string name="menu_delete">Delete Todo</string> <string name="todo_summary">Summary</string> <string name="todo_description">Delete Todo</string> <string name="todo_edit_summary">Summary</string> <string name="todo_edit_description">Description</string> <string name="todo_edit_confirm">Confirm</string> </resources>
res/drawable
drawable-hdpi drawable-mdpi drawable-ldpi
res/layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/icon" android:layout_width="30dp" android:layout_height="24dp" android:layout_marginLeft="4dp"
vogella.com
Tutorials Training Books Shop Contact us android:src="@drawable/reminder" > </ImageView>
<TextView android:id="@+id/label" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="6dp" android:lines="1" android:text="@+id/TextView01" android:textSize="24dp" > </TextView> </LinearLayout>
todo_list.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> <TextView android:id="@android:id/empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/no_todos" /> </LinearLayout>
todo_edit.xml TodoDetailActivity
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Spinner android:id="@+id/category" android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@array/priorities" > </Spinner> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="match_parent" android:layout_height="wrap_content" > <EditText android:id="@+id/todo_edit_summary" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:hint="@string/todo_edit_summary" android:imeOptions="actionNext" > </EditText> </LinearLayout> <EditText android:id="@+id/todo_edit_description" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="top" android:hint="@string/todo_edit_description" android:imeOptions="actionNext" > </EditText> <Button android:id="@+id/todo_edit_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/todo_edit_confirm" > </Button> </LinearLayout>
vogella.com
Tutorials
Training
Books
Shop
Contact us
TodosOverviewActivity.java
package de.vogella.android.todos; import import import import import import import import import import import import import import import import import import import android.app.ListActivity; android.app.LoaderManager; android.content.CursorLoader; android.content.Intent; android.content.Loader; android.database.Cursor; android.net.Uri; android.os.Bundle; android.view.ContextMenu; android.view.ContextMenu.ContextMenuInfo; android.view.Menu; android.view.MenuInflater; android.view.MenuItem; android.view.View; android.widget.AdapterView.AdapterContextMenuInfo; android.widget.ListView; android.widget.SimpleCursorAdapter; de.vogella.android.todos.contentprovider.MyTodoContentProvider; de.vogella.android.todos.database.TodoTable;
/* * TodosOverviewActivity displays the existing todo items * in a list * * You can create new ones via the ActionBar entry "Insert" * You can delete existing ones via a long press on the item */
public class TodosOverviewActivity extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor> { private static final int ACTIVITY_CREATE = 0; private static final int ACTIVITY_EDIT = 1; private static final int DELETE_ID = Menu.FIRST + 1; // private Cursor cursor; private SimpleCursorAdapter adapter;
/** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.todo_list); this.getListView().setDividerHeight(2); fillData(); registerForContextMenu(getListView()); } // create the menu based on the XML defintion @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.listmenu, menu); return true; } // Reaction to the menu selection @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.insert: createTodo(); return true; } return super.onOptionsItemSelected(item); } @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case DELETE_ID: AdapterContextMenuInfo info = (AdapterContextMenuInfo) item .getMenuInfo(); Uri uri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + info.id); getContentResolver().delete(uri, null, null); fillData(); return true; } return super.onContextItemSelected(item); }
private void createTodo() { Intent i = new Intent(this, TodoDetailActivity.class); startActivity(i); }
// Opens the second activity if an entry is clicked @Override
vogella.com
Tutorials Training Books Shop Contact us Intent i = new Intent(this, TodoDetailActivity.class); Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id); i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i); }
private void fillData() {
// Fields from the database (projection) // Must include the _id column for the adapter to work String[] from = new String[] { TodoTable.COLUMN_SUMMARY }; // Fields on the UI to which we map int[] to = new int[] { R.id.label };
getLoaderManager().initLoader(0, null, this); adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from, to, 0); setListAdapter(adapter); }
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_ID, 0, R.string.menu_delete); } // creates a new loader after the initLoader () call @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY }; CursorLoader cursorLoader = new CursorLoader(this, MyTodoContentProvider.CONTENT_URI, projection, null, null, null); return cursorLoader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { adapter.swapCursor(data); } @Override public void onLoaderReset(Loader<Cursor> loader) { // data is not available anymore, delete reference adapter.swapCursor(null); }
}
TodoDetailActivity.java
package de.vogella.android.todos; import import import import import import import import import import import import import android.app.Activity; android.content.ContentValues; android.database.Cursor; android.net.Uri; android.os.Bundle; android.text.TextUtils; android.view.View; android.widget.Button; android.widget.EditText; android.widget.Spinner; android.widget.Toast; de.vogella.android.todos.contentprovider.MyTodoContentProvider; de.vogella.android.todos.database.TodoTable;
/* * TodoDetailActivity allows to enter a new todo item * or to change an existing */ public class TodoDetailActivity extends Activity { private Spinner mCategory; private EditText mTitleText; private EditText mBodyText;
private Uri todoUri;
@Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.todo_edit);
mCategory = (Spinner) findViewById(R.id.category); mTitleText = (EditText) findViewById(R.id.todo_edit_summary); mBodyText = (EditText) findViewById(R.id.todo_edit_description); Button confirmButton = (Button) findViewById(R.id.todo_edit_button); Bundle extras = getIntent().getExtras();
vogella.com
Tutorials Training Books Shop Contact us .getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);
// Or passed from the other activity if (extras != null) { todoUri = extras .getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);
fillData(todoUri); } confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (TextUtils.isEmpty(mTitleText.getText().toString())) { makeToast(); } else { setResult(RESULT_OK); finish(); } } }); } private void fillData(Uri uri) { String[] projection = { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_DESCRIPTION, TodoTable.COLUMN_CATEGORY }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor != null) { cursor.moveToFirst(); String category = cursor.getString(cursor .getColumnIndexOrThrow(TodoTable.COLUMN_CATEGORY)); for (int i = 0; i < mCategory.getCount(); i++) { String s = (String) mCategory.getItemAtPosition(i); if (s.equalsIgnoreCase(category)) { mCategory.setSelection(i); } } mTitleText.setText(cursor.getString(cursor .getColumnIndexOrThrow(TodoTable.COLUMN_SUMMARY))); mBodyText.setText(cursor.getString(cursor .getColumnIndexOrThrow(TodoTable.COLUMN_DESCRIPTION)));
// always close the cursor cursor.close();
} } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); saveState(); outState.putParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri); }
@Override protected void onPause() { super.onPause(); saveState(); }
private void saveState() { String category = (String) mCategory.getSelectedItem(); String summary = mTitleText.getText().toString(); String description = mBodyText.getText().toString();
// only save if either summary or description // is available
if (description.length() == 0 && summary.length() == 0) { return; } ContentValues values = new ContentValues(); values.put(TodoTable.COLUMN_CATEGORY, category); values.put(TodoTable.COLUMN_SUMMARY, summary); values.put(TodoTable.COLUMN_DESCRIPTION, description); if (todoUri == null) { // New todo todoUri = getContentResolver().insert(MyTodoContentProvider.CONTENT_URI, values); } else { // Update todo getContentResolver().update(todoUri, values, null, null); } } private void makeToast() { Toast.makeText(TodoDetailActivity.this, "Please maintain a summary", Toast.LENGTH_LONG).show(); } }
vogella.com
Tutorials
Training
Books
Shop
Contact us
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.vogella.android.todos" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" /> <application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".TodosOverviewActivity" 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=".TodoDetailActivity" android:windowSoftInputMode="stateVisible|adjustResize" > </activity> <provider android:name=".contentprovider.MyTodoContentProvider" android:authorities="de.vogella.android.todos.contentprovider" > </provider> </application> </manifest>
TodoDetailActivity
vogella.com
Tutorials
Training
Books
Shop
Contact us
adb shell
# Switch to the data directory cd /data/data # Our application cd de.vogella.android.todos # Switch to the database dir cd databases # Check the content ls # Assuming that there is a todotable file # connect to this table sqlite3 todotable.db
ListViews
ListActivities
db.beginTransaction(); try { for (int i= 0; i< values.lenght; i++){ // TODO prepare ContentValues object values db.insert(your_table, null, values); // In case you do larger updates yieldIfContededSafely() } db.setTransactionSuccessful(); } finally { db.endTransaction(); }
yieldIfContededSafely()
vogella.com
Tutorials
Training
Books
Shop
Contact us