Okhttp的简单封装与使用

Okhttp是一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso),用于替代HttpUrlConnection和Apache HttpClient(android API23 6.0里已移除HttpClient,现在已经打不出来)。

下面就对Okhttp的单独使用做一个简单的封装(在App版本更新的例子里抽取出来的,里面的一些名字可能跟版本更新有关,使用的是时候注意适当更改一下):

1.添加依赖

implementation 'com.squareup.okhttp3:okhttp:3.12.0'

2.添加网络权限

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

3.开始写类内容

(1)新建类AppUpdater。

我们在做一个可以独立模块功能的时候,我们尽可能有一个对外的类,,这里面对外的类就是AppUpdater。其他的一些操作都放到这个类的内部或者其他类里面,对使用者是不可见的;也就是说,使用者所有的操作都是通过AppUpdater进行调用。所以要把这个类写成一个单例。他还需要一个网络模块,通过接口隔离实现,所以要建立一个接口,INetManager。

package com.wjy.myupdateapp.updater;

import com.wjy.myupdateapp.updater.net.INetManager;
import com.wjy.myupdateapp.updater.net.OkhttpNetManager;

/**
 * created by WangJinyong
 */
public class AppUpdater {

    //单例
    private static AppUpdater sInstance = new AppUpdater();

    //网络请求,下载的能力
    //okhttp,volley,httpclient,httpurlconn
    /**
     * 接口隔离  具体实现    可以随意使用哪一种网路请求,只要改变一下NetManager就可以了,
     * 这里使用的是OkhttpNetManager,如果使用其他网路请求,则将OkhttpNetManager改成其他网路请求
     *
     */
    private INetManager mNetManager = new OkhttpNetManager();

    public void setNetManager(INetManager manager){
        mNetManager = manager;
    }

    public INetManager getNetManager(){
        return mNetManager;
    }

    //对外提供一个static方法
    public static AppUpdater getInstance(){
        return sInstance;
    }
}

     (2)上面用到一个网络接口INetManager,所以新建一个INetManager接口,这个接口里面有get请求、post请求、upload上传、download下载以及cancel关闭。

get请求:需要传递url,异步的Callback

post请求:需要传递url,RequestBody请求体,异步的Callback

upload上传:可以跟post一样

download下载:需要传递url,上传的文件File,异步的Callback

cancel关闭

(3)新建get请求里的Callback,这里起名叫INetCallBack,里面返回成功和失败

package com.wjy.myupdateapp.updater.net;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 11:20
 * Describe: 网络请求  get
 */
public interface INetCallBack {

    void success(String response);

    void failed(Throwable throwable);
}

(4)新建download下载里面的Callback,这里起名叫INetDownloadCallBack,需要返回成功、失败、下载进度。

package com.wjy.myupdateapp.updater.net;

import java.io.File;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 11:20
 * Describe: 下载接口 回调
 */
public interface INetDownloadCallBack {

    void success(File apkFile);

    void progress(int progress);

    void failed(Throwable throwable);
}

(5)在上面(1)AppUpdater中,接口隔离网络模块,来具体实现,新建了一个OkhttpNetManager来实现INetManager,这样写的好处是可以随意使用哪一种网路请求,只要改变一下NetManager就可以了,这里使用的是OkhttpNetManager,如果使用其他网路请求,则将OkhttpNetManager改成其他网路请求。

package com.wjy.myupdateapp.updater.net;

import android.os.Handler;
import android.os.Looper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 11:33
 * Describe: ${describe}
 */
public class OkhttpNetManager implements INetManager {

    private static OkHttpClient sOkhttpClient;

    private static Handler sHandler = new Handler(Looper.getMainLooper());

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(5*1000, TimeUnit.SECONDS);
        sOkhttpClient = builder.build();

        //http
        //https  自签名,Okhttp握手错误
//        builder.sslSocketFactory();
    }

    @Override
    public void get(String url, final INetCallBack callBack,Object tag) {
        //requestbuilder -> Request -> Call -> execute/enqueue
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sOkhttpClient.newCall(request);
//        Response response = call.execute();//同步
        call.enqueue(new Callback() {//异步
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void post(String url,RequestBody requestBody, final INetCallBack callBack) {
        Request.Builder builder = new Request.Builder();
        Request request = builder
                        .url(url)
                        .post(requestBody)//传递请求体   //与get的区别在这里
                        .build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void upload(String url, RequestBody requestBody, final INetCallBack callBack) {
        Request.Builder builder = new Request.Builder();
        Request request = builder
                .url(url)
                .post(requestBody)//传递请求体   //与get的区别在这里
                .build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //非 ui 线程
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);//把异常传过去
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {//可能会产生异常
                    final String string = response.body().string();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.failed(e);//把异常传过去
                }
            }
        });
    }

    @Override
    public void download(String url, final File targetFile, final INetDownloadCallBack callback,Object tag) {
        if (targetFile.exists()){//判断是否存在
            targetFile.getParentFile().mkdirs();
        }

        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sOkhttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.failed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                OutputStream os = null;
                try {
                    final long totalLen = response.body().contentLength();

                    is = response.body().byteStream();
                    os = new FileOutputStream(targetFile);

                    byte[] buffer = new byte[8*1024];
                    long curLen = 0;

                    int bufferLen = 0;
                    while (!call.isCanceled() && (bufferLen = is.read(buffer)) !=-1){
                        os.write(buffer,0,bufferLen);
                        curLen += bufferLen;

                        final long finalCurLen = curLen;
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.progress((int) (finalCurLen * 1.0f / totalLen * 100));
                                //*1.0f  原因:一个小的数字除以一个大的数字,正常除的话始终为0,* 1.0f就会转化为float对象
                                //这样除完就是个零点几的小数,再乘以100就是一个几十的数字

                            }
                        });
                    }

                    if (call.isCanceled()){
                        return;
                    }

                    try {
                        targetFile.setExecutable(true,false);//可执行
                        targetFile.setReadable(true,false);//可读
                        targetFile.setWritable(true,false);//可写
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.success(targetFile);
                        }
                    });
                } catch (final Throwable e) {
                    if (call.isCanceled()){
                        return;
                    }
                    e.printStackTrace();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.failed(e);
                        }
                    });
                }finally {
                    if (is != null){
                        is.close();
                    }
                    if (os != null){
                        os.close();
                    }
                }
            }
        });
    }

    @Override
    public void cancel(Object tag) {
        //排队的
        List<Call> queuedCalls = sOkhttpClient.dispatcher().queuedCalls();
        if (queuedCalls != null){
            for (Call call : queuedCalls){
                if (tag.equals(call.request().tag())){
                    call.cancel();
                }
            }
        }

        //正在执行的(正在下载的)
        List<Call> runningCalls = sOkhttpClient.dispatcher().runningCalls();
        if (runningCalls != null){
            for (Call call : runningCalls){
                if (tag.equals(call.request().tag())){
                    call.cancel();
                }
            }
        }
    }
}

4.每种请求的使用

(1)post请求的使用

btn_post.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RequestBody requestBody = new FormBody.Builder()//创建表单请求体
                        .add("version",String.valueOf(AppUtils.getVersionCode(MainActivity.this)))
                        .build();
                AppUpdater.getInstance().getNetManager().post(URL_HOST, requestBody, new INetCallBack() {
                    @Override
                    public void success(String response) {
                        Log.e("tag","请求成功response="+response);
                    }

                    @Override
                    public void failed(Throwable throwable) {
                        throwable.printStackTrace();
                        Toast.makeText(MainActivity.this,"请求失败!",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });

(2)文件上传

btn_upload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String filePath = "/sdcard/UVCCamera/img_goods.png";//文件地址
                File file = new File(filePath);
                Log.e("tag","file.getName()="+file.getName());
                RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"),file);//MediaType.parse("image/*")参考https://www.w3school.com.cn/media/media_mimeref.asp
                RequestBody requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("file",file.getName(),fileBody)
                        .build();
                AppUpdater.getInstance().getNetManager().upload(URL, requestBody, new INetCallBack() {
                    @Override
                    public void success(String response) {
                        Log.e("tag","response="+response);
                    }

                    @Override
                    public void failed(Throwable throwable) {
                        Log.e("tag","failed");
                    }
                });
            }
        });

(3)base64图片上传,就是post请求

btn_uploadImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String stream = null;
                String filePath = "/sdcard/UVCCamera/img_goods.png";//图片地址
                stream = Base64StringTool.getcomImageBase64(Base64StringTool.getSmallBitmap(filePath));
                if (TextUtils.isEmpty(stream)) {
                    Toast.makeText(MainActivity.this,"图片上传失败!",Toast.LENGTH_SHORT).show();
                    return;
                }

                RequestBody requestBody = new FormBody.Builder()//创建表单请求体
                        .add("file",stream)
                        .build();
                AppUpdater.getInstance().getNetManager().post(URL, requestBody, new INetCallBack() {
                    @Override
                    public void success(String response) {
                        Log.e("tag","请求成功response="+response);
                    }

                    @Override
                    public void failed(Throwable throwable) {
                        throwable.printStackTrace();
                        Toast.makeText(MainActivity.this,"请求失败!",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });

(4)get请求,这里以App下载更新为例

btn_updater.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AppUpdater.getInstance().getNetManager().get(url, new INetCallBack() {
                    @Override
                    public void success(String response) {
                        Log.e("tag","response="+response);
                        //1.解析json
                        DownloadBean downloadBean = DownloadBean.parse(response);
                        if (downloadBean == null){
                            Toast.makeText(MainActivity.this,"版本检测接口返回数据异常!",Toast.LENGTH_SHORT).show();
                            return;
                        }

                        //2.检测:是否需要弹窗
                        try {
                            long versinCode = Long.parseLong(downloadBean.versionCode);
                            if (versinCode <= AppUtils.getVersionCode(MainActivity.this)){
                                Toast.makeText(MainActivity.this,"已经是最新版本,无需更新!",Toast.LENGTH_SHORT).show();
                                return;
                            }
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                            Toast.makeText(MainActivity.this,"版本检测接口返回版本号异常!",Toast.LENGTH_SHORT).show();
                            return;
                        }

                        //3.弹窗
                        UpdateVersionShowDialog.show(MainActivity.this,downloadBean);

                        //4.下载
                    }

                    @Override
                    public void failed(Throwable throwable) {
                        throwable.printStackTrace();
                        Toast.makeText(MainActivity.this,"版本更新失败!",Toast.LENGTH_SHORT).show();
                    }
                },MainActivity.this);
            }
        });

在请求成功返回Json数据解析时候,放到实体类里解析,Json数据解析成对象,不暴露在外面

DownloadBean downloadBean = DownloadBean.parse(response);
package com.wjy.myupdateapp.updater.bean;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 14:24
 * Describe: ${describe}
 */
public class DownloadBean implements Serializable {

    public String title;
    public String content;
    public String url;
    public String md5;
    public String versionCode;

    //Json数据解析成对象
    public static DownloadBean parse(String response) {
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(response);
            String title = jsonObject.optString("title");
            String content = jsonObject.optString("content");
            String url = jsonObject.optString("url");
            String md5 = jsonObject.optString("md5");
            String versionCode = jsonObject.optString("versionCode");

            DownloadBean downloadBean = new DownloadBean();
            downloadBean.title = title;
            downloadBean.content = content;
            downloadBean.url = url;
            downloadBean.md5 = md5;
            downloadBean.versionCode = versionCode;
            return downloadBean;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
}

5.在onDestroy里将网络请求关闭

    @Override
    protected void onDestroy() {
        super.onDestroy();
        AppUpdater.getInstance().getNetManager().cancel(this);
    }

6.附下载弹窗、AppUtils工具类和base64工具类

(1)下载弹窗

package com.wjy.myupdateapp.updater.ui;

import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;

import com.wjy.myupdateapp.R;
import com.wjy.myupdateapp.updater.AppUpdater;
import com.wjy.myupdateapp.updater.bean.DownloadBean;
import com.wjy.myupdateapp.updater.net.INetDownloadCallBack;
import com.wjy.myupdateapp.updater.utils.AppUtils;

import java.io.File;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 15:21
 * Describe: ${describe}
 */
public class UpdateVersionShowDialog extends DialogFragment {

    private static final String KEY_DOWNLOAD_BEAN = "download_bean";

    private DownloadBean downloadBean;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle arguments = getArguments();
        if (arguments != null){
            downloadBean = (DownloadBean) arguments.getSerializable(KEY_DOWNLOAD_BEAN);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.dialog_updater,container,false);
        bindEvents(view);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    }

    private void bindEvents(View view) {
        TextView tv_title = view.findViewById(R.id.tv_title);
        TextView tv_content = view.findViewById(R.id.tv_content);
        final TextView tv_update = view.findViewById(R.id.tv_update);
        tv_title.setText(downloadBean.title);
        tv_content.setText(downloadBean.content);
        tv_update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                v.setEnabled(false);//点完 将按钮设置为不可点,不然每次点击都会重复的下载
                final File targetFile = new File(getActivity().getCacheDir(),"target.apk");
                //4.下载
                AppUpdater.getInstance().getNetManager().download(downloadBean.url, targetFile, new INetDownloadCallBack() {
                    @Override
                    public void success(File apkFile) {
                        v.setEnabled(true);
                        //安装的代码
                        Log.e("tag","success="+apkFile.getAbsolutePath());
                        dismiss();

                        String fileMd5 = AppUtils.getFileMd5(targetFile);
                        Log.e("tag","fileMd5="+fileMd5);
                        if (fileMd5 != null && fileMd5.equals(downloadBean.md5)){
                            AppUtils.installApk(getActivity(),apkFile);
                        }else {
                            Toast.makeText(getActivity(),"md5 检测失败!",Toast.LENGTH_SHORT).show();
                        }

                        AppUtils.installApk(getActivity(),apkFile);
                    }

                    @Override
                    public void progress(int progress) {
                        //更新界面的代码
                        Log.e("tag","progress="+progress);
                        tv_update.setText(progress+"%");
                    }

                    @Override
                    public void failed(Throwable throwable) {
                        v.setEnabled(true);
                        Toast.makeText(getActivity(),"文件下载失败!",Toast.LENGTH_SHORT).show();
                    }
                },UpdateVersionShowDialog.this);
            }
        });
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        Log.e("tag","onDismiss");
        AppUpdater.getInstance().getNetManager().cancel(this);
    }

    public static void show(FragmentActivity activity, DownloadBean bean){
        Bundle bundle = new Bundle();
        bundle.putSerializable(KEY_DOWNLOAD_BEAN,bean);
        UpdateVersionShowDialog dialog = new UpdateVersionShowDialog();
        dialog.setArguments(bundle);
        dialog.show(activity.getSupportFragmentManager(),"updateVersionShowDialog");
    }
}

(2)AppUtils工具类

package com.wjy.myupdateapp.updater.utils;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * Created by wjy.
 * Date: 2019/11/19
 * Time: 15:13
 * Describe: ${describe}
 */
public class AppUtils {

    /**
     * 获取版本号
     * @param context
     * @return
     */
    public static long getVersionCode(Context context) {
        PackageManager packageManager = context.getPackageManager();
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                return packageInfo.getLongVersionCode();
            }else {
                return packageInfo.versionCode;
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 下载完安装apk文件  并做了适配
     * 1.Android N  做FileProvider适配       在AndroidManifest里写 provider
     * 2.Android O  做INSTALL PERMISSION的适配  在AndroidManifest里添加REQUEST_INSTALL_PACKAGES权限
     * @param activity
     * @param apkFile
     */
    public static void installApk(Activity activity, File apkFile) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        Uri uri = null;

        //1.Android N  做FileProvider适配
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            uri = FileProvider.getUriForFile(activity,activity.getPackageName()+".fileprovider",apkFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }else {
            uri = Uri.fromFile(apkFile);
        }

        intent.setDataAndType(uri,"application/vnd.android.package-archive");
        activity.startActivity(intent);
        //这是一个非常早期的installApk的写法,现在就会遇到很多问题
        //1.Android N  就要做FileProvider适配
        //2.Android O  就要做INSTALL PERMISSION的适配
    }

    /**
     * 获取文件MD5的算法
     * @param targetFile
     * @return
     */
    public static String getFileMd5(File targetFile) {
        if (targetFile == null || !targetFile.isFile()){
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte[] buffer = new byte[1024];
        int len = 0;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(targetFile);
            while ((len = in.read(buffer)) != -1){
                digest.update(buffer,0,len);
            }
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            if (in != null){
                try {
                    in.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
        byte[] result = digest.digest();
        BigInteger bigInteger = new BigInteger(1,result);
        return bigInteger.toString(16);
    }
}

(3)base64工具类

package com.wjy.myupdateapp.updater.tools;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import static com.lidroid.xutils.bitmap.core.BitmapDecoder.calculateInSampleSize;

public class Base64StringTool {
	/**
	 * 文件转Base64
	 * @param filepath
	 * @return
	 */
	public static String fileToBase64(String filepath){
		// 获得输入流
		FileInputStream inStream = null;
		try {
			inStream = new FileInputStream(filepath);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		// new一个缓冲区
		byte[] buffer = new byte[1024];
		int len = 0;
		// 使用ByteArrayOutputStream类来处理输出流
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		try {
			while ((len = inStream.read(buffer)) != -1) {
				// 写入数据
				outStream.write(buffer, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 得到文件的二进制数据
		byte[] data = outStream.toByteArray();
		// 关闭流
		try {
			outStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			inStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return Base64.encodeToString(data, Base64.DEFAULT);
	}

	//将图片压缩成100k以下上传   使用方法getcomImageBase64(getSmallBitmap(filePath))
	public static String getcomImageBase64(Bitmap bitmap) {

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 100是压缩率不压缩,如果是30就是压缩70%,压缩后的存放在baos中
		int options = 100;
		while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
			baos.reset();// 重置baos即清空baos
			options -= 10;// 每次都减少10
			bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
		}
		byte[] bytes = baos.toByteArray();
		try {
			baos.flush();
			baos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return Base64.encodeToString(bytes, Base64.DEFAULT);
	}

	//将图片路径转化成bitmap
	public static Bitmap getSmallBitmap(String filePath) {
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(filePath, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, 480, 800);
		// Decode bitmap with inSampleSize set
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeFile(filePath, options);
	}
}

最后附上整理例子的下载地址:

git地址:https://gitee.com/AlaYu/MyUpdateApp

CSDN地址:https://download.csdn.net/download/u013184970/11997915

发布了92 篇原创文章 · 获赞 38 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/u013184970/article/details/103238988