2013/02/09 このエントリーをはてなブックマークに追加 はてなブックマーク - 【Android】Intentでメールに画像を添付する(Intent to attach images to email)

【Android】Intentでメールに画像を添付する(Intent to attach images to email)






○まずはIntentを試してみるか





自分で作ってるAndroidアプリのバージョンアップとして、
検索した画像と情報をメールに添付しようと考えた。

これが地味にハマってしまったので、自分と誰かしらのために、メモしておく。


文章は割と楽に送れた。
実装はこんな感じ。



        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        // TOアドレス
        intent.setData(Uri.parse("mailto:hoge@hage.com"));
       
        // 宛先を指定
        intent.putExtra(Intent.EXTRA_EMAIL, "FROM");
        // CCを指定
        intent.putExtra(Intent.EXTRA_CC, "CC");
        // BCCを指定
        intent.putExtra(Intent.EXTRA_BCC, "bcc");
        // 件名を指定
        intent.putExtra(Intent.EXTRA_SUBJECT, "件名");
        // 本文を指定
        intent.putExtra(Intent.EXTRA_TEXT, "本文");
        // 画像を添付
        intent.setType("image/jpeg");
        File file = this.getFilesDir();
        intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("ファイルの絶対パス"));
        try {
            startActivityForResult(intent, 0);
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(this, "client not found", Toast.LENGTH_LONG).show();
        }



intent.startActivity(Intent.createChooser(intent, null))を使って、アプリケーションを選ばせるのも手。







○画像の添付はどうやるの?






ただ、画像がなかなかうまくいかない。
出来るなら、端末に画像を保存せずに添付できないものかと思ったけど、
どうやら出来ないらしい。
ファイルとして保存したデータしか引数として渡せないようだ。

一度Bitmapデータを保存する必要がある。

ということでBitmapの保存処理。

実装はこんな感じ。





  /**
     * ImageViewをファイルとして格納する。
     *
     */
    public void savePicture(ImageView view, String fileName) throws IOException {

        // ImageViewをビットマップにキャスト
        BitmapDrawable bd = (BitmapDrawable) view.getDrawable();
        // getBitmapメソッドでビットマップファイルを取り出す。
        Bitmap data = bd.getBitmap();
        FileOutputStream output = openFileOutput(fileName, Context.MODE_WORLD_READABLE);
        data.compress(Bitmap.CompressFormat.PNG, 100, output);
        
    }

保存はどうやらうまく出来たようだ。DDMSで見ても確かにファイルは存在している。
エミュレータでは画像添付成功。




意気揚々と自分の端末でも確認してみる。
が、しかし画像添付に失敗する。なんでよ。








○画像の添付はSDから?






色々、ネットで調べあさった結果、
画像データをSDカードに保存しないと添付できない仕様らしい(おそらく権限の問題?)

ということで、今度はパスを変えてSDの保存しよう。





    /**
     *
     * 画像を端末のsdに保存します。<br>
     * @param fileName String
     * @param view ImageView
     * @param context Context
     */
    public void savePicture(String fileName, ImageView view, Context context) throws IOException {

        // ImageViewをビットマップにキャスト
        BitmapDrawable bd = (BitmapDrawable) view.getDrawable();
        // getBitmapメソッドでビットマップファイルを取り出す。
        Bitmap data = bd.getBitmap();
        // 画像データがなかったらnullを返す
        if (data == null) {
            return null;
        }
        // SDカードのパス取得
        File root = Environment.getExternalStorageDirectory();
        FileOutputStream out = null;

        // 画像をバイト配列に変換する
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        data.compress(CompressFormat.JPEG, 100, os);
        os.flush();
        byte[] w = os.toByteArray();
        os.close();

        // バイト配列をファイルとしてSDカードに書き出す
        out = new FileOutputStream(root + File.separator + "AppName" + File.separator + fileName);
        out.write(w, 0, w.length);
        out.flush();

    }

しかし、例外発生。なんでなんで?










○SDのパスって端末依存なの?









しばらく悩む
またしても、色々調べた結果、端末によってはSDパスの取得の仕方が違うらしい。
実装で、SDのパスの分岐をする。
こんな感じ。





    public void savePicture(String fileName, ImageView view, Context context) throws IOException {

        // (略)
      
      // 端末メーカによってパスが異なることがあるらしい
        File standard = Environment.getExternalStorageDirectory();
        File sd = new File(standard, "sd");
        File ext = new File(standard, "external_sd");
        String fileFullPath = "";
        if (sd.exists() && sd.isDirectory()) {
            fileFullPath = sd + File.separator + "AppName" + File.separator + fileName;
        } else if (ext.exists() && ext.isDirectory()) {
            fileFullPath = ext + File.separator + "AppName" + File.separator + fileName;
        } else {
            fileFullPath = standard + File.separator + "AppName" + File.separator + fileName;
        }

  
        // (略)
    
    }


でもできない。。。なぜ。。。












○エミュレーターの設定?






なんか、エミュレータが怪しいぞ・・・。
eclipseから 「ウィンドウ>AVD Manager>編集」 で
「ハードウェア」のプロパティを確認したら、
「SD card support yes」になってない!アウチ!
あと、「SDカード」のところの「サイズ」も設定しないと駄目だからな!!!(自戒)








これで、余裕っしょ、フゥー♪



、と思いきや、まだ例外出るじゃないですか・・。











○肝心なこと忘れてました







あ、SD使用のパーミッションが無かった。。。。

マニフェストに記入

    <!-- SDカード仕様許可 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />





うし、パーミッションは取れたみたい。だけど例外が発生するなぁ。




あ、もしかして。。。。








○ディレクトリ作ってないじゃん








    public void savePicture(String fileName, ImageView view, Context context) throws IOException {

        // ImageViewをビットマップにキャスト
        BitmapDrawable bd = (BitmapDrawable) view.getDrawable();
        // getBitmapメソッドでビットマップファイルを取り出す。
        Bitmap data = bd.getBitmap();

        // 画像データがなかったらnullを返す
        if (data == null) {
            return null;
        }
        // 端末メーカによってパスが異なることがあるらしい
        File standard = Environment.getExternalStorageDirectory();
        File sd = new File(standard, "sd");
        File ext = new File(standard, "external_sd");
        String fileFullPath = "";
        if (sd.exists() && sd.isDirectory()) {
            fileFullPath = sd + File.separator + "TourPlus" + File.separator + fileName;
        } else if (ext.exists() && ext.isDirectory()) {
            fileFullPath = ext + File.separator + "TourPlus" + File.separator + fileName;
        } else {
            fileFullPath = standard + File.separator + "TourPlus" + File.separator + fileName;
        }

        // アプリ用にディレクトリを作る
        new File(fileFullPath).getParentFile().mkdir();
        FileOutputStream out = null;
        // 画像をバイト配列に変換する
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        data.compress(CompressFormat.JPEG, 100, os);
        os.flush();
        byte[] w = os.toByteArray();
        os.close();

        // バイト配列をファイルとしてSDカードに書き出す
        out = new FileOutputStream(fileFullPath);
        out.write(w, 0, w.length);
        out.flush();

    }


やっとこさ成功。









○まとめ



以上です。今後のために簡単なチェックシートを一応作った。





  • マニフェストにパーミッションは設定しているか。
  • DDMSで確認して画像は保存されているか
  • SDのパスは正しいか
  • エミュレータは正しく設定されているか
  • 保存先の絶対パスは存在するディレクトリか
  • Intentの起動メソッドは適格か




※なお、基本的にI/Oというかストリーム的なものを使うときは、当然finallyでclose処理しないと駄目です。
このエントリではソースを簡潔にするため、はしょっています(言い訳)



0 件のコメント:

コメントを投稿