Androidアプリ 簡単なメモ帳アプリを作る
どうもこんにちは、。InomaCreateです。
今回はAndroidの簡単なメモ帳アプリを作ってみようと思います。
※言語はJavaで作ります。
※今回はデータベースとして、Androidに標準で入っているSQLiteデータベースを使います。
完成版のソースは、以下GitHubからダウンロード可能です。
GitHub(InomaCreate)
動画解説
記事と合わせてご覧ください。
今回作るアプリ
今回簡単なメモ帳アプリを作ります。
画面の上段には、保存したメモのタイトルがリストで表示されます。
メモ帳の追加、編集は下段で行います。(以下図)
1.レイアウトを作る
AndroidStudioを起動し、 「New Project」を作成しましょう。
Templeteは、Empty Activityを選択します。
まずは、アプリのレイアウトを作成します。
レイアウトは、LinearLayout(リニアレイアウト)を使い、縦に要素を並べています。
activity_main.xmlを開き、以下のように実装します。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?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="@+id/lvMemoList" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginBottom="10dp" android:layout_weight="0.6"/> <Button android:id="@+id/btnAdd" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="true" android:onClick="onAddButtonClick" android:text="@string/btn_add"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/tv_lb_name" android:textSize="20sp"/> <EditText android:id="@+id/etTitle" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="@string/tv_lb_note" android:textSize="20sp"/> <EditText android:id="@+id/etNote" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.4" android:gravity="top" android:inputType="textMultiLine"/> <Button android:id="@+id/btnSave" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="false" android:onClick="onSaveButtonClick" android:text="@string/btn_save"/> <Button android:id="@+id/btnDelete" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="false" android:onClick="onDeleteButtonClick" android:text="@string/btn_delete"/> </LinearLayout> |
ボタン名称やラベルなどの固定文字列は、strings.xmlに追加します。
1 2 3 4 5 6 7 8 |
<resources> <string name="app_name">メモ帳アプリ</string> <string name="tv_lb_name">タイトル:</string> <string name="tv_lb_note">内容:</string> <string name="btn_save">保存</string> <string name="btn_add">追加</string> <string name="btn_delete">削除</string> </resources> |
2.データベースヘルパークラスを作る
今回アプリで作成したメモは、データベースに保存していきます。
データベースに保存することで、アプリを終了しても、保存しておいたメモを参照できます。
※データベースは、AndroidOSに標準で搭載されているSQLiteを使います。
SQLiteを使うためにまずは、データベースヘルパークラスを作ります。
以下図のように、Acitivyクラスから、データベースヘルパーのインスタンスを生成し、データベースヘルパークラスから、データベース接続オブジェクト(SQLiteDatabase)を取得し、SQLを実行する仕組みとなります。
以下のようにSQLiteOpenHelperクラスを継承したDataBaseHelperクラスを新規追加しましょう。
コンストラクタでは、使用するデータベース名、Versionなどを指定します。
また、SQLiteOpenHelperクラスのonCreate()とonUpgrade()は抽象メソッドとして定義されているので、必ず定義する必要があります。
onCreateは初回に1回だけ実行されますので、データベースのテーブルを定義します。
onUpgrade()では、データベースのバージョンが更新された場合などの更新処理を記載します。今回は使用しないので中身の処理はありません。
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 32 33 34 35 |
package com.example.databasesample; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "notememo.db"; private static final int DATABASE_VERSION =1; public DatabaseHelper(Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db){ StringBuilder sb = new StringBuilder(); sb.append("CREATE TABLE notememo ("); sb.append("_id INTEGER PRIMARY KEY,"); sb.append("name TEXT,"); sb.append("note TEXT"); sb.append(");"); String sql = sb.toString(); db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } |
今回作成するnotememoテーブルは、以下のカラムで構成します。
カラム名 | 説明 |
---|---|
_id | 主キー(重複しないID)※ |
name | タイトル名 |
note | メモの内容 |
※_idは、主キーといって重複禁止のIDです。
テーブルにデータを追加するごとに、重複しないIDが割り当てられます。
後述するCursorAdapterは、この_idがある前提で実装されているので注意してください。
3.メモ追加機能を追加
まずは、MainActivity.javaに「追加」ボタンが押されたときの処理を記載します。
その前に、ボタン制御やリスト表示用の変数の初期化を実装しておきましょう。
以下を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class MainActivity extends AppCompatActivity { Button btnSave; Button btnDelete; ListView lvMemoList = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSave = findViewById(R.id.btnSave); btnDelete = findViewById(R.id.btnDelete); lvMemoList = findViewById(R.id.lvMemoList); } |
続いて、追加ボタンの処理を実装します。
ボタン押下時の関数は、activity_main.xmlのレイアウト側にonAddButtonClick名前で定義していたので、関数名はonAddButtonClickにします。
1 2 3 4 5 6 7 8 9 10 |
// 追加ボタンの処理 public void onAddButtonClick(View view){ EditText etTitle = findViewById(R.id.etTitle); etTitle.setText("new memo"); EditText etNote = findViewById(R.id.etNote); etNote.setText(""); btnSave.setEnabled(true); } |
追加ボタンの処理は、memo用のタイトルを”new memo”、内容欄を空欄にして、保存ボタンを有効にしています。
続いて、保存ボタン押して、データベースへ保存する処理を追加しましょう。(以下)
処理の概要を簡単に説明すると、
8行目で先程作ったDatabaseHelperクラスのインスタンスを作り、9行目でヘルパークラスからgetWritableDatabase()でデータベース接続オブジェクト(SQLiteDatabase)を取得します。
11行目がデータベースの挿入のSQL文です。12行目でデータベースに通知するためのオブジェクト(Statementオブジェクト)を作成し、title,noteを設定して、Insertを実行します。(17行目)
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 |
public void onSaveButtonClick(View view){ EditText etNote = findViewById(R.id.etNote); String note = etNote.getText().toString(); EditText etTitle = findViewById(R.id.etTitle); String title = etTitle.getText().toString(); DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getWritableDatabase(); try{ String sqlInsert = "INSERT INTO notememo (name, note) VALUES (?, ?)"; SQLiteStatement stmt = db.compileStatement(sqlInsert); stmt.bindString(1,title); stmt.bindString(2,note); stmt.executeInsert(); } finally { db.close(); } etTitle.setText(""); etNote.setText(""); btnSave.setEnabled(false); btnDelete.setEnabled(false); } |
4.メモリスト表示機能を追加
次はデータベースの内容をリストに表示する処理を作ってみましょう。
DB登録した内容をリストに表示するには、
MainActiviy.javaにリスト表示の関数を作ります。(以下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
private void memoListDisplay(){ DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getReadableDatabase(); try { String sql = "SELECT _id,name FROM notememo"; Cursor cursor = db.rawQuery(sql, null); String[] from = {"name"}; int[] to = {android.R.id.text1}; SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,cursor,from,to,0); lvMemoList.setAdapter(simpleCursorAdapter); } finally { db.close(); } } |
先程と同じように、DatabaseHelperのインスタンスを作成し、データベース接続オブジェクトを取得します。(3〜4行目)
次にSELECT文でデータベースから_idとnameを取得します。SQLの実行は、rawQueryメソッドを使います。戻り値はCursorオブジェクトになります。Cursorオブジェクトは、SELECT文の実行結果がまるまる格納されているオブジェクトになります。
次に、simpleCursorAdapterのインスタンスを作成します。
layoutには、リスト表示のレイアウトsimple_list_item_1を指定、cursorには、先程SQLを実行したcursorを指定、fromには、表示させたいカラム、今回は”name”カラム、toには、バインドするID,android.R.id.text1を指定します。
最後の引数は、flgでDBが更新されたときにクエリを再発行してくれるものなどを指定できますが、現在非推奨のため、今回は0を指定しています。
最後に、setAdapterでsimplerCursorAdapterを設定すれば、リストにDBの内容が表示されます。
作成したmemoListDisplay()をonCreateとonSaveButtonClick内でコールしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSave = findViewById(R.id.btnSave); btnDelete = findViewById(R.id.btnDelete); lvMemoList = findViewById(R.id.lvMemoList); memoListDisplay(); } |
1 2 3 4 5 6 7 8 9 10 11 12 |
public void onSaveButtonClick(View view){ EditText etNote = findViewById(R.id.etNote); String note = etNote.getText().toString(); ・・・省略・・・ etTitle.setText(""); etNote.setText(""); btnSave.setEnabled(false); btnDelete.setEnabled(false); memoListDisplay(); } |
5.メモ編集機能を追加
続いて、追加したメモを編集する機能を追加してみましょう。
まずは、データベースから選択したリストのデータを表示する処理から作ります。
onCreateに、リストをクリックした際に呼ばれるリスナーを登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSave = findViewById(R.id.btnSave); btnDelete = findViewById(R.id.btnDelete); lvMemoList = findViewById(R.id.lvMemoList); memoListDisplay(); lvMemoList.setOnItemClickListener(new ListItemClickListener()); } |
続いて、ListItemClickListenerクラスを定義します。
リストをクリックすると、onItemClickメソッドがコールされます。リストのポジション(postion)やデータベースに登録したidが引数で設定されてきますので、ID用の変数memoId宣言しておき、選択されたリストのIdを保持しておくようにします。(10行目) ※編集後に保存を実行する際に使用するため。
選択したリストのタイトル(name)と内容(note)を取得するため、SELECT文でSQLを実行します。(18行目〜19行目)
取得した実行結果はcursorに格納され、cursor.moveToNext()でfalseが返るまでループします。これでSQL実行結果の行データを次々取得することができます。
ループ内の処理で各カラムのindexを取得し、indexから実際のデータを取得しています。(24行目〜32行目)
取得したデータをテキストエディットに設定することで、選択したリストのタイトル、内容を表示させています。(35行目〜39行目)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public class MainActivity extends AppCompatActivity { int memoId = -1; // memo id ・・・省略・・・ private class ListItemClickListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int postion, long id) { Log.i("debug","onItemClick position="+postion+" id="+id); memoId = (int)id; btnSave.setEnabled(true); btnDelete.setEnabled(true); DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getReadableDatabase(); try { String sql = "SELECT name,note FROM notememo WHERE _id = "+ memoId; Cursor cursor = db.rawQuery(sql,null); Log.i("debug","cursor:"+cursor.toString()); String note = ""; String title = ""; while(cursor.moveToNext()){ int idxNote = cursor.getColumnIndex("note"); Log.i("debug","idxNote:"+idxNote); note = cursor.getString(idxNote); Log.i("debug","idxNote="+idxNote+" note="+note); int idxTitle = cursor.getColumnIndex("name"); Log.i("debug","idxtitle:"+idxTitle); title = cursor.getString(idxTitle); Log.i("debug","idxtitle="+idxTitle+" title="+title); } EditText etNote = findViewById(R.id.etNote); etNote.setText(note); EditText etTitle = findViewById(R.id.etTitle); etTitle.setText(title); } finally { db.close(); } } } |
メモの内容を編集後に、保存ボタンを押してデータベースを更新する処理を実装します。
編集後に保存する場合、先程リスト選択時に保存しておいたIDを使って、データベース上のデータを一旦削除して、再度挿入します。
追加ボタンで新規追加したときとSQL文が変わりますので、新規追加or編集が切り分けられるようにフラグsave_selectを追加します。
追加時は、0、編集時は1にします。
1 2 3 4 5 6 7 |
public class MainActivity extends AppCompatActivity { int memoId = -1; // memo id Button btnSave; Button btnDelete; ListView lvMemoList = null; int save_select = 0; // 0:add 1:item select |
1 2 3 4 5 6 7 8 9 10 |
public void onAddButtonClick(View view){ EditText etTitle = findViewById(R.id.etTitle); etTitle.setText("new memo"); EditText etNote = findViewById(R.id.etNote); etNote.setText(""); save_select = 0; // add btnSave.setEnabled(true); } |
1 2 3 4 5 6 7 8 9 10 11 12 |
private class ListItemClickListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int postion, long id) { Log.i("debug","onItemClick position="+postion+" id="+id); save_select = 1; memoId = (int)id;//postion; // positionだと、リストが削除されたときにおかしくなるので、idを取得 btnSave.setEnabled(true); btnDelete.setEnabled(true); DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getReadableDatabase(); |
保存ボタンを押したときの処理に編集時の保存処理を追加します。
先程追加したフラグsave_selectを使い、新規追加時の処理と切り分けます。
IDを使って、該当のデータを一旦DELETEし、 INSERTで挿入しています。(14行目〜26行目)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public void onSaveButtonClick(View view){ EditText etNote = findViewById(R.id.etNote); String note = etNote.getText().toString(); EditText etTitle = findViewById(R.id.etTitle); String title = etTitle.getText().toString(); Log.i("debug","title "+title); DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getWritableDatabase(); if(save_select==1){ try{ String sqlDelete = "DELETE FROM notememo WHERE _id = ?"; SQLiteStatement stmt = db.compileStatement(sqlDelete); stmt.bindLong(1,memoId); stmt.executeUpdateDelete(); String sqlInsert = "INSERT INTO notememo (_id, name, note) VALUES (?, ?, ?)"; stmt = db.compileStatement(sqlInsert); stmt.bindLong(1,memoId); stmt.bindString(2,title); stmt.bindString(3,note); stmt.executeInsert(); } finally { db.close(); } } else { try{ String sqlInsert = "INSERT INTO notememo (name, note) VALUES (?, ?)"; SQLiteStatement stmt = db.compileStatement(sqlInsert); stmt.bindString(1,title); stmt.bindString(2,note); stmt.executeInsert(); } finally { db.close(); } } etTitle.setText(""); etNote.setText(""); btnSave.setEnabled(false); btnDelete.setEnabled(false); memoListDisplay(); } |
6.メモ削除機能を追加
最後に削除キーが押されたときの処理を実装します。
リスト選択した際に保存しておいたIDのデータをDELETEする処理を記載しています。
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 |
public void onDeleteButtonClick(View view){ EditText etNote = findViewById(R.id.etNote); EditText etTitle = findViewById(R.id.etTitle); String title = etTitle.getText().toString(); Log.i("debug","title "+title); DatabaseHelper helper = new DatabaseHelper(MainActivity.this); SQLiteDatabase db = helper.getWritableDatabase(); try{ String sqlDelete = "DELETE FROM notememo WHERE _id = ?"; SQLiteStatement stmt = db.compileStatement(sqlDelete); stmt.bindLong(1,memoId); stmt.executeUpdateDelete(); } finally { db.close(); } etTitle.setText(""); etNote.setText(""); btnSave.setEnabled(false); btnDelete.setEnabled(false); memoListDisplay(); } |
最後に
今回、Androidアプリで簡単なメモ帳アプリを作ってみました。データベースの使い方がわかれば色々応用していろんなアプリが作れると思います。
皆さんもぜひチャレンジしてみてください。
それでは!!
スポンサーリンク