//首先导入第三方的裁剪依赖库
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
//清单文件配置
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
//之后Retrofit的工具类 RetrofitUtils
public class RetrofitUtils {
private static RetrofitUtils retrofitUtils;//工具类对象
private static ApiFunction apiFunction;//请求网络接口
public static OkHttpClient okHttpClient;
//静态快,获取OkHttpClient对象
static {
getOkHttpClient();
}
//单例锁模式
public static RetrofitUtils getInstence(){
if(retrofitUtils==null){
synchronized (RetrofitUtils.class){
if (retrofitUtils==null){
retrofitUtils=new RetrofitUtils();
}
}
}
return retrofitUtils;
}
//单例模式获取okhttp
public static OkHttpClient getOkHttpClient(){
if(okHttpClient==null){
synchronized (OkHttpClient.class){
if(okHttpClient==null){
File fileDir = new File(Environment.getExternalStorageDirectory(), "cache");
long fileSize = 10 * 1024 * 1024;
okHttpClient=new OkHttpClient.Builder()
.addInterceptor(new MyInter())
//打印拦截器日志
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(15, TimeUnit.SECONDS)//设置连接超时时间
.readTimeout(15, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(15, TimeUnit.SECONDS)//设置写入超时时间
//.cache(new Cache(fileDir,fileSize))//写入sd卡
.build();
}
}
}
return okHttpClient;
}
//私有的无参构造
private RetrofitUtils(){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Constants.Base_url)
.addConverterFactory(GsonConverterFactory.create())//添加gson转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.client(okHttpClient)//添加okhttp
.build();
apiFunction=retrofit.create(ApiFunction.class);
}
//获取
public ApiFunction API(){
return apiFunction;
}
//拦截器
static class MyInter implements Interceptor {
private int versionCode;
private Context context;
private SharedPreferences jiLu;
private String token;
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder request_builder = request.newBuilder();
context = MyApp.con;
jiLu = context.getSharedPreferences("JiLu", 0);
if(jiLu!=null){
token = jiLu.getString("token", null);
}
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
versionCode = pi.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if("GET".equals(request.method()))
{
HttpUrl.Builder builder = request.url().newBuilder();
HttpUrl build = builder.addQueryParameter("source", Constants.source)
.addQueryParameter("appVersion", versionCode + "")
.addQueryParameter("token", token + "")
.build();
request = request_builder.url(build).build();
}
if ("POST".equals(request.method())) {
if (request.body() instanceof FormBody) {
System.out.println("FormBody开始添加公共参数");
FormBody.Builder builder = new FormBody.Builder();
FormBody body = (FormBody) request.body();
for (int i = 0; i < body.size(); i++) {
builder.add(body.encodedName(i), body.encodedValue(i));
}
body = builder.add("source", Constants.source)
.add("appVersion", String.valueOf(versionCode))
.add("token", token+"")
.build();
System.out.println("开始添加公共参数55555" );
request = request_builder.post(body).build();
}
//因为传送文件要用到 @Multipart注解
else if(request.body() instanceof MultipartBody)
{
MultipartBody body = (MultipartBody) request.body();
MultipartBody.Builder builder=new MultipartBody.Builder().setType(MultipartBody.FORM);
builder.addFormDataPart("source","android")
.addFormDataPart("appVersion",versionCode+"")
.addFormDataPart("token",token+"");
List<MultipartBody.Part> parts = body.parts();
for (MultipartBody.Part part : parts) {
builder.addPart(part);
}
request=request_builder.post(builder.build()).build();
}
}
return chain.proceed(request);
}
/**
* 添加公共参数
*
* @param oldRequest
* @return
*/
private Request addParam(Request oldRequest) {
jiLu = context.getSharedPreferences("JiLu", 0);
if(jiLu!=null){
token = jiLu.getString("token", null);
}
PackageInfo packageArchiveInfo = MyApp.con.getPackageManager().getPackageArchiveInfo(MyApp.con.getPackageName(), 0);
int versionCode = packageArchiveInfo.versionCode;
HttpUrl.Builder builder = oldRequest.url()
.newBuilder()
.setEncodedQueryParameter("source", "android")
.setEncodedQueryParameter("token",token)
.setEncodedQueryParameter("appVersion",versionCode+"")
;
Request newRequest = oldRequest.newBuilder()
.method(oldRequest.method(), oldRequest.body())
.url(builder.build())
.build();
return newRequest;
}
}
}
//下面我们写 ApiFunction
public interface ApiFunction {
//上传文件
@Multipart
@POST("file/upload")
Observable<BaseUser> uploadFile(@PartMap Map<String, RequestBody> params);
}
//接口工具类
public class Constants {
public static String Base_url="https://www.zhaoapi.cn/";
public static String UpLoad_url="file/upload";
public static String source="android";
}
//转换图片为uri 绝对路径的工具类UtilsImageProcess
public class UtilsImageProcess {
/**
* 将得到的一个Bitmap保存到SD卡上,得到一个URI地址
*/
public static Uri saveBitmap(String path, Bitmap bm) {
//在SD卡上创建目录
File dir = new File(path);
if (!dir.exists()) {
dir.mkdir();
}
try {
FileOutputStream fos = new FileOutputStream(dir);
bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
fos.flush();
fos.close();
return Uri.fromFile(dir);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static Uri saveBitmap(Bitmap bm) {
File tmpDir = new File(Environment.getExternalStorageDirectory() + "/org.chenlijian.test");
if (!tmpDir.exists()) {
tmpDir.mkdir();
}
File img = new File(tmpDir.getAbsolutePath() + "test.png");
try {
FileOutputStream fos = new FileOutputStream(img);
bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
fos.flush();
fos.close();
return Uri.fromFile(img);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 将得到的一个Bitmap保存到SD卡上,得到一个绝对路径
*/
public static String getPath(String path, Bitmap bm) {
//在SD卡上创建目录
//在SD卡上创建目录
File dir = new File(path);
if (!dir.exists()) {
dir.mkdir();
}
File img = new File(path);
try {
FileOutputStream fos = new FileOutputStream(img);
bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
fos.flush();
fos.close();
return img.getCanonicalPath();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static String getPath(Bitmap bm) {
//在SD卡上创建目录
File tmpDir = new File(Environment.getExternalStorageDirectory() + "/org.chenlijian.test");
if (!tmpDir.exists()) {
tmpDir.mkdir();
}
File img = new File(tmpDir.getAbsolutePath() + "/test.png");
try {
FileOutputStream fos = new FileOutputStream(img);
bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
fos.flush();
fos.close();
return img.getCanonicalPath();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 在拍摄照片之前生成一个文件路径Uri,保证拍出来的照片没有被压缩太小,用日期作为文件名,确保唯一性
*/
public static String getSavePath() {
//获取系统相册的路径
String saveDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/service";
File dir = new File(saveDir);
if (!dir.exists()) {
dir.mkdir();
}
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String fileName = saveDir + "/" + formatter.format(date) + ".jpg";
return fileName;
}
/**
* 计算图片的缩放值
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/**
* 根据路径获得图片并压缩,返回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;
// 设置为true,画质更好一点,加载时间略长
options.inPreferQualityOverSpeed = true;
return BitmapFactory.decodeFile(filePath, options);
}
public static Uri convertUri(Uri uri, Context context) {
InputStream is;
try {
is = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
return saveBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
//添加上传文件的工具类 HttpParameterBuilder
public class HttpParameterBuilder {
private static HttpParameterBuilder mParameterBuilder;
private static Map<String, RequestBody> params;
/**
* 构建私有方法
*/
private HttpParameterBuilder() {
}
/**
* 初始化对象
*/
public static HttpParameterBuilder newBuilder() {
if (mParameterBuilder == null) {
mParameterBuilder = new HttpParameterBuilder();
if (params == null) {
params = new HashMap<>();
}
}
return mParameterBuilder;
}
/**
* 添加参数
* 根据传进来的Object对象来判断是String还是File类型的参数
*/
public HttpParameterBuilder addParameter(String key, Object o) {
if (o instanceof String) {
RequestBody body = RequestBody.create(MediaType.parse("text/plain"), (String) o);
params.put(key, body);
} else if (o instanceof File) {
RequestBody body = RequestBody.create(MediaType.parse("image/*"), (File) o);
params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body);
}
return this;
}
/**
* 初始化图片的Uri来构建参数
* 一般不常用
* 主要用在拍照和图库中获取图片路径的时候
*/
public HttpParameterBuilder addFilesByUri(String key, List<Uri> uris) {
for (int i = 0; i < uris.size(); i++) {
File file = new File(uris.get(i).getPath());
RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);
params.put(key + i + "\"; filename=\"" + file.getName() + "", body);
}
return this;
}
/**
* 构建RequestBody
*/
public Map<String, RequestBody> bulider() {
return params;
}
}
//下面是我们的Model
public void UpLoad(@PartMap Map<String, RequestBody> params, final LoadListener loadListener) {
RetrofitUtils.getInstence()
.API()
.uploadFile(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<BaseUser>() {
@Override
public void accept(BaseUser baseUser) throws Exception {
loadListener.Success(baseUser);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
loadListener.Error(throwable.toString());
}
});
}
//presenter
//修改头像
@Override
public void UpLoad(@PartMap Map<String, RequestBody> params) {
iModel.UpLoad(params, new LoadListener() {
@Override
public void Success(Object o) {
showView.TouXiangSuccess(o);
}
@Override
public void Error(String error) {
showView.Error(error);
}
});
}
//之后是我们的view
//头像的布局
<com.facebook.drawee.view.SimpleDraweeView
app:roundAsCircle="true"
app:placeholderImage="@drawable/ic_yonghu"
android:layout_alignParentLeft="true"
android:layout_marginBottom="@dimen/y5"
android:id="@+id/touxiang"
android:layout_width="@dimen/x42"
android:layout_height="@dimen/y40"
/>
//头像的点事件
case R.id.my_image_view:
//找到pop里面的选项
if(uid!=null){//判断是否登录
setPop();
menu.toggle();
}else{
Toast.makeText(this,"请登录账号",Toast.LENGTH_SHORT).show();
}
break;
//展示 popupWindow
//找到pop里面的选项
private void setPop() {
//弹出popupWindow
v = LayoutInflater.from(this).inflate(R.layout.pp, null);
//找到pop里面的选项
Button pai = v.findViewById(R.id.btn_take_photo);
Button xuan = v.findViewById(R.id.btn_pick_photo);
Button qu =v.findViewById(R.id.btn_cancel);
pai.setOnClickListener(this);
xuan.setOnClickListener(this);
qu.setOnClickListener(this);
popupWindow = new PopupWindow(v, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new ColorDrawable(getResources().
getColor(android.R.color.transparent)));
popupWindow.setOutsideTouchable(true);
//显示
popupWindow.showAtLocation(ShowActivity.this.findViewById(R.id.main),
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
}
//pp布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/pop_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#9999"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/btn_take_photo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="20dip"
android:background="#8e8e8e"
android:text="拍照"
android:textStyle="bold" />
<Button
android:id="@+id/btn_pick_photo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="5dip"
android:background="#8e8e8e"
android:text="从相册选择"
/>
<Button
android:id="@+id/btn_cancel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dip"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="15dip"
android:background="#8e8e8e"
android:text="取消"
android:textColor="#ffffff"
/>
</LinearLayout>
</LinearLayout>
//pp的点击事件
@Override
public void onClick(View v) {
switch (v.getId()){
//调用相机
case R.id.btn_take_photo:
//首先创建一个路径
path= UtilsImageProcess.getSavePath();
//转换成uri路径
uri = Uri.fromFile(new File(path));
//打开相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, 666);
popupWindow.dismiss();
break;
//调用相册
case R.id.btn_pick_photo:
//首先创建一个路径
path= UtilsImageProcess.getSavePath();
Intent in = new Intent(Intent.ACTION_GET_CONTENT);
//指定图片的类型
in.setType("image/*");
//打开相册
startActivityForResult(in, 999);
popupWindow.dismiss();
break;
case R.id.btn_cancel:
Toast.makeText(this,"取消了",Toast.LENGTH_SHORT).show();
popupWindow.dismiss();
break;
}
}
//回调方法
//重写
private static final String TAG = "MainActivity-----";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//判断
switch (requestCode) {
case 666:
//拿到相片
Bitmap bitmap = UtilsImageProcess.getSmallBitmap(path);
//通过工具把相片转换成uri
uri = UtilsImageProcess.saveBitmap(path,bitmap);
//调裁剪的第三方
beginCrop(uri);
break;
case 999:
//获取图片的地址,当更新成功之后,直接给控件赋值而不用再请求数据
Uri source= UtilsImageProcess.convertUri(data.getData(), this);
//调裁剪的第三方
beginCrop(source);
break;
case Crop.REQUEST_CROP:
//裁剪完成的方法
handleCrop(data);
break;
//修改昵称成功之后
case 555:
String na = data.getStringExtra("na");
name.setText(na);
break;
default :
Toast.makeText(this,"取消了",Toast.LENGTH_SHORT).show();
break;
}
}
//启动裁剪Activity
private void beginCrop(Uri source) {
Uri destination1 = Uri.fromFile(new File(UtilsImageProcess.getSavePath()));
Crop.of(source, destination1).asSquare().start(this);
}
//处理裁剪得到的图片,上传到服务器
private void handleCrop(Intent data) {
Uri u = Crop.getOutput(data);
Log.e("dasda",u.getPath()+"asdasd");
try {
//拿到剪裁之后的图片
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), u);
//通过工具把bitmap转换为绝对路径,创建文件上传服务器
String imagePath = UtilsImageProcess.getPath(bitmap);
file = new File(imagePath);
postFile(file);
} catch (IOException e) {
e.printStackTrace();
Log.e("sadadas",e.toString());
}
}
//上传头像的方法
public void postFile(File file){
//准备请求的参数,接口路径 HttpParameterBuilder工具类
Map<String, RequestBody> params = HttpParameterBuilder.newBuilder()
.addParameter("uid",uid)
.addParameter("file",file)
.bulider();
//调取工具类更新接口数据
p.UpLoad(params);
}
//更新成功之后刷新头像
//更新头像
@Override
public void TouXiangSuccess(Object o) {
BaseUser u= (BaseUser) o;
Toast.makeText(this,u.getMsg(),Toast.LENGTH_SHORT).show();
if(u.getCode().equals("0")){
//调获取用户数据的方法
p.GetUserRen(map,Constants.User_url);
}
}
//获取用户信息成功
@Override
public void Success(Object o) {
User u= (User) o;
//get头像赋值
setTouxiang(u);
}
private void setTouxiang(User u) {
String icon = u.getData().getIcon();
Uri parse = Uri.parse(u.getData().getIcon());
touxiang.setImageURI(parse);
myImageView.setImageURI(parse);
int gender = u.getData().getGender();
if(gender==0){
xingbie.setImageResource(R.drawable.ic_nan);
}else{
xingbie.setImageResource(R.drawable.ic_nv);
}
}