[公式]Evernote API徹底活用レシピ

第9回 保存した画像を取り出して表示させる

この記事を読むのに必要な時間:およそ 3 分

前回はEvernote APIのAndroid上で画像をEvernoteに保存するサンプルコードについて解説をしました.今度は保存した画像を取り出して,以下のように表示してみましょう。

完成画面のキャプチャ

完成画面のキャプチャ

まずUIの作成をします。res/layout/main.xmlの</LinearLayout>の前に,以下の2つの要素を追加します。Buttonは画像を取得して表示するためのshowImagesメソッドを呼ぶボタンで,GridViewが画像を表示する場所です。

<Button android:id="@+id/button1"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/label_show_button" 
     android:onClick="showImages" />
       
<GridView android:id="@+id/image_grid_view" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" />

ボタンに表示する文字列をres/values/strings.xmlに追加しておきます。

<string name="label_show_button">Show Images</string>

次にHelloEDAM.javaです。先程定義したGridViewのインスタンスを参照できるように,UI要素の変数定義にprivate GridView imgViewを追加します。

// 我々が更新するUI要素
private Button btnSave;
private Button btnShowImage;
private TextView msgArea;
private GridView imgView;

また,onCreateメソッドにimgViewの初期化を追加します。

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
    
  this.msgArea = (TextView)findViewById(R.id.message);
  this.btnSave = (Button) findViewById(R.id.save_button);
  this.btnSave.setEnabled(false);
  this.btnShowImage = (Button) findViewById(R.id.save_button);
  this.btnShowImage.setEnabled(false);
  this.imgView = (GridView) findViewById(R.id.image_grid_view);
  this.imgView.setNumColumns(4);
  setupApi();
}

画像を表示するshowImagesメソッドは以下の通りです。

public void showImages(View view) {
  if (getNoteStore() != null) {
    ImageAdapter imageAdapter = new ImageAdapter(this);
    this.imgView.setAdapter(imageAdapter);      

    try {
      // フィルタにマッチするノート一覧を取得する
      // 第2引数はフィルタの指定,第3引数はoffset, 第4引数は取得するノートの最大件数
      NoteList notes = getNoteStore().findNotes(getAuthToken(), new NoteFilter(), 0, 12);
      Iterator iter = notes.getNotesIterator();
      while(iter.hasNext()) {
        Note note = iter.next();
        if (note.getResources() == null){
          continue;
        }
        // findNotesで取得するノートにはリソースが含まれていないので個別
に取得しなおす
        // 第4引数がtrueだとリソースを含んだノートが取得できる
        // 第6引数はResourceAlternateData (位置情報など)の有無
        Note fullNote = getNoteStore().getNote(getAuthToken(), note.getGuid(), 
            true, true, false, false);
        List resources = fullNote.getResources();
        for (Resource resource : resources) {
          String mime = resource.getMime();
          if (mime.equals("image/png") || mime.equals("image/jpeg") ||
              mime.equals("image/gif") || mime.equals("image/bmp")) {
            Data data = resource.getData();
            Bitmap bitmap = BitmapFactory.decodeByteArray(data.getBody(), 0, data.getSize());
            imageAdapter.add(bitmap);
          }
        }
      }
    } catch (Throwable t) {
      Toast.makeText(this, R.string.err_fetching_notes, Toast.LENGTH_LONG).show();
      Log.e(TAG, getString(R.string.err_fetching_notes), t);
    }
  }
}

NodeList notes = getNoteStore().findNotes(...が一番重要なAPIです。このメソッドにフィルタを設定することで,フィルタにマッチしたノートのリストを取得することができます。例えばある文字列が含まれているノートを抽出とか,特定のタグが付いているノートだけ取得といったことができます。ここでは空のフィルタを設定することで,全ノートを対象としています。

findNotesメソッドで取得したノートにはリソースの情報が含まれていないため,リソースを使いたい場合はgetNoteメソッドで明示的に再取得する必要があります。再取得後に,リソースの中身が画像かどうかをMIMEで判断します。画像だった場合はバイト列からBitmapに変換した後,ImageAdapterに追加します。

ImageAdapterはGridViewで画像を扱うために用意したアダプタです。src/com.evernote.android.sampleの下にImageView.javaというファイルを作成して,以下のコードを置きます。

package com.evernote.android.sample;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
  
  private Context c;
  private ArrayList imageList;
  
  public ImageAdapter(Context c) {
    this(c, new ArrayList());
  }

  public ImageAdapter(Context c, ArrayList imageList) {
    this.c = c;
    this.imageList = imageList;
  }
  
  public void add(Bitmap bitmap) {
    this.imageList.add(bitmap);
  }

  @Override
  public int getCount() {
    return this.imageList.size();
  }

  @Override
  public Object getItem(int position) {
    return this.imageList.get(position);
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;
    
    if (convertView == null) {
      imageView = new ImageView(c);
      imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
      imageView.setPadding(8, 8, 8, 8);
    } else {
      imageView = (ImageView) convertView;
    }
    
    imageView.setImageBitmap(this.imageList.get(position));
    return imageView;
  }

}

実行すると"Show Images"ボタンが追加されているはずです。ボタンを押してしばらくすると,サンプルコードで保存した画像が表示されます。これでAndroid上でのEvernote APIによるノート作成と読み込みができるようになりました。次回も引き続き拡張をしていきます。

著者プロフィール

加藤文彦(かとうふみひろ)

国立情報学研究所新領域融合研究センター特任研究員。普段はWebの研究に従事しており,Web上のデータを型付リンクで繋いでいくLinked Dataがトレンドになると信じて日々活動している。LinkedData.jp主宰。

twitter:fumi1

URL:http://fumi.me

コメント

  • Re: getNote()をノート分呼び出して効率は悪いのではないでしょうか?

    kinopyo様

    ご指摘ありがとうございます.
    仰るとおりfullNoteを取得する前にresourcesの有無を
    確認するほうが正しいと思います.
    確認方法はnullか,あるいはsizeですね.

    Note note = iter.next();
    if (note.getResources() == null){
    continue;
    }
    かあるいは
    if (note.getResourcesSize() < 1){
    continue;
    }

    Commented : #2  加藤 (2011/07/24, 17:35)

  • getNote()をノート分呼び出して効率は悪いのではないでしょうか?

    NoteList notes = getNoteStore().findNotes(getAuthToken(), new NoteFilter(), 0, 12);

    でノートリストを取得し、リソースが含めているかを判断するために個々のノートのGUIDでgetNote()のAPIを呼びだしていますが、それは膨大なAPIコールになりませんか?

    取得したノートリストでresourcesプロパティがnullかどうかをチェックすればいいと思いますが、いかがでしょうか?

    Commented : #1  kinopyo (2011/07/21, 15:36)

コメントの記入