依赖
//gson
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
//glide
implementation 'com.github.bumptech.glide:glide:4.8.0'
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
//RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'//retrofit 库
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'//转换器,请求结果转换成Model
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'//配合Rxjava 使用
//权限
implementation 'com.github.dfqin:grantor:2.5'
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
获取危险权限
private void getPermission() {
PermissionsUtil.requestPermission(this, new PermissionListener() {
@Override
public void permissionGranted(@NonNull String[] permission) {
}
@Override
public void permissionDenied(@NonNull String[] permission) {
}
}, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
}
文件路径
private File file = new File(Environment.getExternalStorageDirectory() + "/Pictures/a.jpg");
bean类
public class UploadBean {
/**
* code : 200
* res : 上传文件成功
* data : {"url":"http://yun918.cn/study/public/uploadfiles/1908A/b.jpg"}
*/
private int code;
private String res;
private DataBean data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getRes() {
return res;
}
public void setRes(String res) {
this.res = res;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public static class DataBean {
/**
* url : http://yun918.cn/study/public/uploadfiles/1908A/b.jpg
*/
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
一、Ok上传
//获取OK对象
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
//获取请求体
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
//多类型请求体
MultipartBody body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key", "tian")
.addFormDataPart("file", file.getName(), requestBody)
.build();
//获取request对象
Request request = new Request.Builder()
.url("http://yun918.cn/study/public/file_upload.php")
.post(body)
.build();
//获取call对象
Call call = okHttpClient.newCall(request);
//call执行请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("TAG", "onFailure: 网络错误" + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String json = response.body().string();
UploadBean uploadBean = new Gson().fromJson(json, UploadBean.class);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, uploadBean.getRes(), Toast.LENGTH_SHORT).show();
Glide.with(MainActivity.this).load(uploadBean.getData().getUrl()).into(ivImg);
}
});
}
});
二、Retrofit上传文件
·接口
public interface ApiService {
String baseUrl = "http://yun918.cn/";
@POST("study/public/file_upload.php")
@Multipart
Observable<UploadBean> upLoad(@Part("key") RequestBody key, @Part MultipartBody.Part file);
}
·上传
//创建retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
//创建接口service对象
ApiService apiService = retrofit.create(ApiService.class);
//封装请求体
RequestBody body= RequestBody.create(MediaType.parse("image/png"), file);
//文件封装
MultipartBody.Part file = MultipartBody.Part.createFormData("file", this.file.getName(), body);
//文本封装
RequestBody requestBody = body.create(MediaType.parse("multipart/form-data"), "tian");
Observable<UploadBean> observable = apiService.upLoad(requestBody , file);
//发送网络请求并处理结果
observable
.subscribeOn(Schedulers.io())//子线程请求
.observeOn(AndroidSchedulers.mainThread())//主线程操作
.subscribe(new Observer<UploadBean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UploadBean uploadBean) {
Toast.makeText(MainActivity.this, uploadBean.getRes(), Toast.LENGTH_SHORT).show();
Glide.with(MainActivity.this).load(uploadBean.getData().getUrl()).into(ivImg);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "onError: 网络错误" + e.getMessage());
}
@Override
public void onComplete() {
}
});
三、拍照(album)上传文件
访问相机权限
<uses-permission android:name="android.permission.CAMERA"/>
获取权限
/**
* 获取权限
*/
private void getPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
//如果有就打开相机
openCamera();
} else {
//获取相机权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 100);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//打开相机
openCamera();
}
}
打开相机
/**
* 打开相机
*/
private void openCamera() {
//创建文件用于保存图片
cameraFile = new File(getCacheDir(), System.currentTimeMillis() + ".jpg");
//如果不存在
if (!cameraFile.exists()) {
try {
cameraFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//判断兼容7.0设备
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
imgUri = Uri.fromFile(cameraFile);
} else {
imgUri = FileProvider.getUriForFile(this, "com.tianyu.upload_album.provider", cameraFile);
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);//将拍好的图片存入指定的uri
startActivityForResult(intent, 200);
}
/**
* 获取拍照结果
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 200) {
//OK
uploadOk(cameraFile);
}
}
4.清单文件中配置FileProvider:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.tianyu.upload_album.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
5.需要在res/xml下创建一个file_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="upload" path=""/>
</paths>
4相册选取照片
1.跳转相册
private void opAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, 300);
}
2.处理回传数据
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 300) {
Uri uri = data.getData();
File file = getFileFromUri(uri);
if (file.exists()) {
uploadOk(file);
}
}
}
3.判断接收回来的uri不为空 处理版本
private File getFileFromUri(Uri uri) {
if (uri == null) {
return null;
}
//处理uri,7.0以后的fileProvider 把URI 以content provider 方式 对外提供的解析方法
switch (uri.getScheme()) {
case "content"://7.0以后
return getFileFromContentUri(uri);
case "file"://7.0以前
return new File(uri.getPath());
default:
return null;
}
}
4.如果是7.0以后的内容提供者解析内容
private File getFileFromContentUri(Uri uri) {
File file = null;
String filePath = null;
ContentResolver resolver = getContentResolver();
String[] filePathColumn = {MediaStore.MediaColumns.DATA};
Cursor cursor = resolver.query(uri, filePathColumn, null, null, null);
if (cursor.moveToNext()) {
filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
}
cursor.close();
if (!TextUtils.isEmpty(filePath)) {
file = new File(filePath);
}
return file;
}
注意事项
- Android P全面禁止了非https链接
我们需要在自己设置非安全连接。
非安全连接设置:在清单列表加一句
默认允许所有网址使用非安全连接
android:usesCleartextTraffic="true"