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