Android10相机拍摄保存照片并显示(解决各种闪退,添加v4包)
1. 测试条件:
1) Eclipse
Eclipse Java EE IDE for Web Developers.
Version: Photon Release (4.8.0)
Build id: 20180619-1200
2) ADT
23.0.7
3) SDK
Android 7, 9
4) build-tools
build-tools=25.0.2
2. 注意事项:
Android6.0开始需动态申请权限
Android7.0开始需使用FileProvider传递存储地址
//7.0之后你的app就算有权限,给出一个URI之后手机也认为你没有权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
3.添加V4包
ChoosePicTest下新建lib文件夹
SDK\extras\android\m2repository\com\android\support\support-v4\24.1.1\support-v4-24.1.1.aar\classes.jar复制到lib文件夹下,改为v4.jar
关闭工程,再打开这样在工程下lib下显示v4.jar,在v4.jar上右击,“Build Path”,“Add to build Path”,工程下出现“Referenced Libraries” “v4.jar”
查看工程的属性,v4.jar是否添加成功。
4. 测试机型:
在Android9、10手机上测试通过。
5. 详细代码
//MainActivity.java
package com.example.choosepictest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import android.support.v4.content.FileProvider;
import android.util.Log;
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
public static final int TAKE_PHOTO = 1;
public static final int CROP_PHOTO = 2;
public static final int TAKE_PHOTO2 = 3;
// 申请相机权限的requestCode
private static final String[] sPermissonVal = {Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static final int PERMISSION_CAMERA_REQUEST_CODE = 3;
private Button takePhoto;
private ImageView picture;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Android需加,不然使用intent打开相机,即使动态申请了相机权限,但还是会闪退
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
takePhoto = (Button) findViewById(R.id.take_photo);
picture = (ImageView) findViewById(R.id.picture);
takePhoto.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
requestPermission();
}
});
}
//申请权限
private void requestPermission() {
// Android6.0开始, 即当API大于等于 23 时,才动态申请权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.d(TAG,"requestPermission, Build.VERSION.SDK_INT = "+Build.VERSION.SDK_INT );
this.requestPermissions(sPermissonVal, PERMISSION_CAMERA_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Log.d(TAG,"onRequestPermissionsResult, requestCode = "+requestCode);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSION_CAMERA_REQUEST_CODE:
Log.d(TAG,"onRequestPermissionsResult, grantResults.length = " + grantResults.length);
Log.d(TAG,"just note, PackageManager.PERMISSION_GRANTED = " + PackageManager.PERMISSION_GRANTED);
//权限请求失败
if (grantResults.length == sPermissonVal.length) {
for (int i=0;i<grantResults.length;i++) {
Log.d(TAG,"onRequestPermissionsResult, result = "+grantResults[i]);
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
//用户已经拒绝过一次,再次弹出权限申请对话框需要给用户一个解释
if (this.shouldShowRequestPermissionRationale(sPermissonVal[i]) == false) {
//弹出对话框引导用户去设置
showDialog(); //手动进入App,单独设置权限管理设置,“拒绝”->"询问"
}else {
Toast.makeText(MainActivity.this, "请求权限被拒绝", Toast.LENGTH_LONG).show();
}
break;
}
}
//允许权限,有调起相机拍照。
for(int i=0;i<grantResults.length;i++) {
if(grantResults[i] != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG,"Permissions Fail, return");
return;
}
}
Log.d(TAG,"openCamera Now");
openCamera();
}else{
Log.d(TAG,"onRequestPermissionsResult 10");
Toast.makeText(MainActivity.this, "授权不完整", Toast.LENGTH_LONG).show();
}
break;
}
}
//弹出提示框
private void showDialog(){
@SuppressWarnings("unused")
AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage("相机需要相机和读写权限,修改成“询问”或者“允许”,是否去设置?")
.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
goToAppSetting();
}
})
.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setCancelable(false)
.show();
}
// 跳转到当前应用的设置界面
private void goToAppSetting(){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
private void openCamera() {
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.d(TAG,"openCamera 1");
// File outputImage = new File(Environment.getExternalStorageDirectory(),"output_image.jpg"); //存储根目录
File outputImage = new File(getExternalCacheDir(),"output_image.jpg"); //内部存储设备/Android/data/com.example.choosepictest/cache/output_image.jpg
try {
if(outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
Log.d(TAG,"openCamera createNewFile");
} catch(IOException e) {
Log.d(TAG,"openCamera e1");
e.printStackTrace();
}
//Android 7.0 FileProvider传入Uri对象
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
imageUri = FileProvider.getUriForFile(MainActivity.this,
"com.example.choosepictest.fileprovider",outputImage);
}else{
imageUri = Uri.fromFile(outputImage);
}
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent,TAKE_PHOTO); //TAKE_PHOTO 拍摄好之后直接保存, TAKE_PHOTO2 拍摄并裁剪后保存
}else {
Log.d(TAG,"openCamera cannot access Storage ");
}
}
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data) {
Log.d(TAG,"onActivityResult 1");
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case TAKE_PHOTO:
if(resultCode == RESULT_OK) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);
}catch(FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case TAKE_PHOTO2:
if(resultCode == RESULT_OK) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("scacle",true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent,CROP_PHOTO);
}
break;
case CROP_PHOTO:
if(resultCode == RESULT_OK) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);
}catch(FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
//project.properties
target=android-28
build-tools=25.0.2
//activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.choosepictest.MainActivity" >
<Button
android:id="@+id/take_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Photo" />
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</RelativeLayout>
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.choosepictest"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-sdk
android:minSdkVersion="23"
android:targetSdkVersion="24" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:authorities="com.example.choosepictest.fileprovider"
android:name="android.support.v4.content.FileProvider"
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文件夹,在xml下新建provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name = "output_image" path = ""/>
</paths>
本文地址:https://blog.csdn.net/lljss1980/article/details/107599492
上一篇: 穿山甲SDK的接入并实现开屏广告
下一篇: iOS-自定义cell