Commit 0a8e6598 authored by yinjiacheng's avatar yinjiacheng

add 图片服务功能

parent 75f0cf84
......@@ -89,6 +89,7 @@ dependencies {
implementation('com.yidian.android:CommonComponent:0.0.88') {
exclude(group: 'com.yidian.android', module: 'NetworkImageLib')
}
implementation files('libs/ks3-androidsdk-1.4.9.jar')
api 'com.github.bumptech.glide:glide:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0'
......
......@@ -14,6 +14,7 @@ import com.scwang.smart.refresh.layout.constant.SpinnerStyle
import com.yidian.common.http.ApiSaveCookiesInterceptor
import com.yidian.common.http.ApiSetCookiesInterceptor
import com.yidian.common.services.AppUpgradeService
import com.yidian.common.services.ImageService
import com.yidian.common.services.XEventService
import com.yidian.common.services.XPageService
import com.yidian.common.services.http.MBHttpReqService
......@@ -209,6 +210,7 @@ open class YdBaseApplication : Application() {
Zap.addService(XEventService.SERVICE_NAME, XEventService())
Zap.addService(AppUpgradeService.SERVICE_NAME, AppUpgradeService())
Zap.addService(MBHttpReqService.SERVICE_NAME, MBHttpReqService())
Zap.addService(ImageService.SERVICE_NAME, ImageService())
}
/**
......
package com.yidian.common.bean
import com.google.gson.annotations.SerializedName
import java.io.Serializable
/**
* author: yinjiacheng
* date: 7/8/21 8:55 AM
* description: 图片服务-选择图片业务参数数据结构
*/
data class SelectImageParamsBean(
@SerializedName("maxCount")
val maxCount: Int,
@SerializedName("selectedImages")
val selectedImages: List<SelectedImage>
) : Serializable
data class SelectedImage(
@SerializedName("id")
val id: String
) : Serializable
package com.yidian.common.bean
/**
* author: yinjiacheng
* date: 7/8/21 8:43 AM
* description: 图片服务-已选择图片数据结构
*/
data class SelectedImageBean(val id: String, val photo_base64_str: String)
package com.yidian.common.bean
/**
* author: yinjiacheng
* date: 7/8/21 8:43 AM
* description: 图片服务-已上传图片数据结构
*/
data class UploadImageBean(val id: String, val image_uploaded_key: String)
package com.yidian.common.http
import com.google.gson.reflect.TypeToken
import com.yidian.common.YdBaseApplication
import com.yidian.common.http.bean.GetKSYunObjectIdBean
import com.yidian.common.http.bean.GetKSYunTokenBean
import com.yidian.common.http.callback.IGetKSYunObjectIdCallback
import com.yidian.http.ServiceFactory
import com.yidian.utils.ToastUtil
/**
* author: yinjiacheng
* date: 7/8/21 4:54 PM
* description: Common网络请求实现
*/
object CommonDataSource {
// 301 获取金山云token接口
fun getKSYunToken(requestParams: HashMap<String, String?>): HttpResult<GetKSYunTokenBean.Response>? {
val timeStamp = System.currentTimeMillis()
val publicParamsMap = HttpParamsUtils.getPublicParamsMap(timeStamp)
val privateParamsMap = HttpParamsUtils.getPrivateParamsMap(requestParams, timeStamp)
val res: HttpResult<Any?>? = ServiceFactory.getInstance().createService(CommonService::class.java)
.getKSYunToken(publicParamsMap, privateParamsMap)
.execute().body()
if (res?.code == 0) {
return HttpParamsUtils.rsaDecryptResult(res, object : TypeToken<GetKSYunTokenBean.Response>() {}.type)
} else {
val decodeResult = HttpResult<GetKSYunTokenBean.Response>()
decodeResult.code = res?.code!!
decodeResult.reason = res.reason
decodeResult.status = res.status
ToastUtil.showToast(YdBaseApplication.context, res.reason)
}
return null
}
// 302 获取金山云ObjectId和Bucket接口
fun getKSYunObjectId(apiCallback: IGetKSYunObjectIdCallback, requestParams: HashMap<String, String?>) {
val timeStamp = System.currentTimeMillis()
val publicParamsMap = HttpParamsUtils.getPublicParamsMap(timeStamp)
val privateParamsMap = HttpParamsUtils.getPrivateParamsMap(requestParams, timeStamp)
ServiceFactory.getInstance().createService(CommonService::class.java)
.getKSYunObjectId(publicParamsMap, privateParamsMap)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<GetKSYunObjectIdBean.Response>() {
override fun onSuccess(result: HttpResult<GetKSYunObjectIdBean.Response>?) {
apiCallback.getKSYunObjectIdSuccess(result?.result)
}
override fun onFailer(result: HttpResult<GetKSYunObjectIdBean.Response>?) {
apiCallback.getKSYunObjectIdFailure(result?.reason)
}
})
}
}
package com.yidian.common.http
import io.reactivex.rxjava3.core.Observable
import retrofit2.Call
import retrofit2.http.*
/**
* author: yinjiacheng
* date: 7/8/21 4:53 PM
* description: Common网络请求定义
*/
interface CommonService {
@Headers("Content-Type: application/json")
@POST(URLs.getKSYunToken)
fun getKSYunToken(@QueryMap commonParams: Map<String, String>, @Body requestParams: Map<String, String?>): Call<HttpResult<Any?>>
@GET(URLs.getKSYunObjectId)
fun getKSYunObjectId(
@QueryMap commonParams: Map<String, String>,
@QueryMap requestParams: Map<String, String?>
): Observable<HttpResult<Any?>>
}
package com.yidian.common.http.bean
/**
* author: yinjiacheng
* date: 5/23/21 12:13 PM
* description: 获取金山云bucket和objectId
*/
class GetKSYunObjectIdBean {
data class Response(val bucket: String, val objectId: String)
}
package com.yidian.common.http.bean
/**
* author: yinjiacheng
* date: 5/23/21 12:13 PM
* description: 获取金山云token
*/
class GetKSYunTokenBean(val request: Request, val response: Response) {
data class Request(
val http_method: String,
val date: String,
val resource: String,
val content_md5: String,
val content_type: String,
val headers: String
)
data class Response(val token: String)
}
package com.yidian.common.http.callback
import com.yidian.common.http.bean.GetKSYunObjectIdBean
/**
* author: yinjiacheng
* date: 5/23/21 12:18 PM
* description: 获取金山云ObjectId
*/
interface IGetKSYunObjectIdCallback {
fun getKSYunObjectIdSuccess(result: GetKSYunObjectIdBean.Response?)
fun getKSYunObjectIdFailure(message: String?)
}
package com.yidian.common.services.BsNewsContentTest
import com.yidian.common.base.BaseFragment
import com.yidian.yac.core.core.YacRouteNode
import com.yidian.yac.core.zap.ZapService
abstract class NewsTest: ZapService() {
abstract fun log()
}
\ No newline at end of file
package com.yidian.common.services
import android.app.Activity
import android.util.Base64
import com.google.gson.Gson
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.listener.OnResultCallbackListener
import com.yidian.common.bean.SelectImageParamsBean
import com.yidian.common.bean.SelectedImageBean
import com.yidian.common.bean.UploadImageBean
import com.yidian.common.utils.GlideEngine
import com.yidian.common.utils.KS3Core
import com.yidian.xarc.xrouter.ResultResolver
import com.yidian.xpage.observer.DStackActivityManager
import com.yidian.yac.core.zap.ZapService
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
import java.io.FileInputStream
/**
* author: yinjiacheng
* date: 7/7/21 7:38 PM
* description: 图片服务
* 提供调用原生相机拍照、图片选择器、图片预览、图片上传能力
*/
class ImageService : ZapService() {
companion object {
private const val TAG = "ImageService"
const val SERVICE_NAME = "ImageService"
// 选择图片
const val ACTION_SELECT_PIC = "selectImage"
// 拍照
const val ACTION_TAKE_PIC = "takePhoto"
// 上传图片
const val ACTION_UPLOAD_PIC = "uploadImage"
// 预览图片 本期不做
const val ACTION_PREVIEW_PIC = "previewPic"
// 权限获取失败
private const val CODE_PERMISSION_GRANT_FAIL = 20301
// 选择失败、选择取消、拍照取消
private const val CODE_ACTION_CANCEL = 20302
// 文件不存在
private const val CODE_FILE_NOT_EXIST = 20306
// 文件上传失败
private const val CODE_FILE_UPLOAD_FAIL = 20307
// 图片最大选择数量
private const val SELECT_PIC_MAX_COUNT = 9
}
private val gson by lazy { Gson() }
private lateinit var resolver: ResultResolver
/**
* 当前栈顶Activity实例
*/
private lateinit var curTopActivity: Activity
/**
* 内存缓存已选择图片
*/
private val cacheSelectedImages by lazy { ArrayList<LocalMedia>() }
override fun onAction(path: String, action: String, params: Any, options: Any, resolver: ResultResolver) {
this.resolver = resolver
curTopActivity = DStackActivityManager.getInstance().topActivity
val resolveParams = params as JSONObject
when (action) {
ACTION_SELECT_PIC -> {
selectPic(gson.fromJson(resolveParams.toString(), SelectImageParamsBean::class.java))
}
ACTION_TAKE_PIC -> {
takePic()
}
ACTION_UPLOAD_PIC -> {
uploadPic(resolveParams.optString("id"))
}
ACTION_PREVIEW_PIC -> {
// 本期不做
}
}
}
override fun onExit() {
}
override fun onInit() {
}
/**
* 选择图片
*/
private fun selectPic(params: SelectImageParamsBean) {
PictureSelector.create(curTopActivity)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.maxSelectNum(SELECT_PIC_MAX_COUNT - params.maxCount)
.forResult(object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: MutableList<LocalMedia>?) {
if (result.isNullOrEmpty()) {
resolver.fail(CODE_ACTION_CANCEL, "select failed", "选择失败")
return
}
cacheSelectedImages.addAll(result as ArrayList<LocalMedia>)
val picList = ArrayList<SelectedImageBean>(SELECT_PIC_MAX_COUNT - params.maxCount)
result.forEach {
picList.add(
SelectedImageBean(
result[0].id.toString(),
Base64.encodeToString(FileInputStream(it.realPath).readBytes(), Base64.DEFAULT)
)
)
}
// 成功回传数据
resolver.success(JSONArray(gson.toJson(picList)))
}
override fun onCancel() {
resolver.fail(CODE_ACTION_CANCEL, "select cancel", "选择取消")
}
})
}
/**
* 拍摄图片
*/
private fun takePic() {
PictureSelector.create(curTopActivity)
.openCamera(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.forResult(object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: MutableList<LocalMedia>?) {
if (result.isNullOrEmpty()) {
resolver.fail(CODE_ACTION_CANCEL, "take failed", "拍照失败")
return
}
cacheSelectedImages.add(result[0])
// 成功回传数据
resolver.success(
JSONArray(
gson.toJson(
arrayListOf(
SelectedImageBean(
result[0].id.toString(),
Base64.encodeToString(FileInputStream(result[0].realPath).readBytes(), Base64.DEFAULT)
)
)
)
)
)
}
override fun onCancel() {
resolver.fail(CODE_ACTION_CANCEL, "take cancel", "拍照取消")
}
})
}
/**
* 上传图片
* @param id 需要上传的图片id
*/
private fun uploadPic(id: String) {
var uploadPic: LocalMedia? = null
cacheSelectedImages.forEach {
// 遍历寻找指定图片
if (id == it.id.toString()) {
uploadPic = it
return@forEach
}
}
uploadPic?.let {
val file = File(it.realPath)
if (!file.exists()) {
resolver.fail(CODE_FILE_NOT_EXIST, "file not exist", "文件不存在")
return
}
KS3Core.INSTANCE.uploadObject(file, KS3Core.ObjectType.IMAGE, KS3Core.ScenarioType.COMMODITY, object : KS3Core.OnKS3TaskListener {
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
resolver.success(JSONObject(gson.toJson(UploadImageBean(id, "${bucket}/${objectKey}"))))
}
override fun onTaskFailure(statesCode: Int, message: String?) {
resolver.fail(CODE_FILE_UPLOAD_FAIL, "upload failed", "上传失败")
}
})
}
}
}
package com.yidian.common.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.listener.OnImageCompleteCallback;
import com.luck.picture.lib.tools.MediaUtils;
import com.luck.picture.lib.widget.longimage.ImageSource;
import com.luck.picture.lib.widget.longimage.ImageViewState;
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
import com.yidian.common.R;
/**
* @author:luck
* @date:2019-11-13 17:02
* @describe:Glide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context
* @param url
* @param imageView
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.into(imageView);
}
/**
* 加载网络图片适配长图方案
* # 注意:此方法只有加载网络图片才会回调
*
* @param context
* @param url
* @param imageView
* @param longImageView
* @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url,
@NonNull ImageView imageView,
SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
Glide.with(context)
.asBitmap()
.load(url)
.into(new ImageViewTarget<Bitmap>(imageView) {
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
if (callback != null) {
callback.onShowLoading();
}
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
super.onLoadFailed(errorDrawable);
if (callback != null) {
callback.onHideLoading();
}
}
@Override
protected void setResource(@Nullable Bitmap resource) {
if (callback != null) {
callback.onHideLoading();
}
if (resource != null) {
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
resource.getHeight());
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
if (eqLongImage) {
// 加载长图
longImageView.setQuickScaleEnabled(true);
longImageView.setZoomEnabled(true);
longImageView.setDoubleTapZoomDuration(100);
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
longImageView.setImage(ImageSource.cachedBitmap(resource),
new ImageViewState(0, new PointF(0, 0), 0));
} else {
// 普通图片
imageView.setImageBitmap(resource);
}
}
}
});
}
/**
* 加载网络图片适配长图方案
* # 注意:此方法只有加载网络图片才会回调
*
* @param context
* @param url
* @param imageView
* @param longImageView
* @ 已废弃
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url,
@NonNull ImageView imageView,
SubsamplingScaleImageView longImageView) {
Glide.with(context)
.asBitmap()
.load(url)
.into(new ImageViewTarget<Bitmap>(imageView) {
@Override
protected void setResource(@Nullable Bitmap resource) {
if (resource != null) {
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
resource.getHeight());
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
if (eqLongImage) {
// 加载长图
longImageView.setQuickScaleEnabled(true);
longImageView.setZoomEnabled(true);
longImageView.setDoubleTapZoomDuration(100);
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
longImageView.setImage(ImageSource.cachedBitmap(resource),
new ImageViewState(0, new PointF(0, 0), 0));
} else {
// 普通图片
imageView.setImageBitmap(resource);
}
}
}
});
}
/**
* 加载相册目录
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.centerCrop()
.sizeMultiplier(0.5f)
.placeholder(R.drawable.picture_image_placeholder)
.into(new BitmapImageViewTarget(imageView) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.
create(context.getResources(), resource);
circularBitmapDrawable.setCornerRadius(8);
imageView.setImageDrawable(circularBitmapDrawable);
}
});
}
/**
* 加载gif
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadAsGifImage(@NonNull Context context, @NonNull String url,
@NonNull ImageView imageView) {
Glide.with(context)
.asGif()
.load(url)
.into(imageView);
}
/**
* 加载图片列表图片
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.placeholder(R.drawable.picture_image_placeholder)
.into(imageView);
}
private GlideEngine() {
}
private static GlideEngine instance;
public static GlideEngine createGlideEngine() {
if (null == instance) {
synchronized (GlideEngine.class) {
if (null == instance) {
instance = new GlideEngine();
}
}
}
return instance;
}
}
package com.yidian.common.utils
import android.content.Context
import android.util.Log
import com.google.gson.Gson
import com.ksyun.ks3.exception.Ks3Error
import com.ksyun.ks3.model.acl.CannedAccessControlList
import com.ksyun.ks3.services.AuthListener
import com.ksyun.ks3.services.Ks3Client
import com.ksyun.ks3.services.Ks3ClientConfiguration
import com.ksyun.ks3.services.handler.PutObjectACLResponseHandler
import com.ksyun.ks3.services.handler.PutObjectResponseHandler
import com.ksyun.ks3.services.request.PutObjectRequest
import com.yidian.common.YdBaseApplication
import com.yidian.common.http.CommonDataSource
import com.yidian.common.http.bean.GetKSYunObjectIdBean
import com.yidian.common.http.callback.IGetKSYunObjectIdCallback
import com.yidian.utils.MD5Util
import com.yidian.yac.ftdevicefinger.core.FtDeviceFingerManager
import cz.msebera.android.httpclient.Header
import java.io.File
/**
* author: yinjiacheng
* date: 5/20/21 11:08 AM
* description: 金山云存储
*/
class KS3Core private constructor(val context: Context) : AuthListener {
private val client by lazy { Ks3Client(this, context) }
private val gson by lazy { Gson() }
private val putObjectResponseHandler by lazy {
object : PutObjectResponseHandler() {
override fun onTaskProgress(progress: Double) {
// work thread
}
override fun onTaskFailure(
statesCode: Int,
error: Ks3Error?,
responceHeaders: Array<out Header>?,
response: String?,
throwable: Throwable?
) {
Log.e(
TAG,
"put object fail:, errorMsg: ${error?.errorMessage}"
)
}
override fun onTaskSuccess(statesCode: Int, responceHeaders: Array<out Header>?) {
Log.d(TAG, "put object success.")
}
override fun onTaskStart() {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
}
}
private val putObjectACLResponseHandler by lazy {
object : PutObjectACLResponseHandler() {
override fun onSuccess(statesCode: Int, responceHeaders: Array<out Header>?) {
Log.d(TAG, "put object acl success.")
}
override fun onFailure(
statesCode: Int,
error: Ks3Error?,
responceHeaders: Array<out Header>?,
response: String?,
throwable: Throwable?
) {
Log.e(TAG, "put object acl fail:, errorMsg: ${error?.errorMessage}")
}
}
}
companion object {
const val TAG = "KS3Core"
const val DEFAULT_BUCKET_NAME = "bp-yidian"
const val DEFAULT_END_POINT = "ks3-cn-beijing.ksyun.com"
const val VIDEO_SUFFIX = ".mp4"
const val IMAGE_SUFFIX = ".jpg"
val INSTANCE: KS3Core by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
KS3Core(context = YdBaseApplication.context)
}
}
init {
setupClient()
}
/**
* 配置金山云client
*/
private fun setupClient() {
client.setConfiguration(Ks3ClientConfiguration.getDefaultConfiguration())
client.setEndpoint(DEFAULT_END_POINT)
}
/**
* 文件上传
* @param path 本地文件全路径
* @param type 文件类型
* @param scenario 业务场景
*/
fun uploadObject(
path: String,
type: ObjectType,
scenario: ScenarioType,
listener: OnKS3TaskListener
) {
CommonDataSource.getKSYunObjectId(object : IGetKSYunObjectIdCallback {
override fun getKSYunObjectIdSuccess(result: GetKSYunObjectIdBean.Response?) {
Log.d(
TAG,
"request getKSYun objectId success, objectId: ${result?.objectId}, bucket: ${result?.bucket}"
)
// 执行金山云上传
val request = PutObjectRequest(
result?.bucket,
result?.objectId + getObjectKeySuffix(type),
File(path)
)
request.cannedAcl = CannedAccessControlList.Private
client.putObject(
request,
KS3CorePutObjectResponseHandler(
result?.bucket,
result?.objectId + getObjectKeySuffix(type),
listener
)
)
}
override fun getKSYunObjectIdFailure(message: String?) {
Log.e(TAG, "request get KSYun objectId fail, message: $message")
}
}, hashMapOf(Pair("scenario", scenario.scenario)))
}
/**
* 文件上传
* @param path 本地文件全路径
* @param scenario 业务场景
*/
fun uploadObject(path: String, scenario: ScenarioType, listener: OnKS3TaskListener) {
CommonDataSource.getKSYunObjectId(object : IGetKSYunObjectIdCallback {
override fun getKSYunObjectIdSuccess(result: GetKSYunObjectIdBean.Response?) {
Log.d(
TAG,
"request getKSYun objectId success, objectId: ${result?.objectId}, bucket: ${result?.bucket}"
)
// 执行金山云上传
val request = PutObjectRequest(result?.bucket, result?.objectId, File(path))
request.cannedAcl = CannedAccessControlList.Private
client.putObject(
request,
KS3CorePutObjectResponseHandler(result?.bucket, result?.objectId, listener)
)
}
override fun getKSYunObjectIdFailure(message: String?) {
Log.e(TAG, "request get KSYun objectId fail, message: $message")
}
}, hashMapOf(Pair("scenario", scenario.scenario)))
}
/**
* 文件上传
* @param file 文件实体
* @param scenario 业务场景
*/
fun uploadObject(file: File, scenario: ScenarioType, listener: OnKS3TaskListener) {
CommonDataSource.getKSYunObjectId(object : IGetKSYunObjectIdCallback {
override fun getKSYunObjectIdSuccess(result: GetKSYunObjectIdBean.Response?) {
Log.d(
TAG,
"request getKSYun objectId success, objectId: ${result?.objectId}, bucket: ${result?.bucket}"
)
// 执行金山云上传
val request = PutObjectRequest(result?.bucket, result?.objectId, file)
request.cannedAcl = CannedAccessControlList.Private
client.putObject(
request,
KS3CorePutObjectResponseHandler(result?.bucket, result?.objectId, listener)
)
}
override fun getKSYunObjectIdFailure(message: String?) {
Log.e(TAG, "request get KSYun objectId fail, message: $message")
}
}, hashMapOf(Pair("scenario", scenario.scenario)))
}
/**
* 文件上传
* @param file 文件实体
* @param type 文件类型
* @param scenario 业务场景
*/
fun uploadObject(
file: File,
type: ObjectType,
scenario: ScenarioType,
listener: OnKS3TaskListener
) {
CommonDataSource.getKSYunObjectId(object : IGetKSYunObjectIdCallback {
override fun getKSYunObjectIdSuccess(result: GetKSYunObjectIdBean.Response?) {
Log.d(
TAG,
"request getKSYun objectId success, objectId: ${result?.objectId}, bucket: ${result?.bucket}"
)
// 执行金山云上传
val request = PutObjectRequest(
result?.bucket,
result?.objectId + getObjectKeySuffix(type),
file
)
request.cannedAcl = CannedAccessControlList.Private
client.putObject(
request,
KS3CorePutObjectResponseHandler(
result?.bucket,
result?.objectId + getObjectKeySuffix(type),
listener
)
)
}
override fun getKSYunObjectIdFailure(message: String?) {
Log.e(TAG, "request get KSYun objectId fail, message: $message")
}
}, hashMapOf(Pair("scenario", scenario.scenario)))
}
/**
* 获取ObjectKey后缀
*/
private fun getObjectKeySuffix(type: ObjectType): String {
return when (type) {
ObjectType.IMAGE -> IMAGE_SUFFIX
ObjectType.VIDEO -> VIDEO_SUFFIX
}
}
/**
* 本地生成ObjectKey
* 作为Object在云空间的唯一标识
*/
private fun getLocalObjectKey(name: String, type: ObjectType): String {
return MD5Util.md5Encrypt32Upper(name + FtDeviceFingerManager.getDeviceFinger()) +
if (type == ObjectType.VIDEO) VIDEO_SUFFIX else IMAGE_SUFFIX
}
/**
* 调用金山云API后 SDK会回调此函数用于获取必要参数向AppServer请求token
*/
override fun onCalculateAuth(
httpMethod: String,
contentType: String,
date: String,
contentMD5: String,
resource: String,
headers: String
): String? {
// 此处由APP端向业务服务器发送post请求返回Token
// 该回调方法运行在非主线程
Log.d(
TAG,
"KSYun calculate auth, httpMethod: $httpMethod, contentType: $contentType, date: $date, contentMD5: $contentMD5, resource: $resource, headers: $headers"
)
val requestParams = HashMap<String, String?>()
requestParams["http_method"] = httpMethod
requestParams["date"] = date
requestParams["resource"] = resource
requestParams["content_md5"] = contentMD5
requestParams["content_type"] = contentType
requestParams["headers"] = headers
return CommonDataSource.getKSYunToken(requestParams)?.result?.token
}
/**
* 业务监听
*/
interface OnKS3TaskListener {
fun onTaskStart()
fun onTaskProgress(progress: Double)
fun onTaskFinish()
fun onTaskCancel()
fun onTaskSuccess(bucket: String?, objectKey: String?)
fun onTaskFailure(statesCode: Int, message: String?)
}
/**
* 上传对象的类型
*/
enum class ObjectType {
VIDEO, IMAGE
}
/**
* 业务场景的类型
*/
enum class ScenarioType(val scenario: String) {
// 身份证
ID_CARD("id_card"),
// 活体数据
ALIVE_DETECT("living_data"),
// 营业执照
BUSINESS_LICENSE("business_license"),
// 商品
COMMODITY("goods")
}
/**
* 金山云object上传handler
*/
class KS3CorePutObjectResponseHandler(
private val bucket: String?,
private val objectKey: String?,
val listener: OnKS3TaskListener
) : PutObjectResponseHandler() {
override fun onTaskProgress(progress: Double) {
// work thread
listener.onTaskProgress(progress)
}
override fun onTaskFailure(
statesCode: Int,
error: Ks3Error?,
responceHeaders: Array<out Header>?,
response: String?,
throwable: Throwable?
) {
Log.e(
TAG,
"put object fail:, errorMsg: ${error?.errorMessage}"
)
listener.onTaskFailure(statesCode, error?.errorMessage)
}
override fun onTaskSuccess(statesCode: Int, responceHeaders: Array<out Header>?) {
Log.d(TAG, "put object success.")
listener.onTaskSuccess(bucket, objectKey)
}
override fun onTaskStart() {
listener.onTaskStart()
}
override fun onTaskFinish() {
listener.onTaskFinish()
}
override fun onTaskCancel() {
listener.onTaskCancel()
}
}
}
......@@ -277,7 +277,8 @@ public static final int *;
#网络相关类
-keep class com.yidian.http.**{*;}
-keep class com.yidian.common.http.**{*;}
-keep class com.yidian.common.bean.**{*;}
-keep class com.yidian.common.http.bean.**{*;}
-keep class com.yidian.shenghuoquan.newscontent.http.**{*;}
-keep class com.yidian.common.utils.*{*;}
-keep class com.yidian.shenghuoquan.newscontent.utils.*{*;}
......@@ -358,3 +359,11 @@ public static final int *;
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#PictureSelector 2.0
-keep class com.luck.picture.lib.** { *; }
#Ucrop
-dontwarn com.yalantis.ucrop**
-keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; }
......@@ -107,7 +107,8 @@
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
tools:replace="android:theme" />
<!-- 以下为友盟推送基本配置信息 start-->
<service
......
......@@ -99,7 +99,9 @@ ext.dependencies = [
// 屏幕适配
'me.jessyan:autosize:1.2.1',
//https://github.com/CymChad/BaseRecyclerViewAdapterHelper
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4',
// PictureSelector2.0 https://github.com/LuckSiege/PictureSelector
'io.github.lucksiege:pictureselector:v2.7.3-rc05'
],
other : [
':CommonLib:Common'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment