読者です 読者をやめる 読者になる 読者になる
スポンサーリンク

たった50行のソースコードで,「関数電卓」のAndroidアプリを作成する方法

java shortcoding 小ネタ javascript Android ブックマークレット


「Hello, World」のAndroidアプリが作れるなら,「関数電卓」のプログラムを今すぐリリースできる。

実装に必要なソースコードは,たった50行。

計算画面のキャプチャ(関数計算として,2の10乗を計算しようとしている):

結果画面のキャプチャ(計算結果が正しく表示された):


ほかに,sin, cos, logなど自由に利用可能。


このアプリを実装するための50行のソースコードを,以下に掲載する。

※ちなみに,Hello, Worldを動かすまでの手順は下記URLを参照。

今から1時間で,Androidアプリの開発環境を構築し,Windows上でサンプルを動作させる手順
http://language-and-engineering.hatenablog.jp/entry/20110724/p1

関数電卓のソースコード


「Hello, World」プロジェクト内の,適当なアクティビティの内容を書き換える。

package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.*;
import android.widget.*;
// 関数電卓を表示するアクティビティ
public class AndroidHelloWorldActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 縦レイアウトを動的に作成
    final LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    setContentView(layout);
    // 数式の入力欄を作成
    final EditText editText = new EditText(this);
    editText.setText("1+1");
    layout.addView(editText);
    // 計算実行ボタンを作成
    Button button = new Button(this);
    button.setText("計算実行");
    layout.addView(button);
    // 計算実行ボタンにベントをセット
    final Activity this_activity = this;
    button.setOnClickListener(new OnClickListener(){
      public void onClick(View v) {
        final String eval_text = editText.getText().toString();
        final WebView wv = new WebView(this_activity);
        this_activity.setContentView(wv);
        wv.getSettings().setJavaScriptEnabled(true);
        // ページの表示終了イベント発生時に,計算結果を表示
        wv.setWebViewClient(new WebViewClient() {
          @Override
          public void onPageFinished(WebView view, String url)
          {
            // ブックマークレットのJSとして評価
            wv.loadUrl( "javascript:(function() { " +
              "document.getElementsByTagName('body')[0].innerHTML = (" +
              eval_text + "); })()" );
          }
        });
        // 仮のページを開く
        wv.loadUrl("http://code.google.com/android");
      }
    });
  }
}

これで49行。

あとは,AndroidManifest.xml 中のmanifestタグ内に,以下の 1 行を書き加える。

コーディングは,合計50行になる。


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


これで終了。Androidの関数電卓アプリが完成。

ツッコミどころ

ツッコミどころは多いが,,


一応,初めは javax.script.ScriptEngine を使って,
ちゃんとまっとうに Java のコードで eval() する予定だった。

(静的型付け言語のJavaでeval()しようとしている時点でまっとうではないが・・・)

JavaからJavaScriptを呼び出すサンプル
http://blog.goo.ne.jp/hiuchida/e/b8bd...
JDK6よりJavaスクリプトAPIが追加されました(JavaScript APIではない)。
JSR-223に準拠していればjavax.scriptにあるスクリプトAPIを使ってどんなスクリプト言語でも実行できるはずですが、今のところJavaScriptの実装(Rhinoをベースにしたもの)しかないようです。

上記URLのコードは,JDK6で正常に動作した。


ところが,いざこのコードをAndroidアプリ中で動かそうとしたら,
必要なライブラリをインポートできない。

Android SDKはJDK5がベースなので,まだscriptingに非対応なのだ。

Issue with javax.script
http://www.coderanch.com/t/512996/jav...

  • I'm working in Eclipse for Android, and initially I was unable to even import javax.script.
  • So this is an Android app? Android is based on Java 1.5 - which does not support javax.script.


Is it possible to reference the javax.script.ScriptEngine library when developing an android application? If not is there anyway possible to evaluate a javascript expression in android?
http://stackoverflow.com/questions/14...

  • javax.script.ScriptEngine is not a default part of android


代替案として,WebViewコンポーネントを経由して,ブックマークレット形式でJavaScript文字列をeval(実行)する方法が紹介されていた。

is it possible to send a javascript string to an invisible WebView and have it evaluate the string
http://stackoverflow.com/questions/18...

  • Yes, via addJavascriptInterface() and sending the browser a javascript: URL, akin to a bookmarklet.


Injecting JavaScript into a WebView
http://lexandera.com/2009/01/injectin...

  • “How can I manipulate the contents of a WebView?”
  • very simple: wait for the original page to finish loading, then inject your own JavaScript code into it by calling webview.loadUrl(“javascript:your-code-here”) when your webvew’s onPageFinished() event is triggered.
  • alert() and confirm() JavaScript functions will not work

なお,WebViewコンポーネントはインターネット接続するので,Manifest.xml中に宣言が必要。

今日のAndroid - WebViewを使ってみるCommentsAdd Star
http://d.hatena.ne.jp/emergent/200902...

  • Androidアプリでインターネット接続するためには、作成する前にすることがある
  • 解決方法は、AndroidManifest.xmlにpermissionの一文を入れること


そういうわけで,Androidアプリ上でユーザが打ち込んだ任意の数式は,
WebViewコンポーネントに渡され,Webkitによって計算される。


数式を打ち込む際には,下記のページを参考にできる。

Mathオブジェクト / JavaScriptリファレンス
http://www.scollabo.com/banban/java/r...


なお,構文解析をしておらず,数式のパース失敗時の動作保証も何もないので,
これは「遊び」レベルのアプリと言える。
(利用は自己責任で)


しかし,構文解析などの高度なロジックを組むことなく,
簡単に関数計算アプリが作れてしまう,という点は面白い。


実際,任意の関数計算機能をユーザに提供する,という目的は果たせているのだし。

(HTMLとJavaScriptだけで済むじゃないかという声が聞こえてきそうだが・・・)


補足

もし,まともに(ただの)電卓アプリを実装したい場合,下記のURLが参考になるだろう。

しかし,おそろしく手間がかかる。

サンプルアプリでおぼえる実践的Android入門
http://codezine.jp/article/detail/5957

  • 四則演算だけができる「MyCalc」というアプリのサンプルコード
  • 設計としては,状態遷移図をちゃんと描く
  • デザインパターンのStateとSingletonを駆使して,数百行規模の実装


AndroidでリフレクションとJavaCCを試す(後編)
http://labs.s-cubism.com/blog/2009/07...

  • Javaで「数式のコンパイラ」を実装し,そのコンパイラに数式を解釈させる方法
  • Javaの「コンパイラコンパイラ」として,JavaCCを活用している

関連する記事:

たった2ファイルで,HTML+JS製のネイティブAndroidアプリを作る手順 (動作するサンプルコード付き。WebViewの活用方法)
http://language-and-engineering.hatenablog.jp/entry/20120710/CreateAndroidApp...


AndroidやiOSの「ハイブリッドアプリ」で,JavaScriptとネイティブ・コードが連携する仕組みを図解 (おまけ:HTML側で施すべき,クロスプラットフォーム対策)
http://language-and-engineering.hatenablog.jp/entry/20120713/p1


jQuery Mobile と HTML5 で、Androidのネイティブアプリを作成する手順
http://language-and-engineering.hatenablog.jp/entry/20120717/CreateAndroidNat...