现在Retrofit2和RxJava2是很流行的框架,可能是我太闭塞的缘故,竟然没有用过这样的框架,请原谅我以前都是在用xUtils3
今天就来说一下Retrofit2和Kotlin结合上传文件
1、首先集成工具
(1)Kotlin就不用说了,Android Studio 3.0 以后自身就有
(2)Retrofit2集成 在项目文件build.gradle 里添加
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:design:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
}
2、
(1)编写一个KtvApiService接口
/**
* 作者:Galen on 2017/12/16 13:56
* 邮箱:[email protected]
*/
interface KtvApiService {
@Multipart
@POST(FACE_DETECT)
fun detectFace(
@Part("api_key") api_key: RequestBody,
@Part("api_secret") api_secret: RequestBody ,
@Part("return_attributes") return_attributes: RequestBody ,
@Part part: MultipartBody.Part ): Call
@FormUrlEncoded
@POST(FACE_SET_GETDETAIL)
fun getFaceSetDetail(@Field("api_key") api_key: String,
@Field("api_secret") api_secret: String,
@Field("outer_id") outer_id: String):Call
}
(2)、编写请求地址配置Constants(是一个静态的类)
/**
* 作者:Galen on 2017/12/16 13:58
* 邮箱:[email protected]
*/
object Constants {
val LOCAL_SAVE_FACE_IMAGE = Environment.getExternalStorageDirectory().absolutePath + "/face.jpg"
val FACE_BASE_URL = "https://api-cn.faceplusplus.com/facepp/v3/"
const val FACE_DETECT = "detect"
val FACE_FEATURE = "facequality,blur"
val FACE_COMPARE = FACE_BASE_URL + "compare"
val FACE_SEARCH = FACE_BASE_URL + "search"
val FACE_SET = FACE_BASE_URL + "faceset/"
val FACE_SET_CREATE = FACE_SET + "create"
val FACE_SET_ADDFACE = FACE_SET + "addface"
val FACE_SET_REMOVEFACE = FACE_SET + "removeface"
val FACE_SET_UPDATE = FACE_SET + "update"
const val FACE_SET_GETDETAIL ="faceset/getdetail"
val FACE_SET_DELETE = FACE_SET + "delete"
val FACE_SET_GETFACESETS = FACE_SET + "getfacesets"
}
(3)编写返回值 DetectFaceResult(我直接用的GsonFormat转的bean文件)
/**
* 作者:Galen on 2017/12/13 19:31
* 邮箱:[email protected]
*/
class DetectFaceResult {
/**
* image_id : rMqAJcCPIa/et7wAJ4BLpw==
* request_id : 1513164138,f175169b-58c5-43af-ba58-d9150cc72f5c
* time_used : 404
* faces : [{"attributes":{"facequality":{"threshold":70.1,"value":74.748},"blur":{"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}},"face_rectangle":{"width":338,"top":87,"left":182,"height":338},"face_token":"5e43726aa72d35e5e78040c6b819dfb1"}]
*/
var image_id: String? = null
var request_id: String? = null
var time_used: Int = 0
var faces: List? = null
class FacesBean {
/**
* attributes : {"facequality":{"threshold":70.1,"value":74.748},"blur":{"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}}
* face_rectangle : {"width":338,"top":87,"left":182,"height":338}
* face_token : 5e43726aa72d35e5e78040c6b819dfb1
*/
var attributes: AttributesBean? = null
var face_rectangle: FaceRectangleBean? = null
var face_token: String? = null
class AttributesBean {
/**
* facequality : {"threshold":70.1,"value":74.748}
* blur : {"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}
*/
var facequality: FacequalityBean? = null
var blur: BlurBean? = null
class FacequalityBean {
/**
* threshold : 70.1
* value : 74.748
*/
var threshold: Double = 0.toDouble()
var value: Double = 0.toDouble()
}
class BlurBean {
/**
* blurness : {"threshold":50,"value":21.626}
* motionblur : {"threshold":50,"value":21.626}
* gaussianblur : {"threshold":50,"value":21.626}
*/
var blurness: BlurnessBean? = null
var motionblur: MotionblurBean? = null
var gaussianblur: GaussianblurBean? = null
class BlurnessBean {
/**
* threshold : 50.0
* value : 21.626
*/
var threshold: Double = 0.toDouble()
var value: Double = 0.toDouble()
}
class MotionblurBean {
/**
* threshold : 50.0
* value : 21.626
*/
var threshold: Double = 0.toDouble()
var value: Double = 0.toDouble()
}
class GaussianblurBean {
/**
* threshold : 50.0
* value : 21.626
*/
var threshold: Double = 0.toDouble()
var value: Double = 0.toDouble()
}
}
}
class FaceRectangleBean {
/**
* width : 338
* top : 87
* left : 182
* height : 338
*/
var width: Int = 0
var top: Int = 0
var left: Int = 0
var height: Int = 0
}
}
}
(4)调用
fun faceDetect() {
//创建Okhttp
val builder = OkHttpClient.Builder()
//添加日志拦截器(自定义日志拦截器)也可以不添加
//builder.addInterceptor(LoggingInterceptor())
val client = builder.build()
val retrofit = Retrofit.Builder()
.client(client)
.baseUrl(FACE_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(KtvApiService::class.java)
val file = File(LOCAL_SAVE_FACE_IMAGE)
val photoRequestBody = RequestBody.create(MediaType.parse("image/jpg"), file)
val photoPart = MultipartBody.Part.createFormData("image_file", file.name, photoRequestBody)
val api_key = RequestBody.create(MediaType.parse("text/plain"), API_KEY)
val api_secret = RequestBody.create(MediaType.parse("text/plain"), API_SECRET)
val return_attributes = RequestBody.create(MediaType.parse("text/plain"), FACE_FEATURE)
if (file.exists()) {
val repos = service.detectFace(api_key, api_secret, return_attributes, photoPart)
repos.enqueue(object : Callback {
override fun onResponse(call: Call?, response: Response?) {
if (response != null) {
Log.e("ScanActivity 成功", response.body().toString())
}
}
override fun onFailure(call: Call?, t: Throwable?) {
Log.e("ScanActivity 失败", t.toString())
}
})
}
}
重点内容
上传图片要携带参数时必须要以这样的格式
@Multipart
@POST(FACE_DETECT)
fun detectFace(
@Part("api_key") api_key: RequestBody,
@Part("api_secret") api_secret: RequestBody ,
@Part("return_attributes") return_attributes: RequestBody ,
@Part part: MultipartBody.Part ): Call
而不是
@Multipart
@POST(FACE_DETECT)
fun detectFace(
@Part("api_key") api_key: String,
@Part("api_secret") api_secret: String,
@Part("return_attributes") return_attributes: String,
@Part part: MultipartBody.Part ): Call
这样上传是错误的
调用的时候
携带的参数应该这样写
上传照片的参数应该这样
val photoRequestBody = RequestBody.create(MediaType.parse("image/jpg"), file)
val photoPart = MultipartBody.Part.createFormData("image_file", file.name, photoRequestBody)
其他参数
val api_key = RequestBody.create(MediaType.parse("text/plain"), API_KEY)
val api_secret = RequestBody.create(MediaType.parse("text/plain"), API_SECRET)
val return_attributes = RequestBody.create(MediaType.parse("text/plain"), FACE_FEATURE)
到此完工
本人第一次在写文章,请多多关照,如需帮助,求留言,也请大家多多指教