欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Android10相机拍摄保存照片并显示(解决各种闪退,添加v4包)

程序员文章站 2022-12-02 15:43:13
1. 测试条件:1) EclipseEclipse Java EE IDE for Web Developers.Version: Photon Release (4.8.0)Build id: 20180619-12002) ADT23.0.73) SDKAndroid 7, 94) build-toolsbuild-tools=25.0.22. 注意事项:Android6.0开始需动态申请权限Android7.0开始需使用FileProvider传递存储地址//7.0之后你的...

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是否添加成功。
Android10相机拍摄保存照片并显示(解决各种闪退,添加v4包)

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

相关标签: Android