Android项目实践——三行代码解决照片选择与压缩

版权声明:本文为博主原创文章,未经博主允许不得转载

系列教程:Android开发之从零开始系列

源码:AnliaLee/PhotoFactory,欢迎star

大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论

初看标题是不是觉得博主是标题党,故意把你们骗了进来?告诉你

博主帮大家封装好了PhotoFactory类,只需三行代码就可以完成选择照片,获取其bitmap或uri路径(可自行配置是否压缩)的功能。下面来看下如何使用PhotoFactory


PhotoFactory简介

使用PhotoFactory分为三步,首先我们要实例化一个photoFactory

PhotoFactory photoFactory = new PhotoFactory(this, this);//(Activity activity,Context context)

设置选择照片的方式

//提供三种选择照片的方式
photoFactory.FactoryStart().SetStartType(PhotoFactory.TYPE_PHOTO_UNTREATED).Start();//调用相机拍照,照相后返回高清原图相片
/*photoFactory.FactoryStart().SetStartType(PhotoFactory.TYPE_PHOTO_AUTO_COMPRESS).Start();//调用相机拍照,照相后返回系统自动压缩过的相片
photoFactory.FactoryStart().SetStartType(PhotoFactory.TYPE_PHOTO_FROM_GALLERY).Start();//从本地相册中选取图片*/

获取相片bitmap或uri

/**
 * 在onActivityResult中调用此方法
 */
photoFactory.FactoryFinish(requestCode,resultCode,data).GetBitmap();
//photoFactory.FactoryFinish(requestCode,resultCode,data).GetUri();

就这么简单,当然,你还可以对照片进行压缩处理,这里提供了三种压缩的方式

addScaleCompress(int w, int h)//按目标宽高缩放
addScaleCompress(int scale)//等比例缩放,缩放比为 原图:新图 = scale:1
addQualityCompress(int targetSize)//质量压缩,targetSize为目标大小

你可以选择其中一种或多种压缩方式对相片进行压缩,例如

//只选择一种压缩方式
photoFactory.FactoryFinish(requestCode,resultCode,data)
        .addQualityCompress(128)
        .GetBitmap();

//按顺序逐步压缩
photoFactory.FactoryFinish(requestCode,resultCode,data)
        .addQualityCompress(128)
        .addScaleCompress(5)
        .addScaleCompress(300,300)
        .GetBitmap();

完整示例

PhotoFactory兼容了Android 7.0 FileProvider获取相片uri的问题,当然具体Provider的配置以及Android 6.0的动态权限管理需要大家在项目中自行完成。这里为了方便大家完成配置,我将完整的流程贴出来供大家参考

1.在Github下载photofactory library并导入到你的项目中

地址:AnliaLee/PhotoFactory

2. 在res\xml目录中创建provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

3. 在AndroidManifest.xml中添加相应权限及配置Provider

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
    android:icon="@mipmap/ic_launcher"
    ...
    >
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
    ...
</application>

4. 在AndroidManifest.xml中添加相应权限及配置Provider

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
    android:icon="@mipmap/ic_launcher"
    ...
    >
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
    ...
</application>

5. 在Activity中进行动态权限管理以及使用PhotoFactory

public class PhotoTestActivity extends AppCompatActivity {
    private Button btnPhoto;
    private ImageView imgPhoto;
    private PhotoFactory photoFactory;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo_test);

        photoFactory = new PhotoFactory(this,this);
        imgPhoto = (ImageView) findViewById(R.id.img_photo);
        btnPhoto = (Button) findViewById(R.id.btn_photo);
        btnPhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(PhotoTestActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    //申请写入权限
                    ActivityCompat.requestPermissions(PhotoTestActivity.this, new String[]{
                            Manifest.permission.WRITE_EXTERNAL_STORAGE
                    }, 100);
                } else {
                    photoFactory.FactoryStart()
                                .SetStartType(PhotoFactory.TYPE_PHOTO_UNTREATED)
                                .Start();
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch(requestCode) {
            case 100:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    photoFactory.FactoryStart()
                            .SetStartType(PhotoFactory.TYPE_PHOTO_UNTREATED)
                            .Start();
                }else{// 没有获取到权限,做特殊处理
                    Toast.makeText(this, "请授予权限!", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == RESULT_CANCELED){
            Toast.makeText(this, "取消", Toast.LENGTH_SHORT).show();
        }else {
            //使用你选取的照片
            Uri uri = photoFactory.FactoryFinish(requestCode,resultCode,data).GetUri();
            imgPhoto.setImageURI(uri);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

PhotoFactory至此介绍完毕,具体实现并不复杂,有兴趣了解内部是如何实现的可以自行查阅源码,如果有不懂的地方或者检查到代码有什么问题欢迎给我留言~


更新

之前的代码虽然简化了选取照片的过程,但没有考虑到把取消选择的处理也封装进来,用户还得在onActivityResult中写一堆代码去处理取消选择的情况,这说明PhotoFactory用起来还不够方便,于是我动手增加了判断取消选择的接口,现在我们可以调用这些新的接口进行容错了

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //依然可以这样去获取相片,但需要你自己去写取消选择的处理
    Uri uri = photoFactory.FactoryFinish(requestCode,resultCode,data).GetUri();
    imgPhoto.setImageURI(uri);

    //现在只要这样调用setOnResultListener就可以一步到位了
    photoFactory.FactoryFinish(requestCode,resultCode,data)
                .setOnResultListener(new PhotoFactory.OnResultListener() {
        @Override
        public void TakePhotoCancel() {
            Toast.makeText(PhotoTestActivity.this, "取消拍照", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void GalleryPhotoCancel() {
            Toast.makeText(PhotoTestActivity.this, "取消选择", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void HasData(PhotoFactory.FinishBuilder resultData) {//正确选取了相片
            Uri uri = resultData.GetUri();
            imgPhoto.setImageURI(uri);
        }
    });
    super.onActivityResult(requestCode, resultCode, data);
}

但是…这样好像就不止三行代码了啊…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值