何を達成したいですか?キャプチャした画像の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>
_
data
のonActivityReuslt
がnullであったため、上記のメソッドは機能しませんでした。
それで、私の目標を達成するために私は何をする必要がありますか?
以下の手順に従ってください。
ステップ-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;
}
}
カメラインテントを呼び出している間
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();
}
}
これはすべてのバージョンで機能します。私もそれをテストしました。