web-dev-qa-db-ja.com

キャプチャした写真のURIを取得するにはどうすればよいですか?

何を達成したいですか?キャプチャした画像のURIを取得してFirebaseに保存したいと思います。私は何を試しましたか?まず、カメラを開く必要がありました。私がそれをした方法の下で:

_ Intent cameraIntent = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null)
        startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
_

画像をキャプチャした後、画像のURIを取得する必要がありました。私がそれをした方法の下で:

_if (resultCode == Activity.RESULT_OK) {
        if (requestCode == CAMERA_REQUEST_CODE) {
            if (data != null) {
                if (data.getData() != null) {
                   Uri capturedImageUri = data.getData(); 
                } else {
                    Toast.makeText(getContext(), getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(getContext(), getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
            }
_

だからすべてが大丈夫だった。ただし、一部のデバイスでのみ。 21台以上のAPIレベルでのみ動作すると思います。他のデバイスでは、getData()はnullを返します。

それで、私は次に何をしましたか?次のコードで画像のビットマップを取得できることがわかりました。

_Bitmap bitmap = (Bitmap)data.getExtras().get("data") ; 
_

だから、私は画像のビットマップを持っています。そして、この画像のURIを取得する必要がありました。私がそれをした方法の下で:

_public Uri getImageUri(Context inContext, Bitmap inImage) {
  String path = 
  Images.Media.insertImage(inContext.getContentResolver(), inImage, 
  "Title", null);
  return Uri.parse(path);
 } 
_

上記のコードはURIを返しますが、画像の品質が非常に悪いです。

それで、私は解決策を探し続けました。そして、正しい方法は、CameraActivityを起動したときにファイルを作成し、そのファイルのURIを保存することであることがわかりました。そしてonActivityResult私はそのuriを取得しようとしました。私がそれをした方法の下で:

_Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {

        }
        if (photoFile != null) {
            Uri photoUri = FileProvider.getUriForFile(getContext(), "i_dont_know_what_to_write_here", photoFile);
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
        }

    }
_

そして私のonActivityResultは次のようになりました:

_    if (resultCode == Activity.RESULT_OK) {
    if (requestCode == CAMERA_REQUEST_CODE) {
        if (data != null) {
 Uri capturedPhotoUri = 
 data.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
   } else {
   Toast.makeText(getContext(), 
   getString(R.string.coudldnt_get_photo), Toast.LENGTH_SHORT).show();
            }
_

上記の概念では、マニフェストにいくつかのタグを追加する必要があります。

_ <provider
        Android:name="Android.support.v4.content.FileProvider"
        Android:authorities="i_dont_know_what_to_write_here"
        Android:exported="false"
        Android:grantUriPermissions="true">
        <meta-data
            Android:name="Android.support.FILE_PROVIDER_PATHS"
            Android:resource="@xml/my_paths" />
        </provider>
_

私のxmlファイルは:

_<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="images"/>
</paths>
_

dataonActivityReusltがnullであったため、上記のメソッドは機能しませんでした。

それで、私の目標を達成するために私は何をする必要がありますか?

5
neo

以下の手順に従ってください。

ステップ-1:res/xmlフォルダーにprovider_paths.xmlを作成し、その中に以下のコードを記述します。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path
        name="external_files"
        path="." />
</paths>

ステップ-2:マニフェストでプロバイダーを以下のように宣言します。

       <provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="${applicationId}.provider"
            Android:exported="false"
            Android:grantUriPermissions="true">
            <meta-data
                Android:name="Android.support.FILE_PROVIDER_PATHS"
                Android:resource="@xml/provider_paths" />
        </provider>

ステップ-3:カメラの意図を以下のように記述します。

    Intent m_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File file = new File(Environment.getExternalStorageDirectory(), "MyPhoto.jpg");
    Uri uri = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);
    m_intent.putExtra(Android.provider.MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(m_intent, REQUEST_CAMERA_IMAGE);

ステップ-4:カメラの結果をonActivityResultで以下のように処理します。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {

        //TODO... onCamera Picker Result
        case REQUEST_CAMERA_IMAGE:
            if (resultCode == RESULT_OK) {

              //File object of camera image
                File file = new File(Environment.getExternalStorageDirectory(), "MyPhoto.jpg");

              //Uri of camera image
                Uri uri = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);

            }
            break;
    }
}
11

カメラインテントを呼び出している間

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);


 File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "IMG_FOLDER");

        try {
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    return null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        imageURI = Uri.fromFile(new File(mediaStorageDir.getPath() + File.separator +
                "profile_img.jpg"));
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageURI);

        startActivityForResult(intent, Utils.CAMERA_REQUEST);

OnActivityResultの内部

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        try {
            if (resultCode == RESULT_OK) {
                if (requestCode == Utils.CAMERA_REQUEST) {
                    if (imageURI != null) {             // use the same uri, that you initialized while calling camera intent
                     // do whatever you want to do with this Uri
                 }
                }
            }
         } catch(Exception E) {}  
  }

ヌガーの場合、スプラッシュ/ランチャーアクティビティに以下のコードを追加する必要があります

if (Build.VERSION.SDK_INT >= 24) {
        try {
            Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
            m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

これはすべてのバージョンで機能します。私もそれをテストしました。

4
Akshay Barodia