Androidを使った備忘録を作ってみよう

本チュートリアルの内容

■ 開発環境の確認

前提とする開発環境

このチュートリアルでは、以下の環境を想定します。Androidの開発はEclipseで行います。Eclipseの設定はすんでいるものとします。

前提知識

以下のチュートリアルで、MySQLを使ったDBの作成方法について復習しておきましょう。

■ 開発するアプリのシナリオ

今回開発するシナリオは以下のようなものを想定します。


利用者は、Androidの備忘録アプリをダウンロードして、自分の端末に入れておきます。メモしたい内容が出来たら、アプリケーションを立ち上げて、メ モの内容を記述し、それをサーバーに送信します。

メモを閲覧したいときには、同じアプリケーションを立ち上げて、検索画面にキーワードを入力し、検索ボタンを押下します。検索キーに部分一致するメモが あった場合、それを端末の画面に表示します。


アプリケーションイメージ
図 アプリケーションイメージ

■ Eclipseを使ってDB接続す る

MySQL Connector/Jを用意する

DB接続には、MySQL Connector/Jを使用します。これを使うことで、直接、Android端末とDBを接続することができます。この接続方法は、比較的、簡単に実装できますが、ネットワークの途中にファイヤウォールがある場合などは、ポートを開放するなどの対処が必要となります。

MySQL Connector/Jは、MySQLのホームページからダウンロードしておきます。

MySQLのHP
図 MySQLのHP

mysql-connector-java-5.1.27.zipがダウンロードされたら、zipを解凍して、出てきたフォルダをわかりやすいところに保存しておきます。 実際に使用するのは、このフォルダ内のmysql-connector-java-5.1.27-bin.jarです。

DBを作成する

次に、今回のアプリケーションで使用するDBを作成します。DBは、以下のような単純なものとします。

Field Type Key Extra
id int(5) PRI auto_increment
memo
char(100)

idを主キーとして、自動発番とし、メモは、50文字以内とします。DB名は、memo_db、テーブル名は、memo_tblとします。

	create table memo_tbl(
	id int(5) auto_increment,
	memo char(100),
	primary key(id));
              

ユーザー名と、パスワードは、memo、memoとして、チュートリアルを進めます。DBは各自、作成しておいてください。

■ 画面を作成する

まず、DBを操作する部分を作成する前に、画面を作成してみましょう。Eclipseを立ち上げて、Androidプロジェクトを作成しま す。プロジェクト名は、NetMemoとしておきます。パッケージ名は、他のパッケージと重ならないような名前をつけておきましょう。

プロジェクト作成(1)
図 プロジェクト作成(1)

次へを押下して、先に進みます。カスタム・ランチャー・アイコンは作らなくてもよいでしょう。また、アクティビティは作成し、初期の画面としては、Blank Activityを選択しておけばよいです。Activity名もデフォルトのもので先に進めましょう。

プロジェクト作成(2)
図 プロジェクト作成(2)

初期画面が表示されたでしょうか。

早速ですが、まず、画面の作成をしておきます。画面は、以下のようにしたいと思います。

画面イメージ
図 画面イメージ

このような画面を実現するのに、2つのレイアウトを使用します。

配置としては、全体をScrollViewとして、その中に、Linearを垂直方向に、配置し、さらに、記録するウィンドウ部分と記録ボタ ン、メモ表示の検索入 力と検索ボタンを水平に配置しておくというレイアウトにします。

画面設計
図 画面設計

作成したプロジェクトの、resフォルダ、layoutフォルダ内の、activity_main.xmlファイルおよび、valuesフォルダ内の、strings.xmlファイルを編集して、上記のレイアウトを完成させてください。この時に、以下のように、それぞれの画面コンポーネントに名称を付けておきます。また、ボタンの部分のレイアウトの見栄えを良くするために、EditTextとButtonに3:1のウェイトをつけておきま す。また、ついでに、ア プリケーションの名前も、ネット備忘録と変更しておきましょう。

画面
図 画面

さて、これで画面のデザインは終了です。

もう一つ、このアプリでは、インターネット接続を行いますので、Manifestファイルの変更もしておきます。これは、単純で、Internet利用の許可を与 えておけば結構です。

    <uses-permission android:name="android.permission.INTERNET" />
              

さらに、MySQL Connector/Jを使用可能にするために、先ほどダウンロードして解凍した、jarファイルを、プロジェクトのlibsフォルダにインポートしておきます。インポートはファイル・システムを選択し、先ほど保存したjarファイルを選択するだけでよいです。

ライブラリのインポート
図 ライブラリのインポート

以下、コードを作成しますが、まずは、コードの全体アルゴリズムを見てみます。

アルゴリズム
図 アルゴリズム

アプリケーション起動時のメソッドで、ボタンの押下判定を行って、その結果、登録ボタンが押されていたら、EditText内の文字を取り込んで、DBに登録(insert)して、検索ボタンが押されたら、EditText内の文字を取り込んで、DBを検索(select)して、検索結果をTextViewに表示するという動作になります。では、まずは、DBに書き込むところのコードを作成してみます。

■ DBに書き込む

DBに書き込むためには、srcフォルダの中の、MainActivity.javaを開きます。Eclipseが作成した初期画面が入っていると思います。まず、使用 するライブラリを追加しておきます。importのところに以下のものを追加します。まだ、使用していないので、警告が出ますが、気にしなくてよいです。

	import java.sql.Connection;
	import java.sql.ResultSet;
	import java.sql.Statement;
	import java.sql.DriverManager;
	import android.widget.TextView;
	import android.os.AsyncTask;
              

さて、ボタンを押したときの動さについて、説明します。今回は、登録ボタンの押下が確認されたら、その時に動作するメソッドを起動して、EditTextの値の読み取りと、DBへの書き込みを行います。ただし、単純にUIを制御するスレッドでDB接続や、SQL文を送るればよいのではなく、接続は、非同期で おこな う必要があります。これは、Android3.0から変更になったということのようです(詳細は他の参考資料へ)。

まず、ボタンを押したときのイベント処理ですが、OnClickListenerを使用します。初期のActivityのままでは、OnClickListenerが実装できないので、Activityクラスにimplements OnClickListenerを追加します。

	public class MainActivity extends Activity implements OnClickListener {
    (コードは省略)
	}
              

そして、以下も追加します。(実際にはEclipseがそのように指示してきます)

	import android.view.View.OnClickListener;
              

onCreateメソッド内に、それぞれのボタンが押された時の処理を記述します。必要に応じて、Buttonのwigetも追加しておきま す。この後も、必要な コンポーネントをimportする必要がありますが、警告が出たら適宜追加してください。

        // Button1の操作
        Button btn1 = (Button)this.findViewById(R.id.btn1);
        Button btn2 = (Button)this.findViewById(R.id.btn2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
              

ボタンを押下したときの処理ですが、流れとしては、UIのスレッドから、非同期クラスのインスタンスを作成し、それを実行することでDB接続をするということに なります。

ではまず、メインのクラスとは別に、非同期のクラスを作成してみます。ここでは、TaskDbInsertというクラスを作成します。AsyncTaskクラス を継承するこのクラスは、3つのパラメータの方の型を指定する必要があります。

	class TaskDbInsert extends AsyncTask <Void,Void,Void >{
        // この中をこれから記述
	}
              

最初が、読み出し元でメソッドが実行される時に渡される引数の型、2つ目は進捗を表現する時に使用する型、3つ目はスレッド終了時に返す値の型です。ここでは、起動時の引数は渡さないのでVoid、進捗も表示しないのでVoidとし、処理の結果も何も渡さないので、3つ目もVoidとしました。

では、実際にクラスの中身を書いていきます。まずは、呼び出し側のActivityをそのままインスタンス生成時の引数としてしまうことと しました(この方法が 適しているかは不明です)。

クラス側でActivityを定義し、コンストラクタにおいて引数として渡されてきたアクティビティを代入します。

    Activity activity = null;
   // コンストラクタ
   public TaskDbInsert(Activity act){
       activity = act;
   }
              

次に、実際の処理を記述します。AsyncTaskでは、doInBackgroundメソッドを実装する必要があり、今回はそのメソッド にDBアクセスの コードを記述します。記述の内容は、通常のDB接続と同じです。IPアドレスは、接続するサーバーのIPアドレスですので、皆さんの環境に合わせて設定してください。

    @Override
    protected Void doInBackground(Void... params) {
        // 入力部の定義
        EditText ed =(EditText)activity.findViewById(R.id.inputTxt);
        String inputTxt=ed.getText().toString();
        // DB接続と書き込み
        try{
            Class.forName("com.mysql.jdbc.Driver");
            Properties props = new Properties();
            props.put("user", "memo");
            props.put("password", "memo");
            props.put("useUnicode", "true");
            props.put("characterEncoding", "UTF-8");
            String dbUrl = "jdbc:mysql://192.168.0.2/memo_db";
            Connection conn=DriverManager.getConnection(dbUrl, props);
            Statement stmt=conn.createStatement();
            String sql="insert into memo_tbl (memo) values ('"+inputTxt+"')";
            stmt.executeUpdate(sql);
            stmt.close();
            conn.close();
        }catch(Exception e){

        }

        return null;
    }
              

また、非同期処理が終了後に、書き込みが終わったことを示すように以下のような処理も書いておきましょう。

    protected void onPostExecute(){
        Toast.makeText(activity,"登録を終了しました", Toast.LENGTH_LONG).show();
    }
              

非同期処理用のクラスの作成は以上です。

では、先にボタン押下を判定し、このクラスのインスタンスを作成し処理する部分を記述しましょう。これは、class MainActivity内にメソッドとして定義します。

   @Override
    public void onClick(View v){
        // ボタン押下時の動作
        if(v.getId()==R.id.btn1){ // ボタン1が押下されたら
            TaskDbInsert task1 = new TaskDbInsert(MainActivity.this);
            task1.execute();
        }
    }
              

ここまで実装することで、メモの登録ができるはずです。実際に、プロジェクトをコンパイルして、実機で動かしてみましょう。

操作画面
図 操作画面

ここで、「牛乳を買ってくること。」と入力してみました。DBに入力されたかを確認するために、DBに接続して、memo_tblを検索 してみましょう。

挿入確認
図 挿入確認

きちんと表示されていますでしょうか。

■ DBから読みだす

DBからの検索は、書き込みと同じように実施することができます。同じように、非同期処理を行うクラスを定義します。

	class TaskDbQuery extends AsyncTask<Void, Void, String>{
      // この中をこれから記述
	}
              

今度は、検索結果をonPostExecuteで表示するために、3つ目の引数をStringにします。Activityについては、先 ほどと同様にインスタ ンスを作成するときに、引数として渡します。

   Activity activity = null;
   
   // コンストラクター
   public TaskDbQuery(Activity act){
       activity = act;
   }
              

doInBackgroundの部分では、検索実行と、あと、検索結果が多すぎるときと少なすぎるときの処理を入れてみました。具体的に は、検索結果がない時には、キーワードを変更せよ、検索結果が5個以上出たときには絞り込みをせよ、というメッセージを出すようにしました。

    @Override
    protected String doInBackground(Void... params) {
        // 検索語の入力部分の定義
        EditText ed =(EditText)activity.findViewById(R.id.searchTxt);
        String qryText=ed.getText().toString();
        // 検索結果用の文字列
        String rsText="";
        // DB接続と検索実行
        try{
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn=DriverManager.getConnection("jdbc:mysql://192.168.0.2/memo_db","memo","memo");
            Statement stmt=conn.createStatement();
            String sql="select memo from memo_tbl where memo like '%"+qryText + "%'";
            ResultSet rs=stmt.executeQuery(sql);
            int rsCnt=0;
            while(rs.next()){
                rsText+=rs.getString(1)+"\n";
                rsCnt++;
            }
            // 検索結果が多すぎるとき、少なすぎるときの処理
            if(rsCnt==0){
                rsText="検索結果がありません。キーワードを変更してください。";
            }else if(rsCnt>5){
                rsText="5個以上見つかりました。キーワードを変更してください。";
            }
            rs.close();
            stmt.close();
            conn.close();
        }catch(Exception e){
            rsText=e.getMessage();
        }
        return rsText;
    }
              

そして、onPostExecuteとして以下を記述します。

    protected void onPostExecute(String result){
        TextView tv = (TextView)activity.findViewById(R.id.result);
        tv.setText(result);
    }
              

これで、非同期処理のクラスは完成です。次に、ボタン押下時の処理を追加しておきます。

    @Override
    public void onClick(View v){
        // ボタン押下時の動作
        if(v.getId()==R.id.btn1){ // ボタン1が押下されたら
            TaskDbInsert task1 = new TaskDbInsert(MainActivity.this);
            task1.execute();
        }else if(v.getId()==R.id.btn2){ // ボタン2が押下されたら
            TaskDbQuery task2 = new TaskDbQuery(MainActivity.this);
            task2.execute();
        }
    }
              

else if以下が追加部分です。

では、先ほど入力した、メモが検索できるか実際に試してみましょう。検索窓に「牛乳」と入れて、検索ボタンを押下してみました。

入力
図 入力

すると、以下のような画面が表示されました。確かに検索されていますね。

検索結果
図 検索結果

もっとメモを入れて、試してみてください。


ページの先頭へ