はじめに

このチュートリアルでは、 シンプルなオーディオフィンガープリント技術搭載のAndroidアプリを一から構築する方法を説明します。オーディオフィンガープリント技術は、小さなオーディオサンプルを生成し識別のためにそれをGracenoteに送信します。 AndroidデバイスからグレースノートのメタデータにアクセスするためにMobile Clientは多数の方法を提供しておりそれらのほとんどはSDKのサンプルアプリケーションで実証されています。
SDKを使用することは実はとてもシンプルなのですが、ベテランのAndroid開発者の方でもない限り、サンプルアプリの深さを見てしまうと難しいと思ってしまうかもしれません。

開発環境の設定

はじめに、開発環境がセットアップされていることを確認して下さい。少し面倒でトリッキーかもしれませんが、Getting Started GuideのSet Up Your Android Development Environmentに従って進めていけば大丈夫です。 デバッグ作業では実際のデバイスを使用したほうが、エミュレータを使用するよりも簡単です。いずれにせよ、Getting Started Guide をすべてフォローする価値はあります。そしてサンプルアプリを実行し問題なく動いていることを確認して下さい。

プロジェクトの作成

環境を設定したら、次のステップは新しいAndroidのアプリケーションプロジェクトを作成することです。(File > New > Project > Android > Android Application Project) デフォルト設定で問題ないはずです。私はBlankActivityで開始することを選びました。忘れる前に、必要なライブラリを追加してみましょう。 SDKのlibsディレクトリに移動します。armeabiディレクトリとGN_Music_SDK.jarを選択し、パッケージ·エクスプローラー内部のlibsディレクトリ(下の画像の赤い矢印を参照)にドラッグします。ダイアログボックスで、"ファイルとフォルダをコピーする"を選択します。

Androidのマニフェストファイルの変更

インターネットにアクセスし、デバイスにオーディオを録音するには、メインプロジェクトディレクトリの下にあるAndroidManifest.xml ファイルを更新する必要があります。(下のスクリーンショットの青い矢印を参照)<manifest>タグ内のどこでもいいので次のコードを追加します。

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

UIの作成

次に、それぞれ1つのTextViewとボタン要素で構成される非常にシンプルなUIを設定します。たったそれだけです。"Hello World" と表示されたデフォルトTextViewを削除し、一番上の"フォームのウィジェット"メニューから大きいTextViewをドラッグしました。メインレイアウトのXMLページでは、TextViewの内容を編集することができます。フィンガープリントのルックアップ後に楽曲のメタデータを記述するところに、"song_info" としてIDを変更しました。デフォルトのテキストも変更しました。

<TextView
    android:id="@+id/song_info"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="40dp"
    android:text="Song Info"
    android:textAppearance="?android:attr/textAppearanceLarge"/>

同じように、フィンガープリントを開始するボタンを作成しました。 それを "fp_button" と名付け、テキストを "Fingerprint!"と設定します。

<Button
    android:id="@+id/fp_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="130dp"
    android:text="Fingerprint!" />

下の図で、最終的なレイアウトを確認できます。

アプリケーションのコーディング

実際にコーディングをしてみましょう。MainActivity.javaファイルを開きます。私のファイルはsrc/com.example.demo2/にあります。また、プロジェクト名を "demo2" としていない限り、あなたのファイルは別のディレクトリにあるはずです。一般的に、Eclipseはどのファイルをインポートすべきか探し出すのに非常に便利です。コードに新しいクラスを追加すると、IDEはエラーの箇所をアンダーラインで知らせ、クラスを解決するためのimportを提案します。作業をシンプルに保つために、私はあらかじめ次のクラスをインポートしておきます。

import com.gracenote.mmid.MobileSDK.GNOperations;
import com.gracenote.mmid.MobileSDK.GNSearchResponse;
import com.gracenote.mmid.MobileSDK.GNSearchResult;
import com.gracenote.mmid.MobileSDK.GNSearchResultReady;
import com.gracenote.mmid.MobileSDK.GNConfig;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

アプリのロジックは極めてシンプルです。

  1. ボタンが押されると、関数が呼び出されマイクを通して音楽を録音する。
  2. 楽曲を識別するためにGracenoteデータベースで検索。
  3. 一致するものが見つかった場合、アーティスト名、曲のタイトルが表示される。

幸いなことに、SDKはフィンガープリントをルックアップするシンプルな関数呼び出し - GNOperations.recognizeMIDStreamFromMic - を持ちます。 先ほど、ルックアップをトリガしレスポンス処理するGNConfigオブジェクト(GNOperation)ために必要)の設定でおわっていました。これをするには、MainActivity クラスは3つのメンバ変数を必要とします。

private GNConfig config;
private TextView song_info;
private Button fp_button;

onCreate関数の中で、GNConfigオブジェクトを初期化します。

config = GNConfig.init("NNNNNNN-NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN",this.getApplicationContext());

注意: Nの部分は、アカウントプロファイルの "マイアプリ" ページで確認できるあなたのクライアントIDと置き換えて下さい。

GNConfigオブジェクトのほかに、すべてのGNOperation 機能は操作が終了したときに呼び出される関数の結果を必要とします。すでにConfigオブジェクトを初期化したので、今度はGNSearchResultReady インタフェースを実装するクラスを作成する必要があります。そのためには、RecognizeFromMicと名付けた新しいクラスは、関数GNResultReadyを実装する必要があります。GNResultReadyに加えて、doFingerprintという関数を作成しました。それは単純にGNOperations.recognizeMIDStreamFromMicを呼び出します。

class RecognizeFromMic implements GNSearchResultReady {
    void doFingerprint(
        GNOperations.recognizeMIDStreamFromMic(this,config);
    }
    public void GNResultReady(GNSearchResult result) {
        song_info = (TextView) findViewById(R.id.song_info);
        if (result.isFingerprintSearchNoMatchStatus()) {
            song_info.setText("no match");
        } else {
            GNSearchResponse response = result.getBestResponse();
            song_info.setText(response.getTrackTitle() + " by " + response.getArtist());
        }
    }
}

一致するものが返された場合にGNResultReadyが機能します。そうでない場合は、"no match"とsong_info TextViewに記述します。ルックアップが一致するものを返した場合、song_info TextViewに最適な応答としてのアーティスト名と曲名を表示します。

結果コールバック関数が定義され、 フィンガープリントルックアップはボタンクリックに結びつけられました。onCreate関数では、fp_buttonを初期化します。

fp_button = (Button) findViewById(R.id.fp_button);

そして、RecognizeFromMicオブジェクトを作成するためにリスナーを設定し、ボタンが押されたときdoFingerprintを呼ぶことにします。

fp_button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        RecognizeFromMic task = new RecognizeFromMic();
        task.doFingerprint();
    }
});

最後に

このアプリはそれを取得するのと同じくらい簡単です。SDKにはその他にも探求すべき機能がたくさんあります。APIを介してアクセスすることができるメタデータの種類、テキストやファイルで検索する方法については、SDKに同梱されているドキュメントやデモアプリをチェックしてみて下さい。Happy hacking!

リファレンス

あなたの最終的なMainActivity.javaファイルは次のようになります。

package com.example.demo2;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

import com.gracenote.mmid.MobileSDK.GNOperations;
import com.gracenote.mmid.MobileSDK.GNSearchResponse;
import com.gracenote.mmid.MobileSDK.GNSearchResult;
import com.gracenote.mmid.MobileSDK.GNSearchResultReady;
import com.gracenote.mmid.MobileSDK.GNConfig;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

	private GNConfig config;
	private TextView song_info;
	private Button fp_button;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        config = GNConfig.init("NNNNNNN-NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN",this.getApplicationContext());
        fp_button = (Button) findViewById(R.id.fp_button);
        fp_button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                RecognizeFromMic task = new RecognizeFromMic();
                task.doFingerprint();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    class RecognizeFromMic implements GNSearchResultReady {
        void doFingerprint(){
            GNOperations.recognizeMIDStreamFromMic(this,config);
        }
        public void GNResultReady(GNSearchResult result) {
            song_info = (TextView) findViewById(R.id.song_info);
            if (result.isFingerprintSearchNoMatchStatus()) {
                song_info.setText("no match");
            } else {
                GNSearchResponse response = result.getBestResponse();
                song_info.setText(response.getTrackTitle() + " by " + response.getArtist());
            }
        }
    }
}