Android Call System Album to Select Photos

  • 2021-12-11 08:53:48
  • OfStack

Preface

Choosing pictures to upload in photo albums is also a very common function, such as WeChat friends circle and so on. But they are custom selectors, which can select multiple pictures and modify them. Here we talk about the simplest one: call the photo album of the system, select a picture and show it. In addition, some readers also think of the function of choosing pictures by taking pictures with cameras. You can also refer to my other article Android under 1 to take pictures with system cameras

Use steps

Here, I explain how to realize this function through a simple demo. First look at the layout:


 <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" />

It's very simple, that is, one button and one imageView. Then let's think about how to implement this function:

If you open the album first, you must start the album activity implicitly; Then the photo album returns to a path, and we will take this path to show the corresponding photos on the path. The idea is quite simple, let's write about it:
Look at the code first:


 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) {
   // Dynamic application authority 
    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{
    // Execute the method of starting the album 
     openAlbum();
    }
   }
  });
  }
// Get the result of the permission 
@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," You refused ",Toast.LENGTH_SHORT).show();
  }
 }

// How to start an album 
private void openAlbum(){
  Intent intent = new Intent("android.intent.action.GET_CONTENT");
  intent.setType("image/*");
  startActivityForResult(intent,2);
 }

Here first initialize the control, and then dynamically apply for permissions, because we must read photos to read memory permissions, remember to write permissions in AndroidManifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

After obtaining permission, open album selection. action corresponding to the photo album is android. intent. action. GET_CONTENT, setType ("image/*") This method means to display all the photos and then start the activity. After starting the activity to select the photo, it will return 1 intent to onActivityResult method, so the next main job is to get the return path.

We know that after Android 4.4, we can't directly give the real path of the file to other applications, so the returned uri is encapsulated, so we need to parse and take out the path inside. So here we have to judge the Android version for different logic, first look at the code:


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

// Android version is greater than 4.4 The processing method of 
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
 private void handImage(Intent data){
  String path =null;
  Uri uri = data.getData();
  // According to different uri Perform different parsing 
  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();
  }
  // Show pictures 
  displayImage(path);
 }


// Android is less than 4.4 The processing method of 
private void handImageLow(Intent data){
  Uri uri = data.getData();
  String path = getImagePath(uri,null);
  displayImage(path);
 }

//content Type of uri Method of getting picture path 
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;
 }

// Method of showing pictures according to paths 
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();
  }
 }

There are many codes above, but don't panic. Let's come one by one, which is not difficult to understand. First of all, we know that different versions have two different ways to display pictures, namely handImage and handImageLow. content type uri gets the real path through getImagePath, and the real path can be displayed through displayImage. So the main job is how to get the real path. Now that the train of thought is clear, let's look at it one by one:

First, look at the next two tool methods: getImagePath and displayImage.

getImagePath learned that the content provider will know that this is to get data through the content provider. An Cursor object is obtained through this uri and selection. What is Cursor? Readers who don't know can check Cursor in this blog Android. The real path is then obtained through the MediaStore. Images. Media. DATA parameter of the Cursor object. displayImage this method receives 1 real path string, obtains Bitmap directly through BitmapFactory. decodeFile this method and then displays it

With the tool approach, our purpose is clear: uri of content type or String of real path.
First of all, the version is lower than 4.4, because the return is the real uri, that is, the one at the beginning of content, so get the real path directly through getImagePath and then show it through displayImage.

The next one may seem a bit of a headache, because you have to parse different types of Uri. Let's look at it one by one:

The first is uri of document type. As for what is document type uri, it is not in depth here, as long as you know that there is this type of uri, how to deal with it. First, we need to get an DocumentId, and then deal with it in two cases:

The first one is in media format, and then we have to take out the second half of the string before we can get the real id. Here, the real id refers to id in the corresponding database table, which is used for selection. MediaStore.Images.Media.EXTERNAL_CONTENT_URI is the content type of this photo, and then put selection in it.
In the second way, uri of content type can be obtained by ContentUris. withAppendedId, which is responsible for connecting id and contentUri into a new Uri. This method is not explained in detail here.

The second type is content type, so it doesn't need to be used directly The third type is file, this is the real path, which can be obtained directly by getPath.

Well, all our questions will be solved by this time.

Summary

After reading it, do you find that the idea is very simple but there are many blind spots in knowledge? That's true. But when we work out all these details, we will learn a lot, which is equivalent to taking points and areas. There are still many things that have not been explained in detail:
ContentUris, BitmapFactory, Cursor, DocumentsContract, etc. Because this is another big piece of content, if you want to talk about it, it will involve a lot of content, so it is easy to deviate from our theme, so just know what it is.

References

[Line 1 Code] Guo Lin

The above is the Android call system photo album selection details, more information about Android call system photo album please pay attention to other related articles on this site!


Related articles: