キラッとプリ☆チャンのコーデ管理アプリを作ってみた話

# 前置き

Qiitaで記事投稿やってみた！という気持ちで大変恐縮ではあります。

---

# 本題

**職業訓練校で学んだ程度ではあるのだが、Androidのアプリを作ることはできる。**
下記の書籍を参考にしながら、タイトルのアプリを簡単ではあるけど、作った。

[基礎&応用力をしっかり育成! Androidアプリ開発の教科書 なんちゃって開発者にならないための実践ハンズオン ](https://www.amazon.co.jp/dp/4798152021/ref=cm_sw_r_tw_dp_U_x_zgGhDbD7QVDQE)

## とあるフォロワーの要望からすべてが始まった

勉強も兼ねて、先ほど紹介した書籍のサンプルプログラムをサクサクっと作った。
「勉強するわけだから、自分でも楽しく作れるものを作りたいな」という気持ちが出てくる。
最初は、アイカツ！キャラクターのような喋り口で、お天気予報とか、マストドンのインスタンス「キラキラッター」にアクセスするような、簡単なアプリを作ろうとしていた。

…で、言ってみた。すると。

>ちゃんぷりのコーデ管理アプリ作って定期的にメンテしてくれたらたぶん首位いくレベルでDLされるよ💕

とか言われちゃったので、本気にした。

## どう作ったの、おじさん？

コーデ保存ってことは、SharedPreferenceかSQLite？
と思ったので、まずは書籍のサンプルプログラムでSQLiteを軽く理解して制作を始めようと思った。

イメージ画像としてはこんな感じ。メモ書きなので見づらいのはご容赦。
![メモ書き。画像大きくてすまんやで…](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290478/b0f5612e-8245-2972-2fd7-6b6beca5731e.jpeg)
実際は、画像内の「それか、こうか」以下の実装になりましたとさ。おわり。

## ソースコード

なにかの参考になればと思ったので、一部抜粋なテイで載せてみた。

        // ListViewオブジェクトを取得
        ListView lvPrichan = findViewById(R.id.lv_prichan);

        // リストビューに表示するプリチャン稼働弾のリストオブジェクトを作成
        List<String> prichanCorde = new ArrayList<>();

        // リストデータの登録。プリチャン稼働弾が増えたとしても
        // 簡単に追記できるようにした
        prichanCorde.add("キラッとプリ☆チャン ジュエル１弾");
        prichanCorde.add("キラッとプリ☆チャン ジュエル２弾");
        prichanCorde.add("キラッとプリ☆チャン ジュエル３弾");

        // アダプターオブジェクトを作成
        ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this,
                android.R.layout.simple_list_item_1,prichanCorde);
        lvPrichan.setAdapter(adapter);
        lvPrichan.setOnItemClickListener(new ListItemClickListener());
    }

    private class ListItemClickListener implements AdapterView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            switch (position) {
                case 0:
                    // ジュエル１弾のコーデリスト
                    Intent priJ1intent = new Intent(MainActivity.this,PrichanJewel1.class);
                    startActivity(priJ1intent);
                    break;
                case 1:
                    // ジュエル２弾のコーデリスト
                    Intent priJ2intent = new Intent(MainActivity.this,PrichanJewel2.class);
                    startActivity(priJ2intent);
                    break;
                case 2:
                    // ジュエル３弾のコーデリスト
                    Toast.makeText(MainActivity.this,"まだないよ",Toast.LENGTH_SHORT).show();
                    break;

上記はメイン画面処理。コーデ管理画面の処理は下記。

    // 選択されたコーデの主キーIDを表すフィールド
    int _prichanId = -1;
    // 選択されたコーデ名を表すフィールド
    String _prichanCordeName = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_prichan_jewel1);
        // リストビューを取得
        ListView lvJprichan = findViewById(R.id.lv_J1prichan);
        // リスナーを登録
        lvJprichan.setOnItemClickListener(new ListItemClickListener());
        // 長押しリスナーを登録
        lvJprichan.setOnItemLongClickListener(new ListItemLongClickListener());
    }

    private class ListItemClickListener implements AdapterView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // タップされた行番号をフィールドの主キーIDに代入
            _prichanId = position;
            // タップされた行のデータを取得してフィールドに代入
            _prichanCordeName = (String) parent.getItemAtPosition(position);
            // データベースヘルパーオブジェクトを作成
            J1DatabaseHelper helper = new J1DatabaseHelper(PrichanJewel1.this);
            // データベース接続オブジェクトを作成
            SQLiteDatabase db = helper.getWritableDatabase();

            String cordeGet = "";
            try {
                String sql = "select * from J1prichancorde where _id = " + _prichanId;
                Cursor cursor = db.rawQuery(sql, null);
                if (cursor.moveToNext()) {
                    int idxCorde = cursor.getColumnIndex("cordeget");
                    cordeGet = cursor.getString(idxCorde);
                }
            }
            finally {
                db.close();
            }
            if (cordeGet.equals("true")) {
                // 所持データを保持されたことを表示
                Toast.makeText(PrichanJewel1.this,
                        "持っているコーデカードだよ。",
                        Toast.LENGTH_SHORT).show();
            }
            else {
                Toast.makeText(PrichanJewel1.this,
                        "持っていないコーデカードだよ。",
                        Toast.LENGTH_SHORT).show();
            }
        }
    }

    private class ListItemLongClickListener implements AdapterView.OnItemLongClickListener {

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            
                // タップされた行番号をフィールドの主キーIDに代入
                _prichanId = position;
                // タップされた行のデータを取得してフィールドに代入
                _prichanCordeName = (String) parent.getItemAtPosition(position);
                // データベースヘルパーオブジェクトを作成
                J1DatabaseHelper helper = new J1DatabaseHelper(PrichanJewel1.this);
                // データベース接続オブジェクトを作成
                SQLiteDatabase db = helper.getWritableDatabase();
                try {
                    // インサート文を用意
                    String sqlInsert = "insert into J1prichancorde (_id, name, cordeget) values (?,?,?)";
                    // SQL文字列を元にプリペアードステートメントを取得
                    SQLiteStatement stmt = db.compileStatement(sqlInsert);
                    // 変数のバインド
                    stmt.bindLong(1, _prichanId);
                    stmt.bindString(2, _prichanCordeName);
                    stmt.bindString(3,"true");
                    stmt.executeInsert();
                }
                finally {
                    // データベースを閉じる
                    db.close();
                }
                Toast.makeText(PrichanJewel1.this,
                        "登録完了！",Toast.LENGTH_SHORT).show();
            }
            // 通常のクリックイベントを発生させない
            return true;

最初、これで無事動くじゃろ～～～
**と思ってたおじさんが馬鹿だった。**

Insert処理の問題で、アプリが落ちるという出来事が起きた。

```
            // タップされた行番号をフィールドの主キーIDに代入
            _prichanId = position;
            // タップされた行のデータを取得してフィールドに代入
            _prichanCordeName = (String) parent.getItemAtPosition(position);
            // データベースヘルパーオブジェクトを作成
            J1DatabaseHelper checkhelper = new J1DatabaseHelper(PrichanJewel1.this);
            // データベース接続オブジェクトを作成
            SQLiteDatabase checkdb = checkhelper.getWritableDatabase();
            String cordeGet = "";
            try {
                String sql = "select * from J1prichancorde where _id = " + _prichanId;
                Cursor cursor = checkdb.rawQuery(sql, null);
                if (cursor.moveToNext()) {
                    int idxCorde = cursor.getColumnIndex("cordeget");
                    cordeGet = cursor.getString(idxCorde);
                }
            }
            finally {
                checkdb.close();
            }
            if (cordeGet.equals("true")) {
                Toast.makeText(PrichanJewel1.this,"既に登録しているから、登録できないよ！",
                        Toast.LENGTH_SHORT).show();
            }
```

既にInsertでデータベースに挿入してて、長押ししてしまった時とかあるじゃろ？
そういう時に
**「既に入ってるからInsertはさせんよ。じゃあの。（エラーで終了）」**
となるので、こうした。

ここまで作るのにおじさんは一日かかりました。

## で、使ってもらった。

**十分管理できる！**
と嬉しい言葉をいただきましたァん♪
また、こんな言葉も頂いた。

>リストでチェックマーク選べて最終確定できて中で保持できてたらそれだけでも違う！

この実装に関しては、調査が必要だが、できないことでもないだろう。と思っているので
やってみようと思う。

以上です。