Commit 67333c9a by 刘鹏

feat : 删除mdt

parent ea02ed48
...@@ -183,6 +183,7 @@ dependencies { ...@@ -183,6 +183,7 @@ dependencies {
api rootProject.ext.dependencies["butterknife"] api rootProject.ext.dependencies["butterknife"]
kapt rootProject.ext.dependencies["butterknife-compiler"] kapt rootProject.ext.dependencies["butterknife-compiler"]
implementation 'com.tencent.tpns:tpns:1.3.2.1-release'
if (true) { if (true) {
//开发模式 //开发模式
...@@ -221,11 +222,8 @@ dependencies { ...@@ -221,11 +222,8 @@ dependencies {
implementation project(':m-fm') implementation project(':m-fm')
implementation modularPublication('com.ydl:m-fm-api') implementation modularPublication('com.ydl:m-fm-api')
//mdt项目
api project(':m-mdt-Source')
} else { } else {
//发布模式 //发布模式
api 'com.ydl:m-user-module-ydl:0.0.6' api 'com.ydl:m-user-module-ydl:0.0.6'
api rootProject.ext.dependencies["ydl-webview"] api rootProject.ext.dependencies["ydl-webview"]
......
package com.ydl.component.rtc.debug;
import android.text.TextUtils;
import android.util.Base64;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.zip.Deflater;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/*
* Module: GenerateTestUserSig
*
* Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
* 其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
*
* Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
*
* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
*
* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
*
* Reference:https://cloud.tencent.com/document/product/269/32688#Server
*/
public class GenerateTestUserSig {
/**
* 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
* <p>
* 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) 创建应用,即可看到 SDKAppId,
* 它是腾讯云用于区分客户的唯一标识。
*/
public static final int SDKAPPID = 1400646402;
/**
* 签名过期时间,建议不要设置的过短
* <p>
* 时间单位:秒
* 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
*/
private static final int EXPIRETIME = 604800;
/**
* 向后台请求推拉流地址
* <p>
* key:url_push 获取RTMP推流地址
* key:url_play_flv 获取FLV播放地址
*/
public static final String URL_FETCH_PUSH_URL = "PLACEHOLDER";
/**
* 计算签名用的加密密钥,获取步骤如下:
* <p>
* step1. 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) ,如果还没有应用就创建一个,
* step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
* step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
* <p>
* 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
* 文档:https://cloud.tencent.com/document/product/269/32688#Server
*/
private static final String SECRETKEY = "84ed667420eee66e4d99de8d7f76b40ca6b9f8fffacb885068aaa9493cae7a0a";
/**
* 计算 UserSig 签名
* <p>
* 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密。
*
* @note: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
* <p>
* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
* <p>
* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
* <p>
* 文档:https://cloud.tencent.com/document/product/269/32688#Server
*/
public static String genTestUserSig(String userId) {
return GenTLSSignature(SDKAPPID, userId, EXPIRETIME, null, SECRETKEY);
}
/**
* 生成 tls 票据
*
* @param sdkappid 应用的 appid
* @param userId 用户 id
* @param expire 有效期,单位是秒
* @param userbuf 默认填写null
* @param priKeyContent 生成 tls 票据使用的私钥内容
* @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据
*/
private static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
if (TextUtils.isEmpty(priKeyContent)) {
return "";
}
long currTime = System.currentTimeMillis() / 1000;
JSONObject sigDoc = new JSONObject();
try {
sigDoc.put("TLS.ver", "2.0");
sigDoc.put("TLS.identifier", userId);
sigDoc.put("TLS.sdkappid", sdkappid);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.time", currTime);
} catch (JSONException e) {
e.printStackTrace();
}
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.encodeToString(userbuf, Base64.NO_WRAP);
try {
sigDoc.put("TLS.userbuf", base64UserBuf);
} catch (JSONException e) {
e.printStackTrace();
}
}
String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
if (sig.length() == 0) {
return "";
}
try {
sigDoc.put("TLS.sig", sig);
} catch (JSONException e) {
e.printStackTrace();
}
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
}
private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
String contentToBeSigned = "TLS.identifier:" + userId + "\n"
+ "TLS.sdkappid:" + sdkappid + "\n"
+ "TLS.time:" + currTime + "\n"
+ "TLS.expire:" + expire + "\n";
if (null != base64Userbuf) {
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
}
try {
byte[] byteKey = priKeyContent.getBytes("UTF-8");
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
hmac.init(keySpec);
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));
return new String(Base64.encode(byteSig, Base64.NO_WRAP));
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private static byte[] base64EncodeUrl(byte[] input) {
byte[] base64 = new String(Base64.encode(input, Base64.NO_WRAP)).getBytes();
for (int i = 0; i < base64.length; ++i) {
switch (base64[i]) {
case '+':
base64[i] = '*';
break;
case '/':
base64[i] = '-';
break;
case '=':
base64[i] = '_';
break;
default:
break;
}
}
return base64;
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
buildToolsVersion rootProject.ext.android["buildToolsVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
api "com.tencent.liteav:LiteAVSDK_TRTC:latest.release"
api rootProject.ext.dependencies["gson"]
api 'com.google.android.material:material:1.0.0'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.liteav.demo.beauty">
</manifest>
\ No newline at end of file
package com.tencent.liteav.demo.beauty;
import android.graphics.Bitmap;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.tencent.liteav.beauty.TXBeautyManager;
import com.tencent.liteav.demo.beauty.model.BeautyInfo;
import com.tencent.liteav.demo.beauty.model.ItemInfo;
import com.tencent.liteav.demo.beauty.model.TabInfo;
public interface Beauty {
void setBeautyManager(@NonNull TXBeautyManager beautyManager);
void setBeautySpecialEffects(@NonNull TabInfo tabinfo, @IntRange(from = 0) int tabPosition, @NonNull ItemInfo itemInfo, @IntRange(from = 0) int itemPosition);
void setBeautyStyleAndLevel(int style, int level);
void setMotionTmplEnable(boolean enable);
void fillingMaterialPath(@NonNull BeautyInfo beautyInfo);
void setCurrentFilterIndex(@NonNull BeautyInfo beautyInfo, @IntRange(from = 0) int index);
void setCurrentBeautyIndex(@NonNull BeautyInfo beautyInfo, @IntRange(from = 0) int index);
void setOnFilterChangeListener(OnFilterChangeListener listener);
void clear();
int getFilterProgress(@NonNull BeautyInfo beautyInfo, @IntRange(from = 0) int index);
int getFilterSize(@NonNull BeautyInfo beautyInfo);
ItemInfo getFilterItemInfo(@NonNull BeautyInfo beautyInfo, @IntRange(from = 0) int index);
Bitmap getFilterResource(@NonNull BeautyInfo beautyInfo, @IntRange(from = 0) int index);
BeautyInfo getDefaultBeauty();
interface OnFilterChangeListener {
void onChanged(Bitmap filterImage, int index);
}
}
package com.tencent.liteav.demo.beauty;
import android.graphics.Bitmap;
/**
* 美颜参数
*/
public class BeautyParams {
// 美颜类型
public int mBeautyStyle = 0;
// 美颜
public int mBeautyLevel = 4;
// 美白
public int mWhiteLevel = 1;
// 红润
public int mRuddyLevel = 0;
// 滤镜LUT图
public Bitmap mFilterBmp;
// 滑动滤镜索引
public int mFilterIndex;
// 滤镜程度
public float mFilterMixLevel = 0;
// 大眼
public int mBigEyeLevel;
// 瘦脸
public int mFaceSlimLevel;
// 瘦鼻
public int mNoseSlimLevel;
// 缩下巴
public int mChinSlimLevel;
// V脸
public int mFaceVLevel;
// 短脸
public int mFaceShortLevel;
// 亮眼
public int mEyeLightenLevel = 0;
// 白牙
public int mToothWhitenLevel = 0;
// 祛皱
public int mWrinkleRemoveLevel = 0;
// 祛眼袋
public int mPounchRemoveLevel = 0;
// 祛法令纹
public int mSmileLinesRemoveLevel = 0;
// 发际线
public int mForeheadLevel = 0;
// 眼距
public int mEyeDistanceLevel = 0;
// 眼角
public int mEyeAngleLevel = 0;
// 嘴型
public int mMouthShapeLevel = 0;
// 鼻翼
public int mNoseWingLevel = 0;
// 鼻子位置
public int mNosePositionLevel = 0;
// 嘴唇厚度
public int mLipsThicknessLevel = 0;
// 脸型
public int mFaceBeautyLevel = 0;
// 长腿
public int mLongLegLevel = 0;
// 瘦腰
public int mThinWaistLevel = 0;
// 瘦体
public int mThinBodyLevel = 0;
// 瘦肩
public int mThinShoulderLevel = 0;
// 动效文件路径
public String mMotionTmplPath;
// 绿幕
public String mGreenFile;
// 滤镜效果程度
public int mFilterStrength;
}
package com.tencent.liteav.demo.beauty.adapter;
import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.tencent.liteav.demo.beauty.R;
import com.tencent.liteav.demo.beauty.model.ItemInfo;
import com.tencent.liteav.demo.beauty.model.TabInfo;
import com.tencent.liteav.demo.beauty.utils.BeautyUtils;
import com.tencent.liteav.demo.beauty.utils.ResourceUtils;
import java.util.ArrayList;
import java.util.List;
public class ItemAdapter extends BaseAdapter {
private Context mContext;
private TabInfo mTabInfo;
private List<ItemInfo> mItemInfoList;
private OnItemClickListener mItemClickListener;
public interface OnItemClickListener {
void onItemClick(ItemInfo itemInfo, int position);
}
// 当前选中
private int mSelectPos;
public ItemAdapter(Context context) {
mContext = context;
}
public void setData(TabInfo tabInfo) {
setData(tabInfo, 0);
}
public void setData(TabInfo tabInfo, int defaultIndex) {
mTabInfo = tabInfo;
mSelectPos = defaultIndex;
if (mItemInfoList == null) {
mItemInfoList = new ArrayList<>();
}
mItemInfoList.clear();
mItemInfoList.addAll(tabInfo.getTabItemList());
notifyDataSetChanged();
}
@Override
public int getCount() {
return mTabInfo.getTabItemList().size();
}
@Override
public ItemInfo getItem(int position) {
return mItemInfoList.get(position);
}
@Override
public long getItemId(int position) {
return mItemInfoList.get(position).getItemId();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.beauty_view_item, parent, false);
holder = new ViewHolder(convertView);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.icon.getLayoutParams();
int width, height;
if (mTabInfo.getTabItemIconWidth() == LinearLayout.LayoutParams.MATCH_PARENT) {
width = LinearLayout.LayoutParams.MATCH_PARENT;
} else if(mTabInfo.getTabItemIconWidth() == LinearLayout.LayoutParams.WRAP_CONTENT) {
width = LinearLayout.LayoutParams.WRAP_CONTENT;
} else {
width = BeautyUtils.dip2px(mContext, mTabInfo.getTabItemIconWidth());
}
if (mTabInfo.getTabItemIconHeight() == LinearLayout.LayoutParams.MATCH_PARENT) {
height = LinearLayout.LayoutParams.MATCH_PARENT;
} else if (mTabInfo.getTabItemIconHeight() == LinearLayout.LayoutParams.WRAP_CONTENT) {
height = LinearLayout.LayoutParams.WRAP_CONTENT;
} else {
height = BeautyUtils.dip2px(mContext, mTabInfo.getTabItemIconHeight());
}
layoutParams.width = width;
layoutParams.height = height;
holder.icon.setLayoutParams(layoutParams);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final ItemInfo itemInfo = getItem(position);
BeautyUtils.setTextViewText(holder.title, ResourceUtils.getString(itemInfo.getItemName()));
BeautyUtils.setTextViewSize(holder.title, mTabInfo.getTabItemNameSize());
if (mSelectPos == position) {
BeautyUtils.setTextViewColor(holder.title, mTabInfo.getTabItemNameColorSelect());
BeautyUtils.setImageResource(holder.icon, itemInfo.getItemIconSelect());
} else {
BeautyUtils.setTextViewColor(holder.title, mTabInfo.getTabItemNameColorNormal());
BeautyUtils.setImageResource(holder.icon, itemInfo.getItemIconNormal());
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(itemInfo, position);
if (mSelectPos != position) {
mSelectPos = position;
notifyDataSetChanged();
}
}
}
});
return convertView;
}
public void setOnItemClickListener(OnItemClickListener itemClickListener) {
mItemClickListener = itemClickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView icon;
private TextView title;
public ViewHolder(View itemView) {
super(itemView);
icon = (ImageView) itemView.findViewById(R.id.beauty_iv_icon);
title = (TextView) itemView.findViewById(R.id.beauty_tv_title);
}
}
}
package com.tencent.liteav.demo.beauty.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.tencent.liteav.demo.beauty.model.BeautyInfo;
import com.tencent.liteav.demo.beauty.model.TabInfo;
import com.tencent.liteav.demo.beauty.utils.BeautyUtils;
public class TabAdapter extends BaseAdapter implements View.OnClickListener {
private Context mContext;
private BeautyInfo mBeautyInfo;
private TextView mTextSelected;
private OnTabChangeListener mTabClickListener;
public interface OnTabChangeListener {
void onTabChange(TabInfo tabInfo, int position);
}
public TabAdapter(Context context, BeautyInfo beautyInfo) {
mContext = context;
mBeautyInfo = beautyInfo;
}
@Override
public int getCount() {
return mBeautyInfo.getBeautyTabList().size();
}
@Override
public TabInfo getItem(int position) {
return mBeautyInfo.getBeautyTabList().get(position);
}
@Override
public long getItemId(int position) {
return mBeautyInfo.getBeautyTabList().get(position).getTabId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tabView;
if (convertView == null) {
tabView = new TextView(mContext);
BeautyUtils.setTextViewColor(tabView, mBeautyInfo.getBeautyTabNameColorNormal());
BeautyUtils.setTextViewSize(tabView, mBeautyInfo.getBeautyTabNameSize());
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(mBeautyInfo.getBeautyTabNameWidth(), mBeautyInfo.getBeautyTabNameHeight());
tabView.setLayoutParams(layoutParams);
} else {
tabView = (TextView) convertView;
}
if (position == 0) {
tabView.setPadding(BeautyUtils.dip2px(mContext, 20), 0, BeautyUtils.dip2px(mContext, 11), BeautyUtils.dip2px(mContext, 30));
} else {
tabView.setPadding(BeautyUtils.dip2px(mContext, 12), 0, BeautyUtils.dip2px(mContext, 11), BeautyUtils.dip2px(mContext, 30));
}
BeautyUtils.setTextViewText(tabView, getItem(position).getTabName());
tabView.setTag(position);
tabView.setOnClickListener(this);
if (position == 0) {
setCurrentPosition(0, tabView);
}
return tabView;
}
@Override
public void onClick(View view) {
int index = (int) view.getTag();
setCurrentPosition(index, view);
}
private void setCurrentPosition(int position, View view) {
if (mTextSelected != null) {
BeautyUtils.setTextViewColor(mTextSelected, mBeautyInfo.getBeautyTabNameColorNormal());
}
mTextSelected = (TextView) view;
BeautyUtils.setTextViewColor(mTextSelected, mBeautyInfo.getBeautyTabNameColorSelect());
if (mTabClickListener != null) {
mTabClickListener.onTabChange(getItem(position), position);
}
}
public void setOnTabClickListener(OnTabChangeListener tabClickListener) {
mTabClickListener = tabClickListener;
}
}
package com.tencent.liteav.demo.beauty.constant;
public class BeautyConstants {
public static final int TAB_TYPE_BEAUTY = 10001; // 美颜
public static final int TAB_TYPE_FILTER = 10002; // 滤镜
public static final int TAB_TYPE_MOTION = 10003; // 动效
public static final int TAB_TYPE_BEAUTY_FACE = 10004; // 美妆
public static final int TAB_TYPE_GESTURE = 10005; // 手势
public static final int TAB_TYPE_CUTOUT_BACKGROUND = 10006; // 抠背
public static final int TAB_TYPE_GREEN = 10007; // 绿幕
public static final int ITEM_TYPE_BEAUTY_SMOOTH = 20101; // 光滑
public static final int ITEM_TYPE_BEAUTY_NATURAL = 20102; // 自然
public static final int ITEM_TYPE_BEAUTY_PITU = 20103; // 天天P图
public static final int ITEM_TYPE_BEAUTY_WHITE = 20104; // 美白
public static final int ITEM_TYPE_BEAUTY_RUDDY = 20105; // 红润
public static final int ITEM_TYPE_BEAUTY_BIG_EYE = 20106; // 大眼
public static final int ITEM_TYPE_BEAUTY_FACES_LIM = 20107; // 瘦脸
public static final int ITEM_TYPE_BEAUTY_FACEV = 20108; // V脸
public static final int ITEM_TYPE_BEAUTY_CHIN = 20109; // 下巴
public static final int ITEM_TYPE_BEAUTY_FACE_SHORT = 20110; // 短脸
public static final int ITEM_TYPE_BEAUTY_NOSES_LIM = 20111; // 瘦鼻
public static final int ITEM_TYPE_BEAUTY_EYE_BRIGHT = 20112; // 亮眼
public static final int ITEM_TYPE_BEAUTY_TOOTH_WHITE = 20113; // 白牙
public static final int ITEM_TYPE_BEAUTY_WRINKLE_REMOVE = 20114; // 祛皱
public static final int ITEM_TYPE_BEAUTY_POUCH_REMOVE = 20115; // 祛眼袋
public static final int ITEM_TYPE_BEAUTY_SMILE_LINES = 20116; // 袪法令纹
public static final int ITEM_TYPE_BEAUTY_FOREHEAD = 20117; // 发际线
public static final int ITEM_TYPE_BEAUTY_EYE_DISTANCE = 20118; // 眼距
public static final int ITEM_TYPE_BEAUTY_EYE_ANGLE = 20119; // 眼角
public static final int ITEM_TYPE_BEAUTY_MOUTH_SHAPE = 20120; // 嘴型
public static final int ITEM_TYPE_BEAUTY_NOSEWING = 20121; // 鼻翼
public static final int ITEM_TYPE_BEAUTY_NOSE_POSITION = 20122; // 鼻子位置
public static final int ITEM_TYPE_BEAUTY_MOUSE_WIDTH = 20123; // 嘴唇厚度
public static final int ITEM_TYPE_BEAUTY_FACE_SHAPE = 20124; // 脸型
public static final int ITEM_TYPE_FILTER_FACE_SHAPE = 20201; // 无特效
public static final int ITEM_TYPE_FILTER_BAIXI = 20202; // 白皙
public static final int ITEM_TYPE_FILTER_STANDARD = 20203; // 标准
public static final int ITEM_TYPE_FILTER_ZIRAN = 20204; // 自然
public static final int ITEM_TYPE_FILTER_CHEERY = 20205; // 樱红
public static final int ITEM_TYPE_FILTER_CLOUD = 20206; // 云裳
public static final int ITEM_TYPE_FILTER_PURE = 20207; // 纯真
public static final int ITEM_TYPE_FILTER_ORCHID = 20208; // 白兰
public static final int ITEM_TYPE_FILTER_VITALITY = 20209; // 元气
public static final int ITEM_TYPE_FILTER_SUPER = 20210; // 超脱
public static final int ITEM_TYPE_FILTER_FRAGRANCE = 20211; // 香氛
public static final int ITEM_TYPE_FILTER_WHITE = 20212; // 美白
public static final int ITEM_TYPE_FILTER_ROMANTIC = 20213; // 浪漫
public static final int ITEM_TYPE_FILTER_FRESH = 20214; // 清新
public static final int ITEM_TYPE_FILTER_BEAUTIFUL = 20215; // 唯美
public static final int ITEM_TYPE_FILTER_PINK = 20216; // 粉嫩
public static final int ITEM_TYPE_FILTER_REMINISCENCE = 20217; // 怀旧
public static final int ITEM_TYPE_FILTER_BLUES = 20218; // 蓝调
public static final int ITEM_TYPE_FILTER_COOL = 20219; // 清凉
public static final int ITEM_TYPE_FILTER_JAPANESE = 20220; // 日系
public static final int ITEM_TYPE_MOTION_NONE = 20301; // 动效,无特效
public static final int ITEM_TYPE_MOTION_MATERIAL = 20302; // 动效,素材
public static final int ITEM_TYPE_BEAUTY_FACE_NONE = 20401; // 美妆,无特效
public static final int ITEM_TYPE_BEAUTY_FACE_MATERIAL = 20402; // 美妆,素材
public static final int ITEM_TYPE_GESTURE_NONE = 20501; // 手势,无特效
public static final int ITEM_TYPE_GESTURE_MATERIAL = 20502; // 手势,素材
public static final int ITEM_TYPE_CUTOUT_BACKGROUND_NONE = 20601; // 抠背,无特效
public static final int ITEM_TYPE_CUTOUT_BACKGROUND_MATERIAL = 20602; // 抠背,AI
public static final int ITEM_TYPE_GREEN_NONE = 20701; // 绿幕,无特效
public static final int ITEM_TYPE_GREEN_GOOD_LUCK = 20702; // 绿幕,good luck
public static final String BEAUTY_BG_GRAY = "#CC000000";// 灰色背景
}
package com.tencent.liteav.demo.beauty.download;
public interface DownloadListener {
void onDownloadFail(String errorMsg);
void onDownloadProgress(final int progress);
void onDownloadSuccess(String filePath);
}
package com.tencent.liteav.demo.beauty.download;
import android.content.Context;
import android.text.TextUtils;
import com.tencent.liteav.demo.beauty.utils.BeautyUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpFileHelper implements Runnable {
private static final int BUFFERED_READER_SIZE = 8192;
private static final int TIMEOUT = 30000;
private Context mContext;
private HttpFileListener mListener;
private String mURL;
private String mFolder;
private String mFilename;
private long mContentLength;
private long mDownloadingSize;
private boolean mNeedProgress;
public HttpFileHelper(Context context, String URL, String folder, String filename, HttpFileListener listener, boolean needProgress) {
mContext = context;
mURL = URL;
mFolder = folder;
mFilename = filename;
mListener = listener;
mNeedProgress = needProgress;
}
@Override
public void run() {
if (!BeautyUtils.isNetworkAvailable(mContext)
|| TextUtils.isEmpty(mURL)
|| TextUtils.isEmpty(mFolder)
|| TextUtils.isEmpty(mFilename)
|| !mURL.startsWith("http")) {
fail(null);
return;
}
File dstFolder = new File(mFolder);
if (!dstFolder.exists()) {
dstFolder.mkdirs();
} else {
if (dstFolder.isFile()) {
if (mListener != null) {
mListener.onSaveFailed(dstFolder, null);
return;
}
}
}
File dstFile = new File(mFolder + File.separator + mFilename);
HttpURLConnection client = null;
InputStream responseIs = null;
FileOutputStream fos = null;
int statusCode = -1;
boolean success = false;
Exception failException = null;
try {
if (dstFile.exists()) {
dstFile.delete();
}
dstFile.createNewFile();
client = (HttpURLConnection) new URL(mURL).openConnection();
// 设置网络超时参数
client.setConnectTimeout(TIMEOUT);
client.setReadTimeout(TIMEOUT);
client.setDoInput(true);
client.setRequestMethod("GET");
statusCode = client.getResponseCode();
success = client.getResponseCode() == HttpURLConnection.HTTP_OK;
if (success) {
if (mNeedProgress) {
mContentLength = client.getContentLength();
}
responseIs = client.getInputStream();
int length = -1;
byte[] buffer = new byte[BUFFERED_READER_SIZE];
fos = new FileOutputStream(dstFile);
mDownloadingSize = 0;
mListener.onProgressUpdate(0);
while ((length = responseIs.read(buffer)) != -1) {
fos.write(buffer, 0, length);
if (mNeedProgress) {
int pre = (int) (mDownloadingSize * 100 / mContentLength);
mDownloadingSize += length;
int now = (int) (mDownloadingSize * 100 / mContentLength);
if (pre != now && mListener != null) {
mListener.onProgressUpdate(now);
}
}
}
fos.flush();
if (mListener != null) {
mListener.onProgressUpdate(100);
mListener.onSaveSuccess(dstFile);
}
} else {
failException = new HttpStatusException("http status got exception. code = " + statusCode);
}
} catch (Exception e) {
failException = e;
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
if (responseIs != null) {
responseIs.close();
}
if (client != null) {
client.disconnect();
}
mListener.onProcessEnd();
} catch (IOException e) {
e.printStackTrace();
}
}
if (!success || null != failException) {
mListener.onSaveFailed(dstFile, failException);
}
}
private void fail(Exception e) {
if (mListener != null) {
mListener.onSaveFailed(null, e);
}
mListener = null;
}
}
package com.tencent.liteav.demo.beauty.download;
import java.io.File;
public interface HttpFileListener {
void onProgressUpdate(int progress);
void onSaveSuccess(File file);
void onSaveFailed(File file, Exception e);
void onProcessEnd();
}
package com.tencent.liteav.demo.beauty.download;
/**
* Http状态异常[自定义抛出的异常]
*/
public class HttpStatusException extends Exception {
public HttpStatusException(String detailMessage) {
super(detailMessage);
}
}
package com.tencent.liteav.demo.beauty.download;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import com.tencent.liteav.demo.beauty.R;
import com.tencent.liteav.demo.beauty.utils.BeautyUtils;
import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 美颜模块素材下载
*/
public class MaterialDownloader {
public static final String DOWNLOAD_FILE_POSTFIX = ".zip";
public static final String ONLINE_MATERIAL_FOLDER = "cameraVideoAnimal";
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private Context mContext;
private boolean mProcessing;
private String mURL;
private String mMaterialId;
private DownloadListener mListener;
private DownloadThreadPool mDownloadThreadPool;
public MaterialDownloader(Context context, String materialId, String url) {
mContext = context;
mMaterialId = materialId;
mURL = url;
mProcessing = false;
}
public void start(@Nullable DownloadListener listener) {
if (listener == null || TextUtils.isEmpty(mURL) || mProcessing) {
return;
}
mProcessing = true;
mListener = listener;
mListener.onDownloadProgress(0);
HttpFileListener fileListener = new HttpFileListener() {
@Override
public void onSaveSuccess(@NonNull File file) {
//删除该素材目录下的旧文件
File path = new File(file.toString().substring(0, file.toString().indexOf(DOWNLOAD_FILE_POSTFIX)));
if (path.exists() && path.isDirectory()) {
File[] oldFiles = path.listFiles();
if (oldFiles != null) {
for (File f : oldFiles) {
f.delete();
}
}
}
String dataDir = BeautyUtils.unZip(file.getPath(), file.getParentFile().getPath());
if (TextUtils.isEmpty(dataDir)) {
mListener.onDownloadFail(mContext.getString(R.string.beauty_video_material_download_progress_material_unzip_failed));
stop();
return;
}
file.delete();
mListener.onDownloadSuccess(dataDir);
stop();
}
@Override
public void onSaveFailed(File file, Exception e) {
mListener.onDownloadFail(mContext.getString(R.string.beauty_video_material_download_progress_download_failed));
stop();
}
@Override
public void onProgressUpdate(int progress) {
mListener.onDownloadProgress(progress);
}
@Override
public void onProcessEnd() {
mProcessing = false;
}
};
File onlineMaterialDir = BeautyUtils.getExternalFilesDir(mContext, ONLINE_MATERIAL_FOLDER);
if (onlineMaterialDir == null || onlineMaterialDir.getName().startsWith("null")) {
mListener.onDownloadFail(mContext.getString(R.string.beauty_video_material_download_progress_no_enough_storage_space));
stop();
return;
}
if (!onlineMaterialDir.exists()) {
onlineMaterialDir.mkdirs();
}
ThreadPoolExecutor threadPool = getThreadExecutor();
threadPool.execute(new HttpFileHelper(mContext, mURL, onlineMaterialDir.getPath(), mMaterialId + DOWNLOAD_FILE_POSTFIX, fileListener, true));
}
public void stop() {
mListener = null;
}
public synchronized ThreadPoolExecutor getThreadExecutor() {
if (mDownloadThreadPool == null || mDownloadThreadPool.isShutdown()) {
mDownloadThreadPool = new DownloadThreadPool(CORE_POOL_SIZE);
}
return mDownloadThreadPool;
}
public static class DownloadThreadPool extends ThreadPoolExecutor {
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public DownloadThreadPool(int poolSize) {
super(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(),
Executors.defaultThreadFactory(), new DiscardOldestPolicy());
}
}
}
package com.tencent.liteav.demo.beauty.model;
import java.util.List;
/**
* 美颜面板相关属性
* 成员变量名和 assets/default_beauty_data.json 的 key 相对应,便于 json 解析
*/
public class BeautyInfo {
private int beauty_tab_name_size; // int, tab文字大小
private int beauty_tab_name_width; // int, tab 宽度
private int beauty_tab_name_height; // int, tab 高度
private String beauty_bg; // color/drawable, beauty布局的背景色值
private String beauty_tab_name_color_normal;// color, tab文字常规颜色
private String beauty_tab_name_color_select;// color, tab文字选中颜色
private List<TabInfo> beauty_tab_list;
public String getBeautyBg() {
return beauty_bg;
}
public void setBeautyBg(String beauty_bg) {
this.beauty_bg = beauty_bg;
}
public int getBeautyTabNameWidth() {
return beauty_tab_name_width;
}
public int getBeautyTabNameHeight() {
return beauty_tab_name_height;
}
public String getBeautyTabNameColorNormal() {
return beauty_tab_name_color_normal;
}
public String getBeautyTabNameColorSelect() {
return beauty_tab_name_color_select;
}
public int getBeautyTabNameSize() {
return beauty_tab_name_size;
}
public List<TabInfo> getBeautyTabList() {
return beauty_tab_list;
}
@Override
public String toString() {
return "BeautyInfo{" +
", beauty_bg='" + beauty_bg + '\'' +
", beauty_tab_name_width=" + beauty_tab_name_width +
", beauty_tab_name_height=" + beauty_tab_name_height +
", beauty_tab_name_color_normal='" + beauty_tab_name_color_normal + '\'' +
", beauty_tab_name_color_select='" + beauty_tab_name_color_select + '\'' +
", beauty_tab_name_size=" + beauty_tab_name_size +
", beauty_tab_list=" + beauty_tab_list +
'}';
}
}
package com.tencent.liteav.demo.beauty.model;
/**
* 美颜面板 item 相关属性
* 成员变量名和 assets/default_beauty_data.json 的 key 相对应,便于 json 解析
*/
public class ItemInfo {
private long item_id; // long, item id,item 唯一标识
private int item_type; // int, item 类型,item 的功能
private int item_level; // int, 特效级别,-1代表无特效级别,即不显示SeekBar
private String item_name; // string, item 名称
private String item_material_url; // string, 素材 url
private String item_material_path; // string, 素材本地路径
private String item_icon_normal; // drawable, item 常规 icon
private String item_icon_select; // drawable, item 选中 icon
public long getItemId() {
return item_id;
}
public int getItemType() {
return item_type;
}
public String getItemName() {
return item_name;
}
public String getItemIconNormal() {
return item_icon_normal;
}
public String getItemIconSelect() {
return item_icon_select;
}
public void setItemLevel(int item_level) {
this.item_level = item_level;
}
public int getItemLevel() {
return item_level;
}
public String getItemMaterialUrl() {
return item_material_url;
}
public String getItemMaterialPath() {
return item_material_path;
}
public void setItemMaterialPath(String item_material_path) {
this.item_material_path = item_material_path;
}
@Override
public String toString() {
return "ItemInfo{" +
"item_id=" + item_id +
", item_type=" + item_type +
", item_name='" + item_name + '\'' +
", item_material_url='" + item_material_url + '\'' +
", item_level=" + item_level +
", item_icon_normal='" + item_icon_normal + '\'' +
", item_icon_select='" + item_icon_select + '\'' +
", item_material_path='" + item_material_path + '\'' +
'}';
}
}
package com.tencent.liteav.demo.beauty.model;
import java.util.List;
/**
* 美颜面板 tab 相关属性
* 成员变量名和 assets/default_beauty_data.json 的 key 相对应,便于 json 解析
*/
public class TabInfo {
private long tab_id; // long, tab id,tab 唯一标识
private int tab_type; // int, tab类型
private int tab_item_name_size; // int, item文字大小
private int tab_item_icon_width; // int, item icon 宽度
private int tab_item_icon_height; // int, item icon 高度
private int tab_item_level_hint_size; // int, 进度条提示文字大小
private int tab_item_level_value_size; // int, 进度条值文字大小
private String tab_name; // string, tab 名称
private String tab_item_name_color_normal; // string, item 文件常规颜色
private String tab_item_name_color_select; // string, item 文件选中颜色
private String tab_item_level_hint_color; // string, 进度条提示文字颜色
private String tab_item_level_value_color; // string, 进度条值文字颜色
private String tab_item_level_progress_drawable;// string, 进度条背景颜色
private String tab_item_level_progress_thumb; // string, 进度条 bar 颜色
private int tab_item_list_default_selected_index; // int, 默认选中的item
private List<ItemInfo> tab_item_list;
public long getTabId() {
return tab_id;
}
public int getTabType() {
return tab_type;
}
public String getTabName() {
return tab_name;
}
public int getTabItemNameSize() {
return tab_item_name_size;
}
public String getTabItemNameColorNormal() {
return tab_item_name_color_normal;
}
public String getTabItemNameColorSelect() {
return tab_item_name_color_select;
}
public int getTabItemIconWidth() {
return tab_item_icon_width;
}
public int getTabItemIconHeight() {
return tab_item_icon_height;
}
public String getTabItemLevelHintColor() {
return tab_item_level_hint_color;
}
public int getTabItemLevelHintSize() {
return tab_item_level_hint_size;
}
public String getTabItemLevelValueColor() {
return tab_item_level_value_color;
}
public int getTabItemLevelValueSize() {
return tab_item_level_value_size;
}
public String getTabItemLevelProgressDrawable() {
return tab_item_level_progress_drawable;
}
public String getTabItemLevelProgressThumb() {
return tab_item_level_progress_thumb;
}
public int getTabItemListDefaultSelectedIndex() {
return tab_item_list_default_selected_index;
}
public List<ItemInfo> getTabItemList() {
return tab_item_list;
}
@Override
public String toString() {
return "TabInfo{" +
"tab_id=" + tab_id +
", tab_name='" + tab_name + '\'' +
", tab_item_name_size=" + tab_item_name_size +
", tab_item_name_color_normal='" + tab_item_name_color_normal + '\'' +
", tab_item_name_color_select='" + tab_item_name_color_select + '\'' +
", tab_item_icon_width=" + tab_item_icon_width +
", tab_item_icon_height=" + tab_item_icon_height +
", tab_item_level_hint_color='" + tab_item_level_hint_color + '\'' +
", tab_item_level_hint_size=" + tab_item_level_hint_size +
", tab_item_level_value_color='" + tab_item_level_value_color + '\'' +
", tab_item_level_value_size=" + tab_item_level_value_size +
", tab_item_level_progress_drawable='" + tab_item_level_progress_drawable + '\'' +
", tab_item_level_progress_thumb='" + tab_item_level_progress_thumb + '\'' +
", tab_item_list_default_selected_index='" + tab_item_list_default_selected_index + '\'' +
", tab_item_list=" + tab_item_list +
'}';
}
}
package com.tencent.liteav.demo.beauty.utils;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.gson.Gson;
import com.tencent.liteav.demo.beauty.model.BeautyInfo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class BeautyUtils {
private static final String TAG = "BeautyUtils";
private static final String DEFAULT_BEAUTY_DATA = "default_beauty_data.json";
@SuppressLint("StaticFieldLeak")
private static Application sApplication;
public static BeautyInfo getDefaultBeautyInfo() {
return createBeautyInfo(readAssetsFile(DEFAULT_BEAUTY_DATA));
}
public static BeautyInfo createBeautyInfo(String json) {
Gson gson = new Gson();
return gson.fromJson(json, BeautyInfo.class);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static void setTextViewText(TextView textView, String resName) {
textView.setText(ResourceUtils.getString(resName));
}
public static void setTextViewColor(TextView textView, String resName) {
textView.setTextColor(ResourceUtils.getColor(resName));
}
public static void setTextViewSize(TextView textView, int size) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
}
public static void setImageResource(ImageView imageView, String res) {
imageView.setImageResource(ResourceUtils.getDrawableId(res));
}
public static String readAssetsFile(String fileName) {
StringBuilder sb = new StringBuilder();
InputStream is = null;
BufferedReader br = null;
try {
is = getApplication().getAssets().open(fileName);
br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String readLine;
while ((readLine = br.readLine()) != null) {
sb.append(readLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) is.close();
if (br != null) br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public static Application getApplication() {
if (sApplication != null) return sApplication;
Application app = getApplicationByReflect();
init(app);
return app;
}
public static String getPackageName() {
return getApplication().getPackageName();
}
private static void init(final Application app) {
if (sApplication == null) {
if (app == null) {
sApplication = getApplicationByReflect();
} else {
sApplication = app;
}
} else {
if (app != null && app.getClass() != sApplication.getClass()) {
sApplication = app;
}
}
}
private static Application getApplicationByReflect() {
try {
@SuppressLint("PrivateApi")
Class<?> activityThread = Class.forName("android.app.ActivityThread");
Object thread = activityThread.getMethod("currentActivityThread").invoke(null);
Object app = activityThread.getMethod("getApplication").invoke(thread);
if (app == null) {
throw new NullPointerException("You should init first.");
}
return (Application) app;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
throw new NullPointerException("You should init first.");
}
public static synchronized String unZip(@NonNull String zipFile, @NonNull String targetDir) {
if (TextUtils.isEmpty(zipFile)) {
return null;
} else {
File file = new File(zipFile);
if (!file.exists()) {
return null;
} else {
File targetFolder = new File(targetDir);
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
String dataDir = null;
short BUFFER = 4096;
FileInputStream fis = null;
ZipInputStream zis = null;
FileOutputStream fos = null;
BufferedOutputStream dest = null;
try {
fis = new FileInputStream(file);
zis = new ZipInputStream(new BufferedInputStream(fis));
while (true) {
String strEntry;
ZipEntry entry;
do {
if ((entry = zis.getNextEntry()) == null) {
return dataDir;
}
strEntry = entry.getName();
} while (strEntry.contains("../"));
if (entry.isDirectory()) {
String count1 = targetDir + File.separator + strEntry;
File data1 = new File(count1);
if (!data1.exists()) {
data1.mkdirs();
}
if (TextUtils.isEmpty(dataDir)) {
dataDir = data1.getPath();
}
} else {
byte[] data = new byte[BUFFER];
String targetFileDir = targetDir + File.separator + strEntry;
File targetFile = new File(targetFileDir);
try {
fos = new FileOutputStream(targetFile);
dest = new BufferedOutputStream(fos, BUFFER);
int count;
while ((count = zis.read(data)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
} catch (IOException var41) {
var41.printStackTrace();
} finally {
try {
if (dest != null) {
dest.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException var40) {
var40.printStackTrace();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (zis != null) {
zis.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return dataDir;
}
}
}
public static boolean isEmpty(@Nullable Collection object) {
return null == object || object.isEmpty();
}
public static boolean isNetworkAvailable(@NonNull Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return false;
} else {
NetworkInfo networkInfo = connectivity.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnectedOrConnecting();
}
}
@Nullable
public static File getExternalFilesDir(@NonNull Context context, String folder) {
if (context == null) {
Log.e(TAG, "getExternalFilesDir context is null");
return null;
}
File sdcardDir = context.getApplicationContext().getExternalFilesDir(null);
if (sdcardDir == null) {
Log.e(TAG, "sdcardDir is null");
return null;
}
String path = sdcardDir.getPath();
File file = new File(path + File.separator + folder);
try {
if (file.exists() && file.isFile()) {
file.delete();
}
if (!file.exists()) {
file.mkdirs();
}
} catch (Exception var5) {
var5.printStackTrace();
}
return file;
}
}
package com.tencent.liteav.demo.beauty.utils;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import androidx.annotation.StringRes;
public class ResourceUtils {
private static final String TYPE_QUOTE_PREFIX = "@";
private static final String TYPE_COLOR_PREFIX = "#";
private static final String TYPE_STRING = "string";
private static final String TYPE_COLOR = "color";
private static final String TYPE_DRAWABLE = "drawable";
public static int getDrawableId(String resName) {
if (resName.startsWith(TYPE_QUOTE_PREFIX)) {
return getResources().getIdentifier(resName, TYPE_DRAWABLE, BeautyUtils.getPackageName());
}
throw new IllegalArgumentException("\"" + resName + "\" is illegal, must start with \"@\".");
}
public static int getStringId(String resName) {
return getResources().getIdentifier(resName, TYPE_STRING, BeautyUtils.getPackageName());
}
public static String getString(String resName) {
if (resName.startsWith(TYPE_QUOTE_PREFIX)) {
return getResources().getString(getStringId(resName.substring(1)));
}
return resName;
}
public static String getString(@StringRes int resId) {
return getResources().getString(resId);
}
public static int getColor(String resName) {
if (resName.startsWith(TYPE_COLOR_PREFIX)) {
return Color.parseColor(resName);
}
if (resName.startsWith(TYPE_QUOTE_PREFIX)) {
return getResources().getColor(getColorId(resName));
}
throw new IllegalArgumentException("\"" + resName + "\" is unknown color.");
}
public static int getColorId(String resName) {
return getResources().getIdentifier(resName, TYPE_COLOR, BeautyUtils.getPackageName());
}
public static Resources getResources() {
return BeautyUtils.getApplication().getResources();
}
public static Drawable getLinearDrawable(int color) {
GradientDrawable drawable = new GradientDrawable();
drawable.setColor(color);
drawable.setShape(GradientDrawable.RECTANGLE);
drawable.setCornerRadii(new float[]{
BeautyUtils.dip2px(BeautyUtils.getApplication(), 10), BeautyUtils.dip2px(BeautyUtils.getApplication(), 10),
BeautyUtils.dip2px(BeautyUtils.getApplication(), 10), BeautyUtils.dip2px(BeautyUtils.getApplication(), 10),
0, 0, 0, 0});
return drawable;
}
}
package com.tencent.liteav.demo.beauty.utils;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
public class SPUtils {
private static final String SP_NAME_DEFAULT = "beauty_default";
private static SPUtils sInstance;
private SharedPreferences mSharedPreferences;
public static SPUtils get() {
return get(SP_NAME_DEFAULT, Context.MODE_PRIVATE);
}
public static SPUtils get(final int mode) {
return get(SP_NAME_DEFAULT, mode);
}
public static SPUtils get(String spName) {
return get(spName, Context.MODE_PRIVATE);
}
public static SPUtils get(String spName, final int mode) {
if (sInstance == null) {
synchronized (SPUtils.class) {
if (sInstance == null) {
sInstance = new SPUtils(spName, mode);
}
}
}
return sInstance;
}
private SPUtils(final String spName, final int mode) {
mSharedPreferences = BeautyUtils.getApplication().getSharedPreferences(spName, mode);
}
public void put(@NonNull final String key, final String value) {
put(key, value, false);
}
public void put(@NonNull final String key, final String value, final boolean isCommit) {
if (isCommit) {
mSharedPreferences.edit().putString(key, value).commit();
} else {
mSharedPreferences.edit().putString(key, value).apply();
}
}
public String getString(@NonNull final String key) {
return getString(key, "");
}
public String getString(@NonNull final String key, final String defaultValue) {
return mSharedPreferences.getString(key, defaultValue);
}
}
package com.tencent.liteav.demo.beauty.view;
import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.tencent.liteav.demo.beauty.R;
public class ProgressDialog {
private Dialog mDialog;
private TextView mTextMsg;
public void createLoadingDialog(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.beauty_layout_loading_progress, null);
LinearLayout layout = (LinearLayout) v.findViewById(R.id.beauty_ll_progress);
ImageView spaceshipImage = (ImageView) v.findViewById(R.id.beauty_iv_progress_img);
mTextMsg = (TextView) v.findViewById(R.id.beauty_tv_msg);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(context, R.anim.beauty_load_progress_animation);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
mDialog = new Dialog(context, R.style.BeautyLoadingDialog);
mDialog.setCancelable(false);
mDialog.setContentView(layout, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT));
}
public void setCancelable(boolean cancelable) {
if (mDialog != null) {
mDialog.setCancelable(cancelable);
}
}
public void setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
if (mDialog != null) {
mDialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
}
}
public void show() {
if (mDialog != null) {
mDialog.show();
}
}
public void dismiss() {
if (mDialog != null) {
mDialog.dismiss();
}
}
public void setMsg(String msg) {
if (mTextMsg == null) {
return;
}
if (mTextMsg.getVisibility() == View.GONE) {
mTextMsg.setVisibility(View.VISIBLE);
}
mTextMsg.setText(msg);
}
}
package com.tencent.liteav.demo.beauty.view;
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.HorizontalScrollView;
public class TCHorizontalScrollView extends HorizontalScrollView {
private DataSetObserver mObserver;
private Adapter mAdapter;
public TCHorizontalScrollView(Context context) {
super(context);
initialize();
}
public TCHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public TCHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
public void setAdapter(Adapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mObserver);
updateAdapter();
}
private void updateAdapter() {
ViewGroup group = (ViewGroup) getChildAt(0);
group.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
View view = mAdapter.getView(i, null, group);
group.addView(view);
}
}
void initialize() {
mObserver = new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
updateAdapter();
}
@Override
public void onInvalidated() {
super.onInvalidated();
((ViewGroup) getChildAt(0)).removeAllViews();
}
};
}
public void setClicked(int position) {
((ViewGroup) getChildAt(0)).getChildAt(position).performClick();
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="1500"
android:fromDegrees="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:repeatMode="restart"
android:startOffset="-1"
android:toDegrees="+360" />
</set>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment