教材:第一行代码(第2版)
新建项目CameraAlbumTest
调用摄像头拍照
//activity_main.xml<?xml version=\"1.0\" encoding=\"utf-8\"?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"android:orientation=\"vertical\"android:layout_width=\"match_parent\"android:layout_height=\"match_parent\">//打开摄像头<Buttonandroid:id=\"@+id/take_photo\"android:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"android:text=\"Take Photo\"/>//将拍到的图片显示出来<ImageViewandroid:id=\"@+id/picture\"android:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:layout_gravity=\"center_horizontal\"/></LinearLayout>
//MainActivitypublic class MainActivity extends AppCompatActivity {private static final int TAKE_PHOTO = 1;private ImageView picture;private Uri imageUri;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button takePhoto = (Button) findViewById(R.id.take_photo);picture = (ImageView) findViewById(R.id.picture);takePhoto.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {// 创建File对象,用于存储拍照后的图片// 将图片命名为output_image.jpg,并将它存放在手机SD卡的应用关联缓存目录下// getExternalCacheDir()可以得到这个目录File outputImage = new File(getExternalCacheDir(),\"output_image.jpg\");try {if (outputImage.exists()){outputImage.delete();}outputImage.createNewFile();}catch (IOException e){e.printStackTrace();}// 进行一个判断// 如果运行设备的系统版本低于Android 7.0,就调用Uri的fromFile()方法将File对象转换成Uri对象// 这个Uri对象标识着output_image.jpg这张图片的本地真实路径// 否则,就调用FileProvider的getUriForFile()方法将File对象转换成一个封装过的Uri对象// getUriForFile()方法接收 3个参数,第一个参数要求传入Context对象,第二个参数可以是任意唯一的字符串,第三个参数则是我们刚刚创建的File对象// 之所以要进行这样一层转换,是因为从Android 7.0系统开始,直接使用本地真实路径的Uri被认为是不安全的,会抛出一个FileUriExposedException 异常// 而FileProvider则是-种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性if (Build.VERSION.SDK_INT >= 24){imageUri = FileProvider.getUriForFile(MainActivity.this, \"com.example.cameraalbumtest.fileprovider\", outputImage);}else{imageUri = Uri.fromFile(outputImage);}//启用相机程序Intent intent = new Intent(\"android.media.action.IMAGE_CAPTURE\");intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(intent, TAKE_PHOTO);}});}//报错 Overriding method should call super.onActivityResult//不影响结果@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent 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;default:break;}}}
//在res目录下新建文件夹xml//在xml下进行操作New→File//命名为file_paths.xml<?xml version=\"1.0\" encoding=\"utf-8\"?><paths xmlns:android=\"http://schemas.android.com/apk/res/android\"><external-path //指定Uri共享name=\"my_images\" //自定义path=\"\" /> //path为空时表示将整个SD卡进行共享,这里会报错,不影响结果</paths>
//AndroidManifest.xml<?xml version=\"1.0\" encoding=\"utf-8\"?><manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"package=\"com.example.cameraalbumtest\">//声明访问SD卡的权限<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" /><application......//对内容提供器进行注册<providerandroid:name=\"androidx.core.content.FileProvider\"android:authorities=\"com.example.cameraalbumtest.fileprovider\"android:exported=\"false\"android:grantUriPermissions=\"true\"><meta-dataandroid:name=\"android.support.FILE_PROVIDER_PATHS\"android:resource=\"@xml/file_paths\" /></provider></application></manifest>
从相册中选择照片
//在activity_main.xml中添加代码//注意:这个按钮控件在上两个控件之间<Buttonandroid:id=\"@+id/choose_from_album\"android:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"android:text=\"Choose From Album\"/>
//MainActivity//添加代码public class MainActivity extends AppCompatActivity {......public static final int CHOOSE_PHOTO = 2;@Overrideprotected void onCreate(Bundle savedInstanceState) {......Button chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);//相机按钮takePhoto.setOnClickListener(new View.OnClickListener() {......});//照片按钮chooseFromAlbum.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//动态申请读取SD卡权限if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE},1);}else{openAlbum();}}});}private void openAlbum(){Intent intent = new Intent(\"android.intent.action.GET_CONTENT\");intent.setType(\"image/*\");startActivityForResult(intent,CHOOSE_PHOTO); //打开相册}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){switch (requestCode){case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){openAlbum();}else{Toast.makeText(this,\"You denied the permission\", Toast.LENGTH_SHORT).show();}break;default:}}//Overriding method should call super.onActivityResult@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data){switch (requestCode){case TAKE_PHOTO:......case CHOOSE_PHOTO:if (resultCode == RESULT_OK){//判断手机系统版本号if (Build.VERSION.SDK_INT >= 19){//4.4及以上系统使用这个方法处理图片handleImageOnKitKat(data);}else{handleImageBeforeKitKat(data);}}......}}@TargetApi(19)private void handleImageOnKitKat(Intent data){String imagePath = null;Uri uri = data.getData();if(DocumentsContract.isDocumentUri(this,uri)){/*如果是document类型的Uri,则通过document id处理*/String docId = DocumentsContract.getDocumentId(uri);if(\"com.android.providers.media.documents\".equals(uri.getAuthority())){String id = docId.split(\":\")[1]; //解析出数字格式的idString selection = MediaStore.Images.Media._ID + \"=\" + id;imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);}else if(\"com.android.providers.downloads.documents\".equals(uri.getAuthority())){Uri contentUri = ContentUris.withAppendedId(Uri.parse(\"content://downloads/public_downloads\"),Long.valueOf(docId));imagePath = getImagePath(contentUri,null);}}else if(\"content\".equalsIgnoreCase(uri.getScheme())){//如果是content类型的uri,则使用普通方式处理imagePath = getImagePath(uri,null);}else if(\"file\".equalsIgnoreCase(uri.getScheme())){//如果是file类型的uri,直接获取图片路径即可imagePath = uri.getPath();}displayImage(imagePath); //根据图片路径显示图片}private void handleImageBeforeKitKat(Intent data){Uri uri = data.getData();String imagePath = getImagePath(uri,null);displayImage(imagePath);}private String getImagePath(Uri uri,String selection){String path = null;//通过Uri和selection来获取真实的图片路径Cursor cursor = getContentResolver().query(uri,null,selection,null,null);if(cursor != null){if (cursor.moveToFirst()){path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));}cursor.close();}return path;}private void displayImage(String imagePath){if(imagePath != null){Bitmap bitmap = BitmapFactory.decodeFile(imagePath);picture.setImageBitmap(bitmap);}else {Toast.makeText(this,\"failed to get image\", Toast.LENGTH_SHORT).show();}}}