LoginSignup
24
24

More than 5 years have passed since last update.

写真を共有するとき

Last updated at Posted at 2014-01-01

2014/01/04 1:47追記
全然違いました。PicPlayなど確かにWRITE権限/READ権限の有無で挙動が違うアプリもあるようなので、Intentの指定部分はこれだけでもいいですが、Seesmicは以下のコードだけではダメなようです(なぜか以前は上手くいったと思っていた)。

実際はというと、SeesmicはIntent.EXTRA_STREAMで「file://」なURLを送ることには対応していないようです。必ず「content://」なURLで渡す必要があります(この動作は望ましいものなのかどうかはわかりませんが。脆弱性対策的な意味でもあるのかな?)。

そんなわけで、MediaStoreに登録済みの画像であれば、その「content://」なURLを取得して渡すようにしましょう というのが正解です(Android標準のGalleryアプリもこのような挙動なので、さすがにこれで不具合を起こすようなアプリはないものと思われます というか、思いたい)。

Fileから、「content://」のURIを取得するには、以下のようにします。

MediaStoreに登録されていない画像である場合
  File file = /* 適当なFile(外部ストレージ上に保存している画像であること) */
  ContentResolver cr = context.getContentResolver();
  ContentValues cv = new ContentValues();
  cv.put(MediaStore.Images.Media.TITLE, file.getName());
  cv.put(MediaStore.Images.Media.DISPLAY_NAME, file.getName());
  cv.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
  cv.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
  cv.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
  Uri uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
MediaStoreに登録済みの画像である場合
  File file = /* 適当なFile(外部ストレージ上に保存している画像であること) */
  ContentResolver cr = context.getContentResolver();

  Cursor c = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { BaseColumns._ID },
      MediaStore.Images.ImageColumns.DATA + " LIKE ?",
      new String[] { Uri.fromFile(file).getPath() }, null);
  c.moveToFirst();
  long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
  c.close();
  Uri uri = Uri.withAppendedPath(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Long.toString(id));

ここで取得したuriをIntent.EXTRA_STREAMの値に設定することで、Seesmicでも読み取れる方法で写真を共有することが出来ます。

以下、原文

Androidで写真を別アプリに共有させたいときは、大体の場合次のように書くと思います

通常の場合
  File file = /* 送信したいファイルを指定 */
  Intent intent = new Intent(Intent.ACTION_SEND);
  intent.setType("image/jpeg");
  intent.setClassName(/*起動したいアプリのパッケージ名*/, /*起動したいアクティビティのクラス名*/);
  intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
  try {
    startActivityForResult(intent, REQUEST_SEND);
  } catch (ActivityNotFoundException e) {
    Toast.makeText(getActivity(), アプリケーションの起動に失敗しました, Toast.LENGTH_SHORT).show();
  }

こんな感じでも大体大丈夫なのですが、一部のアプリはこのインテントでは画像を処理してくれなかったり、共有先のアプリが正常に動作しないことがあるようです(Seesmic Ver1.8.13、PicPlay Pro Ver3.5.1で確認)。

結論から言うと、FLAG_GRANT_READ_URI_PERMISSIONやFLAG_GRANT_WRITE_URI_PERMISSIONが設定された画像でないと、上手く動作しないアプリがあるようです。
なので、とりあえずこういう風に指定したら良い。

改善案
  File file = /* 送信したいファイルを指定 */
  Intent intent = new Intent(Intent.ACTION_SEND);
  intent.setType("image/jpeg");
  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); /* 追加 */
  intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); /* 追加 */
  intent.setClassName(/*起動したいアプリのパッケージ名*/, /*起動したいアクティビティのクラス名*/);
  intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
  try {
    startActivityForResult(intent, REQUEST_SEND);
  } catch (ActivityNotFoundException e) {
    Toast.makeText(getActivity(), アプリケーションの起動に失敗しました, Toast.LENGTH_SHORT).show();
  }

本当はIntent#setClipData()も使うといいらしいのですが、そのへんはよくわからなかったのでひとまずこのまま。
インテントについてはまだよく理解できてないところもありそうですが、ひとまずこれでちゃんとアプリが起動できます。

24
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
24