!!!Android Notepad チュートリアル [Android][Java][Eclipse] *http://developer.android.com/resources/tutorials/notepad/index.html !!準備 !ダウンロードして展開 *http://developer.android.com/resources/tutorials/notepad/codelab/NotepadCodeLab.zip !!!(1) 簡単なノートリストの作成 *新しいノートを追加する(まだ編集はできない) *ListActivity を使ってみる *SQLiteを使ってみる !!プロジェクトの作成 *Create project from existing source を選択 *解凍したフォルダから、NotepadCodeLab/Notepadv1 を選択 *Finish {{ref_image android_notepad01.jpg}} !!NotesDbAdapter !用途 *NotesDbAdapterはSQLiteへのデータアクセスをカプセル化する。 !宣言 *クラスの先頭で、テーブルのフィールドおよびデータベースが存在しない場合に生成する文字列を定義 *データベースは data という名前で、notes という _id、title、bodyの3つのフィールドをもつテーブルを一つ持つ。 !コンストラクタ *コンストラクタは、Context パラメータを取り、それにより Android OS との通信を許可。これは Android にアクセスする一般的な方法 *Activity クラスは Context を実装しているため、Contextが必要な時に渡すことができる。 !メソッド ::open() *open()メソッドは、DatabaseHelper のインスタンスを呼び出す。 *DatabaseHelper は SQLiteOpenHelper のローカル実装。 *getWritableDatabase() で、データベースを作成、オープン ::close() *データベースを閉じてリリースを解放 ::createNote() *新しい note のためのタイトルと本文の文字列を引数に取り、note をデータベースに作成する *作成が成功した場合、_id を返す。 ::deleteNote() *行ID を引数に取り、note をデータベースから削除 ::fetchAllNotes() *クエリーを発行して、カーソルを得る *query() には、データベーステーブル名、取得したいカラムリスト、残りのフィールドは順に、selection、selectionArgs、 groupBy、 having、orderBy *fetchNote()は、fetchAllNotes() と同様だが、行IDで1つの note を取得する ::updateNote() *行ID、タイトル、本文を引数に取り、[ContentValues|http://developer.android.com/reference/android/content/ContentValues.html]を使ってnoteを更新する。 !!レイアウト !LinearLayout の設定 ::すべての Android のXMLレイアウトのヘッダーは以下で始まらなければいけない . ::次に、たいていの場合、以下の様なレイアウトを置く LinearLayout ::トップレベルのコンポーネントまたはレイアウトで Android のネームスペースを宣言する xmlns:android="http://schemas.android.com/apk/res/android" !!LinearLayout !!行のレイアウト !notes_row.xml *res/layout に notes_row.xml を作成 !!Notepadv1 クラスの編集 !オーバーライドメソッド ::onCreate() *Activityが開始されたときに呼び出される。 *リソースの設定、ステートの設定を実施 ::onCreateOptionsMenu() *Activity メニューの有効化 *ユーザーがメニューボタンをたたいた時に呼び出される ::onOptionsItemSelected() *他の半数のメニューと等しい *メニューから生成されるイベントを制御 !基底クラスの変更 *Activity を ListActivity に public class Notepadv1 extends ListActivity !onCreate() private NotesDbAdapter mDbHelper; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.notepad_list); mDbHelper = new NotesDbAdapter(this); mDbHelper.open(); fillData(); } *fillData() はまだ未作成 !onCreateOptionsMenu() Notepad v1 No Notes Yet Add Item public class Notepadv1 extends ListActivity { public static final int INSERT_ID = Menu.FIRST; : @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub boolean result = super.onCreateOptionsMenu(menu); menu.add(0, INSERT_ID, 0, R.string.menu_insert); return result; } !onOptionsItemSelected() @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case INSERT_ID: createNote(); return true; } return super.onOptionsItemSelected(item); } !createNote() public void createNote() { String noteName = "Note " + mNoteNumber++; mDbHelper.createNote(noteName, ""); fillData(); } !fillData() private void fillData() { Cursor c = mDbHelper.fetchAllNotes(); startManagingCursor(c); String[] from = new String[] { NotesDbAdapter.KEY_TITLE }; int[] to = new int[] { R.id.text1 }; SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to); setListAdapter(notes); } !!ここまでで、起動 {{ref_image android_notepad02.jpg}} !!!(2) Activity の追加、高度なレイアウトの使用など *http://developer.android.com/resources/tutorials/notepad/notepad-ex2.html *2つめのActivityを作成しマニフェストに追加 *startActivityForResult()を使って非同期で別のActivityを呼び出す *Bundle オブジェクトで Activity 間でデータを受け渡す *他のさらに高度なレイアウトの使用 *コンテキストメニューの作成 !!プロジェクトの作成 *上記 Notepadv1 同様に、NotepadCodeLab/Notepadv2 からプロジェクトを作成する。 */res/values/strings.xml に今回追加する機能の文字列が追加されている。 *Notepadv2 クラス には、カーソルを使うための mNotesCursor フィールドとともに、いくつかの定数が定義されている。 *fillData()では、mNotesCursor カーソルフィールドを使うようになっている。 *onCreate()は変更なし。 *いくつかのオーバーライドメソッドが記述されている(onCreateContextMenu(), onContextItemSelected(), onListItemClick() and onActivityResult()) !!表示されている note を削除するためのコンテキストメニューを追加する !registerForContextMenu() *ListView のアイテムそれぞれに順にコンテキストメニューにregisterForContextMenu()を呼び出して登録 *onCreate() の最後に以下を追加 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.notes_list); mDbHelper = new NotesDbAdapter(this); mDbHelper.open(); fillData(); registerForContextMenu(getListView()); } !onCreateContextMenu() @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); // TODO: fill in rest of method super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_ID, 0, R.string.menu_delete); } !onContextItemSelected() @Override public boolean onContextItemSelected(MenuItem item) { // TODO: fill in rest of method switch(item.getItemId()) { case DELETE_ID: AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); mDbHelper.deleteNote(info.id); fillData(); return true; } return super.onContextItemSelected(item); } !onActivityResult() @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, intent); Bundle extras = intent.getExtras(); switch(requestCode) { case ACTIVITY_CREATE: String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.createNote(title, body); fillData(); break; case ACTIVITY_EDIT: Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (mRowId != null) { String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE); String editBody = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.updateNote(mRowId, editTitle, editBody); } fillData(); break; } } !createNote() private void createNote() { // TODO: fill in implementation Intent i = new Intent(this, NoteEdit.class); startActivityForResult(i, ACTIVITY_CREATE); } !onListItemClick() @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); // TODO: fill in rest of method Cursor c = mNotesCursor; c.moveToPosition(position); Intent i = new Intent(this, NoteEdit.class); i.putExtra(NotesDbAdapter.KEY_ROWID, id); i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE))); i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY))); startActivityForResult(i, ACTIVITY_EDIT); } !onActivityResult() @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); // TODO: fill in rest of method Bundle extras = intent.getExtras(); switch(requestCode) { case ACTIVITY_CREATE: String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.createNote(title, body); fillData(); break; case ACTIVITY_EDIT: Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (mRowId != null) { String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE); String editBody = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.updateNote(mRowId, editTitle, editBody); } fillData(); break; } } !!NoteEdit クラスの追加 public class NoteEdit extends Activity { private EditText mTitleText; private EditText mBodyText; private Long mRowId; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.note_edit); mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm); confirmButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Bundle bundle = new Bundle(); bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString()); bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString()); if (mRowId != null) { bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId); } Intent mIntent = new Intent(); mIntent.putExtras(bundle); setResult(RESULT_OK, mIntent); finish(); } } ); mRowId = null; Bundle extras = getIntent().getExtras(); if (extras != null) { String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (title != null) { mTitleText.setText(title); } if (body != null) { mBodyText.setText(body); } } } } !!AndroidManifest.xml の編集 *を追加 : !!ここまでで起動 {{ref_image android_notepad03.jpg}} ::コンテキストメニューは、コントロールパッド長押し {{ref_image android_notepad04.jpg}} !!!(3) *http://developer.android.com/resources/tutorials/notepad/notepad-ex3.html *ライフサイクルイベントの利用 *アプリケーション !!プロジェクトの作成 *同様に、Notepadv3 からプロジェクトを作成。 *上記 Notepadv2 を完成させた状態と Notepadv3 は同じ !!NoteEdit クラス !onCreate() *メンバ変数の宣言 private NotesDbAdapter mDbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbHelper = new NotesDbAdapter(this); mDbHelper.open(); setContentView(R.layout.note_edit); mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm); mRowId = savedInstanceState != null ? savedInstanceState.getLong(NotesDbAdapter.KEY_ROWID) : null; if (mRowId == null) { Bundle extras = getIntent().getExtras(); mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID) : null; } populateFields(); confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { setResult(RESULT_OK); finish(); } }); } !populateFields() を作成 private void populateFields() { if (mRowId != null) { Cursor note = mDbHelper.fetchNote(mRowId); startManagingCursor(note); mTitleText.setText(note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE))); mBodyText.setText(note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY))); } } !オーバーライドメソッドを実装 ::onSaveInstanceState() @Override protected void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub super.onSaveInstanceState(outState); outState.putLong(NotesDbAdapter.KEY_ROWID, mRowId); } ::onPause() *saveState()は後ほど作成 @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); saveState(); } ::onResume() @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); populateFields(); } !saveState() を追加 private void saveState() { String title = mTitleText.getText().toString(); String body = mBodyText.getText().toString(); if (mRowId == null) { long id = mDbHelper.createNote(title, body); if (id > 0) { mRowId = id; } } else { mDbHelper.updateNote(mRowId, title, body); } } !!Notepadv3 !onActivityResult() @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); fillData(); } !onListItemClick() @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Intent i = new Intent(this, NoteEdit.class); i.putExtra(NotesDbAdapter.KEY_ROWID, id); startActivityForResult(i, ACTIVITY_EDIT); }