Android 호출 시스템 앨범 선택 사진

머리말
앨범 에서 사진 을 선택해 올 리 는 것 도 흔 한 기능 이다.예 를 들 어 위 챗 모멘트 등 이다.그러나 이들 은 사용자 정의 선택 기로 여러 장의 그림 을 선택 하고 수정 할 수 있다.여기 서 우 리 는 가장 간단 한 것 을 말 합 니 다.시스템 의 앨범 을 호출 하여 그림 을 선택 하고 보 여 줍 니 다.또 어떤 독자 들 은 카 메 라 를 통 해 사진 을 찍 는 기능 을 선택해 야 한 다 는 생각 도 들 었 고,나의 또 다른 글 도 참고 할 수 있 었 다.
사용 절차
여기 서 나 는 간단 한 demo 를 통 해 이 기능 을 어떻게 실현 하 는 지 설명 한다.먼저 레이아웃 보기:

 <Button
  android:id="@+id/button2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="5dp"
  android:layout_marginEnd="52dp"
  android:layout_marginRight="52dp"
  android:text="choose"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

 <ImageView
  android:id="@+id/imageView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="29dp"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toBottomOf="@+id/button"
  app:srcCompat="@mipmap/ic_launcher_round" />
간단 합 니 다.버튼 하나 와 imageView 입 니 다.그리고 이 기능 이 어떻게 실현 되 는 지 생각해 보 자.
먼저 앨범 을 열 면 앨범 activity 를 암시 적 으로 시작 해 야 합 니 다.그리고 앨범 은 경 로 를 되 돌려 줍 니 다.우 리 는 이 경 로 를 가지 고 경로 에 해당 하 는 사진 을 보 여 줍 니 다.생각 이 매우 간단 하 니 우리 가 써 보 자.
우선 코드 보기:

 private Uri imageUri;
 private ImageView imageView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  imageView = findViewById(R.id.imageView);
  Button button1 = findViewById(R.id.button2);
  button1.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
   //      
    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();
    }
   }
  });
  }
//       
@Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  if (requestCode == 1){
   if (grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED) openAlbum();
   else Toast.makeText(MainActivity.this,"    ",Toast.LENGTH_SHORT).show();
  }
 }

//       
private void openAlbum(){
  Intent intent = new Intent("android.intent.action.GET_CONTENT");
  intent.setType("image/*");
  startActivityForResult(intent,2);
 }
여기 서 컨트롤 을 초기 화한 다음 동적 으로 권한 을 신청 합 니 다.사진 을 읽 으 려 면 메모리 의 권한 을 읽 어야 하기 때 문 입 니 다.AndroidManifest 에 권한 을 기록 해 야 합 니 다.<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />권한 을 가 져 오 면 앨범 선택 을 엽 니 다.앨범 에 대응 하 는 action 은 android.intent.action.GET 입 니 다.CONTENT,setType("image/*")이 방법 은 모든 사진 을 표시 한 다음 활동 을 시작 하 는 것 을 나타 낸다.이벤트 시작 후 사진 을 선택 하면 인 텐트 를 onActivity Result 방법 으로 되 돌려 줍 니 다.따라서 다음 작업 은 되 돌아 오 는 경 로 를 가 져 오 는 것 입 니 다.
우 리 는 안 드 로 이 드 4.4 이후 에 파일 의 실제 경 로 를 다른 응용 프로그램 에 직접 적용 할 수 없다 는 것 을 알 고 있 기 때문에 돌아 오 는 uri 는 봉 인 된 것 이기 때문에 우 리 는 안의 경 로 를 분석 하여 꺼 내야 한다.그래서 여기 서 우 리 는 안 드 로 이 드 버 전 을 판단 하여 서로 다른 논 리 를 하고 코드 를 먼저 봐 야 한다.

@Override
 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
 if (requestCode == 2){
 //      
    if (resultCode == RESULT_OK&&data!=null){
    if (Build.VERSION.SDK_INT>=19)
    handImage(data);
    else handImageLow(data);
   }
  }
 }

//      4.4     
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
 private void handImage(Intent data){
  String path =null;
  Uri uri = data.getData();
  //     uri       
  if (DocumentsContract.isDocumentUri(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;
    path = 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));
    path = getImagePath(contentUri,null);
   }
  }else if ("content".equalsIgnoreCase(uri.getScheme())){
   path = getImagePath(uri,null);
  }else if ("file".equalsIgnoreCase(uri.getScheme())){
   path = uri.getPath();
  }
  //    
  displayImage(path);
 }


//    4.4     
private void handImageLow(Intent data){
  Uri uri = data.getData();
  String path = getImagePath(uri,null);
  displayImage(path);
 }

//content   uri         
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;
 }

//           
private void displayImage(String imagePath){
  if (imagePath != null){
   Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
   imageView.setImageBitmap(bitmap);
  }else{
   Toast.makeText(this,"fail to set image",Toast.LENGTH_SHORT).show();
  }
 }
위의 코드 는 매우 많 지만 당황 하지 마라.우리 하나씩 하 자.이해 하기 어렵 지 않다.먼저 우 리 는 서로 다른 버 전에 서 그림 을 보 여 주 는 두 가지 방법 이 있다 는 것 을 알 고 있다.바로 handImage 와 handImage Low 이다.content 형식의 uri 는 getImagePath 라 는 방법 으로 실제 경 로 를 얻 고 실제 경 로 는 display Image 라 는 방법 으로 보 여 줍 니 다.그래서 중요 한 일 은 어떻게 진실 한 경 로 를 얻 느 냐 하 는 것 이다.이제 생각 이 뚜렷 해 졌 으 니 하나씩 보 자.
먼저 두 가지 도구 방법 을 살 펴 보 겠 습 니 다:getImagePath 와 display Image.
4.567917.getImagePath 에서 콘 텐 츠 제공 기 를 배 웠 을 때 이것 이 바로 콘 텐 츠 제공 기 를 통 해 데 이 터 를 얻 는 것 임 을 알 수 있 습 니 다.이 uri 와 selection 을 통 해 Cursor 대상 을 가 져 옵 니 다.Cursor 가 뭐 죠?모 르 는 독 자 는 이 블 로그 안 드 로 이 드 의 Cursor 를 볼 수 있다.그리고 이 Cursor 대상 의 MediaStore.Images.Media.DATA 라 는 매개 변 수 를 통 해 실제 경 로 를 얻 을 수 있 습 니 다
  • display Image 라 는 방법 은 실제 경로 문자열 을 받 고 BitmapFactory.decodeFile 이라는 방법 으로 Bitmap 를 가 져 와 서 표시 하면 됩 니 다
  • 도구 방법 을 알 게 된 후에 우리 의 목적 은 명확 합 니 다.content 형식의 uri 나 실제 경로 의 String 입 니 다.
    먼저 버 전이 4.4 보다 낮 습 니 다.진실 한 uri,즉 content 로 시작 하 는 것 을 되 돌려 주기 때문에 getImagePath 를 통 해 진실 한 경 로 를 얻 고 display Image 를 통 해 보 여주 면 됩 니 다.
    다음은 머리 가 좀 아파 보일 수 있 습 니 다.다양한 유형의 Uri 를 해석 해 야 하기 때 문 입 니 다.우리 하나씩 보 자.
    4.567917.첫 번 째 는 document 형식의 uri 입 니 다.document 형식의 uri 가 무엇 인지 에 대해 서 는 깊이 파고 들 지 않 습 니 다.이런 유형의 uri 가 있 으 면 어떻게 처리 해 야 하 는 지 알 면 됩 니 다.먼저 우 리 는 DocumentId 를 얻 은 다음 에 두 가지 상황 으로 나 누 어 처리 해 야 한다첫 번 째 는 미디어 형식 입 니 다.그 다음 에 우 리 는 후반 문자열 을 꺼 내야 진정한 id 를 얻 을 수 있 습 니 다.여기 서 진정한 id 는 데이터베이스 시트 에 있 는 id 를 가리 키 며 selection 에 사용 합 니 다.MediaStore.Images.Media.EXTERNAL_CONTENT_URI 는 바로 이 사진 의 content 형식 uri 이 며,selection 을 넣 으 면 됩 니 다.
    두 번 째 는 ContentUris.withAppendedId 라 는 방법 을 통 해 content 형식의 uri 를 얻 을 수 있 습 니 다.이 방법 은 id 와 contentUri 를 새로운 Uri 로 연결 하 는 것 을 책임 집 니 다.이 방법 은 여기 서도 상세 하 게 설명 하지 않 는 다.
    4.567917.두 번 째 는 콘 텐 츠 유형 인 데 그냥 쓰 면 돼 요.4.567918.
    4.567917.세 번 째 는 file 형식 입 니 다.이것 이 바로 실제 경로 입 니 다.getPath 를 통 해 얻 을 수 있 습 니 다자,이제 우리 의 모든 의문 도 해결 되 었 다.
    작은 매듭
    보고 나 니 생각 은 간단 하지만 실현 되 는 지식의 맹점 이 많 지 않 을까요?그 렇 긴 한데.그러나 우리 가 이런 세부 사항 을 모두 해결 한 후에 우 리 는 많은 것 을 배 울 것 이다.이것 은 약간의 면 이 있 는 것 과 같다.글 에는 아직 상세 하지 않 은 것 이 많다.
    ContentUris,BitmapFactory,Cursor,DocumentsContract 등.이것 은 또 다른 비교적 큰 내용 이기 때문에 말 하려 면 많은 내용 과 관련 될 것 이 고 우리 의 주 제 를 벗 어 나 기 쉬 우 므 로 대충 무엇 인지 알 면 된다.
    참고 자료
    Android 는 시스템 카 메 라 를 사용 하여 사진 을 찍 습 니 다.
    이상 은 안 드 로 이 드 호출 시스템 앨범 선택 사진 의 상세 한 내용 입 니 다.안 드 로 이 드 호출 시스템 앨범 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!

    좋은 웹페이지 즐겨찾기