質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.09%

SQLiteDataBaseが上手く使えません。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 4,110

score 27

現在周囲のAPをスキャンしてデータベースに値を格納しようとしているのですがContentValuesへの値の設定の仕方がわかりません。このプログラムの場合にはどのように値を格納するように改変したらよいでしょうか? どうかよろしくお願いします。

public class MainActivity extends AppCompatActivity {
    /** Called when the activity is first created. */
    private static MySQLiteHelper helper;
    private SQLiteDatabase db;
    private Context context;
    private ListView listView;
    private String ssid;
    private int date ;
    private int level;
    private int freq;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        helper = new MySQLiteHelper(this);
        db = helper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(helper.COLUM_SSID,ssid);
        values.put(helper.COLUM_FREQ,freq);
        values.put(helper.COLUM_LEVEL,level);
        values.put(helper.COLUM_DATE,date); //時刻を入れたい ButtonContent.time();
        db.insert(helper.TABLE_NAME,null,values);


        listView = (ListView)findViewById(R.id.listView);  //Listviewにリンク

        final ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
        listView.setAdapter(adapter); //ListViewに渡す
        final WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);

        /* メインスレッド以外から UI を触るための 仲介役 */
        final Handler handler = new Handler();

        /* 一定時間ごとに 実行してほしいことを run() の中に書く */
        final TimerTask timerTask = new TimerTask(){
            @Override
            public void run() {
                if (manager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
                    // APをスキャン
                    manager.startScan();
                    // スキャン結果を取得
                    List<ScanResult> apList = manager.getScanResults();
                    final String[] aps = new String[apList.size()];
                    for (int i = 0; i < apList.size(); i++) {
                        aps[i] ="SSID" + apList.get(i).SSID + "\n"  + apList.get(i).frequency + "MHz"
                                + apList.get(i).level + "dBm" + ButtonContent.time();
                    }

                    /* スキャンが終わったら表示する */
                    /* TimerTask は メインスレッドで実行できないので、UIを触りたいのでHandlerを使う */
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            /* リストをきれいさっぱり空にして */
                            adapter.clear();
                            /* 新しい情報を全部足して */
                            adapter.addAll(aps);
                            /* 中身変わったと教える */
                            adapter.notifyDataSetChanged();
                        }
                    });
                }
            }
        };
        /* TimerTaskは UI スレッドで実行できないので 別なスレッドの中で実行する */
        new Thread(new Runnable() {
            @Override
            public void run() {
                new Timer(true).schedule(timerTask, 0, 500);
            }
        }).start();
    }


    @Override
    public void onDestroy(){
        super.onDestroy();
        db.close();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


}


SQLiteOpenHelperクラスです。↓
public class MySQLiteHelper extends SQLiteOpenHelper implements BaseColumns {

    private static final int DATABASE_VIRSION = 1;
    private static final String DATABASE_NAME = "sqlite_wifi.db";

    //テーブル名やカラムはデータベースのアクセスに必要なのでpublic
    public static final String TABLE_NAME = "mytable";
    public static final String COLUM_ID = "_id";
    public static final String COLUM_SSID = "ssid";
    public static final String COLUM_FREQ = "freq";  //カラムの割り振り、ID カラムIDには_idを使うことが必須事項
    public static final String COLUM_LEVEL = "level";
    public static final String COLUM_DATE = "date" ;

    private static final String MY_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + COLUM_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
            COLUM_SSID + " TEXT NOT NULL," + COLUM_FREQ + " INTEGER NOT NULL," + COLUM_LEVEL + " INTEGER NOT NULL," + COLUM_DATE + "INTEGER NOT NULL );"; //クエリ分の作成処理

    private static final String DROP_TABLE = "drop table " + TABLE_NAME; //tableの削除

    public MySQLiteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VIRSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(MY_CREATE_TABLE); //tableを作成するSQLを実行
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DROP_TABLE);
        onCreate(db);  //tableを削除して再生成
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

データベース構造を変更した際に,private static final int DATABASE_VIRSION = 1;の値を変更すること.
SQL文を正しく作ること.の2つで解決するはずです.
参考までに,write()メソッドを呼ぶことで,データを追加できるサンプル.
Activityなどから,必要に応じて write(context, scanResultList, date);を呼ぶことでデータベースを更新できます.
/* BaseColumns を使うなら これ自身に COLUM_ID を 定義する必要はありませんね */
/* 私的には使う必要性を感じません */
class MySQLiteHelper extends SQLiteOpenHelper /* implements BaseColumns */ {

    /* VIRSION -> VERSION */
    /* Database の構成を変更したら この値を変更する */
    /* e.g.) column 名を書き変えた, column を増やした */
    /* 通常 インクリメント (+1) するだけでよい*/
    private static final int DATABASE_VIRSION = 2;
    private static final String DATABASE_NAME = "sqlite_wifi.db";

    //テーブル名やカラムはデータベースのアクセスに必要なのでpublic
    /* COLUM -> COLUMN */
    public static final String TABLE_NAME = "mytable";
    public static final String COLUM_ID = "_id";
    public static final String COLUM_SSID = "ssid";
    public static final String COLUM_FREQ = "freq";  //カラムの割り振り、ID カラムIDには_idを使うことが必須事項
    public static final String COLUM_LEVEL = "level";
    public static final String COLUM_DATE = "date";

    private static final String MY_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + 
            COLUM_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
            COLUM_SSID + " TEXT NOT NULL," + 
            COLUM_FREQ + " INTEGER NOT NULL," + 
            COLUM_LEVEL + " INTEGER NOT NULL," + 
            COLUM_DATE + " INTEGER NOT NULL );"; /* スペース抜けの修正 */

    private static final String DROP_TABLE = "drop table " + TABLE_NAME; //tableの削除

    public MySQLiteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VIRSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(MY_CREATE_TABLE); //tableを作成するSQLを実行
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DROP_TABLE);
        onCreate(db);  //tableを削除して再生成
    }


    /* 汎用メソッド追加 */
    /* date の型を知らないので long にしてあります */
    public static void write(Context context, List<ScanResult> resultList, long date) {
        final SQLiteDatabase db = new MySQLiteHelper(context).getWritableDatabase();
        try {
            for (ScanResult scanResult : resultList) {
                ContentValues values = new ContentValues();
                values.put(COLUM_SSID, scanResult.SSID);
                values.put(COLUM_FREQ, scanResult.frequency);
                values.put(COLUM_LEVEL, scanResult.level);
                values.put(COLUM_DATE, date); //時刻を入れたい ButtonContent.time();
                /* insert にすべきか update にすべきかは 考え所ですね */
                db.insert(TABLE_NAME, null, values);
            }
        } finally {
            db.close();
        }
    }

    /* データベースからデータを取ってくる */
    public static List<MyResult> read(Context context) {
        /* Database を読み取り専用で開く */
        final SQLiteDatabase db = new MySQLiteHelper(context).getReadableDatabase();

        try {
            /* rawQuery() にてデータベースから指定アイテムを取ってくる */
            /* ? をわざわざ使わなくてもいいと考えるだろうが SQL インジェクション対策になる */
            /* ダメな例) db.rawQuery("SELECT * FROM " + TABLE_NAME, new String[0]) */
            /* もし TABLE_NAME に悪質なSQL文が入っていたら...? */
            final Cursor cursor = db.rawQuery("SELECT * FROM ?", new String[]{TABLE_NAME});
            try {
                /* columnIndex は データベースを作った際に */
                /* 実行した CREATE TABLE 句の 順番で割り振られている */
                /* 手動で 0, 1, 2, 3 と振ることもできるが column 変更への耐性がなくなる */
                /* 良くない例) int ssidIndex = 1; int freqIndex = 2; ... */
                final int ssidIndex = cursor.getColumnIndex(COLUM_SSID);
                final int freqIndex = cursor.getColumnIndex(COLUM_FREQ);
                final int levelIndex = cursor.getColumnIndex(COLUM_LEVEL);
                final int dateIndex = cursor.getColumnIndex(COLUM_DATE);

                /* ArrayList のコンストラクタは 引数を取らなくてもよいが */
                /* サイズがわかっている場合には 指定した方が 高速である */
                /* ScanResult クラス は自分では扱えないため 自前で作ってみた */
                final List<MyResult> scanResults = new ArrayList<>(cursor.getCount());

                /* 最後まで cursor を動かす */
                /* Cursor は結構特殊な 振る舞いをします この書き方は覚えておきましょう */
                while (cursor.moveToNext()) {
                    final String ssid = cursor.getString(ssidIndex);
                    final int frequency = cursor.getInt(freqIndex);
                    final int level = cursor.getInt(levelIndex);
                    final long date = cursor.getInt(dateIndex);
                    scanResults.add(new MyResult(ssid, frequency, level, date));
                }
                return scanResults;
            } finally {
                /* 忘れずに close させるために try-finally を使用 */
                cursor.close();
            }
        } finally {
            db.close();

        }
    }
}

class MyResult {
    public final String ssid;
    public final int frequency;
    public final int level;
    public final long date;

    public MyResult(String ssid, int frequency, int level, long date) {
        this.ssid = ssid;
        this.frequency = frequency;
        this.level = level;
        this.date = date;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/06 04:47

    Androidで,アクセスポイント探索,PCに送信.
    PCで,アクセスポイント情報受信,ファイルに保存ってことですね.
    可能です.Androidの障壁を除けば,できないことはありません!

    キャンセル

  • 2015/11/06 05:34

    ありがとうございます!
    調べてみます!

    キャンセル

  • 2015/11/06 17:32

    どういたしまして

    キャンセル

0

何が出来ないのかよくわかりませんが
for (int i = 0; i < apList.size(); i++) {}の中で
ContentValues values = new ContentValues();
        values.put(helper.COLUM_SSID,ssid);
        values.put(helper.COLUM_FREQ,freq);
        values.put(helper.COLUM_LEVEL,level);
        values.put(helper.COLUM_DATE,date); //時刻を入れたい ButtonContent.time();
        db.insert(helper.TABLE_NAME,null,values);
上記の処理を行えばいいでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/28 21:28

    いくつかtoukibiさんの質問を拝見しておりますが,private static final int DATABASE_VIRSION = 1;の値を変更していないように見えます.Version値はデータベースの構成を変更したとき(カラム名を変更したり,追加したり),変えなければなりません.これを変えることで,HelperクラスはonUpgrade()を呼び,データベースを作り直します.これで解決するはずです.

    キャンセル

  • 2015/10/28 21:30 編集

    私は開発前の状態でバージョンを上げるのはあまり良いとは思えないですがいかがでしょうか?
    でも、データベースを変更した場合は「バージョンを上げる」か、「データを削除する」かどちらかをしないといけないですよ。

    キャンセル

  • 2015/10/28 21:43

    私は,デバッグ中にもまめにデータベースの削除・作成を行い,動作確認を行いたいため,しばしばバージョンを上げます.もちろんチェックの度に,"DROP TABLE"を行ってもよいのでしょうが,比較すると書き換えが多いです.(コメントアウトするにしても)int型なので,メジャーリリースの際に,10000単位で数値を上げるとかの工夫をすれば十分だと思っています.(e.g. int VERSION = MAJOR * 10000 + MINOR)

    キャンセル

0

コメントと間違えたため削除します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.09%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る