在訪問相冊的時候由於是跨進程訪問相冊資源,所以必須具備ContentProvider的基本知識,使用相機的時候需要指定照片存儲位置,需要具備FileProvider的原理和使用
由於訪問相冊和使用相機,所以我們需要動態申請權限。使用easypermissions
implementation 'pub.devrel:easypermissions:0.3.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" />
1. 動態申請權限
private String[] permissions = {Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
if(EasyPermissions.hasPermissions(this,permissions)){
}
else{
EasyPermissions.requestPermissions(this,"訪問相冊權限",1,permissions);
}
使用easypermissions
步驟
1.重寫onRequestPermissionsResult
,在內部調用EasyPermissions.onRequestPermissionsResult
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode,permissions,grantResults,this);
}
2.使該類繼承implements EasyPermissions.PermissionCallbacks
,然後重寫onPermissionsGranted
和onPermissionsDenied
進行授權判斷
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
Toast.makeText(this, "相關權限獲取成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Toast.makeText(this, "請同意相關權限,否則功能無法使用", Toast.LENGTH_SHORT).show();
}
2. 打開相冊並且獲取選中的圖片
打開相冊:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent,2);
獲取選中圖片
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 2 &&resultCode == RESULT_OK){
String imagePath = null;
Uri uri = data.getData();
if(DocumentsContract.isDocumentUri(MainActivity.this,uri)){
String docId = DocumentsContract.getDocumentId(uri);
if("com.android.providers.media.documents".equals(uri.getAuthority())) {
String id=docId.split(":")[1];
String 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())){
imagePath = getImagePath(uri,null);
}
else if("file".equalsIgnoreCase(uri.getScheme())){
imagePath = uri.getPath();
}
//展示選中的圖片
if(imagePath != null) {
Intent intent = new Intent(MainActivity.this, PictureActivity.class);
intent.putExtra("url", imagePath);
startActivity(intent);
}
}
}
private String getImagePath(Uri uri,String selection) {
String path = null;
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;
}
3.使用相機拍照並且存儲到指定文件
打開相機設定存儲位置
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//用來打開相機的Intent
if(takePhotoIntent.resolveActivity(getPackageManager())!=null){//這句作用是如果沒有相機則該應用不會閃退,要是不加這句則當系統沒有相機應用的時候該應用會閃退
File imageFile = createImageFile();//創建用來保存照片的文件
Uri ImageUri = null;
if(imageFile!=null){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
/*7.0以上要通過FileProvider將File轉化爲Uri*/
ImageUri = FileProvider.getUriForFile(this,"com.example.qsbk.fileProvider",imageFile);
}else {
/*7.0以下則直接使用Uri的fromFile方法將File轉化爲Uri*/
ImageUri = Uri.fromFile(imageFile);
}
}
//設置文件存儲位置
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,ImageUri);
startActivityForResult(takePhotoIntent,3);//啓動相機
}
private File createImageFile() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_"+timeStamp+"_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File imageFile = null;
try {
imageFile = File.createTempFile(imageFileName,".jpg",storageDir);
} catch (IOException e) {
e.printStackTrace();
}
return imageFile;
}
FileProvider的源碼部分(這裏不做講解,具體請參考FileProvider的原理和使用:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.qsbk.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!--代表的目錄即爲:Environment.getExternalStorageDirectory()/Android/data/包名/-->
<external-path
name="files_root"
path="Android/data/com.example.qsbk/" />
<!--代表的目錄即爲:Environment.getExternalStorageDirectory()-->
<external-path
name="external_storage_root"
path="." />
<!--代表的目錄即爲:Environment.getExternalStorageDirectory()/pics -->
<external-path
name="external"
path="pics" />
</paths>
知識拓展Intent.ACTION_PICK
(一)、調用圖庫,獲取所有本地圖片:
Intent imageIntent = new Intent(Intent.ACTION_GET_CONTENT);
imageIntent.setType("image/*");
startActivityForResult(imageIntent, PICK_CODE); //PICK_CODE是常量
(二)、調用本地聯繫人:
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT);
(三)、調用音樂,獲取所有本地音樂文件:
Intent audioIntent = new Intent(Intent.ACTION_GET_CONTENT);
audioIntent.setType("audio/*");
startActivityForResult(audioIntent, PICK_AUDIO);
(四)、調用視頻,獲取所有本地視頻文件:
Intent videoIntent = new Intent(Intent.ACTION_GET_CONTENT);
videoIntent.setType("video/*");
startActivityForResult(videoIntent, PICK_VIDEO);
參考博客:https://www.cnblogs.com/wucaiyun1/p/4933049.html