我正在使用意图启动相机:
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getParent().startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
并使用:
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
photoImage.setImageBitmap(thumbnail);
photoImage.setVisibility(View.VISIBLE);
但它只是一个缩略图,我如何获得完整的位图?我知道我可以使用自己的Activity并使用:
Camera.PictureCallback()
但是无论如何使用Intent做到了吗?
谢谢!
编辑:
我也尝试过:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
imageView.setImageURI(uri);
}
适用于从图库中选择的照片,但对于相机意图,data.getData()返回null。
答案 0 :(得分:101)
要获得全尺寸的相机图像,您应该将相机指向临时文件中保存图片,例如:
private URI mImageUri;
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
File photo;
try
{
// place where to store camera taken picture
photo = this.createTemporaryFile("picture", ".jpg");
photo.delete();
}
catch(Exception e)
{
Log.v(TAG, "Can't create file to take picture!");
Toast.makeText(activity, "Please check SD card! Image shot is impossible!", 10000);
return false;
}
mImageUri = Uri.fromFile(photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
//start camera intent
activity.startActivityForResult(this, intent, MenuShootImage);
private File createTemporaryFile(String part, String ext) throws Exception
{
File tempDir= Environment.getExternalStorageDirectory();
tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
if(!tempDir.exists())
{
tempDir.mkdirs();
}
return File.createTempFile(part, ext, tempDir);
}
然后在图像捕获意图完成后 - 只需使用以下代码从imageUri
抓取您的照片:
public void grabImage(ImageView imageView)
{
this.getContentResolver().notifyChange(mImageUri, null);
ContentResolver cr = this.getContentResolver();
Bitmap bitmap;
try
{
bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, mImageUri);
imageView.setImageBitmap(bitmap);
}
catch (Exception e)
{
Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Failed to load", e);
}
}
//called after camera intent finished
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
//MenuShootImage is user defined menu option to shoot image
if(requestCode==MenuShootImage && resultCode==RESULT_OK)
{
ImageView imageView;
//... some code to inflate/create/find appropriate ImageView to place grabbed image
this.grabImage(imageView);
}
super.onActivityResult(requestCode, resultCode, intent);
}
PS 代码需要针对Android M中应用的新安全限制进行修订 - FileProvider:mImageUri
必须打包FileProvider
答案 1 :(得分:34)
打开相机并将图像保存到某个特定目录
private String pictureImagePath = "";
private void openBackCamera() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = timeStamp + ".jpg";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
File file = new File(pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, 1);
}
处理图片
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
File imgFile = new File(pictureImagePath);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
}
}
}
答案 2 :(得分:6)
即使这是一个古老的问题而且它有一个可接受的答案, 我想分享我的解决方案 在这种情况下,您不必创建临时文件 此外,我们创建一个选择器,为用户提供:使用相机拍照或从图库中选择现有照片。
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent chooser = new Intent(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.chooseaction));
Intent[] intentArray = {cameraIntent};
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooser, RESULT_LOAD_IMAGE);
在这里我们检索结果:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// todo use appropriate resultCode in your case
if (requestCode == RESULT_LOAD_IMAGE && resultCode == FragmentActivity.RESULT_OK) {
if (data.getData() != null) {
// this case will occur in case of picking image from the Gallery,
// but not when taking picture with a camera
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
// do whatever you want with the Bitmap ....
} catch (IOException e) {
e.printStackTrace();
}
} else {
// this case will occur when taking a picture with a camera
Bitmap bitmap = null;
Cursor cursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.ImageColumns.ORIENTATION}, MediaStore.Images.Media.DATE_ADDED,
null, "date_added DESC");
if (cursor != null && cursor.moveToFirst()) {
Uri uri = Uri.parse(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)));
String photoPath = uri.toString();
cursor.close();
if (photoPath != null) {
bitmap = BitmapFactory.decodeFile(photoPath);
}
}
if (bitmap == null) {
// for safety reasons you can
// use thumbnail if not retrieved full sized image
bitmap = (Bitmap) data.getExtras().get("data");
}
// do whatever you want with the Bitmap ....
}
super.onActivityResult(requestCode, resultCode, data);
}
}
答案 3 :(得分:2)
我也使用了Vicky的答案,但是我必须将uri保存到一个包中以避免在方向改变时丢失它。因此,如果您在倾斜设备后没有从您的意图中获得结果,那可能是因为您的uri无法在方向更改后继续存在。
static final int CAMERA_CAPTURE_REQUEST = 1;
static final String ARG_CURRENT_PIC_URI = "CURRENT_PIC_URI";
String pictureImagePath = folderName + "/" + imageFileName;
File file = new File(Environment.getExternalStorageDirectory(), pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);
mCurrentPicUri = outputFileUri.getPath();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, CAMERA_CAPTURE_REQUEST);
活动结果代码:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_CAPTURE_REQUEST && resultCode == Activity.RESULT_OK)
{
File imgFile = new File(mCurrentPicUri);
// do something with your image
// delete uri
mCurrentPicUri = "";
}
}
将uri保存到捆绑包中:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save uri to bundle
outState.putString(ARG_CURRENT_PIC_URI, mCurrentPicUri);
}
在创建时从保存的包中检索它:
if (bundle.containsKey(ARG_CURRENT_PIC_URI))
mCurrentPicUri = bundle.getString(ARG_CURRENT_PIC_URI);
答案 4 :(得分:0)
要从相机捕捉最大图片尺寸,我希望这些简单的步骤非常有用
s = ["j.smith@google.com-20170927.txt", "a.cooper@google.com-20170925.txt", "s.king@google.com-20170926.txt"]
for name, filename in [i.split('-') for i in s]:
new_file_data = ["ID NAME:"+name[:name.index("@")]+"\n" if i.startswith("ID NAME:") else "MAIL:mailto:"+name + "\n" if i.startswith("MAIL") else i for i in open(name+filename)]
final_file = open(name+filename, 'w')
for line in new_file_data:
final_file.write(line)
final_file.close()
此处,每个移动设备支持的尺寸,从最大尺寸固定为图片尺寸到捕捉。
答案 5 :(得分:0)
请勿使用onActivityResult
的数据。我花了很多时间来测试不同的解决方案。相机保存图片(即使您未在AndroidManifest中设置相机和读卡的权限),但onActivityResult
返回data == null
并且MediaStore
返回错误的路径。在这些解决方案中,您只需获取最后一个图库图片,而不是您的照片。
private Uri photoUri;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
...
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_RESULT) {
if (resultCode == RESULT_OK) {
if (photoUri != null) {
image.setImageURI(photoUri);
}
}
}
}
private void showCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
photoUri = null;
if (file != null) {
photoUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, CAMERA_REQUEST);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(timeStamp, ".jpg", storageDir);
}
答案 6 :(得分:0)
API级别29
我尝试了接受的答案,但是API级别29中已弃用了接受的答案中使用的Environment.getExternalStorageDirectory()
和随后的答案中使用的Environment.getExternalStoragePublicDirectory()
。 API级别29中不推荐使用的第三个答案。以下代码(在Kotlin中)将完整图像存储在this stackoverflow answer中的MediaStore.Images.Media.DATA
中,用于另一个问题,并且不依赖于MediaStore
:
FileProvider
答案 7 :(得分:0)
好的,是时候还钱了。 所以你有 Mainfest 的权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
你也有你的提供者元数据
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
一个遗漏的细节是 (android:authorities applicationId) 你需要添加你自己的应用程序包名称。
所以你在 xml
文件夹下有 res
文件,正如我们在 manifest
上提到的,在它下面你用 ;
file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="my_images"
path="Pictures" />
</paths>
我们完成了复制粘贴第 1 部分。现在在我们上面的活动中onCreate(savedInstanceState: Bundle?)
定义这些美女
val REQUEST_IMAGE_CAPTURE = 1
lateinit var currentPhotoPath: String
var cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
你可能想看看原始资源,但像往常一样缺少细节 Android 开发者:link
另一个缺少的细节是 packageName + ".fileprovider",
如果您有方法,请注意您需要提供自己的包名称。
// org android developers
private fun dispatchTakePictureIntent() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
// Ensure that there's a camera activity to handle the intent
takePictureIntent.resolveActivity(packageManager)?.also {
// Create the File where the photo should go
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
ex.message
null
}
// Continue only if the File was successfully created
photoFile?.also {
val photoURI: Uri = FileProvider.getUriForFile(
this,
packageName + ".fileprovider",
it
)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
}
createImageFile
函数
// org android developers
@Throws(IOException::class)
private fun createImageFile(): File {
// Create an image file name
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val storageDir: File = this!!.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
return File.createTempFile(
"JPEG_${timeStamp}_", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
).apply {
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = absolutePath
}
}
测试。
使用 onClick 事件调用您的 dispatchTakePictureIntent()
方法,确保允许权限
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
var mBitmap_org = MediaStore.Images.Media.getBitmap(
this.getContentResolver(),
//Uri.parse(currentPhotoPath)
Uri.fromFile(File(currentPhotoPath))
);
//mImg_display?.setImageBitmap(mBitmap_org)
}
}
不要检查数据,我们将通过 imagePath 获取它。如果您正在检查 Uri.parse(currentPhotoPath)
,请确保它是 Uri.fromFile(File(currentPhotoPath))
现在你有了你的位图,有时间花其他时间/天如何调整解码大小,保存。
还有一种保存tokken图像的方法,如果我需要tokken图像保存在图库中,也许你可以帮我看看我应该把它放在哪里
// org android developers
private fun galleryAddPic() {
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
val f = File(currentPhotoPath)
mediaScanIntent.data = Uri.fromFile(f)
sendBroadcast(mediaScanIntent)
}
}