内容提供者 (获取媒体库图片显示出来)Android10.0 适配

内容提供者 (获取媒体库图片显示出来)

  • 呈现效果
    • 设计步骤
      • 注意问题

Android 10.0 适配问题都解决了
项目源码.

呈现效果

内容提供者 (获取媒体库图片显示出来)Android10.0 适配_第1张图片
内容提供者 (获取媒体库图片显示出来)Android10.0 适配_第2张图片
内容提供者 (获取媒体库图片显示出来)Android10.0 适配_第3张图片

设计步骤

  1. 第一步:先定义两个Activity,一个获取数据并用来展示,一个展示媒体库图片并提供选择
    MainActivity

     

PackageImageActivity


    

    





  1. 第二步: Android6.0以后的动态申请权限。

     private void checkReadPermission() {
             int readPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
             int writePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
             if (readPermission != PackageManager.PERMISSION_GRANTED && writePermission != PackageManager.PERMISSION_GRANTED) {
                 requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, READ_PERMISSION_CORD);
             }
         }
     	   @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
         if (requestCode == READ_PERMISSION_CORD) {
             if (grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                 Log.d(TAG, "拥有权限");
             }
         }
     }
    
  2. 第三步 从MainActivity 跳转到 PackageImageActivity

     	public void pickImages(View view) {
     	        Intent intent = new Intent(MainActivity.this, PackageImage.class);
     	        startActivity(intent);
     	    }
    

4. 第四步 使用LoaderManager 异步获取数据

	private void initLoaderManager() {
	        imageItemList.clear();
	        LoaderManager loaderManager = LoaderManager.getInstance(this);
	        loaderManager.initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks() {
	            /**
	             * 因为图库图片可能较多,不能在主线程进行耗时操作
	             * 在子线程进行操作
	             * @param id  
	             * @param args
	             * @return  一个CurSor 装载
	             */
	            @NonNull
	            @Override
	            public Loader onCreateLoader(int id, @Nullable Bundle args) {

            if (id == LOADER_ID) {
                return new CursorLoader(PackageImage.this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        new String[]{MediaStore.Images.Media._ID}, null, null, MediaStore.Images.Media.DATE_ADDED+" DESC");
            }
            return null;
        }

        /**
         * 装载完成后调用
         * @param loader   一个对象
         * @param cursor   光标,包含所有图片信息。
         */
        @Override
        public void onLoadFinished(@NonNull Loader loader, Cursor cursor) {
            if (cursor != null) {

                while (cursor.moveToNext()) {

                    String id = cursor.getString(0);
	//                      **因为Android 10.0 以后进行分区存储。我们即使申请权限,也不能访问SD卡的内容。
	//                      因此如果这里获取path 后面使用Glide 加载图片会报FileNoFOUND错误。所以我们通过ID获取Uri**
	                        Uri uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,id);
	                        imageItemList.add(uri);
	                        adapter.setData(imageItemList);
	                    }
	                }
	            }

        /**
         * 重新装载是调用
         * @param loader 
         */
        @Override
        public void onLoaderReset(@NonNull Loader loader) {

        }
    });
    }
  1. 第五步 使用recyclerView 将获取的图片信息,展现出来

    @NonNull
        @Override
        public InnerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false);
            //使用该方法,获取屏幕长度,将每一个图片尺寸设置x/3
            Point point = SizeUtils.getScreenSize(view.getContext());
            RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(point.x / 3, point.y / 3);
            view.setLayoutParams(layoutParams);
            return new InnerHolder(view);
        }
    
  2. 第六步 在Adapter 里面暴露一个接口,用于将数据传出来

     public void setOnItemSelectedNum(onItemSelectedNum onItemSelectedNum){
             this.mOnItemSelectedNum = onItemSelectedNum;
         }
     
         public interface onItemSelectedNum{
             void onItemSelectedChange(List list);
         }
    
  3. 第七步 设计事件,用于表示选中图片

     @Override
         public void onBindViewHolder(@NonNull InnerHolder holder, int position) {
             View view = holder.itemView;
             ImageView imageView = view.findViewById(R.id.iv);
             final View visibility = view.findViewById(R.id.visibility);
             final CheckBox select = view.findViewById(R.id.select);
             final Uri uri = mimageItems.get(position);
             Glide.with(imageView.getContext()).load(uri).into(imageView);
     //      先根据状态来渲染,防止紊乱
             if (mselect.contains(uri)) {
                 select.setButtonDrawable(R.drawable.image1);
                 visibility.setVisibility(View.VISIBLE);
             } else {
                 select.setButtonDrawable(R.drawable.image2);
                 visibility.setVisibility(View.INVISIBLE);
             }
     
             imageView.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
     //                如果已经没被选择,添加
                     if (!mselect.contains(uri)) {
                         if(mselect.size()>=9){
                             Toast.makeText(select.getContext(),"最多选择"+MAX_SELECTED_PIC+"张图片",Toast.LENGTH_SHORT).show();
     
                         }else{
                             mselect.add(uri);
                             select.setButtonDrawable(R.drawable.image1);
                             visibility.setVisibility(View.VISIBLE);
                         }
     
                     } else {
     //                    如果已经被选择,删除,更改可见度
                         mselect.remove(uri);
                         select.setButtonDrawable(R.drawable.image2);
                         visibility.setVisibility(View.INVISIBLE);
                     }
                     mOnItemSelectedNum.onItemSelectedChange(mselect);
                 }
             });
         }
    
  4. 第八步 选择完成,将图片传回。需要使前后数据一致。我们使用一个PickerConfig(单例模式) 来实现。 在两个Activity都初始化它

     public class PickerConfig {
         //最大选择图片数量
         private int max_selected_pic = 1;
         private OnItemSelectedFinished monItemSelectedFinished = null;
     
         public OnItemSelectedFinished getMonItemSelectedFinished() {
             return monItemSelectedFinished;
         }
    
         private PickerConfig(){}
         private static PickerConfig pickerConfig;
     
         public static PickerConfig getInstance(){
             if(pickerConfig==null){
                 pickerConfig =new PickerConfig();
             }
             return pickerConfig;
         }
     
         public void setOnItemSelectedFinished(OnItemSelectedFinished onItemSelectedFinished){
             this.monItemSelectedFinished = onItemSelectedFinished;
         }
     
     
         public interface OnItemSelectedFinished{
             void onItemSelectedFinished(List list);
         }
     
         public int getMax_selected_pic() {
             return max_selected_pic;
         }
     
         public void setMax_selected_pic(int max_selected_pic) {
             this.max_selected_pic = max_selected_pic;
         }
     }
    
  5. 第九步, 两个Activity初始化上面方法。 选择完成 ,数据返回

     public void finishedPic(View view){
     
             //需要获取数据
             List list = adapter.getMselect();
             //把数据通知给其他地方
             PickerConfig.OnItemSelectedFinished monItemSelectedFinished = mpickerConfig.getMonItemSelectedFinished();
             if(monItemSelectedFinished!=null){
                 monItemSelectedFinished.onItemSelectedFinished(list);
             }
     
             //结束
             finish();
         } 
    
  6. 第十步,将获取的数据在MainActivity 使用recyclView实现。
    可以如果返回图片少于3个,就按几列展示。大于三列的三列显示

    private void initConfig() {
            PickerConfig pickerConfig = PickerConfig.getInstance();
            pickerConfig.setMax_selected_pic(MAX_SELECTED_PIC);
            pickerConfig.setOnItemSelectedFinished(new PickerConfig.OnItemSelectedFinished() {
                @Override
                public void onItemSelectedFinished(List list) {
                    int horNum =1;
                    if(list.size()<3){
                        horNum =list.size();
                    }else{
                        horNum =3;
                    }
    
                    GridLayoutManager gridLayoutManager =new GridLayoutManager(MainActivity.this,horNum);
                    recyclerView.setLayoutManager(gridLayoutManager);
                    mainAdapter.setData(list,horNum);
                }
            });
        }
    

注意问题

1. Android10.0 为了保存隐私,不允许访问SD卡的等内容。我们需要使用
MediaStore.Images.Media 得到uri 不能使用path路径
2. Glide4.x 以上版本需要
implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’
并且创建
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
}
4. 如果没有报错,但图片没有加载出来。可能是因为适配器的设置长宽参数不合适

你可能感兴趣的:(android,android,studio)