Android WEBサーバーと連動するノートアプリを作る (PhoneGap)
実装概要
PhoneGapフレームワークを利用して、androidアプリを製作します。機能としては、ブログのように、タイトル、内容を記入して、送信し、それらが反映されるというシンプルなものです。データベースは、サーバーにあるMySQLを利用します。また、フレームワーク内では、PHPは使えませんので、処理は、サーバーで行い、クライアント側のブラウザでは、jQueryのajax()でPOST送信することで、データを送信し、処理内容を受け取るようにします。PhoneGepの環境構築には、Node.js等の準備が必要で、初めての場合は、前回投稿した、Androidアプリ開発 PhoneGapによる開発環境と実機での実行のメモを参考程度に、ご覧ください。あくまで、起動確認のサンプルのような形で作成しましたので、セキュリティー対策が不備であったり、div idが数値になっていたり、突っ込みどころはあると思いますが、こういう感じというイメージで参考程度にご覧ください。
今回は、PhoneGapフレームワーク上で編集するのは、index.htmlだけです。その他のファイルは、サーバーに設置して、index.htmlとajax通信でデータのやり取りを行います。(起動の確認の為、サーバーにindex.htmlを置いてもPCブラウザより確認できます。)
・サンプルのサーバー側のファイル構成
データベースの準備
まずは、フォームからのデータを登録するデータベースを作る必要があります。
postテーブル
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
title varchar(30) NOT NULL,
content text NOT NULL,
date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
データベースの準備が完了したら、db.phpにMySQLに接続情報を記載します。それをあとで読み込んで使うようにします。(このあたりは、host dbname $user $password の部分は、環境にあわせて、変更してください。)
【db.php】
<?php function db_connect(){ $dsn = 'mysql:host=localhost;dbname=sample;charset=utf8'; $user = 'root'; $password = 'japan'; try{ $dbh = new PDO($dsn, $user, $password); return $dbh; }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } } ?>
index.htmlの解説
index.htmlでは、javascriptによるサーバーに置いたファイルとの通信になります。まず、スクリプト部分の解説を上から順に解説します。
data_select.phpより、既にあるデータ一覧を読み込み、それらをdiv id=”all” の部分に入れる。
$.get('http://sample.com/data_select.php', function (data) { $('#all').html(data); });
・[ノートを作る]ボタンの処理
ボタンを押すと、外部のdata_insert.phpにPOSTデータが送信され、データベースに1件のデータが追加される。その後、追加されたデータの1件を取得し、
の部分に追加する。
$('#post').click(function(){ if ($('button').hasClass('upd')) { alert('その他のページの編集が完了していません。'); }else if( $('#title').val() === '' || $('#content').val() === '' ) { alert('空白箇所があります。'); }else{ var title = $("#title").val(); var content = $("#content").val(); $.ajax({ url: 'http://sample.com/data_insert.php', type: 'POST', data: { 'title': title, 'content': content}, timeout: 10000, dataType: 'text' }).done(function( data ) { $('#title').val(''); $('#content').val(''); $('#all').append(data); }); } });
1件分のデータには、それぞれidがつけられています。それらのidに応じて、その部分の削除や編集が行われます。
・[削除]ボタンの処理を押すと、外部のdata_delete.phpに削除する部分のidが送信され、その部分が削除されます。
・[編集]ボタンを押すと、外部のdata_edit.phpより編集フォームを読み込みます。
・[更新]ボタンは、data_edit.phpのフォームを読み込んだ時に表示されるボタンですが、このボタンを押すと、外部のdata_update.phpに更新データが送信され、データベースのデータが更新されます。
$('#all').on('click','button.del',function(){ var id = $(this).parent().parent().attr("id"); var req = window.confirm('No.' + id +' 本当にこのページを削除しますか?') if (req==true) { $.ajax({ url: 'http://sample.com/data_delete.php', type: 'POST', data:{ id:id }, timeout: 10000, dataType: 'text' }).done(function( data ) { $('#' + id).replaceWith(''); }); }else{ } }).on('click','button.edt',function(){ if ($('button').hasClass('upd')) { alert('その他のページの編集が完了していません。'); }else{ var id = $(this).parent().parent().attr("id"); $.ajax({ url: 'http://www.sample.com/data_edit.php', type: 'POST', data:{ id:id }, timeout: 10000, dataType: 'text' }).done(function( data ) { $('#' + id).replaceWith(data); }); } }).on('click','button.upd',function(){ if( $('.title').val() === '' || $('.content').val() === '' ) { alert('空白箇所があります。'); }else{ var title = $(".title").val() var content = $(".content").val() var id = $(this).parent().attr("id"); $.ajax({ url: 'http://sample.com/data_update.php', type: 'POST', data: { title: title, content: content, id: id}, timeout: 10000, dataType: 'text' }).done(function( data ) { $('#' + id).replaceWith(data) }); } });
html部分は、下記のようになっており、非常に少なく、要は、追加するフォームと、表示する
があるだけです。これをみても分かるように、ほとんどがjavascriptの操作になります。
タイトル: <input id="title"><br> 内容: <textarea id="content" rows="3"></textarea><br> <button id="post">ページを作る</button> <div id="all"></div>
サーバー設置のPHPファイル
サーバーに設置した、phpファイルは、phonegape上のindex.htmlに書かれているjavascriptの命令によって、処理が開始されます。もともとデータベースにあるデータ一覧をindex.htmlに読み込んだり、index.htmlより、受け取った、POSTデータをもとに、データベースへの登録・削除・更新をおこない、それらの結果をhtmlとして、index.htmlに書き換えたりします。
【data_select.php】
… index.htmlのjQueryの.get()メソッドで取得される一覧データです。
<?php require_once("db.php"); $dbh = db_connect(); try{ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT * FROM post"; $stmt = $dbh->query($sql); $data = $stmt->fetchAll(); }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } foreach ($data as &$val) { echo '<div id="'. $val['id'] .'"><h3>' .$val['title'] . '</h3><p>' .$val['date']. ' ' . $val['content']. '<button class="del ui-btn ui-icon-delete ui-btn-icon-left">削除</button><button class="edt ui-btn ui-icon-edit ui-btn-icon-left">編集</button></p></div>' ; } ?>
【data_insert.php】
… index.htmlの[ノートを作る]ボタンを押したときに、ajax()メソッドを使って、POSTされるデータを受け取り、そのデータを元に、追加した1件分のデータを取得し、index.htmlに返します。
<?php require_once("db.php"); $dbh = db_connect(); try{ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "INSERT INTO post (title,content) VALUES(:title, :content)"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':title', $_POST['title']); $stmt->bindValue(':content', $_POST['content']); $stmt->execute(); $pid = $dbh->lastInsertId(); $sql = "SELECT * FROM post WHERE id = :id"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', $pid); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } ?> <div id="<?=$data['id']?>"> <h3><?=$data['title']?></h3><p><?=$data['date']?><?=$data['content']?><button class="del ui-btn ui-icon-delete ui-btn-icon-left">削除</button><button class="edt ui-btn ui-icon-edit ui-btn-icon-left">編集</button></p> </div>
【data_delete.php】
… index.htmlより、削除する部分のidを受け取り、それを元に、削除を行います。
<?php require_once("db.php"); $dbh = db_connect(); try{ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "DELETE FROM post WHERE id = :id"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', $_POST['id']); $stmt->execute(); }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } ?>
【data_edit.php】
… index.htmlのそれぞれの[編集]ボタンを押した際に、その部分のidが.ajax()メソッドを通じて、POSTデータとして渡ってきます。それをもとに、その部分のデータをフォームに設置したhtmlデータをindex.htmlに返します。
<?php require_once("db.php"); $dbh = db_connect(); try{ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT * FROM post WHERE id = :id"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', $_POST['id']); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } ?> <div id="<?=$data['id'] ?>"> 件名: <input class="title" value="<?=$data['title'] ?>"><br> 本文: <textarea class="content" rows="3" ><?=$data['content'] ?></textarea><br> <button class="upd ui-btn ui-icon-edit ui-btn-icon-left">更新</button> </div>
【data_update.php】
… data_edit.phpより読み込まれたフォームにある[更新]ボタンを押したときに、その部分のidが、.ajax()メソッド
通じてわたってきますが、そのデータを更新します。その後、更新後の1件分のデータを取得して、index.htmlに返します。
<?php require_once("db.php"); $dbh = db_connect(); try{ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "UPDATE post SET title = :title, content =:content WHERE id =:id"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':title',$_POST['title']); $stmt->bindValue(':content',$_POST['content']); $stmt->bindValue(':id',$_POST['id']); $stmt->execute(); $sql = "SELECT * FROM post WHERE id = :id"; $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', $_POST['id']); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); }catch (PDOException $e){ print('Error:'.$e->getMessage()); die(); } ?> <div id="<?=$data['id'] ?>"> <h3><?=$data['title'] ?></h3><p><?=$data['date'] ?><?=$data['content'] ?><button class="del ui-btn ui-icon-delete ui-btn-icon-left">削除</button><button class="edt ui-btn ui-icon-edit ui-btn-icon-left">編集</button></p> </div>
【追加 2018.3.1】
サンプルのシュミレーターでは、ブラウザによっては、クロスドメイン制約で非同期時に指定したURLに通信できない可能性があります。そこで、それを回避するために、読み込む側のPHPファイルの頭に、header(“Access-Control-Allow-Origin: *”);を追加して、通信許可してください。
感想
PhoneGapフレームワークを使うと、javascriptの知識で、アプリが作れるのが便利なところです。また、デバックは、androidでやっていますが、iOSでも起動できるので、これがハイブリットアプリの良いところです。
それとコードを書いていて、ビルドして気づいたことですが、スマフォ上では、jqeruyの.load()メソッドが動いていないことに気づきました。stackoverflowに 「Will jQuery .load() Work On PhoneGap?」記事があり、フレームワークの仕様によるものなので、記事にあるように.get()に変更しました。
//$("#all").load("http://sample.com/data_select.php"); $.get('http://sample.com/data_select.php', function (data) { $('#all').html(data); });
おそらく、こういうのはまだ他にもあると思います。
それと記事にまとめる際に、アプリのビルドについては書いてないのですが、このあたりは前回のAndroidアプリ開発 PhoneGapによる開発環境と実機での実行のメモを参考ください。