Android : 如何在 android 牛轧糖中写入相机意图
Android : How to write camera intent in android nougat
在我的 android 应用程序中,我必须在单击按钮时使用相机拍摄图像。它在除 Android 7 (Nougat) 之外的所有 Android 版本中都运行良好。当我选择相机选项时,即使授予了权限,应用程序也会退出。我认为问题出在调用相机的 Intent 中。下面是我的代码。
camera = (ImageView) dialog.findViewById(R.id.camera);
camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCamera();
dialog.dismiss();
}
});
private void clickCamera() { // 1 for icon and 2 for attachment
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.CAMERA }, MY_REQUEST_CODE);
} else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, MY_REQUEST_CODE_STORAGE);
} else {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA); // 1 for REQUEST_CAMERA (icon) and 2 for REQUEST_CAMERA_ATT (attachment)
}
}
}
private static Uri getImageFileUri(){
// Create a storage directory for the images
// To be safe(r), you should check that the SD card is mounted
// using Environment.getExternalStorageState() before doing this
imagePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyProject");
if (!imagePath.exists()) {
if (!imagePath.mkdirs()) {
return null;
} else {
// create new folder
}
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File image = new File(imagePath, "MyProject_" + timeStamp + ".jpg");
if (!image.exists()) {
try {
image.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// Create an File Uri
return Uri.fromFile(image);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, MY_REQUEST_CODE_STORAGE);
} else {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Doesn't have permission... ", Toast.LENGTH_SHORT).show();
}
return;
}
case MY_REQUEST_CODE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Doesn't have permission...", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
牛轧糖的问题是什么?是因为getImageFileUri()
返回的Uri
吗?
你好,请关注作为参考。它将向您展示如何使用 File Provider 当您将 targetSDK 设置为 24 并更改以下内容时。在您的 private static Uri getImageFileUri()
方法中
更改此行
return Uri.fromFile(image);
到
FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", createImageFile());
希望这能帮助您解决问题。
更多信息请访问 -
Setting Up File Sharing - Offical documentation
使用 File Provider 它会帮助你
尝试这不是制造问题的意图,一旦您拍照并保存到 SD 卡并取回牛轧糖中的 uri 不同....
在您的应用程序上实现 FileProvider 非常容易。首先,您需要在 AndroidManifest.xml 标签下添加一个 FileProvider 标签,如下所示:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<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>
</application>
</manifest>
然后在res文件夹下的xml文件夹中创建一个provider_paths.xml文件。如果文件夹不存在,可能需要创建。
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>
完成! FileProvider 现已声明并可以使用。
最后一步是更改下面 MainActivity.java
中的代码行
Uri photoURI = Uri.fromFile(createImageFile());
到
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());
然后....完成!您的应用程序现在应该可以在任何 Android 版本(包括 Android Nougat)上完美运行。干杯!
此处修复了您在 7.0 版本中的相机意图问题,
file:// 不再允许(Android N)以 Intent 附加,否则它将
抛出 FileUriExposedException 这可能会导致您的应用程序立即调用崩溃。
请检查问题和解决方案的完整细节。
好吧,Android 的工作就是让开发人员在每次更新时都活得像地狱:)
google 员工,这里是针对使用过 Android 文档中示例的开发人员的分步指南;
1-在你用过的部分
Uri.fromFile(image)
您需要使用此代码段:
Uri photoURI = FileProvider.getUriForFile(mContext,
"com.sample.test.fileprovider",
image);
当然不用说了,你要把com.sample.test
改成你的包名
2- 现在您需要在 AndroidManifest.xml 中声明您的提供商,在应用程序标签下,粘贴此标签:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.sample.test.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
3- 注意 android:resource="@xml/file_paths"
你需要在 res/xml/
文件夹下创建一个同名 file_paths
的 xml 文件并将其放入其中:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="pictures"/>
</paths>
在网络上的其他几个片段和文档本身,它说你需要写这个
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
而不是我们的,它实际上取决于您的代码,如果您使用 Environment.getExternalStorageDirectory().getPath()
创建您的文件,则不需要它,但如果您完全按照文档进行操作,则需要坚持使用文档
在我的 android 应用程序中,我必须在单击按钮时使用相机拍摄图像。它在除 Android 7 (Nougat) 之外的所有 Android 版本中都运行良好。当我选择相机选项时,即使授予了权限,应用程序也会退出。我认为问题出在调用相机的 Intent 中。下面是我的代码。
camera = (ImageView) dialog.findViewById(R.id.camera);
camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCamera();
dialog.dismiss();
}
});
private void clickCamera() { // 1 for icon and 2 for attachment
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.CAMERA }, MY_REQUEST_CODE);
} else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, MY_REQUEST_CODE_STORAGE);
} else {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA); // 1 for REQUEST_CAMERA (icon) and 2 for REQUEST_CAMERA_ATT (attachment)
}
}
}
private static Uri getImageFileUri(){
// Create a storage directory for the images
// To be safe(r), you should check that the SD card is mounted
// using Environment.getExternalStorageState() before doing this
imagePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyProject");
if (!imagePath.exists()) {
if (!imagePath.mkdirs()) {
return null;
} else {
// create new folder
}
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File image = new File(imagePath, "MyProject_" + timeStamp + ".jpg");
if (!image.exists()) {
try {
image.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// Create an File Uri
return Uri.fromFile(image);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, MY_REQUEST_CODE_STORAGE);
} else {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Doesn't have permission... ", Toast.LENGTH_SHORT).show();
}
return;
}
case MY_REQUEST_CODE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
currentImageUri = getImageFileUri();
Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
// start the image capture Intent
startActivityForResult(intentPicture, REQUEST_CAMERA);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Doesn't have permission...", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
牛轧糖的问题是什么?是因为getImageFileUri()
返回的Uri
吗?
你好,请关注private static Uri getImageFileUri()
方法中
更改此行
return Uri.fromFile(image);
到
FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", createImageFile());
希望这能帮助您解决问题。
更多信息请访问 -
Setting Up File Sharing - Offical documentation
使用 File Provider 它会帮助你
尝试这不是制造问题的意图,一旦您拍照并保存到 SD 卡并取回牛轧糖中的 uri 不同....
在您的应用程序上实现 FileProvider 非常容易。首先,您需要在 AndroidManifest.xml 标签下添加一个 FileProvider 标签,如下所示:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<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>
</application>
</manifest>
然后在res文件夹下的xml文件夹中创建一个provider_paths.xml文件。如果文件夹不存在,可能需要创建。
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>
完成! FileProvider 现已声明并可以使用。
最后一步是更改下面 MainActivity.java
中的代码行Uri photoURI = Uri.fromFile(createImageFile());
到
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());
然后....完成!您的应用程序现在应该可以在任何 Android 版本(包括 Android Nougat)上完美运行。干杯!
此处修复了您在 7.0 版本中的相机意图问题,
file:// 不再允许(Android N)以 Intent 附加,否则它将 抛出 FileUriExposedException 这可能会导致您的应用程序立即调用崩溃。
请检查问题和解决方案的完整细节。
好吧,Android 的工作就是让开发人员在每次更新时都活得像地狱:)
google 员工,这里是针对使用过 Android 文档中示例的开发人员的分步指南;
1-在你用过的部分
Uri.fromFile(image)
您需要使用此代码段:
Uri photoURI = FileProvider.getUriForFile(mContext,
"com.sample.test.fileprovider",
image);
当然不用说了,你要把com.sample.test
改成你的包名
2- 现在您需要在 AndroidManifest.xml 中声明您的提供商,在应用程序标签下,粘贴此标签:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.sample.test.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
3- 注意 android:resource="@xml/file_paths"
你需要在 res/xml/
文件夹下创建一个同名 file_paths
的 xml 文件并将其放入其中:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="pictures"/>
</paths>
在网络上的其他几个片段和文档本身,它说你需要写这个
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
而不是我们的,它实际上取决于您的代码,如果您使用 Environment.getExternalStorageDirectory().getPath()
创建您的文件,则不需要它,但如果您完全按照文档进行操作,则需要坚持使用文档