プログラミング: 2013年5月アーカイブ

PhoneGap という、クロスプラットフォーム・モバイルアプリケーション開発フレームワークを使って Android アプリケーション作る手順。

  1. Eclipse で Android アプリの新プロジェクト作成。
  2. PhoneGap ディレクトリ\lib\android\cordova-2.7.0.jar を、プロジェクトの libs 以下にコピー(2.7.0 の部分は、使用する PhoneGap のバージョンによって異なる)
  3. プロジェクトの assets フォルダの下に www というフォルダを作成。
  4. 作成した www フォルダ以下に、PhoneGap ディレクトリ\lib\android\cordova-2.7.0.js をコピー。
  5. プロジェクトの res ディレクトリ以下に、PhoneGap ディレクトリ\lib\android\xml フォルダをコピー。
  6. プロジェクトの src フォルダ内に MainActivity.java が作成されているので、ソースコードを 4箇所修正する。
  7. プロジェクトの AndroidManifest.xml を修正(2箇所)
  8. プロジェクトの assets/www フォルダの下に、HTMLファイル(取り敢えず index.html)を作成する。

MainActivity.java の修正はこんな感じ(修正前の行もコメントにして残してある)

import android.os.Bundle;
//import android.app.Activity;
import org.apache.cordova.DroidGap;
import android.view.Menu;

//public class MainActivity extends Activity {
public class MainActivity extends DroidGap {

@Override
//protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
super.loadUrl("file:///android_asset/www/index.html");
}

AndroidManifest.xml の修正はこんな感じ。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.netandfield.denshibooq"
    android:versionCode="1"
    android:versionName="1.0"
    android:windowSoftInputMode="adjustPan" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

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

    <application
        android:allowBackup="true"

※ともに、太字のところが修正点。

あとは、index.html を始めとし、HTML5 と JavaScript でアプリを作っていくだけ。
以前、Adobe Flash Builder では、自宅用と職場用を買って、それぞれの PC から Dropbox 上に作ったワークスペースを共有して、つまり、会社で作ったプログラムを、自宅に帰ってから修正して実行してみる・・・なんてことをしていたわけだが・・・
(ちなみに、Flash Builder も Eclipse ベースの IDE である)

Android 用のプロジェクトじゃそういうこと出来んの?

会社の ADT bundle Eclipse で作成した Android アプリを、自宅の ADT bundle Eclipse(バージョンは同じだが、会社は 64bit版、自宅は 32bit版)でビルドしようとしたら「ソースが見つからない」とかエラーが出て実行出来ず・・・

会社で、Android SDK のバージョン上げたら同じようなことになってしまったけど・・・

やっぱ、32bit版と 64bit版ではワークスペース、というかプロジェクトを共有することって出来んのかね。
まあ、一からプロジェクト作り直して、ソースをコピーしてやれば問題なく動くんだけど・・・

Subversion とか使ってソースの共有せいという話なんかなあ。

自分独り、会社と自宅でソース共有したいだけなのに、ちょっと不便だな(^^;
いやあ、もう、なんかめちゃくちゃですよ・・・(^^;
Android 開発環境、色々面倒くせえって言うのはホントだね(^^;

ある Android 開発の入門書には、「開発環境をアップデートして動作しなくなった場合」の回答として、「開発環境を1から作りなおしてください」とか書いてあるからな(^^;

今日の状況。

取り敢えずキャッシュやレジストリをクリアしてみようと思って、"eclipse -clean" で Eclipse を実行。

20130517_ADT_ERROR1.jpg
起動すると、「Please update ADT to the latest version.」と言われるので、最新バージョンを検索。

20130517_ADT_ERROR2.jpg
更新は検出されなかった様子。

で、今まで動いていたプログラムを実行しようとすると、何故か内部エラー発生。
「java.lang.NullPointerException」だって。

20130517_ADT_ERROR3.jpg
SDK Manager 開こうとすれば「設定で Android SDK のロケーションが設定されていません。」のエラー。

20130517_ADT_ERROR4.jpg
でも「設定」を見てみたら、正しい場所が指定されているし・・・(「Please update ADT to the latest version.」エラーは相変わらず出てるが・・・)

20130517_ADT_ERROR5.jpg
わけわから~ん!!

はい。素直に ADT バンドル版 Eclipse を再インストールします・・・とほほ・・・
Android GCM のサーバ用の API キーの入手を行なう時、「Create new Server key」を選択する。

そうすると、その API キーを使用するサーバを IP アドレスで指定出来るので、セキュリティ上良いんですわ。

Accept requests from these server IP addresses の入力欄に、一行に 1IPずつ記入する。
うちの会社はインターネット上にテスト用のサーバを 3台持ってるんで、それらの IP アドレスを記入する。

こんな感じ。

181.XXX.XXX.105/32
213.XXX.XXX.127/32
124.XXX.XXX.122/32

1台ずつの設定なので 32ビットのネットマスクをかけているが、複数のサーバを指定することも出来る。
その時は、

221.XXX.XXX.0/24

みたいに設定するわけですわ。

で、この IP アドレス以外のサーバから、GCM サーバにメッセージを送信してみた。

本来なら、id=0:1368593107767685%921c249ace0038c9 みたいなメッセージIDが返ってくるんだけど、

$ ./gcm_message_send.pl
<HTML>
<HEAD>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>

という具合に、401 Unauthorized エラーの HTML ソースが返ってくる。

GCM サーバ(https://android.googleapis.com/gcm/send)を閲覧する権限が無いってわけだな。

バッチリじゃん!
GCM のクライアントのテスト。

ADT 導入済みの Eclipse で、Android SDK Manager を起動して Extras→Google Cloud Messaging for Android Library をインストールする。

20130515_Android2.jpg
そしたら、SDK Path(うちの場合は C:\usr\local\adt-bundle\sdk)\extras\google\gcm\samples の下に gcm-demo-client というクライアントのサンプルプログラムができているので、これを Eclipse でビルド&実行する。

手順としては、「Android アプリケーション・プロジェクト」を gcm-demo-client とか適当な名前で作成し、libs、res、src ディレクトリの中は一旦全部削除して、SDK Path\extras\google\gcm\samples\gcm-demo-client の中身で上書きするっていう具合にしてるんだけど、もっとサンプルソースをプロジェクトに組み込む良いやり方があるのかね?

これで、プロジェクトの実行を行なうと、USB 接続された実機を使うか、それともエミュレータを使うか聞かれるので、実機 ASUS TF101 を選択。TF101 上でサンプルプログラムが実行される。

で、TF101 に向けてメッセージをプッシュすると、端末下部にそのメッセージが表示されるんだけど、それは数秒ですぐ消えちゃうので、サンプルプログラム上にメッセージを表示するように、ちょっとプログラムを修正する。

Android GCM 受信したメッセージを表示」というサイトなどを参考に。

具体的には、GCMIntentService.java を修正。

import android.os.Bundle;
を追加して、onMessage を、

    protected void onMessage(Context context, Intent intent) {
        Log.i(TAG, "Received message");

        // ここから追加&修正
        Bundle extras = intent.getExtras();
        String result = extras.getString("message");
        //String message = getString(R.string.gcm_message);
        String message = getString(R.string.gcm_message) + " = " + result;
        // ここまで
        displayMessage(context, message);
        // notifies user
        generateNotification(context, message);
    }

こんな風に修正。

これで、

20130515_Android1.jpg
こんな感じで、プッシュしたメッセージがアプリ画面にも表示される。

ちなみに、最初のメッセージが化けているのは EUC-JP で送ったから(^^;;;
当然メッセージは UTF-8 で送らないと駄目駄目。
Android 端末へのメッセージのプッシュをする場合のプログラムね。

GCM サービスを使うための API キーの入手の手順とかは、
を参照。(日本語訳です)

で、Google が用意しているサンプルプログラムをクライアントで動かして、メッセージを実際に端末に向けてプッシュするところまでテストしてみたんだけど、ざっとググってみたところ、サーバ側のプログラムを Perl で書いてる例が無かったので、簡単なものを作ってみた。

まず、クライアント(Android 端末上のアプリ)から regID を取得するプログラム。
(クライアントで、SERVER_URL にセットしている URL)

・・・っても、POSTで送られてくるデータをファイルに書き出してるだけだけどな。

#!/usr/bin/perl
#
# gcm_demo.cgi
#

read (STDIN, $postdata, $ENV{'CONTENT_LENGTH'});

open OUT, ">>/tmp/gcm_test.txt";
print OUT "POST $postdata\n";
close(OUT);

print "Content-type: text/html;charset=UTF-8\n\n";
print "DEMO";

exit();

これで、Android 側でクライアントを実行すると、

# cat /tmp/gcm_test.txt
POST regId=APA91bHi1fbAcCk1qwCMu6jO4IlJuAtXXXXXXXX_hhyK7atS6i6G_GuhtprPGroMnZkNQvKTWuAPxXXXXXXXXTLv-mKpIi_Ek9CpDPWvJQ79IZjmyXXXXXXXXttIgKOcf-GTcHRC8VmND3UpXXXXXXXXvfC4bw5hJw

という具合に regID(端末識別番号みたいなもん)が取得出来る。

regID が取得出来たらメッセージ送信プログラムにセット。

#!/usr/bin/perl
#
# gcm_message_send.pl
#
use LWP;

$ua = LWP::UserAgent->new;
$res = $ua->post(
"https://android.googleapis.com/gcm/send",
{
'registration_id' => "APA91bHi1fbAcCk1qwCMu6jO4IlJuAtXXXXXXXX_hhyK7atS6i6G_GuhtprPGroMnZkNQvKTWuAPxXXXXXXXXTLv-mKpIi_Ek9CpDPWvJQ79IZjmyXXXXXXXXttIgKOcf-GTcHRC8VmND3UpXXXXXXXXvfC4bw5hJw",
'collapse_key' => 'update',
'data.message' => "これはサーバからのテストメッセージです",
},
"User-Agent"    => "NAF Perl Program/0.1",
"Authorization" => "key=AIzaSyDsXXXXXXXX9Lyazw0NYRVrXXXXXXXXHk",
"Content-Type"  => "application/x-www-form-urlencoded;charset=UTF-8"
);

print $res->content;

これを実行したら、

$ ./gcm_message_send.pl
id=0:13685xxxxxxxx632%921cxxxxxxxx38c9

という具合に、https://android.googleapis.com/gcm/send がちゃんとメッセージ ID を返してくるので、ばっちりだろう。

必要最小限の一番シンプルな例ってことで(笑)

Perl 使いの皆様へ。参考まで。
既にインストール済みの Eclipse に、後から Android Development Tools をインストールすると、どうも上手くいかんというか・・・

「ヘルプ」→「新規ソフトウェアのインストール」で「作業対象」に https://dl-ssl.google.com/android/eclipse/ を指定して入れたんだけど、俺が参考にしている記事だと、「ADT Plugin をインストールしたら、続けて(自動的に)Android SDK のインストールが始まる・・・と書いてあるんだけど、一向に始まらない。
ADT Plusgin のインストールが終わったら、Eclipse が再起動をするよう促してくるのに従うと、起動したとたん、Android の設定画面が開き、「SDK ロケーション」を指定するように怒られる。

いや、知らんがな。どっかに入ったの?パスなんかわからんて。

仕方ないので、Android SDK を手動インストール。

http://developer.android.com/sdk/index.html からファイルを落としてきて、解凍。

適当に、c:\usr\local\adt-bundle みたいなディレクトリを作って、そこに解凍したファイルを全部移動。
そしたら、C:\usr\local\adt-bundle\eclipse\eclipse.exe を実行してみよう。

ほれ、スプラッシュ画面がちょっと違うけど、Eclipse が起動したでしょ?

20130510_eclipse_splash.jpg
ちゃんと、メニューの下に 20130510_android_icon.jpg というアイコンが2つ追加された Eclipse がね。

どうしても既存の Eclipse にまとめたい人はアレだけど、Eclipse なんて複数インストールできるし同時に複数起動出来るので、開発言語、あるいはターゲットのプロダクト別に Eclipse を用意する方法でもいいと思うけどね。
そもそも俺の環境には、Aptana Studio とか Adobe Flash Builder とか、Eclipse ベースの開発環境が既に複数セットアップされているしな(笑)

このアーカイブについて

このページには、2013年5月以降に書かれたブログ記事のうちプログラミングカテゴリに属しているものが含まれています。

前のアーカイブはプログラミング: 2013年4月です。

次のアーカイブはプログラミング: 2013年7月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら