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

第10回ノートを別の画像で置き換える

前回はEvernoteに保存した画像をAndroid上で表示させてみました。今回は表示した画像をタップすることで、ノートを別の画像で置き換えられるようにしたいと思います。

まず、GridViewのアイテムをタップしたときの処理には、android.widget.AdapterView.OnItemClickListenerを実装する必要があります。

import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

public class HelloEDAM extends Activity implements OnItemClickListener {

そして、onCreateメソッドでGridViewに自分自身をリスナーとして追加します。

this.imgView = (GridView) findViewById(R.id.image_grid_view);
this.imgView.setNumColumns(4);
this.imgView.setOnItemClickListener(this);

OnItemClickListenerで実装しなければならないのは、onItemClickメソッドです。このメソッドがGridViewのアイテムをタップしたときに実際に呼び出されます。ここでは、"Select Image..."ボタンで選択した画像を使用して、タップした画像に対応したノートを更新します。

public void onItemClick(AdapterView> parent, View v, int position, long id) {
  if (getNoteStore() != null && this.filePath != null) {
    try {
      // 現在の位置のオブジェクトを取得
      ImageResource image = (ImageResource)parent.getItemAtPosition(position);
      Note note = getNoteStore().getNote(getAuthToken(), image.getNoteGuid(), 
          true, true, false, false);

      // 現在の画像をリソースから削除
      Iterator iter = note.getResourcesIterator();
      while (iter.hasNext()) {
        Resource resource = iter.next();
        if(resource.getGuid().equals(image.getGuid())) {
          iter.remove();
        }
      }

      // 選択した画像のリソースを設定
      InputStream in = new BufferedInputStream(new FileInputStream(this.filePath)); 
      FileData data = new FileData(EDAMUtil.hash(in), new File(this.filePath));
      in.close();
      Resource resource = new Resource();
      resource.setData(data);
      resource.setMime(this.mimeType);
      note.addToResources(resource);

      // ノートの更新
      String content = 
        NOTE_PREFIX + "

このノートは新しい画像で置き換えられました

" + "" + NOTE_SUFFIX; note.setContent(content); getNoteStore().updateNote(getAuthToken(), note); Toast.makeText(this, R.string.msg_image_saved, Toast.LENGTH_LONG).show(); } 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); } } }

ImageResource image = (ImageResource)parent.getItemAtPosition(position);で、タップした場所に対応するオブジェクトを取得します。ImageResourceは前回使用したBitmapの代わりに新しく用意したクラスですが、詳しくは後述します。ImageResourceに含まれるノートのGUIDを指定して、Evernoteからリソースを含んだノートを取得します。

ノートに含まれる画像を置き換えるために、まず現在の画像をノートのリソース内から探して削除します。リソースから削除をせずにノートの<en-media>だけ消してしまうと、ノートには表示されない画像を裏で保持することになってしまいますので気をつけてください。その後に選択した画像のリソースをノートに加えますが、コードはsaveImageメソッドと同様です。

ノートの更新には、updateNoteメソッドを用います。createNoteメソッドと使い方は同じですが、ノートが更新の対象となるGUIDを含んでいる必要があります。ここではノートのコンテンツを完全に新しくして置き換える形を取りましたが、以前のコンテンツのen-mediaを書き換えて画像だけを変更するというのでも良いでしょう。

タップの場所とノートやリソースのGUIDを紐づける

さて、前回は画像を表示させることだけを考えていたので、ImageAdapterにはBitmapを登録するようにしていました。しかし、更新するためにはタップされた場所とノートやリソースのGUIDが紐づいていないといけません。そのため、必要な情報を持つためのImageResourceというクラスを作成して、Bitmapの代わりにImageAdapterに登録するようにしました。以下のコードをImageResource.javaとして、src/com.evernote.android.sampleに置いてください。渡したリソースからノートのGUID、リソースのGUID、bitmapだけ取り出して持つようにしています。

package com.evernote.android.sample;

import com.evernote.edam.type.Data;
import com.evernote.edam.type.Resource;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class ImageResource {
  
  private String noteGuid;
  private String guid;
  private Bitmap bitmap;
   
  public ImageResource(Resource resource) {
    this.noteGuid = resource.getNoteGuid();
    this.guid = resource.getGuid();
    Data data = resource.getData();
    this.bitmap = BitmapFactory.decodeByteArray(data.getBody(), 0, data.getSize());
  }
  
  public String getNoteGuid() {
    return this.noteGuid;
  }
  
  public String getGuid() {
    return this.guid;
  }
  
  public Bitmap getBitmap() {
    return this.bitmap;
  }
}

また、ImageAdapterの中のBitmapを全てImageResourceに変更します。

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

  public ImageAdapter(Context c, ArrayList<ImageResource> imageList) {
    this.c = c;
    this.imageList = imageList;
  }

......
  
  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).getBitmap());
    return imageView;
  }
}

最後に、HelloEDAM.javaのshowImageメソッドでImageAdapterに画像を追加する部分を、以下のように簡略化します。データからBitmapの作成はImageResourceに任せるようにしました。

for (Resource resource : resources) {
  String mime = resource.getMime();
  for(mime.equals("image/png") || mime.equals("image/jpeg") ||
    mime.equals("image/gif") || mime.equals("image/bmp")) {
    ImageResource image = new ImageResource(resource);
    imageAdapter.add(image)
  }
}

これで完成です。"Show Images"で画像一覧を表示した後に、"Select Image..."で画像を選択してください。表示した画像をタップしてしばらくすると"Image saved to Evernote"というメッセージが表示されますので、サンドボックス上のデータを見てみましょう。以下のようにノートが変更されているはずです。もう一度"Show Image"を押して再取得するとAndroid側の表示も変更されます。今後の改良としてはEvernote側を変更すると同時にAndroid側の画像も更新するといったことが考えられます。

変更後の画像ノート
変更後の画像ノート

今回まで数回に渡って、モバイルアプリケーションの例としてAndroidからのEvernoteの操作について解説をしました。次回からはWebサービスの例として、Google App EngineからEvernote APIを使ってみたいと思います。

今回取り上げたサンプルコードはこちらからダウンロードできます。

ダウンロード後、Eclipse上でimportして、consumer_key、consumer_password、username、passwordを設定すれば動きます。

おすすめ記事

記事・ニュース一覧