はじめに
第2回目の本稿は、「docomo Developer support」で公開されているAPIをアプリから実行する方法を解説しましょう(本稿は、2014年11月18日時点の最新情報に基づいております)。
対象読者
JavaとEclipseを用いたAndroidアプリの開発で、基本的な知識がある方を対象とします。
APIの組み込み方
前回は、APIコンソールを使ってAPIの機能を試してみましたが、今回は、実際のアプリからAPIを呼び出してみましょう。
APIを呼び出す方法
公開されているAPIのほとんどは、Web API形式に対応しています。Web APIとは、HTTPでの通信を利用してデータをやり取りする道具です。HTTP通信なら、一般的なWebサイトへアクセスするのと同等なので、多くの環境からAPIを実行することができます。Androidアプリに限らず、iOSでも、Windowsのアプリケーションでも可能です。
SDKを利用する
Javaで開発するAndroidアプリでも、標準のライブラリを使って、HTTP通信を行うことができます。HTTP通信のプログラムは、ある程度、決まった手順になっていますので、APIを呼び出す処理は、難しい実装ではありません。
ただ、通信処理は煩雑になりがちですので、「docomo Developer support」では、APIごとにSDKも提供されています。SDKは、APIに対応したJavaのクラスライブラリとなっており、通信処理などを意識することなく、単にクラスのメソッドを実行するだけで、APIを呼び出せるようになっています。つまり、SDKを利用すれば、より手軽にAPIを処理できるというわけです。
なおAPIにもよりますが、現状SDKには、Android環境に特化したもの、より汎用的にJavaに対応したもの、iOSに対応したもの、の3種類が用意されています。
アプリ/APIの申請
前回解説したとおり、APIをアプリから利用するためには、まずは開発用APIキーの取得が必要です。
APIキーの取得には、「docomo Developer support」にログインして、マイページを開き、「新規アプリケーション申請へ」というボタンをクリックします。すると、アプリ/APIの申請ページになるので、ここで、必要事項を入力します。
入力必須項目は、アプリケーション名、アプリケーション概要、サービス予定日、アプリケーションタイプ(Webアプリかネイティブアプリかどうか)、コールバックURL(必要ないならhttps://dummy)、提供者名、サポートメールアドレスです。
商用でない限り、特に厳密に入力する必要はありません。またアプリの審査中でなければ、後から変更することもできます。
必須項目を入力したら、「API機能選択へ」というボタンをクリックします。API機能選択ページに遷移しますので、ここで必要なAPIを選択します。
今回は、画像認識APIを使いますので、画像認識にチェックして、一番下のボタンをクリックしましょう。確認ページに移りますので、ここで「利用申請する」というボタンをクリックすれば申請が完了です。
APIキーは、マイページの「アプリ/APIの申請・管理」ページにある、アプリケーション情報に表示されます。
画像認識APIを利用するには
では次に、実際のアプリで画像認識APIのSDKを利用してみましょう。
画像認識API
画像認識APIは、公開されたばかりの最新APIで、画像に写っている物を認識、解析して、その名称などの情報を取得することができます。
認識できるものは、書籍やDVD、CD、PCソフト、ゲームソフト、食品パッケージといった商品です。現在、500万件以上の市販品情報が登録されていて、その名称や関連情報のWebページURL、認識の確からしさを表すスコアなども取得可能です。
画像認識では、3つのAPIが利用できます。
API名 | 処理内容 |
---|---|
画像認識 | 画像に写る商品を認識し、名称を含む商品情報を返却する。 |
認識結果の候補全体に対するフィードバック | 画像認識の結果一覧が妥当だったか否かをフィードバックする。 |
認識結果の各候補に対するフィードバック | 画像認識の個々の結果が妥当だったか否かをフィードバックする。 |
なお認識できる画像ファイルは、JPEG、PNG、GIF、BMP、TIFF形式で、サイズの上限は10MBです。推奨画像サイズは、VGA(640×480)相当ということですが、スマートフォンで撮影した画像程度なら、そのまま処理できるようです。
SDK
画像認識APIのSDKは、APIのページからダウンロードすることができます。
提供されているファイル(執筆時点では、Image_Recognition_SDK_for_Android_v1.0.0.zip)には、ライブラリ本体に、サンプルアプリ、利用ガイドなどが含まれています。
利用ガイド(画像認識SDK for Android利用ガイド_v1.0.0.pdf)には、SDKの使い方が詳しく載っていますので、実際のAPI利用の際には、併せて参考にしてください。
ライブラリについて
SDKで提供されるライブラリファイルは、次のようなファイルで構成されています。
ファイル名 | ライブラリ概要 |
---|---|
docomo-common-android-sdk-1.0.1.jar | docomo SDK共通ライブラリ |
docomo-imagerecognition-android-sdk-1.0.0.jar | 画像認識ライブラリ |
jackson-annotations-2.2.3.jar | Jacksonライブラリ |
jackson-core-2.2.3.jar | 〃 |
jackson-databind-2.2.3.jar | 〃 |
画像認識API用の他に、JSONデータを扱うためのオープンソースライブラリである、Jacksonライブラリが含まれています。
サンプルアプリ
SDKには、サンプルアプリも含まれています。まずは、このサンプルをビルドしてみましょう。サンプルアプリは、Eclipseのプロジェクトとして提供されています。SDKのsampleフォルダにzipファイルがありますので、解凍して、Eclipseにインポートします。
プロジェクトのlibsフォルダには、前述のライブラリファイルが含まれています。プロジェクトからSDKのライブラリを使うには、このように、libsフォルダにコピーするだけです。
APIキーの設定とAPIの実行手順
このアプリを実行するには、先ほど取得したAPIキーの設定が必要です。APIキーは、プロジェクトのRecognitionActivity.javaにある、RecognitionActivityクラスのフィールドに設定します。
// API キー static final String APIKEY = "";
画像認識APIには3つの処理がありますが、いずれも同様のコードで実行することができます。メインとなる画像認識は、次のようなコードで情報を取得できます。resultDataに、結果のJSONデータが格納されていますので、必要に応じて、そのデータから情報を抽出します。
// 画像認識クラスを作成する ImageRecognition recognize = new ImageRecognition(); // 画像認識リクエストデータクラスを用いてパラメータを設定する ImageRecognitionRequestParam requestParam = new ImageRecognitionRequestParam(); requestParam.setRecog(Recog.ALL); requestParam.setFilePath(画像ファイル名); // 画像認識クラスにリクエストデータを渡し、レスポンスデータを取得する ImageRecognitionResultData resultData = recognize.request(requestParam);
画像認識APIとカメラ機能を連携する
サンプルアプリは、画像のパス名を入力し、画像認識のボタンをタップすると、APIを実行して商品情報を表示します。また、その結果が妥当だったかどうかを、フィードバック(報告)することもできます。
今回は、このサンプルを少し改造してみましょう。Androidのカメラ機能や画像ギャラリーと連携するようにして、すぐに画像認識を試せるようにしてみます。
AndroidManifest.xmlへの追加
撮影したカメラ画像を保存するために、マニフェストファイルのPermission属性に、INTERNET、READ_EXTERNAL_STORAGEと共に、保存用のWRITE_EXTERNAL_STORAGEを追加します。
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
RecognitionActivity.javaの変更
次に、RecognitionActivity.javaを変更します。最初に、カメラで撮影した画像ファイルのURI用に、RecognitionActivityクラスのフィールドを追加します。
private Uri bitmapUri; // 画像ファイルのURI
そして、pushExecButtonメソッドを変更し、onActivityResultメソッドのオーバーライドを追加します。元のpushExecButtonメソッドでは、APIを実行するようになっていますが、これをカメラ撮影と画像ギャラリーと連携する処理に変更します。また、onActivityResultメソッドでは、撮影した画像または画像ギャラリーの画像ファイルのURIを用いて、APIを実行するようにします。
@SuppressLint("NewApi") private void pushExecButton() { // ギャラリー選択のIntent(1) Intent intent = new Intent(); // APIレベル19(Kit)以降と区別する(2) intent.setAction((Build.VERSION.SDK_INT < 19) ? Intent.ACTION_GET_CONTENT: Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); // カメラ撮影して保存する画像ファイル名を設定しておく(3) File mediaFile = new File( Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM), System.currentTimeMillis() + ".jpg"); bitmapUri = Uri.fromFile(mediaFile); // カメラ撮影のIntent(4) Intent intent_camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent_camera.putExtra(MediaStore.EXTRA_OUTPUT, bitmapUri); // ギャラリー選択でcreateChooserし、カメラ撮影のIntentを追加する(5) Intent chooserIntent = Intent.createChooser(intent, "画像の選択"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { intent_camera }); startActivityForResult(chooserIntent, 1); } @SuppressLint("NewApi") @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if (resultCode == RESULT_OK) { String path = bitmapUri.getPath(); // カメラ画像のパス名 if (data != null) { // カメラ画像でない場合は、画像ギャラリーから取得する(6) if (!data.getData().getPath().equals(bitmapUri.getPath())) { // APIレベル19(Kit)以降と区別する(7) Cursor cursor; if (Build.VERSION.SDK_INT < 19) { String[] columns = { MediaColumns.DATA }; cursor = getContentResolver().query(data.getData(), columns, null, null, null); } else { String id = DocumentsContract.getDocumentId( data.getData()); String selection = "_id=?"; String[] selectionArgs = new String[]{id.split(":")[1]}; cursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaColumns.DATA}, selection, selectionArgs, null); } if (cursor.moveToFirst()) { path = cursor.getString(0); } } } // 画像のパス名を表示する EditText editText = (EditText)findViewById(R.id.edit_path); editText.setText(path); AlertDialog.Builder dlg = new AlertDialog.Builder(this); // パラメータを設定する ImageRecognitionRequestParam requestParam = new ImageRecognitionRequestParam(); requestParam.setRecog(Recog.ALL); // 画像のパスを設定する requestParam.setFilePath(path); // 実行 task = new RecognitionAsyncTask(dlg); task.execute(requestParam); } } }
この変更でのポイントは、次の3点です。
- カメラ機能と画像ギャラリーの連携に、intent機能を使う
- intentで呼び出した処理の戻り値を、onActivityResultで処理する
- KitKat以降では、画像ギャラリーの扱いが異なる
Androidでは、カメラ機能を直接操作することもできますが、標準のカメラアプリを使う方がかんたんです。ここでは、カメラアプリと画像ギャラリーを呼び出すために、intent機能を使っています(コメント行の(1)、(4))。また、Intent.createChooserを使って、カメラアプリと画像ギャラリーの両方に対応したintentを発行しています(5)。
intentで呼び出した処理(Activity)の戻り値は、onActivityResultメソッドをオーバーライドすることで処理することができます。onActivityResultメソッドの3つめの引数に、intentの戻り値(画像ファイルのURI)が格納されています。
ただし、カメラ画像では、この値がNULLとなる機種がほとんどです。そのため、これがNULLか、あるいは設定したURI(3)と同じであれば、カメラ画像、そうでなければ、画像ギャラリーのURIと判断しています(6)。
Android 4.4(KitKat、APIレベル19)から、Storage Access Frameworkという機能が搭載され、画像ギャラリーから戻される画像URIが変更されました。そのため、Build.VERSION.SDK_INTで、実行している機種のAPIレベルを調べ、レベルに応じて処理を変更しています(2、7)。
実行してみよう
変更したアプリを起動し、「画像認識要求実行」をボタンをタップすると、カメラ撮影か、ギャラリーかを選択できるダイアログが表示されるようになります。
カメラで撮影するか、ギャラリーの画像を選択すると、元の画面に戻ります。しばらくすると画像が認識され、次のような表示になります。身近にある商品なら、たいてい認識できるのではないでしょうか。
最後に
今回は、APIの呼び出し方と、画像認識APIを例にしてSDKの使い方を解説しました。次回も、提供されているSDKを利用して楽しいAndroidアプリを作ってみます。
docomo Developer supportではアプリケーション・アプリケーションアイデアを対象としたコンテストを開催しています。応募要項や募集期間などの詳細はサイトにてご確認ください。
なお、ドコモはdocomo Developer supportからAPI提供を検討される企業様を募集しており、オープンイノベーションを加速する良質で実績の高いAPIの提供プラットフォームを目指しております。詳細は上記サイトに随時掲載していきます。