○まずは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 件のコメント:
コメントを投稿