完成美颜UI 90%
@ -40,6 +40,7 @@ import com.yunbao.faceunity.utils.CSVUtils;
|
||||
import com.yunbao.faceunity.utils.FURenderer;
|
||||
import com.yunbao.faceunity.utils.FaceCameraConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.utils.net.OkHttpUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@ -71,6 +72,7 @@ public class FaceManager implements SensorEventListener {
|
||||
return;
|
||||
}
|
||||
FaceUnityData.mApplication=context;
|
||||
OkHttpUtils.getInstance().init(context, false);
|
||||
FURenderManager.setCoreDebug(FULogger.LogLevel.OFF);
|
||||
FURenderManager.setKitDebug(FULogger.LogLevel.OFF);
|
||||
FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() {
|
||||
@ -91,9 +93,8 @@ public class FaceManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 配置美颜SDK
|
||||
* @param beautyControlView 控制view
|
||||
*/
|
||||
public void initFURender(Context context, FaceUnityView beautyControlView) {
|
||||
public void initFURender(Context context) {
|
||||
FURenderer.getInstance().setup(context);
|
||||
mFURenderer = FURenderer.getInstance();
|
||||
mFURenderer.setInputTextureType(FUInputTextureEnum.FU_ADM_FLAG_COMMON_TEXTURE);
|
||||
@ -104,11 +105,17 @@ public class FaceManager implements SensorEventListener {
|
||||
mFURenderer.setInputOrientation(CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_FRONT));
|
||||
mFURenderer.setMarkFPSEnable(true);
|
||||
mFaceUnityDataFactory = FaceUnityDataFactory.getInstance();
|
||||
beautyControlView.bindDataFactory(mFaceUnityDataFactory);
|
||||
|
||||
SensorManager mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
|
||||
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定控制view
|
||||
*/
|
||||
public void bindControlView(FaceUnityView view){
|
||||
view.bindDataFactory(mFaceUnityDataFactory);
|
||||
}
|
||||
|
||||
private boolean mIsFirstFrame = true;
|
||||
|
@ -0,0 +1,124 @@
|
||||
package com.yunbao.faceunity.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.adapters.vh.AnimViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.AnimojiViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BaseViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautyBodyViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautyShapeViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautySkinViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BigHeadViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.FilterViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.FineStickerViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.MakeupViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.StickerViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.StyleViewHolder;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<? extends BaseBean> list;
|
||||
public int selectPosition = -1;
|
||||
|
||||
public ContainerRecyclerAdapter(Context mContext) {
|
||||
this.mContext = mContext;
|
||||
}
|
||||
|
||||
public void setList(ArrayList<? extends BaseBean> list) {
|
||||
this.list = list;
|
||||
this.selectPosition = 0;
|
||||
}
|
||||
|
||||
public int getSelectPosition() {
|
||||
return selectPosition;
|
||||
}
|
||||
|
||||
public void setSelectPosition(int selectPosition) {
|
||||
this.selectPosition = selectPosition;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater from = LayoutInflater.from(mContext);
|
||||
BaseViewHolder vh;
|
||||
switch (viewType) {
|
||||
case FaceParam.FACE_BEAUTY_SKIN:
|
||||
vh = new BeautySkinViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_SHAPE:
|
||||
vh = new BeautyShapeViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_BODY:
|
||||
vh = new BeautyBodyViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_FILTER:
|
||||
vh = new FilterViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP:
|
||||
vh = new MakeupViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_STYLE:
|
||||
vh = new StyleViewHolder(from.inflate(R.layout.list_item_face_config_style, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_ANIMOJI:
|
||||
vh = new AnimojiViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_ANIM:
|
||||
vh = new AnimViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_STICKER:
|
||||
vh = new StickerViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BIG_HEAD:
|
||||
vh = new BigHeadViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_FINE_STICKER:
|
||||
case FaceParam.FACE_FINE_STICKER_MIDDLE:
|
||||
case FaceParam.FACE_FINE_STICKER_HIGH:
|
||||
case FaceParam.FACE_FINE_STICKER_GAME:
|
||||
vh = new FineStickerViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
default:
|
||||
vh = new BeautySkinViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item_face_config, parent, false));
|
||||
}
|
||||
vh.adapter = this;
|
||||
return vh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return list.get(position).getBeanType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
|
||||
holder.setData(list.get(position));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.yunbao.faceunity.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.common.adapter.OnItemClickListener;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.MenuGroupBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter<MenuGroupRecyclerAdapter.Vh> {
|
||||
private Context context;
|
||||
private List<MenuGroupBean> list;
|
||||
private OnItemClickListener onItemClickListener;
|
||||
|
||||
public MenuGroupRecyclerAdapter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
}
|
||||
|
||||
public void setList(List<MenuGroupBean> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(LayoutInflater.from(context).inflate(R.layout.list_item_menu_group, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh holder, int position) {
|
||||
holder.setData(list.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
|
||||
protected class Vh extends RecyclerView.ViewHolder {
|
||||
ImageView icon;
|
||||
TextView title;
|
||||
|
||||
public Vh(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_text);
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (onItemClickListener != null) {
|
||||
onItemClickListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setData(MenuGroupBean menuGroupBean) {
|
||||
icon.setImageResource(menuGroupBean.getIconId());
|
||||
title.setText(menuGroupBean.getTitleId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class AnimViewHolder extends BaseViewHolder{
|
||||
ImageView imageView;
|
||||
public AnimViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageView=itemView.findViewById(R.id.iv_control);
|
||||
imageView.setBackgroundResource(R.drawable.bg_control_square_selector);
|
||||
itemView.setOnClickListener(v -> setSelectPosition(getAdapterPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
imageView.setImageResource(data.getImageRes());
|
||||
imageView.setSelected(getAdapterPosition()==getSelectPosition());
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class AnimojiViewHolder extends BaseViewHolder{
|
||||
ImageView imageView;
|
||||
public AnimojiViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageView=itemView.findViewById(R.id.iv_control);
|
||||
itemView.setOnClickListener(v -> setSelectPosition(getAdapterPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
imageView.setImageResource(data.getImageRes());
|
||||
imageView.setSelected(getAdapterPosition()==getSelectPosition());
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
|
||||
public ContainerRecyclerAdapter adapter;
|
||||
|
||||
public int getSelectPosition() {
|
||||
return adapter.selectPosition;
|
||||
}
|
||||
|
||||
public void setSelectPosition(int selectPosition) {
|
||||
adapter.selectPosition = selectPosition;
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public BaseViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
public abstract void setData(BaseBean data);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
public class BeautyBodyViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
public BeautyBodyViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
public class BeautyShapeViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
public BeautyShapeViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
public class BeautySkinViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
public BeautySkinViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class BigHeadViewHolder extends BaseViewHolder{
|
||||
ImageView imageView;
|
||||
public BigHeadViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageView=itemView.findViewById(R.id.iv_control);
|
||||
itemView.setOnClickListener(v -> setSelectPosition(getAdapterPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
imageView.setImageResource(data.getImageRes());
|
||||
if(getAdapterPosition()==0){
|
||||
imageView.setBackgroundResource(R.drawable.bg_control_oval2_selector);
|
||||
}else{
|
||||
//imageView.setBackgroundResource(R.drawable.bg_control_oval_selector);
|
||||
}
|
||||
imageView.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.adapters.vh.BaseViewHolder;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class FilterViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
|
||||
public FilterViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class FineStickerViewHolder extends BaseViewHolder {
|
||||
ImageView imageView;
|
||||
|
||||
public FineStickerViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageView = itemView.findViewById(R.id.iv_control);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
if (data.getImageUrl().isEmpty()) {
|
||||
imageView.setImageResource(R.mipmap.icon_control_none);
|
||||
} else {
|
||||
ImgLoader.display(imageView.getContext(), data.getImageUrl(), imageView);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class MakeupViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private int index = -1;
|
||||
|
||||
public MakeupViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
itemView.setOnClickListener(v -> {
|
||||
setSelectPosition(getAdapterPosition());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if (getSelectPosition() == getAdapterPosition()) {
|
||||
icon.setSelected(true);
|
||||
title.setSelected(true);
|
||||
return;
|
||||
}
|
||||
icon.setSelected(false);
|
||||
title.setSelected(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class StickerViewHolder extends BaseViewHolder{
|
||||
ImageView imageView;
|
||||
public StickerViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageView=itemView.findViewById(R.id.iv_control);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
imageView.setImageResource(data.getImageRes());
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
public class StyleViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
public StyleViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon=itemView.findViewById(R.id.iv_control);
|
||||
title=itemView.findViewById(R.id.tv_control);
|
||||
itemView.setOnClickListener(v -> setSelectPosition(getAdapterPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
public class FaceParam {
|
||||
public static final int FACE_BEAUTY=100;
|
||||
public static final int FACE_BEAUTY_SKIN=101;
|
||||
public static final int FACE_BEAUTY_SHAPE=102;
|
||||
public static final int FACE_BEAUTY_FILTER=103;
|
||||
public static final int FACE_BEAUTY_STYLE=104;
|
||||
public static final int FACE_MAKEUP=200;
|
||||
public static final int FACE_BEAUTY_BODY=300;
|
||||
public static final int FACE_BIG_HEAD=400;
|
||||
public static final int FACE_ANIMOJI=500;
|
||||
public static final int FACE_STICKER=600;
|
||||
public static final int FACE_FINE_STICKER=700;
|
||||
public static final int FACE_FINE_STICKER_MIDDLE=701;
|
||||
public static final int FACE_FINE_STICKER_HIGH=702;
|
||||
public static final int FACE_FINE_STICKER_GAME=703;
|
||||
public static final int FACE_ANIM=800;
|
||||
}
|
@ -1,12 +1,16 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
public class AnimationFilterBean {
|
||||
private int style=0;
|
||||
private int iconId;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public AnimationFilterBean(int style, int iconId) {
|
||||
this.style = style;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
public class AnimationFilterBean extends BaseBean {
|
||||
private int iconId;
|
||||
private int style=0;
|
||||
|
||||
public AnimationFilterBean(int iconId, int style) {
|
||||
this.iconId = iconId;
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public int getStyle() {
|
||||
@ -24,4 +28,31 @@ public class AnimationFilterBean {
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return style+"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_ANIM;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String? Animoji 道具路径
|
||||
* @constructor
|
||||
*/
|
||||
public class AnimojiBean extends BaseBean{
|
||||
private int iconId;
|
||||
private String path;
|
||||
|
||||
public AnimojiBean(int iconId, String path) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_ANIMOJI;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String? Animoji 道具路径
|
||||
* @constructor
|
||||
*/
|
||||
data class AnimojiBean(val iconId: Int, val path: String?)
|
@ -0,0 +1,15 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
abstract class BaseBean {
|
||||
abstract val key: String
|
||||
abstract val desRes: Int
|
||||
abstract val imageRes: Int
|
||||
abstract val beanType: Int
|
||||
|
||||
abstract fun getModelAttributeData(): ModelAttributeData
|
||||
|
||||
open fun getImageUrl():String {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,17 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.repo.BodyBeautySource;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* DESC:美体
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class BodyBeautyBean {
|
||||
public class BodyBeautyBean extends BaseBean {
|
||||
private String key;//名称标识
|
||||
private int desRes;//描述
|
||||
private int closeRes;//图片
|
||||
@ -17,6 +24,7 @@ public class BodyBeautyBean {
|
||||
this.openRes = openRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
@ -48,4 +56,20 @@ public class BodyBeautyBean {
|
||||
public void setOpenRes(int openRes) {
|
||||
this.openRes = openRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return closeRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_BEAUTY_BODY;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return Objects.requireNonNull(BodyBeautySource.buildModelAttributeRange().get(key));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -11,14 +14,16 @@ package com.yunbao.faceunity.entity
|
||||
* @constructor
|
||||
*/
|
||||
data class FaceBeautyBean(
|
||||
val key: String,
|
||||
val desRes: Int,
|
||||
override val key: String,
|
||||
override val desRes: Int,
|
||||
val closeRes: Int,
|
||||
val openRes: Int,
|
||||
val toastDesRes: Int,
|
||||
val canUseFunction: Boolean = true,
|
||||
val buttonType: ButtonType = ButtonType.NORMAL_BUTTON//定义一项按钮功能 普通按钮 返回按钮 子项按钮
|
||||
) {
|
||||
, override val beanType: Int
|
||||
, override val imageRes: Int
|
||||
) : BaseBean() {
|
||||
constructor(key: String, desRes: Int, closeRes: Int, openRes: Int) : this(
|
||||
key,
|
||||
desRes,
|
||||
@ -26,17 +31,47 @@ data class FaceBeautyBean(
|
||||
openRes,
|
||||
0,
|
||||
true,
|
||||
ButtonType.NORMAL_BUTTON
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
FaceParam.FACE_BEAUTY_SKIN,
|
||||
closeRes
|
||||
)
|
||||
|
||||
constructor(key: String, desRes: Int, closeRes: Int, openRes: Int,toastDesRes: Int,canUseFunction: Boolean) : this(
|
||||
constructor(
|
||||
key: String,
|
||||
desRes: Int,
|
||||
closeRes: Int,
|
||||
openRes: Int,
|
||||
toastDesRes: Int,
|
||||
canUseFunction: Boolean
|
||||
) : this(
|
||||
key,
|
||||
desRes,
|
||||
closeRes,
|
||||
openRes,
|
||||
toastDesRes,
|
||||
canUseFunction,
|
||||
ButtonType.NORMAL_BUTTON
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
FaceParam.FACE_BEAUTY_SKIN,
|
||||
closeRes
|
||||
)
|
||||
constructor(
|
||||
key: String,
|
||||
desRes: Int,
|
||||
closeRes: Int,
|
||||
openRes: Int,
|
||||
toastDesRes: Int,
|
||||
canUseFunction: Boolean,
|
||||
type:Int
|
||||
):this(
|
||||
key,
|
||||
desRes,
|
||||
closeRes,
|
||||
openRes,
|
||||
toastDesRes,
|
||||
canUseFunction,
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
type,
|
||||
closeRes
|
||||
)
|
||||
|
||||
enum class ButtonType {
|
||||
@ -44,4 +79,8 @@ data class FaceBeautyBean(
|
||||
BACK_BUTTON,
|
||||
SUB_ITEM_BUTTON
|
||||
}
|
||||
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return FaceBeautySource.buildModelAttributeRange()?.get(key)!!
|
||||
}
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* DESC:美颜滤镜
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class FaceBeautyFilterBean {
|
||||
public class FaceBeautyFilterBean extends BaseBean {
|
||||
|
||||
private String key;//名称标识
|
||||
private int imageRes;//图片
|
||||
@ -24,6 +28,7 @@ public class FaceBeautyFilterBean {
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
@ -32,6 +37,7 @@ public class FaceBeautyFilterBean {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return imageRes;
|
||||
}
|
||||
@ -40,6 +46,7 @@ public class FaceBeautyFilterBean {
|
||||
this.imageRes = imageRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return desRes;
|
||||
}
|
||||
@ -55,4 +62,18 @@ public class FaceBeautyFilterBean {
|
||||
public void setIntensity(double intensity) {
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
|
||||
return FaceParam.FACE_BEAUTY_FILTER;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,4 +7,15 @@ package com.yunbao.faceunity.entity
|
||||
* @property desRes Int 描述
|
||||
* @constructor
|
||||
*/
|
||||
data class FaceBeautyStyleBean @JvmOverloads constructor(val key: String, val imageRes: Int, val desRes: Int)
|
||||
data class FaceBeautyStyleBean(
|
||||
override val key: String,
|
||||
override val imageRes: Int,
|
||||
override val desRes: Int,
|
||||
override val beanType:Int,
|
||||
):
|
||||
BaseBean(){
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return null!!
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,386 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
|
||||
import com.faceunity.core.avatar.model.Avatar;
|
||||
import com.faceunity.core.avatar.model.Scene;
|
||||
import com.faceunity.core.avatar.scene.ProcessorConfig;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUTranslationScale;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.faceunity.FUSceneKit;
|
||||
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||
import com.faceunity.core.model.prop.sticker.FineSticker;
|
||||
import com.faceunity.core.utils.FileUtils;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity;
|
||||
import com.yunbao.faceunity.infe.AbstractFineStickerDataFactory;
|
||||
import com.yunbao.faceunity.repo.AvatarSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 15:28.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
public class FineStickerDataFactory extends AbstractFineStickerDataFactory {
|
||||
private static final String TAG = "FineStickerDataFactory";
|
||||
private static FineStickerDataFactory factory;
|
||||
public static FineStickerDataFactory getInstance(){
|
||||
if(factory==null){
|
||||
factory=new FineStickerDataFactory();
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||
/*当前选中道具模型*/
|
||||
private FineSticker currentProp;
|
||||
/*菜单视图*/
|
||||
/*当前选中道具*/
|
||||
private FineStickerEntity.DocsBean currentSticker;
|
||||
/*当前道具的类型 普通单bundle,avatar 默认为普通单bundle*/
|
||||
private BundleType mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE;
|
||||
|
||||
//avatar相关
|
||||
/* 场景 */
|
||||
private Scene mSceneModel;
|
||||
/* 对象 */
|
||||
private Avatar mCurrentAvatarModel;
|
||||
/*3D抗锯齿*/
|
||||
public Antialiasing antialiasing;
|
||||
|
||||
//avatar用于区分bundle类型的关键字
|
||||
private final String COMPONENTS_STR = "components";
|
||||
private final String ANIM_STR = "anim";
|
||||
private final String INFO = "info.json";
|
||||
private final String ZIP = ".zip";
|
||||
private final String AVATAR = "avatar";
|
||||
|
||||
public FineStickerDataFactory() {
|
||||
// StickerDownloadHelper.getInstance().setCallback(downloadHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定菜单视图
|
||||
*
|
||||
*/
|
||||
public void bindView() {
|
||||
|
||||
}
|
||||
|
||||
public void setCallback(StickerDownloadHelper.Callback downloadHelper) {
|
||||
StickerDownloadHelper.getInstance().setCallback(downloadHelper);
|
||||
|
||||
}
|
||||
|
||||
public void refuseEvent() {
|
||||
StickerDownloadHelper.getInstance().setCallback(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换道具
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
@Override
|
||||
public void onItemSelected(FineStickerEntity.DocsBean bean) {
|
||||
currentSticker = bean;
|
||||
if (bean != null && bean.getTool().getBundle().getUid().endsWith(ZIP)) {
|
||||
//复合道具
|
||||
if (AVATAR.equals(bean.getTool().getCategory())) {
|
||||
//avatar道具
|
||||
if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) {
|
||||
//移除旧的道具
|
||||
mFURenderKit.getPropContainer().removeAllProp();
|
||||
currentProp = null;
|
||||
adapterMaxFace();
|
||||
}
|
||||
if (bean.getUnZipFilePaths() != null) {
|
||||
buildAvatarModel(bean);
|
||||
//当前为 avatar bundle
|
||||
mCurrentBundleType = BundleType.AVATAR_BUNDLE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//普通道具
|
||||
if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) {
|
||||
mFURenderKit.getPropContainer().removeAllProp();
|
||||
currentProp = null;
|
||||
if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) {
|
||||
adapterMaxFace();
|
||||
FineSticker prop = adapterBean(bean.getFilePath());
|
||||
mFURenderKit.getPropContainer().addProp(prop);
|
||||
currentProp = prop;
|
||||
}
|
||||
} else if (mCurrentBundleType == BundleType.AVATAR_BUNDLE) {
|
||||
//关闭avatar 相关的东西
|
||||
if (mSceneModel != null && mCurrentAvatarModel != null) {
|
||||
mSceneModel.removeAvatar(mCurrentAvatarModel);
|
||||
FUSceneKit.getInstance().removeScene(mSceneModel);
|
||||
mSceneModel = null;
|
||||
mCurrentAvatarModel = null;
|
||||
}
|
||||
|
||||
//设置道具
|
||||
if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) {
|
||||
adapterMaxFace();
|
||||
FineSticker prop = adapterBean(bean.getFilePath());
|
||||
mFURenderKit.getPropContainer().addProp(prop);
|
||||
currentProp = prop;
|
||||
}
|
||||
}
|
||||
|
||||
//当前为普通bundle
|
||||
mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE;
|
||||
}
|
||||
|
||||
if (mBundleTypeListener != null) {
|
||||
mBundleTypeListener.bundleType(mCurrentBundleType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建avatar -> scene
|
||||
* @param bean
|
||||
*/
|
||||
private void buildAvatarModel(FineStickerEntity.DocsBean bean) {
|
||||
//启动avatar基本逻辑
|
||||
if (antialiasing == null)
|
||||
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||
//3d抗锯齿
|
||||
mFURenderKit.setAntialiasing(antialiasing);
|
||||
//判断是avatar 控件 -> 查看是否有json文件
|
||||
ArrayList<String> unZipFilePaths = bean.getUnZipFilePaths();
|
||||
int hasJson = unZipFilePaths.indexOf(INFO);
|
||||
|
||||
ArrayList<String> strComponents = new ArrayList<>();//组件Bundle
|
||||
ArrayList<String> strAnimations = new ArrayList<>();//动画Bundle
|
||||
if (hasJson >= 0) {
|
||||
//用json的描述赋予每一个bundle自己的职责,还可以赋予其他参数
|
||||
String jsonPath = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + unZipFilePaths.get(hasJson);
|
||||
//解析json文件 ->
|
||||
String json = FileUtils.loadStringFromExternal(jsonPath);
|
||||
//解析avatar的json文件
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(json);
|
||||
JSONArray components = jsonObject.getJSONArray("components");
|
||||
for(int i =0 ;i < components.length();i++) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + components.get(i);
|
||||
strComponents.add(path);
|
||||
}
|
||||
|
||||
JSONArray anims = jsonObject.getJSONArray("anims");
|
||||
for(int i =0 ;i < anims.length();i++) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + anims.get(i);
|
||||
strAnimations.add(path);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//根据bundle的命名赋予每一个bundle自己的职责
|
||||
for (String str:unZipFilePaths) {
|
||||
if (str.startsWith(COMPONENTS_STR)) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str;
|
||||
strComponents.add(path);
|
||||
} else if (str.startsWith(ANIM_STR)){
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str;
|
||||
strAnimations.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSceneModel == null) {
|
||||
mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations);
|
||||
mSceneModel = AvatarSource.buildSceneModel(mCurrentAvatarModel);
|
||||
mSceneModel.processorConfig.setTrackScene(ProcessorConfig.TrackScene.SceneFull);
|
||||
mCurrentAvatarModel.transForm.setTranslationScale(new FUTranslationScale(0.5f, 0f, 0.1f));
|
||||
} else {
|
||||
if (mCurrentAvatarModel != null)
|
||||
mSceneModel.removeAvatar(mCurrentAvatarModel);
|
||||
mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations);
|
||||
mSceneModel.addAvatar(mCurrentAvatarModel);
|
||||
}
|
||||
FUSceneKit.getInstance().addScene(mSceneModel);
|
||||
FUSceneKit.getInstance().setCurrentScene(mSceneModel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据adpater 调整业务模型
|
||||
* 0:维持竖屏
|
||||
* 1:仅限一人
|
||||
* 2:美妆道具
|
||||
* 3:点击事件
|
||||
* 4:翻转
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private FineSticker adapterBean(String path) {
|
||||
String adapter = currentSticker.getTool().getAdapter();
|
||||
if (adapter == null || !adapter.contains("1")) {
|
||||
mFUAIKit.setMaxFaces(4);
|
||||
} else {
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
}
|
||||
if (adapter != null && adapter.trim().length() > 0) {
|
||||
boolean isFlipPoints = adapter.contains("2");
|
||||
boolean is3DFlipH = adapter.contains("4");
|
||||
boolean isClick = adapter.contains("3");
|
||||
return new FineSticker(new FUBundleData(path), isFlipPoints, is3DFlipH, isClick);
|
||||
} else {
|
||||
return new FineSticker(new FUBundleData(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络回调
|
||||
*/
|
||||
private StickerDownloadHelper.Callback downloadHelper = new StickerDownloadHelper.Callback() {
|
||||
@Override
|
||||
public void onGetTags(String[] tags) {
|
||||
formatTag(tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetList(String tag, FineStickerEntity fineSticker) {
|
||||
new FineStickerTagEntity(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownload(FineStickerEntity.DocsBean entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 获取标签列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public List<FineStickerTagEntity> loadTagList() {
|
||||
String[] tags = StickerDownloadHelper.getInstance().tags();
|
||||
return formatTag(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签对应道具列表
|
||||
*
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public FineStickerEntity loadStickerList(@NotNull FineStickerTagEntity tag) {
|
||||
return StickerDownloadHelper.getInstance().tools(tag.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载道具
|
||||
*
|
||||
* @param docsBean
|
||||
*/
|
||||
@Override
|
||||
public void downloadSticker(@NotNull FineStickerEntity.DocsBean docsBean) {
|
||||
try{
|
||||
StickerDownloadHelper.getInstance().download(docsBean);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG,"downloadSticker",e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 数据转换
|
||||
*
|
||||
* @param tags
|
||||
* @return
|
||||
*/
|
||||
public static List<FineStickerTagEntity> formatTag(String[] tags) {
|
||||
List<FineStickerTagEntity> tagEntityList = new ArrayList<>(tags.length);
|
||||
for (int i = 0; i < tags.length; i++) {
|
||||
tagEntityList.add(new FineStickerTagEntity(tags[i]));
|
||||
}
|
||||
return tagEntityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_HAND, FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
onItemSelected(currentSticker);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束需要释放AI驱动
|
||||
*/
|
||||
public void releaseAIProcessor() {
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
}
|
||||
|
||||
|
||||
private void adapterMaxFace() {
|
||||
if (currentSticker == null) return;
|
||||
String adapter = currentSticker.getTool().getAdapter();
|
||||
if (adapter == null || !adapter.contains("1")) {
|
||||
mFUAIKit.setMaxFaces(4);
|
||||
} else {
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP && currentProp != null && currentProp.isClick()) {
|
||||
currentProp.onClick();
|
||||
}
|
||||
}
|
||||
|
||||
//通过枚举记录每一个bundle的类型
|
||||
public enum BundleType {
|
||||
NORMAL_SINGLE_BUNDLE,//普通的单bundle道具
|
||||
AVATAR_BUNDLE//avatar bundle 一般为多bundle
|
||||
}
|
||||
|
||||
private BundleTypeListener mBundleTypeListener;
|
||||
public interface BundleTypeListener {
|
||||
void bundleType(BundleType bundleType);
|
||||
}
|
||||
public void setBundleTypeListener (BundleTypeListener bundleTypeListener){
|
||||
mBundleTypeListener = bundleTypeListener;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
/**
|
||||
* DESC:美妆-组合妆容
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class MakeupCombinationBean {
|
||||
|
||||
private String key;//名称标识
|
||||
private int imageRes;//图片
|
||||
private int desRes;//描述
|
||||
private String bundlePath;//资源句柄
|
||||
private double intensity = 1.0;//强度
|
||||
|
||||
public MakeupCombinationBean(String key, int imageRes, int desRes, String bundlePath) {
|
||||
this.key = key;
|
||||
this.imageRes = imageRes;
|
||||
this.desRes = desRes;
|
||||
this.bundlePath = bundlePath;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getImageRes() {
|
||||
return imageRes;
|
||||
}
|
||||
|
||||
public void setImageRes(int imageRes) {
|
||||
this.imageRes = imageRes;
|
||||
}
|
||||
|
||||
public int getDesRes() {
|
||||
return desRes;
|
||||
}
|
||||
|
||||
public void setDesRes(int desRes) {
|
||||
this.desRes = desRes;
|
||||
}
|
||||
|
||||
public String getBundlePath() {
|
||||
return bundlePath;
|
||||
}
|
||||
|
||||
public void setBundlePath(String bundlePath) {
|
||||
this.bundlePath = bundlePath;
|
||||
}
|
||||
|
||||
public double getIntensity() {
|
||||
return intensity;
|
||||
}
|
||||
|
||||
public void setIntensity(double intensity) {
|
||||
this.intensity = intensity;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @property key String 名称标识
|
||||
* @property type TypeEnum 类型
|
||||
* @property imageRes Int 图片
|
||||
* @property desRes Int 描述
|
||||
* @property bundlePath FUBundleData 资源句柄
|
||||
* @property jsonPath String 参数配置路径
|
||||
* @property filterName Double 滤镜
|
||||
* @property filterIntensity Double 滤镜强度
|
||||
* @property filterScale Double scale 标准滤镜比率
|
||||
* @property intensity Double 强度
|
||||
* @property jsonPathParams Double 参数配置缓存
|
||||
* @constructor
|
||||
*/
|
||||
data class MakeupCombinationBean @JvmOverloads constructor(
|
||||
override val key: String,
|
||||
val type: TypeEnum,
|
||||
override val imageRes: Int,
|
||||
override val desRes: Int,
|
||||
val bundlePath: String?,
|
||||
val jsonPath: String,
|
||||
val filterName: String,
|
||||
var filterScale: Double = 1.0,
|
||||
var filterIntensity: Double = 0.7,
|
||||
var intensity: Double = 0.7,
|
||||
var jsonPathParams: LinkedHashMap<String, Any>? = null,
|
||||
override val beanType: Int
|
||||
): BaseBean() {
|
||||
enum class TypeEnum {
|
||||
TYPE_NONE, //无
|
||||
TYPE_DAILY,//日常妆,支持自定义
|
||||
TYPE_THEME_SUB,//主题妆_依附于face_makeup
|
||||
TYPE_THEME_MAIN,//主题妆_替换face_makeup
|
||||
}
|
||||
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return null!!
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @property nameRes Int 名称
|
||||
* @property drawable Drawable 图片资源
|
||||
* @property doubleArray ArrayList<DoubleArray>? 颜色数组
|
||||
* @constructor
|
||||
*/
|
||||
data class MakeupCustomBean @JvmOverloads constructor(
|
||||
val nameRes: Int,
|
||||
val drawable: Drawable,
|
||||
val doubleArray: ArrayList<DoubleArray>? = null
|
||||
)
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
/**
|
||||
* 美妆子妆类别
|
||||
* @property nameRes Int 名称
|
||||
* @property key String 标识
|
||||
* @constructor
|
||||
*/
|
||||
data class MakeupCustomClassBean(val nameRes: Int, val key: String)
|
@ -0,0 +1,3 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
data class MenuGroupBean(val titleId :Int,val iconId:Int)
|
@ -0,0 +1,80 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String 道具路径
|
||||
* @property descId Int 道具提示
|
||||
* @constructor
|
||||
*/
|
||||
public class PropBean extends BaseBean {
|
||||
private int iconId;
|
||||
private String path;
|
||||
private int descId;
|
||||
|
||||
public PropBean(int iconId, String path) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public PropBean(int iconId, String path, int descId) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
this.descId = descId;
|
||||
}
|
||||
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getDescId() {
|
||||
return descId;
|
||||
}
|
||||
|
||||
public void setDescId(int descId) {
|
||||
this.descId = descId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return descId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_BIG_HEAD;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String 道具路径
|
||||
* @property descId Int 道具提示
|
||||
* @constructor
|
||||
*/
|
||||
data class PropBean @JvmOverloads constructor(
|
||||
val iconId: Int,
|
||||
val path: String?,
|
||||
val descId: Int = 0
|
||||
)
|
@ -0,0 +1,328 @@
|
||||
package com.yunbao.faceunity.entity.net;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Qinyu on 2021-03-17
|
||||
* @description
|
||||
*/
|
||||
public class FineStickerEntity {
|
||||
/**
|
||||
* count : 2
|
||||
* docs : [{"_id":"6051a0aa6d670000230030c7","index":1,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"},{"_id":"6051a2d36d670000230030c8","index":2,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"}]
|
||||
*/
|
||||
|
||||
private int count;
|
||||
private ArrayList<DocsBean> docs;
|
||||
private boolean isOnline; //手动设置
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public ArrayList<DocsBean> getDocs() {
|
||||
return docs;
|
||||
}
|
||||
|
||||
public void setDocs(ArrayList<DocsBean> docs) {
|
||||
this.docs = docs;
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public void setOnline(boolean online) {
|
||||
isOnline = online;
|
||||
}
|
||||
|
||||
public static class DocsBean extends BaseBean {
|
||||
/**
|
||||
* _id : 6051a0aa6d670000230030c7
|
||||
* index : 1
|
||||
* tool : {"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}}
|
||||
* platform : mobile
|
||||
* tag : 中级道具
|
||||
*/
|
||||
|
||||
private String _id;
|
||||
private int index;
|
||||
private ToolBean tool;
|
||||
private String platform;
|
||||
private String tag;
|
||||
|
||||
private String filePath; //原始下载来的文件的存储地址,手动设置
|
||||
private ArrayList<String> upZipFilePath;//解压的文件位置(绝对路径),手动设置
|
||||
private boolean isDownloading; //手动设置
|
||||
|
||||
// public Effect cast2Effect() {
|
||||
// return new Effect(tool.bundle.name, 0, filePath, 1, Effect.EFFECT_TYPE_STICKER, 0);
|
||||
// }
|
||||
|
||||
public String get_id() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void set_id(String _id) {
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public ToolBean getTool() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
public void setTool(ToolBean tool) {
|
||||
this.tool = tool;
|
||||
}
|
||||
|
||||
public String getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
public void setPlatform(String platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public ArrayList<String> getUnZipFilePaths() {
|
||||
return upZipFilePath;
|
||||
}
|
||||
|
||||
public void setUpZipFilePaths(ArrayList paths) {
|
||||
upZipFilePath = paths;
|
||||
}
|
||||
|
||||
public boolean isDownloading() {
|
||||
return isDownloading;
|
||||
}
|
||||
|
||||
public void setDownloading(boolean downloading) {
|
||||
isDownloading = downloading;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageUrl() {
|
||||
if(tool==null||tool.getIcon()==null){
|
||||
return "";
|
||||
}
|
||||
return tool.getIcon().getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_FINE_STICKER;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class ToolBean {
|
||||
/**
|
||||
* _id : 5f6ae24e570100009e006547
|
||||
* bundle : {"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"}
|
||||
* icon : {"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}
|
||||
*/
|
||||
|
||||
private String _id;
|
||||
private BundleBean bundle;
|
||||
private IconBean icon;
|
||||
private String adapter;
|
||||
private String category;
|
||||
|
||||
public String get_id() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void set_id(String _id) {
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
public BundleBean getBundle() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public void setBundle(BundleBean bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public IconBean getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(IconBean icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public void setAdapter(String adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public static class BundleBean {
|
||||
/**
|
||||
* remark : 优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持
|
||||
* uid : 0a176380-b33e-11e9-8e6a-35012f229fc1.bundle
|
||||
* size : 3872.85
|
||||
* name : hez_ztt_fu.bundle
|
||||
*/
|
||||
|
||||
private String remark;
|
||||
private String uid;
|
||||
private double size;
|
||||
private String name;
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(double size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IconBean {
|
||||
/**
|
||||
* remark : v1.0
|
||||
* uid : 167f72e0-e173-11e8-b908-51298abcbcf5.png
|
||||
* size : 61.83
|
||||
* name : hez_ztt_fu.png
|
||||
* url : http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D
|
||||
*/
|
||||
|
||||
private String remark;
|
||||
private String uid;
|
||||
private double size;
|
||||
private String name;
|
||||
private String url;
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(double size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.yunbao.faceunity.entity.net;
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 16:12.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
public class FineStickerTagEntity {
|
||||
private String tag;
|
||||
|
||||
public FineStickerTagEntity(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FineStickerTagEntity{" +
|
||||
"tag='" + tag + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 15:27.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
abstract class AbstractFineStickerDataFactory {
|
||||
/*切换道具*/
|
||||
abstract fun onItemSelected(bean: FineStickerEntity.DocsBean?)
|
||||
/*获取标签列表*/
|
||||
abstract fun loadTagList(): List<FineStickerTagEntity>
|
||||
/*获取道具列表*/
|
||||
abstract fun loadStickerList(tag: FineStickerTagEntity): FineStickerEntity?
|
||||
/*下载道具*/
|
||||
abstract fun downloadSticker(docsBean: FineStickerEntity.DocsBean)
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceBeautyData;
|
||||
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyStyleBean;
|
||||
@ -107,49 +108,68 @@ public class FaceBeautySource {
|
||||
public static ArrayList<FaceBeautyBean> buildSkinParams() {
|
||||
ArrayList<FaceBeautyBean> params = new ArrayList<>();
|
||||
params.add(new FaceBeautyBean(
|
||||
FaceBeautyParam.BLUR_INTENSITY, R.string.beauty_box_heavy_blur_fine,
|
||||
R.drawable.icon_beauty_skin_buffing_close_selector, R.drawable.icon_beauty_skin_buffing_open_selector
|
||||
FaceBeautyParam.BLUR_INTENSITY
|
||||
, R.string.beauty_box_heavy_blur_fine
|
||||
, R.drawable.icon_beauty_skin_buffing_close_selector
|
||||
, R.drawable.icon_beauty_skin_buffing_open_selector
|
||||
, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.COLOR_INTENSITY, R.string.beauty_box_color_level,
|
||||
R.drawable.icon_beauty_skin_color_close_selector, R.drawable.icon_beauty_skin_color_open_selector
|
||||
R.drawable.icon_beauty_skin_color_close_selector, R.drawable.icon_beauty_skin_color_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.RED_INTENSITY, R.string.beauty_box_red_level,
|
||||
R.drawable.icon_beauty_skin_red_close_selector, R.drawable.icon_beauty_skin_red_open_selector
|
||||
R.drawable.icon_beauty_skin_red_close_selector, R.drawable.icon_beauty_skin_red_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.SHARPEN_INTENSITY, R.string.beauty_box_sharpen,
|
||||
R.drawable.icon_beauty_skin_sharpen_close_selector, R.drawable.icon_beauty_skin_sharpen_open_selector
|
||||
R.drawable.icon_beauty_skin_sharpen_close_selector, R.drawable.icon_beauty_skin_sharpen_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_BRIGHT_INTENSITY, R.string.beauty_box_eye_bright,
|
||||
R.drawable.icon_beauty_skin_eyes_bright_close_selector, R.drawable.icon_beauty_skin_eyes_bright_open_selector
|
||||
R.drawable.icon_beauty_skin_eyes_bright_close_selector, R.drawable.icon_beauty_skin_eyes_bright_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.TOOTH_WHITEN_INTENSITY, R.string.beauty_box_tooth_whiten,
|
||||
R.drawable.icon_beauty_skin_teeth_close_selector, R.drawable.icon_beauty_skin_teeth_open_selector
|
||||
R.drawable.icon_beauty_skin_teeth_close_selector, R.drawable.icon_beauty_skin_teeth_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.REMOVE_POUCH_INTENSITY, R.string.beauty_micro_pouch,
|
||||
R.drawable.icon_beauty_skin_dark_circles_close_selector, R.drawable.icon_beauty_skin_dark_circles_open_selector)
|
||||
R.drawable.icon_beauty_skin_dark_circles_close_selector, R.drawable.icon_beauty_skin_dark_circles_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, R.string.beauty_micro_nasolabial,
|
||||
R.drawable.icon_beauty_skin_wrinkle_close_selector, R.drawable.icon_beauty_skin_wrinkle_open_selector)
|
||||
R.drawable.icon_beauty_skin_wrinkle_close_selector, R.drawable.icon_beauty_skin_wrinkle_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN)
|
||||
);
|
||||
|
||||
return params;
|
||||
@ -173,7 +193,9 @@ public class FaceBeautySource {
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_THINNING_INTENSITY, R.string.beauty_box_cheek_thinning,
|
||||
R.drawable.icon_beauty_shape_face_cheekthin_close_selector, R.drawable.icon_beauty_shape_face_cheekthin_open_selector
|
||||
R.drawable.icon_beauty_shape_face_cheekthin_close_selector, R.drawable.icon_beauty_shape_face_cheekthin_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
@ -181,7 +203,9 @@ public class FaceBeautySource {
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_V_INTENSITY, R.string.beauty_box_cheek_v,
|
||||
R.drawable.icon_beauty_shape_face_v_close_selector, R.drawable.icon_beauty_shape_face_v_open_selector
|
||||
R.drawable.icon_beauty_shape_face_v_close_selector, R.drawable.icon_beauty_shape_face_v_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
@ -189,7 +213,9 @@ public class FaceBeautySource {
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_NARROW_INTENSITY, R.string.beauty_box_cheek_narrow,
|
||||
R.drawable.icon_beauty_shape_face_narrow_close_selector, R.drawable.icon_beauty_shape_face_narrow_open_selector
|
||||
R.drawable.icon_beauty_shape_face_narrow_close_selector, R.drawable.icon_beauty_shape_face_narrow_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
@ -197,7 +223,9 @@ public class FaceBeautySource {
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_SHORT_INTENSITY, R.string.beauty_box_cheek_short,
|
||||
R.drawable.icon_beauty_shape_face_short_close_selector, R.drawable.icon_beauty_shape_face_short_open_selector
|
||||
R.drawable.icon_beauty_shape_face_short_close_selector, R.drawable.icon_beauty_shape_face_short_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
@ -205,105 +233,141 @@ public class FaceBeautySource {
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_SMALL_INTENSITY, R.string.beauty_box_cheek_small,
|
||||
R.drawable.icon_beauty_shape_face_little_close_selector, R.drawable.icon_beauty_shape_face_little_open_selector
|
||||
R.drawable.icon_beauty_shape_face_little_close_selector, R.drawable.icon_beauty_shape_face_little_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, R.string.beauty_box_cheekbones,
|
||||
R.drawable.icon_beauty_shape_cheek_bones_close_selector, R.drawable.icon_beauty_shape_cheek_bones_open_selector
|
||||
R.drawable.icon_beauty_shape_cheek_bones_close_selector, R.drawable.icon_beauty_shape_cheek_bones_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, R.string.beauty_box_lower_jaw,
|
||||
R.drawable.icon_beauty_shape_lower_jaw_close_selector, R.drawable.icon_beauty_shape_lower_jaw_open_selector
|
||||
R.drawable.icon_beauty_shape_lower_jaw_close_selector, R.drawable.icon_beauty_shape_lower_jaw_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_ENLARGING_INTENSITY, R.string.beauty_box_eye_enlarge,
|
||||
R.drawable.icon_beauty_shape_enlarge_eye_close_selector, R.drawable.icon_beauty_shape_enlarge_eye_open_selector
|
||||
R.drawable.icon_beauty_shape_enlarge_eye_close_selector, R.drawable.icon_beauty_shape_enlarge_eye_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_CIRCLE_INTENSITY, R.string.beauty_box_eye_circle,
|
||||
R.drawable.icon_beauty_shape_round_eye_close_selector, R.drawable.icon_beauty_shape_round_eye_open_selector
|
||||
R.drawable.icon_beauty_shape_round_eye_close_selector, R.drawable.icon_beauty_shape_round_eye_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHIN_INTENSITY, R.string.beauty_box_intensity_chin,
|
||||
R.drawable.icon_beauty_shape_chin_close_selector, R.drawable.icon_beauty_shape_chin_open_selector
|
||||
R.drawable.icon_beauty_shape_chin_close_selector, R.drawable.icon_beauty_shape_chin_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.FOREHEAD_INTENSITY, R.string.beauty_box_intensity_forehead,
|
||||
R.drawable.icon_beauty_shape_forehead_close_selector, R.drawable.icon_beauty_shape_forehead_open_selector
|
||||
R.drawable.icon_beauty_shape_forehead_close_selector, R.drawable.icon_beauty_shape_forehead_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.NOSE_INTENSITY, R.string.beauty_box_intensity_nose,
|
||||
R.drawable.icon_beauty_shape_thin_nose_close_selector, R.drawable.icon_beauty_shape_thin_nose_open_selector
|
||||
R.drawable.icon_beauty_shape_thin_nose_close_selector, R.drawable.icon_beauty_shape_thin_nose_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.MOUTH_INTENSITY, R.string.beauty_box_intensity_mouth,
|
||||
R.drawable.icon_beauty_shape_mouth_close_selector, R.drawable.icon_beauty_shape_mouth_open_selector
|
||||
R.drawable.icon_beauty_shape_mouth_close_selector, R.drawable.icon_beauty_shape_mouth_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CANTHUS_INTENSITY, R.string.beauty_micro_canthus,
|
||||
R.drawable.icon_beauty_shape_open_eyes_close_selector, R.drawable.icon_beauty_shape_open_eyes_open_selector
|
||||
R.drawable.icon_beauty_shape_open_eyes_close_selector, R.drawable.icon_beauty_shape_open_eyes_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_SPACE_INTENSITY, R.string.beauty_micro_eye_space,
|
||||
R.drawable.icon_beauty_shape_distance_close_selector, R.drawable.icon_beauty_shape_distance_open_selector
|
||||
R.drawable.icon_beauty_shape_distance_close_selector, R.drawable.icon_beauty_shape_distance_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_ROTATE_INTENSITY, R.string.beauty_micro_eye_rotate,
|
||||
R.drawable.icon_beauty_shape_angle_close_selector, R.drawable.icon_beauty_shape_angle_open_selector
|
||||
R.drawable.icon_beauty_shape_angle_close_selector, R.drawable.icon_beauty_shape_angle_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.LONG_NOSE_INTENSITY, R.string.beauty_micro_long_nose,
|
||||
R.drawable.icon_beauty_shape_proboscis_close_selector, R.drawable.icon_beauty_shape_proboscis_open_selector
|
||||
R.drawable.icon_beauty_shape_proboscis_close_selector, R.drawable.icon_beauty_shape_proboscis_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.PHILTRUM_INTENSITY, R.string.beauty_micro_philtrum,
|
||||
R.drawable.icon_beauty_shape_shrinking_close_selector, R.drawable.icon_beauty_shape_shrinking_open_selector
|
||||
R.drawable.icon_beauty_shape_shrinking_close_selector, R.drawable.icon_beauty_shape_shrinking_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.SMILE_INTENSITY, R.string.beauty_micro_smile,
|
||||
R.drawable.icon_beauty_shape_smile_close_selector, R.drawable.icon_beauty_shape_smile_open_selector
|
||||
R.drawable.icon_beauty_shape_smile_close_selector, R.drawable.icon_beauty_shape_smile_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.BROW_HEIGHT_INTENSITY, R.string.beauty_brow_height,
|
||||
R.drawable.icon_beauty_shape_brow_height_close_selector, R.drawable.icon_beauty_shape_brow_height_open_selector,
|
||||
R.string.brow_height_tips,FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID
|
||||
FaceBeautyParam.BROW_HEIGHT_INTENSITY,
|
||||
R.string.beauty_brow_height,
|
||||
R.drawable.icon_beauty_shape_brow_height_close_selector,
|
||||
R.drawable.icon_beauty_shape_brow_height_open_selector,
|
||||
R.string.brow_height_tips,
|
||||
FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.BROW_SPACE_INTENSITY, R.string.beauty_brow_space,
|
||||
R.drawable.icon_beauty_shape_brow_space_close_selector, R.drawable.icon_beauty_shape_brow_space_open_selector,
|
||||
R.string.brow_space_tips,FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID
|
||||
R.string.brow_space_tips, FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
return params;
|
||||
@ -500,6 +564,7 @@ public class FaceBeautySource {
|
||||
|
||||
/**
|
||||
* 从磁盘获取所有项滤镜强度
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@ -527,13 +592,13 @@ public class FaceBeautySource {
|
||||
*/
|
||||
public static ArrayList<FaceBeautyStyleBean> buildStylesParams() {
|
||||
ArrayList<FaceBeautyStyleBean> params = new ArrayList<>();
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_KUAISHOU, R.drawable.icon_beauty_style_1_selector, R.string.beauty_face_style_1));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_QINGYAN, R.drawable.icon_beauty_style_2_selector, R.string.beauty_face_style_2));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_ZIJIETIAODONG, R.drawable.icon_beauty_style_3_selector, R.string.beauty_face_style_3));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_HUAJIAO, R.drawable.icon_beauty_style_4_selector, R.string.beauty_face_style_4));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_YINGKE, R.drawable.icon_beauty_style_5_selector, R.string.beauty_face_style_5));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_SHANGTANG, R.drawable.icon_beauty_style_6_selector, R.string.beauty_face_style_6));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_BIAOZHUN, R.drawable.icon_beauty_style_7_selector, R.string.beauty_face_style_7));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_KUAISHOU, R.drawable.icon_beauty_style_1_selector, R.string.beauty_face_style_1,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_QINGYAN, R.drawable.icon_beauty_style_2_selector, R.string.beauty_face_style_2,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_ZIJIETIAODONG, R.drawable.icon_beauty_style_3_selector, R.string.beauty_face_style_3,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_HUAJIAO, R.drawable.icon_beauty_style_4_selector, R.string.beauty_face_style_4,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_YINGKE, R.drawable.icon_beauty_style_5_selector, R.string.beauty_face_style_5,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_SHANGTANG, R.drawable.icon_beauty_style_6_selector, R.string.beauty_face_style_6,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_BIAOZHUN, R.drawable.icon_beauty_style_7_selector, R.string.beauty_face_style_7,FaceParam.FACE_BEAUTY_STYLE));
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import com.yunbao.faceunity.entity.FineStickerDataFactory;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class FineStickerSource {
|
||||
|
||||
}
|
@ -1,11 +1,35 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.faceunity.core.controller.makeup.MakeupParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.faceunity.core.model.makeup.Makeup;
|
||||
import com.faceunity.core.utils.FileUtils;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomClassBean;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean.TypeEnum;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DESC:美妆数据构造
|
||||
@ -14,6 +38,7 @@ import java.util.ArrayList;
|
||||
public class MakeupSource {
|
||||
public static String BUNDLE_FACE_MAKEUP = "graphics" + File.separator + "face_makeup.bundle";
|
||||
|
||||
|
||||
//region 组合妆容
|
||||
|
||||
/**
|
||||
@ -23,12 +48,440 @@ public class MakeupSource {
|
||||
*/
|
||||
public static ArrayList<MakeupCombinationBean> buildCombinations() {
|
||||
ArrayList<MakeupCombinationBean> combinations = new ArrayList<MakeupCombinationBean>();
|
||||
combinations.add(new MakeupCombinationBean("origin", R.mipmap.icon_control_none, R.string.makeup_radio_remove, null));
|
||||
combinations.add(new MakeupCombinationBean("naicha", R.mipmap.icon_makeup_combination_tea_with_milk, R.string.makeup_combination_naicha, "makeup/naicha.bundle"));
|
||||
combinations.add(new MakeupCombinationBean("dousha", R.mipmap.icon_makeup_combination_red_bean_paste, R.string.makeup_combination_dousha, "makeup/dousha.bundle"));
|
||||
combinations.add(new MakeupCombinationBean("chaoa", R.mipmap.icon_makeup_combination_super_a, R.string.makeup_combination_chaoa, "makeup/chaoa.bundle"));
|
||||
String jsonDir = FaceUnityConfig.MAKEUP_RESOURCE_JSON_DIR;
|
||||
String bundleDir = FaceUnityConfig.MAKEUP_RESOURCE_COMBINATION_BUNDLE_DIR;
|
||||
combinations.add(new MakeupCombinationBean("origin", TypeEnum.TYPE_NONE, R.mipmap.icon_control_none, R.string.makeup_radio_remove, null, "", FaceBeautyFilterEnum.ZIRAN_2, 1.0,0.0,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("diadiatu", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_diadiatu, R.string.makeup_combination_diadiatu, bundleDir + "diadiatu.bundle", jsonDir + "diadiatu.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("dongling", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_freezing_age, R.string.makeup_combination_dongling, bundleDir + "dongling.bundle", jsonDir + "dongling.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("guofeng", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_guo_feng, R.string.makeup_combination_guofeng, bundleDir + "guofeng.bundle", jsonDir + "guofeng.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("hunxie", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_mixed_race, R.string.makeup_combination_hunxie, bundleDir + "hunxie.bundle", jsonDir + "hunxie.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("jianling", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_age, R.string.makeup_combination_jianling, bundleDir + "jianling.bundle", jsonDir + "jianling.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("nuandong", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_warm_winter, R.string.makeup_combination_nuandong, bundleDir + "nuandong.bundle", jsonDir + "nuandong.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("hongfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_red_maple, R.string.makeup_combination_hongfeng, bundleDir + "hongfeng.bundle", jsonDir + "hongfeng.json", FaceBeautyFilterEnum.ZHIGANHUI_3, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("rose", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_rose, R.string.makeup_combination_rose, bundleDir + "rose.bundle", jsonDir + "rose.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("shaonv", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_girl, R.string.makeup_combination_shaonv, bundleDir + "shaonv.bundle", jsonDir + "shaonv.json", FaceBeautyFilterEnum.ZHIGANHUI_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("ziyun", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_purple_rhyme, R.string.makeup_combination_ziyun, bundleDir + "ziyun.bundle", jsonDir + "ziyun.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("yanshimao", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_bored_cat, R.string.makeup_combination_yanshimao, bundleDir + "yanshimao.bundle", jsonDir + "yanshimao.json", FaceBeautyFilterEnum.ZHIGANHUI_5, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("renyu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_mermaid, R.string.makeup_combination_renyu, bundleDir + "renyu.bundle", jsonDir + "renyu.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chuqiu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_early_autumn, R.string.makeup_combination_chuqiu, bundleDir + "chuqiu.bundle", jsonDir + "chuqiu.json", FaceBeautyFilterEnum.ZHIGANHUI_6, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("qianzhihe", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_paper_cranes, R.string.makeup_combination_qianzhihe, bundleDir + "qianzhihe.bundle", jsonDir + "qianzhihe.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chaomo", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_supermodel, R.string.makeup_combination_chaomo, bundleDir + "chaomo.bundle", jsonDir + "chaomo.json", FaceBeautyFilterEnum.ZHIGANHUI_7, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chuju", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_daisy, R.string.makeup_combination_chuju, bundleDir + "chuju.bundle", jsonDir + "chuju.json", FaceBeautyFilterEnum.ZHIGANHUI_8, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("gangfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_harbour_wind, R.string.makeup_combination_gangfeng, bundleDir + "gangfeng.bundle", jsonDir + "gangfeng.json", FaceBeautyFilterEnum.ZIRAN_8, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("xinggan", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sexy, R.string.makeup_combination_sexy, bundleDir + "xinggan.bundle", jsonDir + "xinggan.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("tianmei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sweet, R.string.makeup_combination_sweet, bundleDir + "tianmei.bundle", jsonDir + "tianmei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("linjia", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_neighbor_girl, R.string.makeup_combination_neighbor, bundleDir + "linjia.bundle", jsonDir + "linjia.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("oumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_occident, R.string.makeup_combination_occident, bundleDir + "oumei.bundle", jsonDir + "oumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("wumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_charming, R.string.makeup_combination_charming, bundleDir + "wumei.bundle", jsonDir + "wumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
return combinations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造美妆模型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Makeup getMakeupModel(MakeupCombinationBean bean) {
|
||||
Makeup makeupModel;
|
||||
if (TypeEnum.TYPE_THEME_MAIN == bean.getType() && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0) {
|
||||
makeupModel = new Makeup(new FUBundleData(bean.getBundlePath()));
|
||||
//新的组合妆容设置滤镜scale
|
||||
makeupModel.setCurrentFilterScale(bean.getFilterScale());
|
||||
} else {
|
||||
makeupModel = new Makeup(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_MAKEUP));
|
||||
}
|
||||
|
||||
if (bean.getKey().equals("origin")) {
|
||||
return makeupModel;
|
||||
}
|
||||
|
||||
if ((TypeEnum.TYPE_THEME_SUB == bean.getType() || TypeEnum.TYPE_DAILY == bean.getType()) && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0)
|
||||
makeupModel.setCombinedConfig(new FUBundleData(bean.getBundlePath()));
|
||||
|
||||
makeupModel.setMakeupIntensity(bean.getIntensity());
|
||||
if (bean.getJsonPathParams() == null) {
|
||||
bean.setJsonPathParams(getLocalParams(bean.getJsonPath()));
|
||||
}
|
||||
LinkedHashMap<String, Object> params = bean.getJsonPathParams();
|
||||
|
||||
//支持自定义,所以需要知道选中了妆容的哪一些项
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
if (value instanceof double[] && ((double[]) value).length > 4) {
|
||||
int count = ((double[]) value).length / 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i == 0) {
|
||||
if (makeupSetMapping.containsKey(key)) {
|
||||
makeupSetMapping.get(key).setValue(makeupModel, value);
|
||||
}
|
||||
} else {
|
||||
if (makeupSetMapping.containsKey(key + (i + 1))) {
|
||||
makeupSetMapping.get(key + (i + 1)).setValue(makeupModel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (makeupSetMapping.containsKey(key)) {
|
||||
makeupSetMapping.get(key).setValue(makeupModel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return makeupModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取本地参数配置
|
||||
*
|
||||
* @param jsonPath String json文件路径
|
||||
* @return LinkedHashMap<String, Any>
|
||||
*/
|
||||
private static LinkedHashMap<String, Object> getLocalParams(String jsonPath) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap(32);
|
||||
map.put(MakeupParam.LIP_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_LINER_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.BLUSHER_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.PUPIL_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_BROW_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_SHADOW_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYELASH_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.FOUNDATION_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.HIGHLIGHT_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.SHADOW_INTENSITY, 0.0);
|
||||
LinkedHashMap<String, Object> jsonParam = FileUtils.INSTANCE.loadParamsFromLocal(FaceUnityData.mApplication, jsonPath);
|
||||
for (Map.Entry<String, Object> entry : jsonParam.entrySet()) {
|
||||
if (entry.getKey().startsWith("tex_")) {
|
||||
if (entry.getValue() instanceof String && ((String) entry.getValue()).contains(".bundle")) {
|
||||
map.put(entry.getKey(), FaceUnityConfig.MAKEUP_RESOURCE_ITEM_BUNDLE_DIR + entry.getValue());
|
||||
}
|
||||
} else {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
interface MakeupSetParam {
|
||||
/**
|
||||
* 模型属性赋值
|
||||
*
|
||||
* @param makeup
|
||||
* @param value
|
||||
*/
|
||||
void setValue(Makeup makeup, Object value);
|
||||
|
||||
}
|
||||
|
||||
/*美妆映射模型*/
|
||||
public static HashMap<String, MakeupSetParam> makeupSetMapping = new HashMap<String, MakeupSetParam>() {
|
||||
{
|
||||
put(MakeupParam.LIP_TYPE, (makeup, value) -> makeup.setLipType((int) value));
|
||||
put(MakeupParam.IS_TWO_COLOR, (makeup, value) -> makeup.setEnableTwoLipColor((int) value == 1));
|
||||
put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_ENABLE, (makeup, value) -> makeup.setLipHighLightEnable((int) value == 1));
|
||||
put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_STRENGTH, (makeup, value) -> makeup.setLipHighLightStrength((double) value));
|
||||
put(MakeupParam.BROW_WARP, (makeup, value) -> makeup.setEnableBrowWarp((double) value == 1.0));
|
||||
put(MakeupParam.BROW_WARP_TYPE, (makeup, value) -> makeup.setBrowWarpType((int) value));
|
||||
/*强度*/
|
||||
put(MakeupParam.MAKEUP_INTENSITY, (makeup, value) -> makeup.setMakeupIntensity((double) value));
|
||||
put(MakeupParam.LIP_INTENSITY, (makeup, value) -> makeup.setLipIntensity((double) value));
|
||||
put(MakeupParam.EYE_LINER_INTENSITY, (makeup, value) -> makeup.setEyeLineIntensity((double) value));
|
||||
put(MakeupParam.BLUSHER_INTENSITY, (makeup, value) -> makeup.setBlusherIntensity((double) value));
|
||||
put(MakeupParam.PUPIL_INTENSITY, (makeup, value) -> makeup.setPupilIntensity((double) value));
|
||||
put(MakeupParam.EYE_BROW_INTENSITY, (makeup, value) -> makeup.setEyeBrowIntensity((double) value));
|
||||
put(MakeupParam.EYE_SHADOW_INTENSITY, (makeup, value) -> makeup.setEyeShadowIntensity((double) value));
|
||||
put(MakeupParam.EYELASH_INTENSITY, (makeup, value) -> makeup.setEyeLashIntensity((double) value));
|
||||
put(MakeupParam.FOUNDATION_INTENSITY, (makeup, value) -> makeup.setFoundationIntensity((double) value));
|
||||
put(MakeupParam.HIGHLIGHT_INTENSITY, (makeup, value) -> makeup.setHeightLightIntensity((double) value));
|
||||
put(MakeupParam.SHADOW_INTENSITY, (makeup, value) -> makeup.setShadowIntensity((double) value));
|
||||
/*子项妆容贴图*/
|
||||
put(MakeupParam.TEX_LIP, (makeup, value) -> makeup.setLipBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_BROW, (makeup, value) -> makeup.setEyeBrowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowBundle3(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowBundle4(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_PUPIL, (makeup, value) -> makeup.setPupilBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_BLUSHER, (makeup, value) -> makeup.setBlusherBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_FOUNDATION, (makeup, value) -> makeup.setFoundationBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_HIGH_LIGHT, (makeup, value) -> makeup.setHighLightBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_SHADOW, (makeup, value) -> makeup.setShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
/*子项妆容颜色*/
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR, (makeup, value) -> makeup.setLipColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR_V2, (makeup, value) -> makeup.setLipColorV2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR2, (makeup, value) -> makeup.setLipColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_LINER_COLOR, (makeup, value) -> makeup.setEyeLinerColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_LASH_COLOR, (makeup, value) -> makeup.setEyeLashColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_BLUSHER_COLOR, (makeup, value) -> makeup.setBlusherColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_BLUSHER_COLOR2, (makeup, value) -> makeup.setBlusherColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_FOUNDATION_COLOR, (makeup, value) -> makeup.setFoundationColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_HIGH_LIGHT_COLOR, (makeup, value) -> makeup.setHighLightColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_SHADOW_COLOR, (makeup, value) -> makeup.setShadowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_PUPIL_COLOR, (makeup, value) -> makeup.setPupilColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR, (makeup, value) -> makeup.setEyeShadowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR2, (makeup, value) -> makeup.setEyeShadowColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR3, (makeup, value) -> makeup.setEyeShadowColor3(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR4, (makeup, value) -> makeup.setEyeShadowColor4(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value)));
|
||||
/* 图层混合模式 */
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowTexBlend2((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowTexBlend3((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowTexBlend4((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_BLUSHER, (makeup, value) -> makeup.setBlusherTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherTexBlend2((int) value));
|
||||
put(MakeupParam.BLEND_TEX_PUPIL, (makeup, value) -> makeup.setPupilTexBlend((int) value));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 构造颜色模型
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public static FUColorRGBData buildFUColorRGBData(Object object) {
|
||||
if (object instanceof double[]) {
|
||||
double[] array = (double[]) object;
|
||||
if (array.length == 4) {
|
||||
return new FUColorRGBData(array[0] * 255, array[1] * 255, array[2] * 255, array[3] * 255);
|
||||
}
|
||||
}
|
||||
return new FUColorRGBData(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
//endregion 组合妆容
|
||||
|
||||
// region 子妆容
|
||||
|
||||
/* 粉底 */
|
||||
public static String FACE_MAKEUP_TYPE_FOUNDATION = "FOUNDATION";
|
||||
/* 口红 */
|
||||
public static String FACE_MAKEUP_TYPE_LIP_STICK = "STICK";
|
||||
/* 腮红 */
|
||||
public static String FACE_MAKEUP_TYPE_BLUSHER = "BLUSHER";
|
||||
/* 眉毛 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_BROW = "EYE_BROW";
|
||||
/* 眼影 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_SHADOW = "EYE_SHADOW";
|
||||
/* 眼线 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_LINER = "EYE_LINER";
|
||||
/* 睫毛 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_LASH = "EYE_LASH";
|
||||
/* 高光 */
|
||||
public static String FACE_MAKEUP_TYPE_HIGH_LIGHT = "HIGHLIGHT";
|
||||
/* 阴影 */
|
||||
public static String FACE_MAKEUP_TYPE_SHADOW = "SHADOW";
|
||||
/* 美瞳 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_PUPIL = "EYE_PUPIL";
|
||||
|
||||
/**
|
||||
* 构造美妆子项类别
|
||||
*/
|
||||
public static ArrayList<MakeupCustomClassBean> buildCustomClasses() {
|
||||
ArrayList<MakeupCustomClassBean> classes = new ArrayList();
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_foundation, FACE_MAKEUP_TYPE_FOUNDATION));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_lipstick, FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_blusher, FACE_MAKEUP_TYPE_BLUSHER));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyebrow, FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_shadow, FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_liner, FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyelash, FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_highlight, FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_shadow, FACE_MAKEUP_TYPE_SHADOW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_contact_lens, FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 美妆单项妆容配置参数
|
||||
*
|
||||
* @return LinkedHashMap<String, ArrayList < MakeupCustomBean>>
|
||||
*/
|
||||
public static LinkedHashMap<String, ArrayList<MakeupCustomBean>> buildCustomItemParams(LinkedHashMap<String, ArrayList<double[]>> colorMap) {
|
||||
LinkedHashMap<String, ArrayList<MakeupCustomBean>> mCustomItems = new LinkedHashMap<>();
|
||||
/*粉底*/
|
||||
ArrayList<MakeupCustomBean> makeupItems = new ArrayList(6);
|
||||
makeupItems.add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
ArrayList<double[]> list = colorMap.get("color_mu_style_foundation_01");
|
||||
for (int i = 3; i < 8; i++) {
|
||||
double[] colors = list.get(i);
|
||||
ColorDrawable drawable = new ColorDrawable(Color.argb((int) (colors[3] * 255), (int) (colors[0] * 255), (int) (colors[1] * 255), (int) (colors[2] * 255)));
|
||||
makeupItems.add(new MakeupCustomBean(0, drawable));
|
||||
}
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_FOUNDATION, makeupItems);
|
||||
|
||||
|
||||
/*口红*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_LIP_STICK, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_fog, getDrawable(R.mipmap.icon_makeup_lip_fog), colorMap.get("color_mu_style_lip_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_moist1, getDrawable(R.mipmap.icon_makeup_lip_moist), colorMap.get("color_mu_style_lip_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_moist2, getDrawable(R.mipmap.icon_makeup_lip_water), colorMap.get("color_mu_style_lip_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_pearl, getDrawable(R.mipmap.icon_makeup_lip_pearl), colorMap.get("color_mu_style_lip_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_bitelip, getDrawable(R.mipmap.icon_makeup_lip_beitelip), colorMap.get("color_mu_style_lip_01")));
|
||||
}
|
||||
});
|
||||
|
||||
/*腮红*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_BLUSHER, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_apple, getDrawable(R.mipmap.icon_makeup_blush_01), colorMap.get("color_mu_style_blush_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_fan, getDrawable(R.mipmap.icon_makeup_blush_02), colorMap.get("color_mu_style_blush_02")));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_eye_corner, getDrawable(R.mipmap.icon_makeup_blush_03), colorMap.get("color_mu_style_blush_03")));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_slight_drunk, getDrawable(R.mipmap.icon_makeup_blush_04), colorMap.get("color_mu_style_blush_04")));
|
||||
}
|
||||
});
|
||||
/*眉毛*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_BROW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_willow, getDrawable(R.mipmap.icon_makeup_eyebrow_01), colorMap.get("color_mu_style_eyebrow_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_wild, getDrawable(R.mipmap.icon_makeup_eyebrow_02), colorMap.get("color_mu_style_eyebrow_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_classical, getDrawable(R.mipmap.icon_makeup_eyebrow_03), colorMap.get("color_mu_style_eyebrow_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_standard, getDrawable(R.mipmap.icon_makeup_eyebrow_04), colorMap.get("color_mu_style_eyebrow_01")));
|
||||
}
|
||||
});
|
||||
|
||||
/*眼影*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_SHADOW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_single, getDrawable(R.mipmap.icon_makeup_eyeshadow_01), colorMap.get("color_mu_style_eyeshadow_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double1, getDrawable(R.mipmap.icon_makeup_eyeshadow_02), colorMap.get("color_mu_style_eyeshadow_02")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double2, getDrawable(R.mipmap.icon_makeup_eyeshadow_03), colorMap.get("color_mu_style_eyeshadow_03")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double3, getDrawable(R.mipmap.icon_makeup_eyeshadow_04), colorMap.get("color_mu_style_eyeshadow_04")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple1, getDrawable(R.mipmap.icon_makeup_eyeshadow_05), colorMap.get("color_mu_style_eyeshadow_05")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple2, getDrawable(R.mipmap.icon_makeup_eyeshadow_06), colorMap.get("color_mu_style_eyeshadow_06")));
|
||||
}
|
||||
});
|
||||
|
||||
/*眼线*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LINER, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_cat, getDrawable(R.mipmap.icon_makeup_eyeliner_01), colorMap.get("color_mu_style_eyeliner_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_drooping, getDrawable(R.mipmap.icon_makeup_eyeliner_02), colorMap.get("color_mu_style_eyeliner_02")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_open, getDrawable(R.mipmap.icon_makeup_eyeliner_03), colorMap.get("color_mu_style_eyeliner_03")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_close, getDrawable(R.mipmap.icon_makeup_eyeliner_04), colorMap.get("color_mu_style_eyeliner_04")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_long, getDrawable(R.mipmap.icon_makeup_eyeliner_05), colorMap.get("color_mu_style_eyeliner_05")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_circular, getDrawable(R.mipmap.icon_makeup_eyeliner_06), colorMap.get("color_mu_style_eyeliner_06")));
|
||||
}
|
||||
});
|
||||
/*睫毛*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LASH, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_natural1, getDrawable(R.mipmap.icon_makeup_eyelash_01), colorMap.get("color_mu_style_eyelash_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_natural2, getDrawable(R.mipmap.icon_makeup_eyelash_02), colorMap.get("color_mu_style_eyelash_02")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_thick1, getDrawable(R.mipmap.icon_makeup_eyelash_03), colorMap.get("color_mu_style_eyelash_03")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_thick2, getDrawable(R.mipmap.icon_makeup_eyelash_04), colorMap.get("color_mu_style_eyelash_04")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate1, getDrawable(R.mipmap.icon_makeup_eyelash_05), colorMap.get("color_mu_style_eyelash_05")));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate2, getDrawable(R.mipmap.icon_makeup_eyelash_06), colorMap.get("color_mu_style_eyelash_06")));
|
||||
}
|
||||
});
|
||||
|
||||
/*高光*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_HIGH_LIGHT, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_highlight_one, getDrawable(R.mipmap.icon_makeup_highlight_01), colorMap.get("color_mu_style_highlight_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_highlight_two, getDrawable(R.mipmap.icon_makeup_highlight_02), colorMap.get("color_mu_style_highlight_02")));
|
||||
}
|
||||
});
|
||||
/*阴影*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_SHADOW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_shadow_one, getDrawable(R.mipmap.icon_makeup_contour_01), colorMap.get("color_mu_style_contour_01")));
|
||||
}
|
||||
});
|
||||
/*美瞳*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_PUPIL, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none)));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_1, getDrawable(R.mipmap.icon_makeup_eyepupil_01), colorMap.get("color_mu_style_eyepupil_01")));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_2, getDrawable(R.mipmap.icon_makeup_eyepupil_03), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_3, getDrawable(R.mipmap.icon_makeup_eyepupil_04), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_4, getDrawable(R.mipmap.icon_makeup_eyepupil_05), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_5, getDrawable(R.mipmap.icon_makeup_eyepupil_06), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_6, getDrawable(R.mipmap.icon_makeup_eyepupil_07), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_7, getDrawable(R.mipmap.icon_makeup_eyepupil_08), null));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_8, getDrawable(R.mipmap.icon_makeup_eyepupil_09), null));
|
||||
}
|
||||
});
|
||||
return mCustomItems;
|
||||
}
|
||||
|
||||
|
||||
//endregion 子妆容
|
||||
|
||||
|
||||
//region 其他
|
||||
|
||||
/**
|
||||
* 获取颜色值配置
|
||||
*
|
||||
* @return LinkedHashMap<String, ArrayList < DoubleArray>>
|
||||
*/
|
||||
public static LinkedHashMap<String, ArrayList<double[]>> buildMakeUpColorMap() {
|
||||
LinkedHashMap<String, ArrayList<double[]>> makeupColorMap = new LinkedHashMap<>(32);
|
||||
String colorJson = FileUtils.INSTANCE.loadStringFromLocal(FaceUnityData.mApplication, FaceUnityConfig.MAKEUP_RESOURCE_COLOR_SETUP_JSON);
|
||||
if (colorJson != null && colorJson.trim().length() > 0) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(colorJson);
|
||||
Iterator<String> keys = jsonObject.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
ArrayList<double[]> colorList = new ArrayList(12);
|
||||
// add additional transparent to fit ui
|
||||
//增加透明色,兼容ColorRecycleView展示
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
JSONObject colorObject = jsonObject.optJSONObject(key);
|
||||
for (int i = 1; i < 6; i++) {
|
||||
JSONArray jsonArray = colorObject.optJSONArray("color" + i);
|
||||
int length = jsonArray.length();
|
||||
double[] colors = new double[length];
|
||||
for (int j = 0; j < length; j++) {
|
||||
colors[j] = jsonArray.optDouble(j, 0.0);
|
||||
}
|
||||
colorList.add(colors);
|
||||
}
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
makeupColorMap.put(key, colorList);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
return makeupColorMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取Drawable对象
|
||||
*
|
||||
* @param res Int
|
||||
* @return Drawable
|
||||
*/
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private static Drawable getDrawable(int res) {
|
||||
return FaceUnityData.mApplication.getResources().getDrawable(res);
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
@ -3,33 +3,53 @@ package com.yunbao.faceunity.ui;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.checkbox.CheckGroup;
|
||||
import com.yunbao.faceunity.control.BodyBeautyControlView;
|
||||
import com.yunbao.faceunity.control.FaceBeautyControlView;
|
||||
import com.yunbao.faceunity.control.MakeupControlView;
|
||||
import com.yunbao.faceunity.control.PropControlView;
|
||||
import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter;
|
||||
import com.yunbao.faceunity.adapters.MenuGroupRecyclerAdapter;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.data.FaceUnityDataFactory;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FineStickerDataFactory;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.MenuGroupBean;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity;
|
||||
import com.yunbao.faceunity.repo.AnimojiSource;
|
||||
import com.yunbao.faceunity.repo.BodyBeautySource;
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||
import com.yunbao.faceunity.repo.MakeupSource;
|
||||
import com.yunbao.faceunity.repo.PropSource;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DESC:
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class FaceUnityView extends LinearLayout {
|
||||
public class FaceUnityView extends LinearLayout implements StickerDownloadHelper.Callback {
|
||||
|
||||
private Context mContext;
|
||||
private RecyclerView menuGroup;
|
||||
private RecyclerView containerRecycler;
|
||||
private ContainerRecyclerAdapter containerAdapter;
|
||||
private TabLayout tabLayout;
|
||||
private TextView title;
|
||||
private LinearLayout menu2, diy, reset, menu2Reset;
|
||||
private ImageView menu2Back, back, close;
|
||||
|
||||
public FaceUnityView(Context context) {
|
||||
super(context);
|
||||
@ -50,20 +70,11 @@ public class FaceUnityView extends LinearLayout {
|
||||
}
|
||||
|
||||
|
||||
private FaceUnityDataFactory mDataFactory;
|
||||
|
||||
private CheckGroup mCheckGroupView;//底部菜单
|
||||
private FaceBeautyControlView mFaceBeautyControlView;//美颜菜单
|
||||
private MakeupControlView mMakeupControlView;//美妆菜单
|
||||
private PropControlView mPropControlView;//道具菜单
|
||||
private BodyBeautyControlView mBodyBeautyControlView;//美体菜单
|
||||
private View lineView;//分割线
|
||||
|
||||
|
||||
private void init() {
|
||||
LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this);
|
||||
initView();
|
||||
bindBottomView();
|
||||
FineStickerDataFactory.getInstance().setCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +83,6 @@ public class FaceUnityView extends LinearLayout {
|
||||
* @param dataFactory FaceUnityDataFactory
|
||||
*/
|
||||
public void bindDataFactory(FaceUnityDataFactory dataFactory) {
|
||||
mDataFactory = dataFactory;
|
||||
|
||||
}
|
||||
|
||||
@ -81,7 +91,27 @@ public class FaceUnityView extends LinearLayout {
|
||||
*/
|
||||
private void initView() {
|
||||
menuGroup = findViewById(R.id.menu_group);
|
||||
containerRecycler = findViewById(R.id.menu2_container_view);
|
||||
tabLayout = findViewById(R.id.menu2_tab);
|
||||
title = findViewById(R.id.menu_title);
|
||||
menu2 = findViewById(R.id.layout_faceunity_menu2);
|
||||
back = findViewById(R.id.menu_back);
|
||||
menu2Back = findViewById(R.id.menu2_back);
|
||||
close = findViewById(R.id.menu_close);
|
||||
reset = findViewById(R.id.menu_reset);
|
||||
menu2Reset = findViewById(R.id.menu2_reset);
|
||||
initMenuGroup();
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
initViewClick();
|
||||
}
|
||||
private void initViewClick(){
|
||||
menu2Back.setOnClickListener(v -> goBackMainMenu());
|
||||
|
||||
}
|
||||
private void goBackMainMenu(){
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
menu2.setVisibility(GONE);
|
||||
menuGroup.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
@ -100,17 +130,190 @@ public class FaceUnityView extends LinearLayout {
|
||||
private void showFunction(int index) {
|
||||
|
||||
}
|
||||
|
||||
private void initMenuGroup() {
|
||||
MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext);
|
||||
menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4));
|
||||
Map<Integer,Integer> layoutItem=new HashMap<>();
|
||||
layoutItem.put(R.string.home_function_name_beauty,R.mipmap.ico_home_beauty);
|
||||
layoutItem.put(R.string.home_function_name_makeup,R.mipmap.ico_home_makeup);
|
||||
layoutItem.put(R.string.home_function_name_beauty_body,R.mipmap.ico_home_beauty_body);
|
||||
layoutItem.put(R.string.home_function_name_beauty_body,R.mipmap.ico_home_beauty_body);
|
||||
layoutItem.put(R.string.home_function_name_big_head,R.mipmap.ico_home_big_head);
|
||||
layoutItem.put(R.string.home_function_name_animoji,R.mipmap.ico_home_animoji);
|
||||
layoutItem.put(R.string.home_function_name_sticker,R.mipmap.ico_home_sticker);
|
||||
layoutItem.put(R.string.home_function_name_fine_sticker,R.mipmap.ico_home_fine_sticker);
|
||||
List<MenuGroupBean> layoutItem = new ArrayList<>();
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty, R.mipmap.ico_home_beauty));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_makeup, R.mipmap.ico_home_makeup));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty_body, R.mipmap.ico_home_beauty_body));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_big_head, R.mipmap.ico_home_big_head));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_animoji, R.mipmap.ico_home_animoji));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_sticker, R.mipmap.ico_home_sticker));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_fine_sticker, R.mipmap.ico_home_fine_sticker));
|
||||
adapter.setList(layoutItem);
|
||||
adapter.setOnItemClickListener(position -> {
|
||||
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
|
||||
title.setVisibility(GONE);
|
||||
switch (position) {
|
||||
case 0:
|
||||
map.put(R.string.beauty_radio_skin_beauty, FaceParam.FACE_BEAUTY_SKIN);
|
||||
map.put(R.string.beauty_radio_face_shape, FaceParam.FACE_BEAUTY_SHAPE);
|
||||
map.put(R.string.beauty_radio_filter, FaceParam.FACE_BEAUTY_FILTER);
|
||||
map.put(R.string.beauty_radio_style, FaceParam.FACE_BEAUTY_STYLE);
|
||||
setContainerRecycler(FaceBeautySource.buildSkinParams());
|
||||
break;
|
||||
case 1:
|
||||
title.setText(R.string.home_function_name_makeup);
|
||||
title.setVisibility(VISIBLE);
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCombinations());
|
||||
break;
|
||||
case 2:
|
||||
title.setText(R.string.home_function_name_beauty_body);
|
||||
title.setVisibility(VISIBLE);
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(BodyBeautySource.buildBodyBeauty());
|
||||
break;
|
||||
case 3:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.BIG_HEAD));
|
||||
break;
|
||||
case 4:
|
||||
changeRecyclerItemCount(5);
|
||||
map.put(R.string.animoji_filter, FaceParam.FACE_ANIMOJI);
|
||||
map.put(R.string.cartoon_filter, FaceParam.FACE_ANIM);
|
||||
setContainerRecycler(AnimojiSource.buildAnimojis());
|
||||
break;
|
||||
case 5:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.STICKER));
|
||||
break;
|
||||
case 6:
|
||||
List<FineStickerTagEntity> tagList = FineStickerDataFactory.getInstance().loadTagList();
|
||||
if (!tagList.isEmpty()) {
|
||||
setTab(createTabs(tagList));
|
||||
}
|
||||
break;
|
||||
}
|
||||
setTab(createTabs(map));
|
||||
menuGroup.setVisibility(GONE);
|
||||
menu2.setVisibility(VISIBLE);
|
||||
});
|
||||
menuGroup.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private List<TabLayout.Tab> createTabs(Map<Integer, Integer> map) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (Integer key : map.keySet()) {
|
||||
TabLayout.Tab tab = tabLayout.newTab().setText(key);
|
||||
tab.setTag(map.get(key));
|
||||
list.add(tab);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<TabLayout.Tab> createTabs(List<FineStickerTagEntity> tags) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (FineStickerTagEntity tag : tags) {
|
||||
TabLayout.Tab tab;
|
||||
if (WordUtil.isZh()) {
|
||||
tab = tabLayout.newTab().setText(tag.getTag().split("/")[0]);
|
||||
} else {
|
||||
tab = tabLayout.newTab().setText(tag.getTag().split("/")[1]);
|
||||
}
|
||||
tab.setTag(tag);
|
||||
list.add(tab);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void setTab(List<TabLayout.Tab> tabs) {
|
||||
tabLayout.removeAllTabs();
|
||||
for (TabLayout.Tab tab : tabs) {
|
||||
tabLayout.addTab(tab);
|
||||
}
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
Object tabTag = tab.getTag();
|
||||
if (tabTag instanceof Integer) {
|
||||
switch ((int) tab.getTag()) {
|
||||
case FaceParam.FACE_BEAUTY_SKIN:
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(FaceBeautySource.buildSkinParams());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_SHAPE:
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(FaceBeautySource.buildShapeParams());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_FILTER:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(FaceBeautySource.buildFilters());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_STYLE:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(FaceBeautySource.buildStylesParams());
|
||||
break;
|
||||
case FaceParam.FACE_ANIMOJI:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(AnimojiSource.buildAnimojis());
|
||||
break;
|
||||
case FaceParam.FACE_ANIM:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(AnimojiSource.buildFilters());
|
||||
break;
|
||||
default:
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
}
|
||||
} else if (tabTag instanceof FineStickerTagEntity) {
|
||||
FineStickerTagEntity tag = (FineStickerTagEntity) tabTag;
|
||||
FineStickerEntity sticker = FineStickerDataFactory.getInstance().loadStickerList(tag);
|
||||
ArrayList<FineStickerEntity.DocsBean> list = new ArrayList<>();
|
||||
FineStickerEntity.DocsBean docsBean = new FineStickerEntity.DocsBean();
|
||||
docsBean.set_id("-1");
|
||||
list.add(docsBean);
|
||||
list.addAll(sticker.getDocs());
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeRecyclerItemCount(int count) {
|
||||
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count));
|
||||
}
|
||||
|
||||
private void setContainerRecycler(ArrayList<? extends BaseBean> list) {
|
||||
if (containerAdapter == null) {
|
||||
containerAdapter = new ContainerRecyclerAdapter(mContext);
|
||||
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
|
||||
containerRecycler.setAdapter(containerAdapter);
|
||||
}
|
||||
containerAdapter.setList(list);
|
||||
containerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetTags(String[] tags) {
|
||||
List<FineStickerTagEntity> list = FineStickerDataFactory.formatTag(tags);
|
||||
setTab(createTabs(list));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetList(String tag, FineStickerEntity fineSticker) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownload(FineStickerEntity.DocsBean entity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
package com.yunbao.faceunity.ui.fragments;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.yunbao.faceunity.dialog.BaseDialogFragment;
|
||||
|
||||
public class FaceContainerFragment extends BaseDialogFragment {
|
||||
@Override
|
||||
protected View createDialogView(LayoutInflater inflater, @Nullable ViewGroup container) {
|
||||
return new LinearLayout(inflater.getContext());
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.yunbao.faceunity.utils
|
||||
|
||||
import android.view.View
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
||||
|
||||
class SeekBarUtils {
|
||||
companion object {
|
||||
/**
|
||||
* 设置滚动条数值
|
||||
* @param value Double 结果值
|
||||
* @param stand Double 标准值
|
||||
* @param range Double 范围区间
|
||||
*/
|
||||
fun seekToSeekBar(bar: DiscreteSeekBar, value: Double, stand: Double, range: Double) {
|
||||
if (stand == 0.5) {
|
||||
bar.min = -50
|
||||
bar.max = 50
|
||||
bar.progress = (value * 100 / range - 50).toInt()
|
||||
} else {
|
||||
bar.min = 0
|
||||
bar.max = 100
|
||||
bar.progress = (value * 100 / range).toInt()
|
||||
}
|
||||
bar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
251
FaceUnity/src/main/java/com/yunbao/faceunity/utils/ZipUtils.java
Normal file
@ -0,0 +1,251 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @author: lijuan
|
||||
* @description: 解压ZIP文件
|
||||
* @date: 2017-04-11
|
||||
* @time: 09:22
|
||||
*/
|
||||
public class ZipUtils {
|
||||
public static final String TAG = "ZIP";
|
||||
|
||||
/**
|
||||
* 解压zip到指定的路径
|
||||
*
|
||||
* @param zipFileString ZIP的名称
|
||||
* @param outPathString 要解压缩路径
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void unZipFolder(String zipFileString, String outPathString) throws Exception {
|
||||
ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
|
||||
ZipEntry zipEntry;
|
||||
String szName = "";
|
||||
while ((zipEntry = inZip.getNextEntry()) != null) {
|
||||
szName = zipEntry.getName();
|
||||
if (zipEntry.isDirectory()) {
|
||||
//获取部件的文件夹名
|
||||
szName = szName.substring(0, szName.length() - 1);
|
||||
File folder = new File(outPathString + File.separator + szName);
|
||||
folder.mkdirs();
|
||||
} else {
|
||||
Log.i(TAG, outPathString + File.separator + szName);
|
||||
File file = new File(outPathString + File.separator + szName);
|
||||
if (!file.exists()) {
|
||||
Log.i(TAG, "Create the file:" + outPathString + File.separator + szName);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
// 获取文件的输出流
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
int len;
|
||||
byte[] buffer = new byte[1024];
|
||||
// 读取(字节)字节到缓冲区
|
||||
while ((len = inZip.read(buffer)) != -1) {
|
||||
// 从缓冲区(0)位置写入(字节)字节
|
||||
out.write(buffer, 0, len);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
inZip.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解压zip到指定的路径
|
||||
*
|
||||
* @param zipFileString ZIP的名称
|
||||
* @param outPathString 要解压缩路径
|
||||
* @throws Exception
|
||||
*/
|
||||
public static ArrayList<String> unZipFolderWithFileName(String zipFileString, String outPathString) throws Exception {
|
||||
//记录所有文件名
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
|
||||
ZipEntry zipEntry;
|
||||
String szName = "";
|
||||
while ((zipEntry = inZip.getNextEntry()) != null) {
|
||||
szName = zipEntry.getName();
|
||||
if (zipEntry.isDirectory()) {
|
||||
//获取部件的文件夹名
|
||||
szName = szName.substring(0, szName.length() - 1);
|
||||
File folder = new File(outPathString + File.separator + szName);
|
||||
folder.mkdirs();
|
||||
} else {
|
||||
Log.i(TAG, outPathString + File.separator + szName);
|
||||
list.add(szName);
|
||||
File file = new File(outPathString + File.separator + szName);
|
||||
if (!file.exists()) {
|
||||
Log.i(TAG, "Create the file:" + outPathString + File.separator + szName);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
// 获取文件的输出流
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
int len;
|
||||
byte[] buffer = new byte[1024];
|
||||
// 读取(字节)字节到缓冲区
|
||||
while ((len = inZip.read(buffer)) != -1) {
|
||||
// 从缓冲区(0)位置写入(字节)字节
|
||||
out.write(buffer, 0, len);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
inZip.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void unZipFolder(String zipFileString, String outPathString, String szName) throws Exception {
|
||||
ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
|
||||
ZipEntry zipEntry;
|
||||
while ((zipEntry = inZip.getNextEntry()) != null) {
|
||||
//szName = zipEntry.getName();
|
||||
if (zipEntry.isDirectory()) {
|
||||
//获取部件的文件夹名
|
||||
szName = szName.substring(0, szName.length() - 1);
|
||||
File folder = new File(outPathString + File.separator + szName);
|
||||
folder.mkdirs();
|
||||
} else {
|
||||
Log.i(TAG, outPathString + File.separator + szName);
|
||||
File file = new File(outPathString + File.separator + szName);
|
||||
if (!file.exists()) {
|
||||
Log.i(TAG, "Create the file:" + outPathString + File.separator + szName);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
// 获取文件的输出流
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
int len;
|
||||
byte[] buffer = new byte[1024];
|
||||
// 读取(字节)字节到缓冲区
|
||||
while ((len = inZip.read(buffer)) != -1) {
|
||||
// 从缓冲区(0)位置写入(字节)字节
|
||||
out.write(buffer, 0, len);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
inZip.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩文件和文件夹
|
||||
*
|
||||
* @param srcFileString 要压缩的文件或文件夹
|
||||
* @param zipFileString 解压完成的Zip路径
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void zipFolder(String srcFileString, String zipFileString) throws Exception {
|
||||
//创建ZIP
|
||||
ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString));
|
||||
//创建文件
|
||||
File file = new File(srcFileString);
|
||||
//压缩
|
||||
zipFiles(file.getParent() + File.separator, file.getName(), outZip);
|
||||
//完成和关闭
|
||||
outZip.finish();
|
||||
outZip.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩文件
|
||||
*
|
||||
* @param folderString
|
||||
* @param fileString
|
||||
* @param zipOutputSteam
|
||||
* @throws Exception
|
||||
*/
|
||||
private static void zipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) throws Exception {
|
||||
if (zipOutputSteam == null)
|
||||
return;
|
||||
File file = new File(folderString + fileString);
|
||||
if (file.isFile()) {
|
||||
ZipEntry zipEntry = new ZipEntry(fileString);
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
zipOutputSteam.putNextEntry(zipEntry);
|
||||
int len;
|
||||
byte[] buffer = new byte[4096];
|
||||
while ((len = inputStream.read(buffer)) != -1) {
|
||||
zipOutputSteam.write(buffer, 0, len);
|
||||
}
|
||||
zipOutputSteam.closeEntry();
|
||||
} else {
|
||||
//文件夹
|
||||
String fileList[] = file.list();
|
||||
//没有子文件和压缩
|
||||
if (fileList.length <= 0) {
|
||||
ZipEntry zipEntry = new ZipEntry(fileString + File.separator);
|
||||
zipOutputSteam.putNextEntry(zipEntry);
|
||||
zipOutputSteam.closeEntry();
|
||||
}
|
||||
//子文件和递归
|
||||
for (int i = 0; i < fileList.length; i++) {
|
||||
zipFiles(folderString, fileString + File.separator + fileList[i], zipOutputSteam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回zip的文件输入流
|
||||
*
|
||||
* @param zipFileString zip的名称
|
||||
* @param fileString ZIP的文件名
|
||||
* @return InputStream
|
||||
* @throws Exception
|
||||
*/
|
||||
public static InputStream upZip(String zipFileString, String fileString) throws Exception {
|
||||
ZipFile zipFile = new ZipFile(zipFileString);
|
||||
ZipEntry zipEntry = zipFile.getEntry(fileString);
|
||||
return zipFile.getInputStream(zipEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回ZIP中的文件列表(文件和文件夹)
|
||||
*
|
||||
* @param zipFileString ZIP的名称
|
||||
* @param bContainFolder 是否包含文件夹
|
||||
* @param bContainFile 是否包含文件
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static List<File> getFileList(String zipFileString, boolean bContainFolder, boolean bContainFile) throws Exception {
|
||||
List<File> fileList = new ArrayList<File>();
|
||||
ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
|
||||
ZipEntry zipEntry;
|
||||
String szName = "";
|
||||
while ((zipEntry = inZip.getNextEntry()) != null) {
|
||||
szName = zipEntry.getName();
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 获取部件的文件夹名
|
||||
szName = szName.substring(0, szName.length() - 1);
|
||||
File folder = new File(szName);
|
||||
if (bContainFolder) {
|
||||
fileList.add(folder);
|
||||
}
|
||||
} else {
|
||||
File file = new File(szName);
|
||||
if (bContainFile) {
|
||||
fileList.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
inZip.close();
|
||||
return fileList;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* GSON 转换器
|
||||
*
|
||||
* @author Richie on 2018.12.22
|
||||
*/
|
||||
public final class GsonConverter {
|
||||
private final static Gson GSON = new Gson();
|
||||
|
||||
private GsonConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* json to bean
|
||||
*
|
||||
* @param json must be JSONObject
|
||||
* @param classOfT
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T jsonToBean(String json, Class<T> classOfT) {
|
||||
return GSON.fromJson(json, classOfT);
|
||||
}
|
||||
|
||||
/**
|
||||
* json to bean list, without generic erase problem, recommend
|
||||
*
|
||||
* @param json must be JSONArray
|
||||
* @param classOfT
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> List<T> jsonToList(String json, Class<T> classOfT) {
|
||||
JsonArray array = JsonParser.parseString(json).getAsJsonArray();
|
||||
List<T> list = new ArrayList<>(array.size());
|
||||
for (JsonElement elem : array) {
|
||||
T t = GSON.fromJson(elem, classOfT);
|
||||
list.add(t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* json to map
|
||||
*
|
||||
* @param json must be JSONObject
|
||||
* @return
|
||||
*/
|
||||
public static <T> Map<String, T> jsonToMap(String json) {
|
||||
return GSON.fromJson(json, new TypeToken<Map<String, T>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* json to bean list containing map
|
||||
*
|
||||
* @param json must be JSONObject
|
||||
* @return
|
||||
*/
|
||||
public static <T> List<Map<String, T>> jsonToMapList(String json) {
|
||||
return GSON.fromJson(json, new TypeToken<List<Map<String, T>>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* bean to json
|
||||
*
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
public static String objectToJson(Object src) {
|
||||
return GSON.toJson(src);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.WebSettings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.FileNameMap;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
|
||||
/**
|
||||
* @author Richie on 2018.12.22
|
||||
*/
|
||||
public final class HttpUtils {
|
||||
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
public static final MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain; charset=utf-8");
|
||||
public static final MediaType MEDIA_TYPE_STREAM = MediaType.parse("application/octet-stream");
|
||||
public static final String HEAD_KEY_USER_AGENT = "User-Agent";
|
||||
private static String sUserAgent;
|
||||
|
||||
private HttpUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 HttpGet 的 url 方便的添加键值对参数
|
||||
*
|
||||
* @param url
|
||||
* @param name
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String attachHttpGetParam(@NonNull String url, @NonNull String name, @NonNull String value) {
|
||||
return url + "?" + name + "=" + value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 HttpGet 的 url 方便的添加键值对参数
|
||||
*
|
||||
* @param url
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public static String attachHttpGetParams(@NonNull String url, @NonNull Map<String, String> params) {
|
||||
StringBuilder sb = new StringBuilder(url);
|
||||
sb.append("?");
|
||||
Set<Map.Entry<String, String>> entries = params.entrySet();
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
try {
|
||||
sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 ‘?’ 和 ‘/’ 判断文件名
|
||||
* http://mavin-manzhan.oss-cn-hangzhou.aliyuncs.com/1486631099150286149.jpg?x-oss-process=image/watermark,image_d2F0ZXJtYXJrXzIwMF81MC5wbmc
|
||||
*/
|
||||
public static String getUrlFileName(String url) {
|
||||
String filename = null;
|
||||
String[] strings = url.split("/");
|
||||
for (String string : strings) {
|
||||
if (string.contains("?")) {
|
||||
int endIndex = string.indexOf("?");
|
||||
if (endIndex != -1) {
|
||||
filename = string.substring(0, endIndex);
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strings.length > 0) {
|
||||
filename = strings[strings.length - 1];
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件名获取MIME类型
|
||||
*/
|
||||
public static MediaType guessMimeType(String fileName) {
|
||||
FileNameMap fileNameMap = URLConnection.getFileNameMap();
|
||||
fileName = fileName.replace("#", ""); //解决文件名中含有#号异常的问题
|
||||
String contentType = fileNameMap.getContentTypeFor(fileName);
|
||||
if (contentType == null) {
|
||||
return MEDIA_TYPE_STREAM;
|
||||
}
|
||||
return MediaType.parse(contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* User-Agent: Mozilla/5.0 (Linux; U; Android 5.0.2; zh-cn; Redmi Note 3 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36
|
||||
*/
|
||||
public static String getUserAgent() {
|
||||
if (TextUtils.isEmpty(sUserAgent)) {
|
||||
String webUserAgent = null;
|
||||
try {
|
||||
Class<?> sysResCls = Class.forName("com.android.internal.R$string");
|
||||
Field webUserAgentField = sysResCls.getDeclaredField("web_user_agent");
|
||||
Integer resId = (Integer) webUserAgentField.get(null);
|
||||
webUserAgent =OkHttpUtils.getInstance().getContext().getString(resId);
|
||||
} catch (Exception e) {
|
||||
// maybe failed on Android P or higher version
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(webUserAgent)) {
|
||||
try {
|
||||
webUserAgent = WebSettings.getDefaultUserAgent(OkHttpUtils.getInstance().getContext());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(webUserAgent)) {
|
||||
try {
|
||||
webUserAgent = System.getProperty("http.agent");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(webUserAgent)) {
|
||||
webUserAgent = "okhttp/square";
|
||||
}
|
||||
|
||||
Locale locale = Locale.getDefault();
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
// Add version
|
||||
final String version = Build.VERSION.RELEASE;
|
||||
if (version.length() > 0) {
|
||||
buffer.append(version);
|
||||
} else {
|
||||
// default to "1.0"
|
||||
buffer.append("1.0");
|
||||
}
|
||||
buffer.append("; ");
|
||||
final String language = locale.getLanguage();
|
||||
if (language != null) {
|
||||
buffer.append(language.toLowerCase(locale));
|
||||
final String country = locale.getCountry();
|
||||
if (!TextUtils.isEmpty(country)) {
|
||||
buffer.append("-");
|
||||
buffer.append(country.toLowerCase(locale));
|
||||
}
|
||||
} else {
|
||||
// default to "en"
|
||||
buffer.append("en");
|
||||
}
|
||||
// add the model for the release build
|
||||
if ("REL".equals(Build.VERSION.CODENAME)) {
|
||||
final String model = Build.MODEL;
|
||||
if (model.length() > 0) {
|
||||
buffer.append("; ");
|
||||
buffer.append(model);
|
||||
}
|
||||
}
|
||||
final String id = Build.ID;
|
||||
if (id.length() > 0) {
|
||||
buffer.append(" Build/");
|
||||
buffer.append(id);
|
||||
}
|
||||
sUserAgent = String.format(webUserAgent, buffer, "Mobile ");
|
||||
}
|
||||
return sUserAgent;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* Https相关的工具类
|
||||
*
|
||||
* @author Richie on 2018.12.22
|
||||
*/
|
||||
final class HttpsUtils {
|
||||
|
||||
/**
|
||||
* 为了解决客户端不信任服务器数字证书的问题,网络上大部分的解决方案都是让客户端不对证书做任何检查,
|
||||
* 这是一种有很大安全漏洞的办法
|
||||
*/
|
||||
public static X509TrustManager UnSafeTrustManager = new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[]{};
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,
|
||||
* 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。
|
||||
* 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true
|
||||
*/
|
||||
public static HostnameVerifier UnSafeHostnameVerifier = new HostnameVerifier() {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public static SSLParams getSslSocketFactory() {
|
||||
return getSslSocketFactoryBase(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* https单向认证
|
||||
* 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证
|
||||
*/
|
||||
public static SSLParams getSslSocketFactory(X509TrustManager trustManager) {
|
||||
return getSslSocketFactoryBase(trustManager, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* https单向认证
|
||||
* 用含有服务端公钥的证书校验服务端证书
|
||||
*/
|
||||
public static SSLParams getSslSocketFactory(InputStream... certificates) {
|
||||
return getSslSocketFactoryBase(null, null, null, certificates);
|
||||
}
|
||||
|
||||
/**
|
||||
* https双向认证
|
||||
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
|
||||
* certificates -> 用含有服务端公钥的证书校验服务端证书
|
||||
*/
|
||||
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) {
|
||||
return getSslSocketFactoryBase(null, bksFile, password, certificates);
|
||||
}
|
||||
|
||||
/**
|
||||
* https双向认证
|
||||
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
|
||||
* X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可
|
||||
*/
|
||||
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) {
|
||||
return getSslSocketFactoryBase(trustManager, bksFile, password);
|
||||
}
|
||||
|
||||
private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) {
|
||||
SSLParams sslParams = new SSLParams();
|
||||
try {
|
||||
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
|
||||
TrustManager[] trustManagers = prepareTrustManager(certificates);
|
||||
X509TrustManager manager;
|
||||
if (trustManager != null) {
|
||||
//优先使用用户自定义的TrustManager
|
||||
manager = trustManager;
|
||||
} else if (trustManagers != null) {
|
||||
//然后使用默认的TrustManager
|
||||
manager = chooseTrustManager(trustManagers);
|
||||
} else {
|
||||
//否则使用不安全的TrustManager
|
||||
manager = UnSafeTrustManager;
|
||||
}
|
||||
// 创建TLS类型的SSLContext对象, that uses our TrustManager
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
// 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
|
||||
// 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书
|
||||
sslContext.init(keyManagers, new TrustManager[]{manager}, null);
|
||||
// 通过sslContext获取SSLSocketFactory对象
|
||||
sslParams.sSLSocketFactory = sslContext.getSocketFactory();
|
||||
sslParams.trustManager = manager;
|
||||
return sslParams;
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
|
||||
try {
|
||||
if (bksFile == null || password == null) {
|
||||
return null;
|
||||
}
|
||||
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
|
||||
clientKeyStore.load(bksFile, password.toCharArray());
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(clientKeyStore, password.toCharArray());
|
||||
return kmf.getKeyManagers();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TrustManager[] prepareTrustManager(InputStream... certificates) {
|
||||
if (certificates == null || certificates.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
// 创建一个默认类型的KeyStore,存储我们信任的证书
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null);
|
||||
int index = 0;
|
||||
for (InputStream certStream : certificates) {
|
||||
String certificateAlias = Integer.toString(index++);
|
||||
// 证书工厂根据证书文件的流生成证书 cert
|
||||
Certificate cert = certificateFactory.generateCertificate(certStream);
|
||||
// 将 cert 作为可信证书放入到keyStore中
|
||||
keyStore.setCertificateEntry(certificateAlias, cert);
|
||||
try {
|
||||
if (certStream != null) {
|
||||
certStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//我们创建一个默认类型的TrustManagerFactory
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
//用我们之前的keyStore实例初始化TrustManagerFactory,这样tmf就会信任keyStore中的证书
|
||||
tmf.init(keyStore);
|
||||
//通过tmf获取TrustManager数组,TrustManager也会信任keyStore中的证书
|
||||
return tmf.getTrustManagers();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
|
||||
for (TrustManager trustManager : trustManagers) {
|
||||
if (trustManager instanceof X509TrustManager) {
|
||||
return (X509TrustManager) trustManager;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class SSLParams {
|
||||
SSLSocketFactory sSLSocketFactory;
|
||||
X509TrustManager trustManager;
|
||||
}
|
||||
}
|
@ -0,0 +1,710 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* OkHttp 工具类
|
||||
*
|
||||
* @author Richie on 2018.12.19
|
||||
*/
|
||||
public final class OkHttpUtils {
|
||||
private static final String NETWORK_FAILURE_MESSAGE = "网络访问失败";
|
||||
private static final String PARSE_FAILURE_MESSAGE = "数据解析失败";
|
||||
private static final String DOWNLOAD_FAILURE_MESSAGE = "文件下载失败";
|
||||
private static final String RESPONSE_FAILURE_MESSAGE = "响应错误 ";
|
||||
private static final String UPLOAD_FAILURE_MESSAGE = "文件上传失败 ";
|
||||
private static final int TIMEOUT = 10;
|
||||
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
|
||||
private OkHttpClient mOkHttpClient;
|
||||
private Context mContext;
|
||||
|
||||
private OkHttpUtils() {
|
||||
}
|
||||
|
||||
public static OkHttpUtils getInstance() {
|
||||
return OkHttpUtilsHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 OkHttp
|
||||
*
|
||||
* @param context
|
||||
* @param debug
|
||||
*/
|
||||
public void init(@NonNull Context context, boolean debug) {
|
||||
mContext = context.getApplicationContext();
|
||||
OkLogger.debug(debug);
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
|
||||
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
|
||||
.writeTimeout(TIMEOUT * 5, TimeUnit.SECONDS)
|
||||
.cookieJar(new CookieJar() {
|
||||
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {
|
||||
cookieStore.put(httpUrl.host(), list);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(@NotNull HttpUrl httpUrl) {
|
||||
List<Cookie> cookies = cookieStore.get(httpUrl.host());
|
||||
return cookies != null ? cookies : new ArrayList<>();
|
||||
}
|
||||
});
|
||||
|
||||
//Android4.4一下手机制定ssl1.2
|
||||
try {
|
||||
SSLSocketFactory factory = new SSLSocketFactoryCompat();
|
||||
builder.sslSocketFactory(factory);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
|
||||
// builder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
|
||||
builder.hostnameVerifier(HttpsUtils.UnSafeHostnameVerifier);
|
||||
mOkHttpClient = builder.build();
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public void getAsString(@NonNull String url, @NonNull OkHttpCallback<String> callback) {
|
||||
getAsString(url, null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Get 请求,返回值是字符串
|
||||
*
|
||||
* @param url
|
||||
* @param paramMap
|
||||
* @param callback
|
||||
*/
|
||||
public void getAsString(@NonNull String url, Map<String, String> paramMap, @NonNull OkHttpCallback<String> callback) {
|
||||
if (paramMap != null) {
|
||||
url = HttpUtils.attachHttpGetParams(url, paramMap);
|
||||
}
|
||||
Request request = buildGetRequest(url);
|
||||
newStringCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Get 请求,返回值是数据实体
|
||||
*
|
||||
* @param url
|
||||
* @param callback
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void getAsEntity(@NonNull String url, @NonNull final OkHttpCallback<T> callback) {
|
||||
getAsEntity(url, null, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Get 请求,返回值是数据实体
|
||||
*
|
||||
* @param url
|
||||
* @param paramMap
|
||||
* @param callback
|
||||
* @param <T>
|
||||
*/
|
||||
public <T> void getAsEntity(@NonNull String url, Map<String, String> paramMap, @NonNull final OkHttpCallback<T> callback) {
|
||||
if (paramMap != null) {
|
||||
url = HttpUtils.attachHttpGetParams(url, paramMap);
|
||||
}
|
||||
Request request = buildGetRequest(url);
|
||||
newEntityCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post 键值对,表单数据,返回字符串
|
||||
*
|
||||
* @param url
|
||||
* @param paramMap
|
||||
* @param callback
|
||||
*/
|
||||
public void postKeyValueAsString(@NonNull String url, Map<String, String> paramMap, @NonNull OkHttpCallback<String> callback) {
|
||||
Request request = buildPostRequest(url, paramMap);
|
||||
newStringCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post 键值对,表单数据,返回数据实体
|
||||
*
|
||||
* @param url
|
||||
* @param paramMap
|
||||
* @param callback
|
||||
*/
|
||||
public <T> void postKeyValueAsEntity(@NonNull String url, Map<String, String> paramMap, @NonNull OkHttpCallback<T> callback) {
|
||||
Request request = buildPostRequest(url, paramMap);
|
||||
newEntityCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post JSON 数据,返回值s字符串
|
||||
*
|
||||
* @param url
|
||||
* @param jsonStr
|
||||
* @param callback
|
||||
*/
|
||||
public void postJsonAsString(@NonNull String url, @NonNull String jsonStr, @NonNull OkHttpCallback<String> callback) {
|
||||
RequestBody requestBody = RequestBody.create(HttpUtils.MEDIA_TYPE_JSON, jsonStr);
|
||||
Request request = buildPostRequest(url, requestBody);
|
||||
newStringCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post JSON 数据,返回值是数据实体
|
||||
*
|
||||
* @param url
|
||||
* @param jsonStr
|
||||
* @param callback
|
||||
*/
|
||||
public <T> void postJsonAsEntity(@NonNull String url, @NonNull String jsonStr, @NonNull OkHttpCallback<T> callback) {
|
||||
RequestBody requestBody = RequestBody.create(HttpUtils.MEDIA_TYPE_JSON, jsonStr);
|
||||
Request request = buildPostRequest(url, requestBody);
|
||||
newEntityCall(callback, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件,并且回调到主线程
|
||||
*
|
||||
* @param url
|
||||
* @param file
|
||||
* @param callback
|
||||
*/
|
||||
public void downloadFile(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback<File> callback) {
|
||||
realDownloadFile(url, file, callback, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件,回调再同一线程
|
||||
*
|
||||
* @param url
|
||||
* @param file
|
||||
* @param callback
|
||||
*/
|
||||
public void downloadFileCallBackExecute(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback<File> callback) {
|
||||
realDownloadFile(url, file, callback, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件 回调同步线程
|
||||
*
|
||||
* @param url
|
||||
* @param file
|
||||
* @param callback
|
||||
*/
|
||||
public void realDownloadFile(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback<File> callback, Boolean callBackInUIThread) {
|
||||
if (file.exists()) {
|
||||
if (callBackInUIThread) {
|
||||
runOnUiThread(() -> {
|
||||
callback.onStart();
|
||||
callback.onSuccess(file);
|
||||
callback.onFinish();
|
||||
});
|
||||
} else {
|
||||
callback.onStart();
|
||||
callback.onSuccess(file);
|
||||
callback.onFinish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
Request request = buildGetRequest(url);
|
||||
callback.onStart();
|
||||
mOkHttpClient.newCall(request)
|
||||
.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
if (callBackInUIThread)
|
||||
onRequestFailure(e, callback);
|
||||
else
|
||||
onRequestFailureCallBackExecute(e, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
InputStream is = null;
|
||||
BufferedOutputStream bos = null;
|
||||
try {
|
||||
is = response.body().byteStream();
|
||||
bos = new BufferedOutputStream(new FileOutputStream(file));
|
||||
byte[] bytes = new byte[10240];
|
||||
int len;
|
||||
while ((len = is.read(bytes)) != -1) {
|
||||
bos.write(bytes, 0, len);
|
||||
}
|
||||
bos.flush();
|
||||
if (callBackInUIThread) {
|
||||
runOnUiThread(() -> callback.onSuccess(file));
|
||||
} else {
|
||||
callback.onSuccess(file);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
OkLogger.printStackTrace(e);
|
||||
if (callBackInUIThread) {
|
||||
runOnUiThread(() -> callback.onFailure(DOWNLOAD_FAILURE_MESSAGE));
|
||||
} else {
|
||||
callback.onFailure(DOWNLOAD_FAILURE_MESSAGE);
|
||||
}
|
||||
} finally {
|
||||
if (bos != null) {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
callback.onFinish();
|
||||
}
|
||||
} else {
|
||||
if (callBackInUIThread) onResponseFailure(response, callback);
|
||||
else onResponseFailureCallBackExecute(response, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param url
|
||||
* @param file
|
||||
* @param callback
|
||||
*/
|
||||
public void uploadFile(@NonNull String url, @NonNull File file, @NonNull final OkHttpCallback<String> callback) {
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
callback.onFailure(UPLOAD_FAILURE_MESSAGE);
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
RequestBody fileBody = RequestBody.create(HttpUtils.MEDIA_TYPE_STREAM, file);
|
||||
Request request = buildPostRequest(url, fileBody);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
}
|
||||
});
|
||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
onRequestFailure(e, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
final String string = response.body().string();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onSuccess(string);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
OkLogger.printStackTrace(e);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(PARSE_FAILURE_MESSAGE);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onResponseFailure(response, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 带参数上传文件
|
||||
*
|
||||
* @param url
|
||||
* @param name
|
||||
* @param file
|
||||
* @param paramMap
|
||||
* @param callback
|
||||
*/
|
||||
public void uploadFile(@NonNull String url, @NonNull String name, @NonNull File file,
|
||||
@NonNull Map<String, String> paramMap, @NonNull final OkHttpCallback<String> callback) {
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
callback.onFailure(UPLOAD_FAILURE_MESSAGE);
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
MultipartBody.Builder mbBuilder = new MultipartBody.Builder();
|
||||
mbBuilder.setType(MultipartBody.FORM);
|
||||
Set<Map.Entry<String, String>> entries = paramMap.entrySet();
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
mbBuilder.addFormDataPart(entry.getKey(), entry.getValue());
|
||||
}
|
||||
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(file.getAbsolutePath());
|
||||
String fileName = System.currentTimeMillis() + "." + fileExtension;
|
||||
mbBuilder.addFormDataPart(name, fileName, RequestBody.create(HttpUtils.MEDIA_TYPE_STREAM, file));
|
||||
Request request = buildPostRequest(url, mbBuilder.build());
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
}
|
||||
});
|
||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
onRequestFailure(e, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
final String string = response.body().string();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onSuccess(string);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
OkLogger.printStackTrace(e);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(PARSE_FAILURE_MESSAGE);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onResponseFailure(response, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消所有网络请求
|
||||
*/
|
||||
public void cancelAll() {
|
||||
List<Call> queuedCalls = mOkHttpClient.dispatcher().queuedCalls();
|
||||
for (Call call : queuedCalls) {
|
||||
call.cancel();
|
||||
}
|
||||
List<Call> runningCalls = mOkHttpClient.dispatcher().runningCalls();
|
||||
for (Call call : runningCalls) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 tag 取消请求,默认情况下,tag 就是 url
|
||||
*
|
||||
* @param tag
|
||||
*/
|
||||
public void cancelTag(@NonNull String tag) {
|
||||
List<Call> queuedCalls = mOkHttpClient.dispatcher().queuedCalls();
|
||||
for (Call call : queuedCalls) {
|
||||
if (tag.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
List<Call> runningCalls = mOkHttpClient.dispatcher().runningCalls();
|
||||
for (Call call : runningCalls) {
|
||||
if (tag.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void onRequestFailure(IOException e, @NonNull final OkHttpCallback<T> callback) {
|
||||
OkLogger.printStackTrace(e);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(NETWORK_FAILURE_MESSAGE);
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> void onRequestFailureCallBackExecute(IOException e, @NonNull final OkHttpCallback<T> callback) {
|
||||
OkLogger.printStackTrace(e);
|
||||
callback.onFailure(NETWORK_FAILURE_MESSAGE);
|
||||
callback.onFinish();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Request buildGetRequest(@NonNull String url) {
|
||||
return new Request.Builder()
|
||||
.get()
|
||||
.url(url)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Request buildPostRequest(@NonNull String url, RequestBody requestBody) {
|
||||
return new Request.Builder()
|
||||
.post(requestBody)
|
||||
.url(url)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Request buildPostRequest(@NonNull String url, Map<String, String> paramMap) {
|
||||
FormBody.Builder builder = new FormBody.Builder();
|
||||
if (paramMap != null && paramMap.size() > 0) {
|
||||
Set<Map.Entry<String, String>> entries = paramMap.entrySet();
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
builder.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
RequestBody formBody = builder.build();
|
||||
return new Request.Builder()
|
||||
.post(formBody)
|
||||
.url(url)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void newStringCall(@NonNull final OkHttpCallback<String> callback, Request request) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
}
|
||||
});
|
||||
mOkHttpClient.newCall(request)
|
||||
.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
onRequestFailure(e, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
final String string = response.body().string();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onSuccess(string);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
OkLogger.printStackTrace(e);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(PARSE_FAILURE_MESSAGE);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onResponseFailure(response, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> void newEntityCall(@NonNull final OkHttpCallback<T> callback, Request request) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onStart();
|
||||
}
|
||||
});
|
||||
mOkHttpClient.newCall(request)
|
||||
.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
onRequestFailure(e, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
String string = response.body().string();
|
||||
Type type = callback.getClass().getGenericSuperclass();
|
||||
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
|
||||
Class<T> responseClass = (Class<T>) params[0];
|
||||
final T t = GsonConverter.jsonToBean(string, responseClass);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onSuccess(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
OkLogger.printStackTrace(e);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(PARSE_FAILURE_MESSAGE);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onResponseFailure(response, callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnUiThread(Runnable runnable) {
|
||||
if (Thread.currentThread() == mMainHandler.getLooper().getThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
mMainHandler.post(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void onResponseFailure(final Response response, @NonNull final OkHttpCallback<T> callback) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onFailure(RESPONSE_FAILURE_MESSAGE + response.code() + ":" + response.message());
|
||||
callback.onFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> void onResponseFailureCallBackExecute(final Response response, @NonNull final OkHttpCallback<T> callback) {
|
||||
callback.onFailure(RESPONSE_FAILURE_MESSAGE + response.code() + ":" + response.message());
|
||||
callback.onFinish();
|
||||
}
|
||||
|
||||
private static class OkHttpUtilsHolder {
|
||||
private static final OkHttpUtils INSTANCE = new OkHttpUtils();
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络请求回调
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract static class OkHttpCallback<T> {
|
||||
/**
|
||||
* 开始
|
||||
*/
|
||||
protected void onStart() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应成功
|
||||
*
|
||||
* @param result
|
||||
*/
|
||||
protected abstract void onSuccess(T result);
|
||||
|
||||
/**
|
||||
* 响应失败
|
||||
*
|
||||
* @param errorMsg
|
||||
*/
|
||||
protected abstract void onFailure(String errorMsg);
|
||||
|
||||
/**
|
||||
* 结束
|
||||
*/
|
||||
protected void onFinish() {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class ProgressOkHttpCallback extends OkHttpCallback<File> {
|
||||
/**
|
||||
* 进度
|
||||
*
|
||||
* @param current
|
||||
* @param total
|
||||
*/
|
||||
protected abstract void onProgress(long current, long total);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* OkHttp 日志的工具类
|
||||
*
|
||||
* @author Richie on 2018.12.31
|
||||
*/
|
||||
public final class OkLogger {
|
||||
private static boolean isEnable = false;
|
||||
private static String tag = "OkHttpUtils";
|
||||
|
||||
public static void debug(boolean isEnable) {
|
||||
debug(tag, isEnable);
|
||||
}
|
||||
|
||||
public static void debug(String tag, boolean isEnable) {
|
||||
OkLogger.tag = tag;
|
||||
OkLogger.isEnable = isEnable;
|
||||
}
|
||||
|
||||
public static void v(String msg) {
|
||||
v(tag, msg);
|
||||
}
|
||||
|
||||
public static void v(String tag, String msg) {
|
||||
if (isEnable) {
|
||||
Log.v(tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void d(String msg) {
|
||||
d(tag, msg);
|
||||
}
|
||||
|
||||
public static void d(String tag, String msg) {
|
||||
if (isEnable) {
|
||||
Log.d(tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void i(String msg) {
|
||||
i(tag, msg);
|
||||
}
|
||||
|
||||
public static void i(String tag, String msg) {
|
||||
if (isEnable) {
|
||||
Log.i(tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void w(String msg) {
|
||||
w(tag, msg);
|
||||
}
|
||||
|
||||
public static void w(String tag, String msg) {
|
||||
if (isEnable) {
|
||||
Log.w(tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void e(String msg) {
|
||||
e(tag, msg);
|
||||
}
|
||||
|
||||
public static void e(String tag, String msg) {
|
||||
if (isEnable) {
|
||||
Log.e(tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printStackTrace(Throwable t) {
|
||||
if (isEnable && t != null) {
|
||||
Log.e(tag, "OkHttp error", t);
|
||||
}
|
||||
}
|
||||
|
||||
public static void log(int level, String message) {
|
||||
switch (level) {
|
||||
case Log.VERBOSE:
|
||||
v(message);
|
||||
break;
|
||||
case Log.DEBUG:
|
||||
d(message);
|
||||
break;
|
||||
case Log.INFO:
|
||||
i(message);
|
||||
break;
|
||||
case Log.WARN:
|
||||
w(message);
|
||||
break;
|
||||
case Log.ERROR:
|
||||
e(message);
|
||||
break;
|
||||
default:
|
||||
v(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
public class SSLSocketFactoryCompat extends SSLSocketFactory{
|
||||
private static final String[] TLS_V12_ONLY = {"TLSv1.2"};
|
||||
|
||||
private final SSLSocketFactory delegate;
|
||||
|
||||
public SSLSocketFactoryCompat() throws KeyManagementException, NoSuchAlgorithmException {
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(null, null, null);
|
||||
delegate = sc.getSocketFactory();
|
||||
}
|
||||
|
||||
public SSLSocketFactoryCompat(SSLSocketFactory delegate) {
|
||||
if (delegate == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
private Socket enableTls12(Socket socket) {
|
||||
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 20) {
|
||||
if (socket instanceof SSLSocket) {
|
||||
((SSLSocket) socket).setEnabledProtocols(TLS_V12_ONLY);
|
||||
}
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return enableTls12(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
return enableTls12(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
return enableTls12(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return enableTls12(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return enableTls12(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
package com.yunbao.faceunity.utils.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.utils.FileUtils;
|
||||
import com.yunbao.faceunity.utils.ZipUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 道具下载 缓存
|
||||
*
|
||||
* @author Richie on 2021.03.03
|
||||
*/
|
||||
public final class StickerDownloadHelper {
|
||||
private static final String TAG = "StickerDownloadHelper";
|
||||
private static final String URL_HOST = "https://items.faceunity.com:4006";
|
||||
private static final String URL_TAGS = URL_HOST + "/api/guest/tags?platform=mobile";
|
||||
private static final String URL_TOOLS = URL_HOST + "/api/guest/tools";
|
||||
private static final String URL_DOWNLOAD = URL_HOST + "/api/guest/download?id=";
|
||||
public static final String STICKER_DIR_PATH = FileUtils.getExternalFileDir(FaceUnityData.mApplication) + "/fine_sticker";
|
||||
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private Gson gson;
|
||||
private String[] mTags;
|
||||
private Map<String, FineStickerEntity> mFineStickerEntityMap = new ArrayMap<>();
|
||||
|
||||
static {
|
||||
File file = new File(STICKER_DIR_PATH);
|
||||
if (!file.exists()) {
|
||||
file.mkdir();
|
||||
}
|
||||
}
|
||||
|
||||
private StickerDownloadHelper() {
|
||||
gson = new Gson();
|
||||
String tagArray = loadFormSp(TAG);
|
||||
JsonArray array = gson.fromJson(tagArray, JsonArray.class);
|
||||
if (null != array) {
|
||||
mTags = new String[array.size()];
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
mTags[i] = array.get(i).toString();
|
||||
mTags[i] = mTags[i].substring(1, mTags[i].length() - 1); // 后台把引号放进来了
|
||||
}
|
||||
} else {
|
||||
mTags = new String[0];
|
||||
}
|
||||
for (int i = 0; i < mTags.length; i++) {
|
||||
String json = loadFormSp(mTags[i]);
|
||||
FineStickerEntity fineSticker = gson.fromJson(json, FineStickerEntity.class);
|
||||
if (null != fineSticker) {
|
||||
mFineStickerEntityMap.put(mTags[i], fineSticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class StickerDownloadHelperHolder {
|
||||
private static StickerDownloadHelper INSTANCE = new StickerDownloadHelper();
|
||||
}
|
||||
|
||||
public static StickerDownloadHelper getInstance() {
|
||||
return StickerDownloadHelperHolder.INSTANCE;
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onGetTags(String[] tags);
|
||||
|
||||
void onGetList(String tag, FineStickerEntity fineSticker);
|
||||
|
||||
void onDownload(FineStickerEntity.DocsBean entity);
|
||||
|
||||
void onDownloadError(FineStickerEntity.DocsBean entity, String msg);
|
||||
}
|
||||
|
||||
private Callback mCallback;
|
||||
|
||||
public void setCallback(Callback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public String[] tags() {
|
||||
// {"code":2,"message":"ok","data":["中级道具","高级道具","专业道具"]}
|
||||
OkHttpUtils.getInstance().getAsEntity(URL_TAGS, new OkHttpUtils.OkHttpCallback<JsonObject>() {
|
||||
@Override
|
||||
protected void onSuccess(JsonObject result) {
|
||||
JsonArray array = null;
|
||||
try {
|
||||
array = result.getAsJsonArray("data");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
mTags = new String[array.size()];
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
mTags[i] = array.get(i).toString();
|
||||
mTags[i] = mTags[i].substring(1, mTags[i].length() - 1); // 后台把引号放进来了
|
||||
}
|
||||
if (null != mCallback) {
|
||||
mCallback.onGetTags(mTags);
|
||||
}
|
||||
saveToSp(TAG, array.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(String errorMsg) {
|
||||
Log.e(TAG, URL_TAGS + " " + errorMsg);
|
||||
}
|
||||
});
|
||||
return mTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据tag获取道具列表
|
||||
*/
|
||||
public FineStickerEntity tools(String tag) {
|
||||
if (mFineStickerEntityMap.get(tag) == null) {
|
||||
FineStickerEntity entity = new FineStickerEntity();
|
||||
entity.setDocs(new ArrayList<>());
|
||||
mFineStickerEntityMap.put(tag, entity);
|
||||
}
|
||||
if (!mFineStickerEntityMap.get(tag).isOnline()) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("platform", "mobile");
|
||||
jsonObject.addProperty("tag", tag);
|
||||
OkHttpUtils.getInstance().postJsonAsEntity(URL_TOOLS, jsonObject.toString(), new OkHttpUtils.OkHttpCallback<JsonObject>() {
|
||||
@Override
|
||||
protected void onSuccess(JsonObject result) {
|
||||
FineStickerEntity entity = gson.fromJson(result.get("data"), FineStickerEntity.class);
|
||||
entity.setOnline(true);
|
||||
mFineStickerEntityMap.put(tag, entity);
|
||||
checkDownloaded(entity);
|
||||
if (null != mCallback) {
|
||||
mCallback.onGetList(tag, entity);
|
||||
}
|
||||
saveToSp(tag, result.get("data").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(String errorMsg) {
|
||||
Log.e(TAG, URL_TOOLS + " " + errorMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
checkDownloaded(mFineStickerEntityMap.get(tag));
|
||||
return mFineStickerEntityMap.get(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取道具下载地址
|
||||
* 获取完就直接开始下载了
|
||||
*/
|
||||
public void download(FineStickerEntity.DocsBean entity) {
|
||||
String url = URL_DOWNLOAD + entity.getTool().get_id() + "&platform=mobile";
|
||||
OkHttpUtils.getInstance().getAsEntity(url, new OkHttpUtils.OkHttpCallback<JsonObject>() {
|
||||
/** {
|
||||
* "code": 2,
|
||||
* "message": "ok",
|
||||
* "data": { // 请自行下载url
|
||||
* "url": "http://tools-manage.oss-cn-hangzhou.aliyuncs.com/0a176380-b33e-11e9-8e6a-35012f229fc1-enc.bundle?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1615967910&Signature=2%2B0YwGKKidAWNqLHEXf0BtByQoI%3D"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
@Override
|
||||
protected void onSuccess(JsonObject result) {
|
||||
realDownload(result.getAsJsonObject("data").get("url").getAsString(), entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(String errorMsg) {
|
||||
Log.e(TAG, url + " " + errorMsg);
|
||||
if (null != mCallback) {
|
||||
mCallback.onDownloadError(entity,errorMsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载道具
|
||||
*/
|
||||
private void realDownload(String url, FineStickerEntity.DocsBean entity) {
|
||||
File dest = new File(STICKER_DIR_PATH, entity.getTool().getBundle().getUid());
|
||||
OkHttpUtils.getInstance().downloadFileCallBackExecute(url, dest, new OkHttpUtils.OkHttpCallback<File>() {
|
||||
@Override
|
||||
protected void onSuccess(File result) {
|
||||
if (entity.getTool().getBundle().getUid().endsWith(".zip")) {
|
||||
//请求成功和解压是一个原子操作
|
||||
//zip,解压
|
||||
boolean unZipSuccess = true;
|
||||
String outPathString = STICKER_DIR_PATH + "/" + entity.getTool().getBundle().getUid().substring(0,entity.getTool().getBundle().getUid().lastIndexOf("."));
|
||||
try {
|
||||
//获取解压后的文件名赋值
|
||||
ArrayList<String> fileNameList = ZipUtils.unZipFolderWithFileName(STICKER_DIR_PATH + "/" + entity.getTool().getBundle().getUid(), outPathString);
|
||||
if (fileNameList != null && !fileNameList.isEmpty())
|
||||
entity.setUpZipFilePaths(fileNameList);
|
||||
else
|
||||
unZipSuccess = false;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
unZipSuccess = false;
|
||||
}
|
||||
|
||||
if (!unZipSuccess) {
|
||||
if (null != mCallback)
|
||||
runOnUiThread(()-> mCallback.onDownloadError(entity,"unZipFolder failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
entity.setFilePath(result.getAbsolutePath());
|
||||
if (null != mCallback)
|
||||
runOnUiThread(()-> mCallback.onDownload(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(String errorMsg) {
|
||||
Log.e(TAG, url + " " + errorMsg);
|
||||
if (null != mCallback)
|
||||
runOnUiThread(()-> mCallback.onDownloadError(entity,errorMsg));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnUiThread(Runnable runnable) {
|
||||
if (Thread.currentThread() == mMainHandler.getLooper().getThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
mMainHandler.post(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
/************************** 缓存相关 **************************/
|
||||
|
||||
private void saveToSp(String key, String value) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(FaceUnityData.mApplication.getPackageName(), Context.MODE_PRIVATE);
|
||||
sp.edit().putString(key, value).apply();
|
||||
}
|
||||
|
||||
private String loadFormSp(String key) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(FaceUnityData.mApplication.getPackageName(), Context.MODE_PRIVATE);
|
||||
return sp.getString(key, "");
|
||||
}
|
||||
|
||||
private void checkDownloaded(FineStickerEntity fineStickerEntity) {
|
||||
if (null == fineStickerEntity.getDocs()) {
|
||||
return;
|
||||
}
|
||||
String[] bundles = new File(STICKER_DIR_PATH).list();
|
||||
HashSet<String> bundleSet = new HashSet<>();
|
||||
if (bundles != null && bundles.length > 0) {
|
||||
Collections.addAll(bundleSet, bundles);
|
||||
}
|
||||
for (FineStickerEntity.DocsBean fineSticker : fineStickerEntity.getDocs()) {
|
||||
if (bundleSet.contains(fineSticker.getTool().getBundle().getUid())) {
|
||||
fineSticker.setFilePath(STICKER_DIR_PATH + "/" + fineSticker.getTool().getBundle().getUid());
|
||||
if (fineSticker.getTool().getBundle().getUid().endsWith(".zip")) {
|
||||
//遍历解压文件地址
|
||||
String path = STICKER_DIR_PATH + "/" + fineSticker.getTool().getBundle().getUid().substring(0,fineSticker.getTool().getBundle().getUid().lastIndexOf("."));
|
||||
fineSticker.setUpZipFilePaths(FileUtils.getFileList(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,6 @@
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/main_color" android:state_selected="true" />
|
||||
<item android:color="#FFC621" android:state_selected="true" />
|
||||
<item android:color="@color/main_color_c5c5c5" />
|
||||
</selector>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_shape_oval2_theme" android:state_selected="true" />
|
||||
<item android:drawable="@color/transparent" />
|
||||
</selector>
|
11
FaceUnity/src/main/res/drawable/bg_shape_oval2_theme.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<stroke
|
||||
|
||||
android:width="3dp"
|
||||
android:color="#FFC621" />
|
||||
|
||||
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
@ -2,7 +2,14 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<stroke
|
||||
android:width="3dp"
|
||||
android:color="@color/main_color" />
|
||||
|
||||
android:width="5dp"
|
||||
android:color="#FFC621" />
|
||||
<padding
|
||||
android:bottom="2dp"
|
||||
android:left="2dp"
|
||||
android:right="2dp"
|
||||
android:top="2dp" />
|
||||
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
@ -4,5 +4,5 @@
|
||||
<corners android:radius="3dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/main_color" />
|
||||
android:color="#FFC621" />
|
||||
</shape>
|
10
FaceUnity/src/main/res/layout/layout_face_container.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/container_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
@ -1,43 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_live_tota"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/rc_picture_icon_back" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_close"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@mipmap/icon_dialog_charge_close" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/menu_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="美顏特效選擇"
|
||||
android:textColor="#F6F7FB"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/menu_reset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:srcCompat="@mipmap/icon_reset" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="@string/dialog_reset"
|
||||
android:textColor="#9A9A9A"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/menu_diy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:srcCompat="@mipmap/icon_custom" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="@string/menu_diy"
|
||||
android:textColor="#9A9A9A"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_faceunity_menu1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/menu_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_faceunity_menu2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="25dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu2_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/rc_picture_icon_back" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/menu2_tab"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
app:tabSelectedTextColor="#F6F7FB"
|
||||
app:tabTextColor="#9A9A9A" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/menu2_reset"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_weight="0.1"
|
||||
android:gravity="center"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:srcCompat="@mipmap/icon_reset" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="@string/dialog_reset"
|
||||
android:textColor="#9A9A9A"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/menu2_container_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Monday" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tuesday" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Wednesday" />
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
android:layout_height="216dp"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
65
FaceUnity/src/main/res/layout/list_item_face_config.xml
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_weight="0"
|
||||
app:srcCompat="@mipmap/icon_beauty_box_buffing_close_normal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="4dp"
|
||||
android:text="TextView"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:text="TextView"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
||||
android:id="@+id/item_seekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/x48"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/x24"
|
||||
android:layout_marginBottom="@dimen/x15"
|
||||
app:dsb_indicatorColor="#CDCDCD"
|
||||
app:dsb_indicatorElevation="0dp"
|
||||
app:dsb_indicatorPopupEnabled="true"
|
||||
app:dsb_max="100"
|
||||
app:dsb_min="0"
|
||||
app:dsb_progressColor="#FFFFFF"
|
||||
app:dsb_rippleColor="#FFFFFF"
|
||||
app:dsb_scrubberHeight="@dimen/x16"
|
||||
app:dsb_thumbSize="@dimen/x32"
|
||||
app:dsb_trackBaseHeight="@dimen/x16"
|
||||
app:dsb_trackColor="#4D4D4D"
|
||||
app:dsb_trackHeight="@dimen/x16"
|
||||
app:dsb_value="0" />
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/x132"
|
||||
android:layout_height="@dimen/x180">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal|bottom"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_control"
|
||||
android:layout_width="@dimen/x88"
|
||||
android:layout_height="@dimen/x88"
|
||||
android:layout_marginBottom="@dimen/x18"
|
||||
android:background="@drawable/bg_control_oval_selector"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@mipmap/icon_big_head" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_control"
|
||||
android:visibility="invisible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/x30"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/recover"
|
||||
android:textColor="@color/tv_main_color_selector"
|
||||
android:textSize="@dimen/text_size_20" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</FrameLayout>
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/x138"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_height="@dimen/x180">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_control"
|
||||
android:layout_width="@dimen/x108"
|
||||
android:layout_height="@dimen/x108"
|
||||
android:layout_marginBottom="@dimen/x16"
|
||||
android:background="@drawable/bg_control_square_selector"
|
||||
android:padding="@dimen/x4"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/x40"
|
||||
android:layout_marginBottom="@dimen/x16"
|
||||
android:textColor="@color/tv_main_color_selector"
|
||||
android:textSize="@dimen/text_size_20" />
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/x132"
|
||||
android:layout_height="@dimen/x180">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal|bottom"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_control"
|
||||
android:layout_width="@dimen/x88"
|
||||
android:layout_height="@dimen/x88"
|
||||
android:layout_marginBottom="@dimen/x18"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_control"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/x30"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/recover"
|
||||
android:textColor="@color/tv_main_color_selector"
|
||||
android:textSize="@dimen/text_size_20" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</FrameLayout>
|
26
FaceUnity/src/main/res/layout/list_item_menu_group.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="40dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@mipmap/ico_home_animoji" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="6dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:text="@string/beauty" />
|
||||
</LinearLayout>
|
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_custom.png
Normal file
After Width: | Height: | Size: 698 B |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_blush_01.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_blush_02.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_blush_03.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_blush_04.png
Normal file
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 54 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_contour_01.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyebrow_01.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyebrow_02.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyebrow_03.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyebrow_04.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_01.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_02.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_03.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_04.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_05.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyelash_06.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_makeup_eyeliner_01.png
Normal file
After Width: | Height: | Size: 11 KiB |