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による開発環境と実機での実行のメモを参考ください。