Compare commits
No commits in common. "dev_680_礼物展馆" and "master" have entirely different histories.
dev_680_礼物
...
master
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,3 +14,4 @@ local.properties
|
|||||||
/live/build/
|
/live/build/
|
||||||
/main/build/
|
/main/build/
|
||||||
/video/build/
|
/video/build/
|
||||||
|
/tmp/full-r8-config.txt
|
@ -1,8 +1,14 @@
|
|||||||
apply plugin: 'com.android.library'
|
//apply plugin: 'com.android.library'
|
||||||
apply plugin: 'img-optimizer'
|
//apply plugin: 'img-optimizer'
|
||||||
apply plugin: 'kotlin-android'
|
//apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-parcelize'
|
//apply plugin: 'kotlin-android-extensions'
|
||||||
apply from: "../package_config.gradle"
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'kotlin-android'
|
||||||
|
id 'kotlin-parcelize'
|
||||||
|
id 'img-optimizer'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace "com.yunbao.faceunity"
|
namespace "com.yunbao.faceunity"
|
||||||
@ -33,7 +39,7 @@ android {
|
|||||||
versionName rootProject.ext.android.versionName
|
versionName rootProject.ext.android.versionName
|
||||||
manifestPlaceholders = rootProject.ext.manifestPlaceholders
|
manifestPlaceholders = rootProject.ext.manifestPlaceholders
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "armeabi-v7a", "arm64-v8a","x86","x86_64"
|
abiFilters "armeabi-v7a", "arm64-v8a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
@ -51,6 +57,9 @@ android {
|
|||||||
sourceCompatibility JavaVersion.VERSION_18
|
sourceCompatibility JavaVersion.VERSION_18
|
||||||
targetCompatibility JavaVersion.VERSION_18
|
targetCompatibility JavaVersion.VERSION_18
|
||||||
}
|
}
|
||||||
|
buildFeatures {
|
||||||
|
buildConfig = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
flatDir {
|
flatDir {
|
||||||
@ -58,15 +67,15 @@ repositories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
api rootProject.ext.dependencies["appcompat-androidx"]
|
implementation rootProject.ext.dependencies["appcompat-androidx"]
|
||||||
api rootProject.ext.dependencies["recyclerview-androidx"]
|
implementation rootProject.ext.dependencies["recyclerview-androidx"]
|
||||||
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
//common
|
//common
|
||||||
api project(path: ':common')
|
implementation project(path: ':common')
|
||||||
|
|
||||||
api 'com.faceunity:core:8.7.0'
|
implementation 'com.faceunity:core:8.3.1'
|
||||||
api 'com.faceunity:model:8.7.0'
|
implementation 'com.faceunity:model:8.3.1'
|
||||||
//implementation 'com.faceunity:nama:8.3.1' //底层库-标准版
|
//implementation 'com.faceunity:nama:8.3.1' //底层库-标准版
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package com.yunbao.faceunity;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.test.platform.app.Instrimport com.yunbao.common.utils.MobclickAgent;ntationRegistry;
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
>
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
@ -9,7 +10,9 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:icon="@mipmap/ico_home_animoji"
|
android:icon="@mipmap/ico_home_animoji"
|
||||||
android:allowBackup="true">
|
android:allowBackup="true"
|
||||||
|
tools:replace="allowBackup"
|
||||||
|
>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@ -96,17 +96,11 @@ public class FaceManager implements SensorEventListener {
|
|||||||
faceUnityView.setIFaceUnityInter(new FaceUnityView.IFaceUnityInter() {
|
faceUnityView.setIFaceUnityInter(new FaceUnityView.IFaceUnityInter() {
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
if(onMirrorChanged!=null){
|
|
||||||
onMirrorChanged.onChange(false);
|
|
||||||
}
|
|
||||||
pauseFace = true;
|
pauseFace = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
if(onMirrorChanged!=null){
|
|
||||||
onMirrorChanged.onChange(true);
|
|
||||||
}
|
|
||||||
pauseFace = false;
|
pauseFace = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -301,18 +295,7 @@ public class FaceManager implements SensorEventListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OnMirrorChanged onMirrorChanged;
|
|
||||||
|
|
||||||
public void setOnMirrorChanged(OnMirrorChanged onMirrorChanged) {
|
|
||||||
this.onMirrorChanged = onMirrorChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FaceStatusChanged {
|
public interface FaceStatusChanged {
|
||||||
void onFaceChanged(int num);
|
void onFaceChanged(int num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface OnMirrorChanged{
|
|
||||||
void onChange(boolean falg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,10 @@ public class FURenderer extends IFURenderer {
|
|||||||
|
|
||||||
|
|
||||||
/* 特效FURenderKit*/
|
/* 特效FURenderKit*/
|
||||||
public FURenderKit mFURenderKit;
|
private FURenderKit mFURenderKit;
|
||||||
|
|
||||||
/* AI道具*/
|
/* AI道具*/
|
||||||
public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor.bundle";
|
public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor_lite.bundle";
|
||||||
public static String BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle";
|
public static String BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle";
|
||||||
|
|
||||||
/* GL 线程 ID */
|
/* GL 线程 ID */
|
||||||
|
@ -15,7 +15,7 @@ public class FaceUnityConfig {
|
|||||||
|
|
||||||
/************************** 算法Model ******************************/
|
/************************** 算法Model ******************************/
|
||||||
// 人脸识别
|
// 人脸识别
|
||||||
public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor.bundle";
|
public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor_lite.bundle";
|
||||||
// 手势
|
// 手势
|
||||||
public static String BUNDLE_AI_HAND = "model" + File.separator + "ai_hand_processor.bundle";
|
public static String BUNDLE_AI_HAND = "model" + File.separator + "ai_hand_processor.bundle";
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package com.yunbao.common.utils;
|
package com.yunbao.faceunity.utils;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -152,36 +151,16 @@ public class ZipUtils {
|
|||||||
* @param zipFileString 解压完成的Zip路径
|
* @param zipFileString 解压完成的Zip路径
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static void zipFolder(List<String> srcFileString, String zipFileString, List<String> filters, Runnable runnable) throws Exception {
|
public static void zipFolder(String srcFileString, String zipFileString) throws Exception {
|
||||||
if (filters == null) {
|
|
||||||
filters = new ArrayList<>();
|
|
||||||
}
|
|
||||||
filters.add(new File(zipFileString).getAbsolutePath());
|
|
||||||
final List<String> tmp = new ArrayList<>(filters);
|
|
||||||
//创建ZIP
|
//创建ZIP
|
||||||
ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString));
|
ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString));
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
for (String src : srcFileString) {
|
|
||||||
File file = new File(src);
|
|
||||||
//压缩
|
|
||||||
zipFiles(file.getParent() + File.separator, file.getName(), outZip, tmp);
|
|
||||||
}
|
|
||||||
//创建文件
|
//创建文件
|
||||||
|
File file = new File(srcFileString);
|
||||||
|
//压缩
|
||||||
|
zipFiles(file.getParent() + File.separator, file.getName(), outZip);
|
||||||
//完成和关闭
|
//完成和关闭
|
||||||
outZip.finish();
|
outZip.finish();
|
||||||
outZip.close();
|
outZip.close();
|
||||||
runnable.run();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,15 +171,9 @@ public class ZipUtils {
|
|||||||
* @param zipOutputSteam
|
* @param zipOutputSteam
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private static void zipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam, List<String> filters) throws Exception {
|
private static void zipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) throws Exception {
|
||||||
if (zipOutputSteam == null)
|
if (zipOutputSteam == null)
|
||||||
return;
|
return;
|
||||||
for (String filter : filters) {
|
|
||||||
if (fileString.startsWith(filter)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("压缩文件:" + folderString + "|" + fileString);
|
|
||||||
File file = new File(folderString + fileString);
|
File file = new File(folderString + fileString);
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
ZipEntry zipEntry = new ZipEntry(fileString);
|
ZipEntry zipEntry = new ZipEntry(fileString);
|
||||||
@ -223,7 +196,7 @@ public class ZipUtils {
|
|||||||
}
|
}
|
||||||
//子文件和递归
|
//子文件和递归
|
||||||
for (int i = 0; i < fileList.length; i++) {
|
for (int i = 0; i < fileList.length; i++) {
|
||||||
zipFiles(folderString, fileString + File.separator + fileList[i], zipOutputSteam, filters);
|
zipFiles(folderString, fileString + File.separator + fileList[i], zipOutputSteam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ import com.google.gson.JsonObject;
|
|||||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||||
import com.yunbao.faceunity.utils.FileUtils;
|
import com.yunbao.faceunity.utils.FileUtils;
|
||||||
import com.yunbao.common.utils.ZipUtils;
|
import com.yunbao.faceunity.utils.ZipUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -334,7 +334,4 @@
|
|||||||
<string name="home_function_name_fine_sticker">Exquisite sticker</string>
|
<string name="home_function_name_fine_sticker">Exquisite sticker</string>
|
||||||
<string name="dialog_reset">Reset</string>
|
<string name="dialog_reset">Reset</string>
|
||||||
<string name="menu_diy">Custom</string>
|
<string name="menu_diy">Custom</string>
|
||||||
|
|
||||||
<string name="toast_not_detect_face">No face tracking</string>
|
|
||||||
<string name="toast_not_detect_face_or_body">No face or body tracking</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply from: "../package_config.gradle"
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace "com.samsung.android.sdk.iap.lib"
|
namespace "com.samsung.android.sdk.iap.lib"
|
||||||
compileSdk rootProject.ext.android.compileSdkVersion
|
compileSdk rootProject.ext.android.compileSdkVersion
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
<manifest
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:versionCode="601000004"
|
android:versionCode="601000004"
|
||||||
android:versionName="6.1.0">
|
android:versionName="6.1.0">
|
||||||
<!-- version code [Major/Minor/Bug fix release/Build number ] : x xx xxx xxx -->
|
<!-- version code [Major/Minor/Bug fix release/Build number ] : x xx xxx xxx -->
|
||||||
|
|
||||||
<application>
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
tools:replace="allowBackup">
|
||||||
<!-- IAP 라이브러리 내 Activity 선언 시작-->
|
<!-- IAP 라이브러리 내 Activity 선언 시작-->
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.samsung.android.sdk.iap.lib.activity.DialogActivity"
|
android:name="com.samsung.android.sdk.iap.lib2.activity.DialogActivity"
|
||||||
android:theme="@style/Theme.Empty"
|
android:theme="@style/Theme.Empty"
|
||||||
android:configChanges="orientation|screenSize"/>
|
android:configChanges="orientation|screenSize"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.samsung.android.sdk.iap.lib.activity.CheckPackageActivity"
|
android:name="com.samsung.android.sdk.iap.lib2.activity.CheckPackageActivity"
|
||||||
android:theme="@style/Theme.Empty"
|
android:theme="@style/Theme.Empty"
|
||||||
android:configChanges="orientation|screenSize"/>
|
android:configChanges="orientation|screenSize"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.samsung.android.sdk.iap.lib.activity.AccountActivity"
|
android:name="com.samsung.android.sdk.iap.lib2.activity.AccountActivity"
|
||||||
android:theme="@style/Theme.Transparent"
|
android:theme="@style/Theme.Transparent"
|
||||||
android:configChanges="orientation|screenSize"/>
|
android:configChanges="orientation|screenSize"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.samsung.android.sdk.iap.lib.activity.PaymentActivity"
|
android:name="com.samsung.android.sdk.iap.lib2.activity.PaymentActivity"
|
||||||
android:theme="@style/Theme.Empty"
|
android:theme="@style/Theme.Empty"
|
||||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|locale|uiMode|fontScale|density"/>
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|locale|uiMode|fontScale|density"/>
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask;
|
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
|
||||||
import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback Interface used with {@link GetOwnedListTask}
|
|
||||||
*/
|
|
||||||
public interface OnGetOwnedListListener {
|
|
||||||
/**
|
|
||||||
* Callback method to be invoked when {@link GetOwnedListTask} has been finished.
|
|
||||||
*
|
|
||||||
* @param _errorVO
|
|
||||||
* @param _ownedList
|
|
||||||
*/
|
|
||||||
void onGetOwnedProducts(ErrorVo _errorVO, ArrayList<OwnedProductVo> _ownedList);
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask;
|
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ProductVo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback Interface used with {@link GetProductsDetailsTask}
|
|
||||||
*/
|
|
||||||
public interface OnGetProductsDetailsListener {
|
|
||||||
/**
|
|
||||||
* Callback method to be invoked when {@link GetProductsDetailsTask} has been finished.
|
|
||||||
*
|
|
||||||
* @param _errorVO
|
|
||||||
* @param _productList
|
|
||||||
*/
|
|
||||||
void onGetProducts(ErrorVo _errorVO, ArrayList<ProductVo> _productList);
|
|
||||||
}
|
|
@ -1,13 +1,13 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.activity;
|
package com.samsung.android.sdk.iap.lib2.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperUtil;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperUtil;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2018-03-06.
|
* Created by sangbum7.kim on 2018-03-06.
|
||||||
@ -16,12 +16,11 @@ import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
|||||||
public class AccountActivity extends Activity {
|
public class AccountActivity extends Activity {
|
||||||
private static final String TAG = AccountActivity.class.getSimpleName();
|
private static final String TAG = AccountActivity.class.getSimpleName();
|
||||||
|
|
||||||
IapHelper mIapHelper = null;
|
com.samsung.android.sdk.iap.lib2.helper.IapHelper mIapHelper = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
mIapHelper = IapHelper.getInstance(this);
|
mIapHelper = IapHelper.getInstance(this);
|
||||||
// ====================================================================
|
// ====================================================================
|
||||||
// 1. If IAP package is installed and valid, start SamsungAccount
|
// 1. If IAP package is installed and valid, start SamsungAccount
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.activity;
|
package com.samsung.android.sdk.iap.lib2.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -8,25 +8,25 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.dialog.BaseDialogFragment;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperUtil;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperUtil;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.PurchaseVo;
|
import com.samsung.android.sdk.iap.lib2.vo.PurchaseVo;
|
||||||
|
|
||||||
|
|
||||||
public abstract class BaseActivity extends Activity {
|
public abstract class BaseActivity extends Activity {
|
||||||
private static final String TAG = BaseActivity.class.getSimpleName();
|
private static final String TAG = BaseActivity.class.getSimpleName();
|
||||||
|
|
||||||
protected ErrorVo mErrorVo = new ErrorVo();
|
protected com.samsung.android.sdk.iap.lib2.vo.ErrorVo mErrorVo = new com.samsung.android.sdk.iap.lib2.vo.ErrorVo();
|
||||||
private Dialog mProgressDialog = null;
|
private Dialog mProgressDialog = null;
|
||||||
protected PurchaseVo mPurchaseVo = null;
|
protected com.samsung.android.sdk.iap.lib2.vo.PurchaseVo mPurchaseVo = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper Class between IAPService and 3rd Party Application
|
* Helper Class between IAPService and 3rd Party Application
|
||||||
*/
|
*/
|
||||||
IapHelper mIapHelper = null;
|
com.samsung.android.sdk.iap.lib2.helper.IapHelper mIapHelper = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag value to show successful pop-up. Error pop-up appears whenever it fails or not.
|
* Flag value to show successful pop-up. Error pop-up appears whenever it fails or not.
|
||||||
@ -64,15 +64,15 @@ public abstract class BaseActivity extends Activity {
|
|||||||
public boolean checkAppsPackage(Activity _activity) {
|
public boolean checkAppsPackage(Activity _activity) {
|
||||||
// 1. If Galaxy Store is installed
|
// 1. If Galaxy Store is installed
|
||||||
// ====================================================================
|
// ====================================================================
|
||||||
if (HelperUtil.isInstalledAppsPackage(this)) {
|
if (com.samsung.android.sdk.iap.lib2.helper.HelperUtil.isInstalledAppsPackage(this)) {
|
||||||
// 1) If Galaxy Store is enabled
|
// 1) If Galaxy Store is enabled
|
||||||
// ================================================================
|
// ================================================================
|
||||||
if (!HelperUtil.isEnabledAppsPackage(this)) {
|
if (!com.samsung.android.sdk.iap.lib2.helper.HelperUtil.isEnabledAppsPackage(this)) {
|
||||||
HelperUtil.showEnableGalaxyStoreDialog(_activity);
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.showEnableGalaxyStoreDialog(_activity);
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// 2) If Galaxy Store is valid
|
// 2) If Galaxy Store is valid
|
||||||
// ================================================================
|
// ================================================================
|
||||||
} else if (HelperUtil.isValidAppsPackage(this)) {
|
} else if (com.samsung.android.sdk.iap.lib2.helper.HelperUtil.isValidAppsPackage(this)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Set error to notify result to third-party application
|
// Set error to notify result to third-party application
|
||||||
@ -84,7 +84,7 @@ public abstract class BaseActivity extends Activity {
|
|||||||
R.string.dream_ph_body_contact_p1sscustomer_servicep2ss_for_more_information_n_nerror_code_c_p3ss),
|
R.string.dream_ph_body_contact_p1sscustomer_servicep2ss_for_more_information_n_nerror_code_c_p3ss),
|
||||||
"", "", ERROR_ISSUER_IAP_CLIENT + ERROR_CODE_INVALID_GALAXY_STORE);
|
"", "", ERROR_ISSUER_IAP_CLIENT + ERROR_CODE_INVALID_GALAXY_STORE);
|
||||||
mErrorVo.setError(HelperDefine.IAP_PAYMENT_IS_CANCELED, errorString);
|
mErrorVo.setError(HelperDefine.IAP_PAYMENT_IS_CANCELED, errorString);
|
||||||
HelperUtil.showInvalidGalaxyStoreDialog(this);
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.showInvalidGalaxyStoreDialog(this);
|
||||||
}
|
}
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ public abstract class BaseActivity extends Activity {
|
|||||||
// 2. If Galaxy Store is not installed
|
// 2. If Galaxy Store is not installed
|
||||||
// ====================================================================
|
// ====================================================================
|
||||||
} else {
|
} else {
|
||||||
HelperUtil.installAppsPackage(this);
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.installAppsPackage(this);
|
||||||
}
|
}
|
||||||
// ====================================================================
|
// ====================================================================
|
||||||
return false;
|
return false;
|
||||||
@ -161,12 +161,12 @@ public abstract class BaseActivity extends Activity {
|
|||||||
else {
|
else {
|
||||||
Log.e(TAG, "finishPurchase: " + mErrorVo.dump());
|
Log.e(TAG, "finishPurchase: " + mErrorVo.dump());
|
||||||
if (mShowErrorDialog) {
|
if (mShowErrorDialog) {
|
||||||
HelperUtil.showIapErrorDialog(
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.showIapErrorDialog(
|
||||||
this,
|
this,
|
||||||
getString(R.string.dream_ph_pheader_couldnt_complete_purchase),
|
getString(R.string.dream_ph_pheader_couldnt_complete_purchase),
|
||||||
mErrorVo.getErrorString(),
|
mErrorVo.getErrorString(),
|
||||||
mErrorVo.getErrorDetailsString(),
|
mErrorVo.getErrorDetailsString(),
|
||||||
new BaseDialogFragment.OnClickListener() {
|
new com.samsung.android.sdk.iap.lib2.dialog.BaseDialogFragment.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick() {
|
public void onClick() {
|
||||||
finish();
|
finish();
|
@ -1,12 +1,12 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.activity;
|
package com.samsung.android.sdk.iap.lib2.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperUtil;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperUtil;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2018-03-07.
|
* Created by sangbum7.kim on 2018-03-07.
|
||||||
@ -27,12 +27,12 @@ public class CheckPackageActivity extends Activity {
|
|||||||
int DialogType = extras.getInt("DialogType");
|
int DialogType = extras.getInt("DialogType");
|
||||||
switch (DialogType) {
|
switch (DialogType) {
|
||||||
case HelperDefine.DIALOG_TYPE_INVALID_PACKAGE: {
|
case HelperDefine.DIALOG_TYPE_INVALID_PACKAGE: {
|
||||||
HelperUtil.showInvalidGalaxyStoreDialog(this);
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.showInvalidGalaxyStoreDialog(this);
|
||||||
mFinishFlag = false;
|
mFinishFlag = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HelperDefine.DIALOG_TYPE_DISABLE_APPLICATION: {
|
case HelperDefine.DIALOG_TYPE_DISABLE_APPLICATION: {
|
||||||
HelperUtil.showEnableGalaxyStoreDialog(this);
|
com.samsung.android.sdk.iap.lib2.helper.HelperUtil.showEnableGalaxyStoreDialog(this);
|
||||||
mFinishFlag = false;
|
mFinishFlag = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
@ -1,16 +1,12 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.activity;
|
package com.samsung.android.sdk.iap.lib2.activity;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment;
|
import com.samsung.android.sdk.iap.lib2.dialog.BaseDialogFragment;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperUtil;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2018-03-05.
|
* Created by sangbum7.kim on 2018-03-05.
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.activity;
|
package com.samsung.android.sdk.iap.lib2.activity;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -9,9 +9,9 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperListenerManager;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperListenerManager;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener;
|
import com.samsung.android.sdk.iap.lib2.listener.OnPaymentListener;
|
||||||
|
|
||||||
public class PaymentActivity extends BaseActivity {
|
public class PaymentActivity extends BaseActivity {
|
||||||
private static final String TAG = PaymentActivity.class.getSimpleName();
|
private static final String TAG = PaymentActivity.class.getSimpleName();
|
||||||
@ -56,7 +56,7 @@ public class PaymentActivity extends BaseActivity {
|
|||||||
super.preDestory();
|
super.preDestory();
|
||||||
if (isFinishing()) {
|
if (isFinishing()) {
|
||||||
OnPaymentListener onPaymentListener =
|
OnPaymentListener onPaymentListener =
|
||||||
HelperListenerManager.getInstance().getOnPaymentListener();
|
com.samsung.android.sdk.iap.lib2.helper.HelperListenerManager.getInstance().getOnPaymentListener();
|
||||||
HelperListenerManager.getInstance().setOnPaymentListener(null);
|
HelperListenerManager.getInstance().setOnPaymentListener(null);
|
||||||
if (null != onPaymentListener) {
|
if (null != onPaymentListener) {
|
||||||
onPaymentListener.onPayment(mErrorVo, mPurchaseVo);
|
onPaymentListener.onPayment(mErrorVo, mPurchaseVo);
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.dialog;
|
package com.samsung.android.sdk.iap.lib2.dialog;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@ -8,7 +8,6 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper;
|
package com.samsung.android.sdk.iap.lib2.helper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2017-07-17.
|
* Created by sangbum7.kim on 2017-07-17.
|
@ -1,12 +1,12 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper;
|
package com.samsung.android.sdk.iap.lib2.helper;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnConsumePurchasedItemsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetOwnedListListener;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetProductsDetailsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener;
|
import com.samsung.android.sdk.iap.lib2.listener.OnPaymentListener;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener;
|
import com.samsung.android.sdk.iap.lib2.helper.task.ConsumePurchasedItemsTask;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener;
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener;
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2017-08-29.
|
* Created by sangbum7.kim on 2017-08-29.
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper;
|
package com.samsung.android.sdk.iap.lib2.helper;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@ -14,9 +14,9 @@ import android.text.Html;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.activity.BaseActivity;
|
import com.samsung.android.sdk.iap.lib2.activity.BaseActivity;
|
||||||
import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment;
|
import com.samsung.android.sdk.iap.lib2.dialog.BaseDialogFragment;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2017-08-17.
|
* Created by sangbum7.kim on 2017-08-17.
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper;
|
package com.samsung.android.sdk.iap.lib2.helper;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -12,21 +12,20 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.samsung.android.iap.IAPConnector;
|
import com.samsung.android.iap.IAPConnector;
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.activity.CheckPackageActivity;
|
import com.samsung.android.sdk.iap.lib2.activity.CheckPackageActivity;
|
||||||
import com.samsung.android.sdk.iap.lib.activity.PaymentActivity;
|
import com.samsung.android.sdk.iap.lib2.activity.PaymentActivity;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.listener.OnConsumePurchasedItemsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetOwnedListListener;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetProductsDetailsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask;
|
import com.samsung.android.sdk.iap.lib2.listener.OnPaymentListener;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener;
|
import com.samsung.android.sdk.iap.lib2.service.BaseService;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener;
|
import com.samsung.android.sdk.iap.lib2.service.ConsumePurchasedItems;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener;
|
import com.samsung.android.sdk.iap.lib2.service.OwnedProduct;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener;
|
import com.samsung.android.sdk.iap.lib2.service.ProductsDetails;
|
||||||
import com.samsung.android.sdk.iap.lib.service.BaseService;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
import com.samsung.android.sdk.iap.lib.service.ConsumePurchasedItems;
|
import com.samsung.android.sdk.iap.lib2.helper.task.ConsumePurchasedItemsTask;
|
||||||
import com.samsung.android.sdk.iap.lib.service.OwnedProduct;
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask;
|
||||||
import com.samsung.android.sdk.iap.lib.service.ProductsDetails;
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -34,6 +33,7 @@ public class IapHelper extends HelperDefine {
|
|||||||
private static final String TAG = IapHelper.class.getSimpleName();
|
private static final String TAG = IapHelper.class.getSimpleName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* When you release a application, this Mode must be set to {@link HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION}
|
||||||
* Please double-check this mode before release.
|
* Please double-check this mode before release.
|
||||||
*/
|
*/
|
||||||
private int mMode = HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION.getValue();
|
private int mMode = HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION.getValue();
|
||||||
@ -46,9 +46,9 @@ public class IapHelper extends HelperDefine {
|
|||||||
|
|
||||||
// AsyncTask for API
|
// AsyncTask for API
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
private com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask mGetProductsDetailsTask = null;
|
private com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask mGetProductsDetailsTask = null;
|
||||||
private com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask mGetOwnedListTask = null;
|
private com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask mGetOwnedListTask = null;
|
||||||
private com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask mConsumePurchasedItemsTask = null;
|
private com.samsung.android.sdk.iap.lib2.helper.task.ConsumePurchasedItemsTask mConsumePurchasedItemsTask = null;
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
private ArrayList<BaseService> mServiceQueue = new ArrayList<BaseService>();
|
private ArrayList<BaseService> mServiceQueue = new ArrayList<BaseService>();
|
||||||
@ -267,7 +267,7 @@ public class IapHelper extends HelperDefine {
|
|||||||
if (mIapConnector == null || mContext == null) {
|
if (mIapConnector == null || mContext == null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
mGetProductsDetailsTask = new com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask(_baseService,
|
mGetProductsDetailsTask = new com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask(_baseService,
|
||||||
mIapConnector,
|
mIapConnector,
|
||||||
mContext,
|
mContext,
|
||||||
_productIDs,
|
_productIDs,
|
||||||
@ -344,7 +344,7 @@ public class IapHelper extends HelperDefine {
|
|||||||
if (mIapConnector == null || mContext == null) {
|
if (mIapConnector == null || mContext == null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
mGetOwnedListTask = new com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask(_baseService,
|
mGetOwnedListTask = new com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask(_baseService,
|
||||||
mIapConnector,
|
mIapConnector,
|
||||||
mContext,
|
mContext,
|
||||||
_productType,
|
_productType,
|
||||||
@ -417,7 +417,7 @@ public class IapHelper extends HelperDefine {
|
|||||||
mConsumePurchasedItemsTask.cancel(true);
|
mConsumePurchasedItemsTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mConsumePurchasedItemsTask = new com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask(_baseService,
|
mConsumePurchasedItemsTask = new com.samsung.android.sdk.iap.lib2.helper.task.ConsumePurchasedItemsTask(_baseService,
|
||||||
mIapConnector,
|
mIapConnector,
|
||||||
mContext,
|
mContext,
|
||||||
_purchaseIds,
|
_purchaseIds,
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper.task;
|
package com.samsung.android.sdk.iap.lib2.helper.task;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
@ -6,9 +6,8 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.samsung.android.iap.IAPConnector;
|
import com.samsung.android.iap.IAPConnector;
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.service.BaseService;
|
||||||
import com.samsung.android.sdk.iap.lib.service.BaseService;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2017-09-01.
|
* Created by sangbum7.kim on 2017-09-01.
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper.task;
|
package com.samsung.android.sdk.iap.lib2.helper.task;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -6,9 +6,9 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.samsung.android.iap.IAPConnector;
|
import com.samsung.android.iap.IAPConnector;
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.service.ConsumePurchasedItems;
|
import com.samsung.android.sdk.iap.lib2.service.ConsumePurchasedItems;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ConsumeVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ConsumeVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper.task;
|
package com.samsung.android.sdk.iap.lib2.helper.task;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -6,9 +6,9 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.samsung.android.iap.IAPConnector;
|
import com.samsung.android.iap.IAPConnector;
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.service.OwnedProduct;
|
import com.samsung.android.sdk.iap.lib2.service.OwnedProduct;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo;
|
import com.samsung.android.sdk.iap.lib2.vo.OwnedProductVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.helper.task;
|
package com.samsung.android.sdk.iap.lib2.helper.task;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -6,9 +6,9 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.samsung.android.iap.IAPConnector;
|
import com.samsung.android.iap.IAPConnector;
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.service.ProductsDetails;
|
import com.samsung.android.sdk.iap.lib2.service.ProductsDetails;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ProductVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ProductVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask;
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ConsumeVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ConsumeVo;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback Interface used with {@link GetOwnedListTask}
|
* Callback Interface used with {@link com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask}
|
||||||
*/
|
*/
|
||||||
public interface OnConsumePurchasedItemsListener {
|
public interface OnConsumePurchasedItemsListener {
|
||||||
/**
|
/**
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask;
|
||||||
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
|
import com.samsung.android.sdk.iap.lib2.vo.OwnedProductVo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback Interface used with {@link com.samsung.android.sdk.iap.lib2.helper.task.GetOwnedListTask}
|
||||||
|
*/
|
||||||
|
public interface OnGetOwnedListListener {
|
||||||
|
/**
|
||||||
|
* Callback method to be invoked when {@link GetOwnedListTask} has been finished.
|
||||||
|
*
|
||||||
|
* @param _errorVO
|
||||||
|
* @param _ownedList
|
||||||
|
*/
|
||||||
|
void onGetOwnedProducts(ErrorVo _errorVO, ArrayList<OwnedProductVo> _ownedList);
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
|
import com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask;
|
||||||
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
|
import com.samsung.android.sdk.iap.lib2.vo.ProductVo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback Interface used with {@link com.samsung.android.sdk.iap.lib2.helper.task.GetProductsDetailsTask}
|
||||||
|
*/
|
||||||
|
public interface OnGetProductsDetailsListener {
|
||||||
|
/**
|
||||||
|
* Callback method to be invoked when {@link GetProductsDetailsTask} has been finished.
|
||||||
|
*
|
||||||
|
* @param _errorVO
|
||||||
|
* @param _productList
|
||||||
|
*/
|
||||||
|
void onGetProducts(ErrorVo _errorVO, ArrayList<ProductVo> _productList);
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback Interface to be invoked when bind to IAPService has been finished.
|
* Callback Interface to be invoked when bind to IAPService has been finished.
|
@ -1,7 +1,7 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.PurchaseVo;
|
import com.samsung.android.sdk.iap.lib2.vo.PurchaseVo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback Interface to be invoked when payment has been finished.
|
* Callback Interface to be invoked when payment has been finished.
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.listener;
|
package com.samsung.android.sdk.iap.lib2.listener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2018-02-28.
|
* Created by sangbum7.kim on 2018-02-28.
|
@ -1,15 +1,15 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.service;
|
package com.samsung.android.sdk.iap.lib2.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.activity.AccountActivity;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.activity.DialogActivity;
|
import com.samsung.android.sdk.iap.lib2.activity.AccountActivity;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.activity.DialogActivity;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ErrorVo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sangbum7.kim on 2018-02-28.
|
* Created by sangbum7.kim on 2018-02-28.
|
||||||
@ -18,8 +18,8 @@ import com.samsung.android.sdk.iap.lib.vo.ErrorVo;
|
|||||||
public abstract class BaseService {
|
public abstract class BaseService {
|
||||||
private static final String TAG = BaseService.class.getSimpleName();
|
private static final String TAG = BaseService.class.getSimpleName();
|
||||||
|
|
||||||
protected ErrorVo mErrorVo = new ErrorVo();
|
protected com.samsung.android.sdk.iap.lib2.vo.ErrorVo mErrorVo = new com.samsung.android.sdk.iap.lib2.vo.ErrorVo();
|
||||||
protected IapHelper mIapHelper = null;
|
protected com.samsung.android.sdk.iap.lib2.helper.IapHelper mIapHelper = null;
|
||||||
protected Context mContext = null;
|
protected Context mContext = null;
|
||||||
|
|
||||||
public BaseService(IapHelper _iapHelper, Context _context) {
|
public BaseService(IapHelper _iapHelper, Context _context) {
|
||||||
@ -28,7 +28,7 @@ public abstract class BaseService {
|
|||||||
mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred));
|
mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorVo getErrorVo() {
|
public com.samsung.android.sdk.iap.lib2.vo.ErrorVo getErrorVo() {
|
||||||
return mErrorVo;
|
return mErrorVo;
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.service;
|
package com.samsung.android.sdk.iap.lib2.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener;
|
import com.samsung.android.sdk.iap.lib2.listener.OnConsumePurchasedItemsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ConsumeVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ConsumeVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -18,9 +18,9 @@ import java.util.ArrayList;
|
|||||||
public class ConsumePurchasedItems extends BaseService {
|
public class ConsumePurchasedItems extends BaseService {
|
||||||
private static final String TAG = ConsumePurchasedItems.class.getSimpleName();
|
private static final String TAG = ConsumePurchasedItems.class.getSimpleName();
|
||||||
|
|
||||||
private OnConsumePurchasedItemsListener mOnConsumePurchasedItemsListener = null;
|
private com.samsung.android.sdk.iap.lib2.listener.OnConsumePurchasedItemsListener mOnConsumePurchasedItemsListener = null;
|
||||||
private static String mPurchaseIds = "";
|
private static String mPurchaseIds = "";
|
||||||
protected ArrayList<ConsumeVo> mConsumeList = null;
|
protected ArrayList<com.samsung.android.sdk.iap.lib2.vo.ConsumeVo> mConsumeList = null;
|
||||||
|
|
||||||
public ConsumePurchasedItems(IapHelper _iapHelper, Context _context, OnConsumePurchasedItemsListener _onConsumePurchasedItemsListener) {
|
public ConsumePurchasedItems(IapHelper _iapHelper, Context _context, OnConsumePurchasedItemsListener _onConsumePurchasedItemsListener) {
|
||||||
super(_iapHelper, _context);
|
super(_iapHelper, _context);
|
@ -1,13 +1,13 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.service;
|
package com.samsung.android.sdk.iap.lib2.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetOwnedListListener;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo;
|
import com.samsung.android.sdk.iap.lib2.vo.OwnedProductVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -18,9 +18,9 @@ import java.util.ArrayList;
|
|||||||
public class OwnedProduct extends BaseService {
|
public class OwnedProduct extends BaseService {
|
||||||
private static final String TAG = OwnedProduct.class.getSimpleName();
|
private static final String TAG = OwnedProduct.class.getSimpleName();
|
||||||
|
|
||||||
private OnGetOwnedListListener mOnGetOwnedListListener = null;
|
private com.samsung.android.sdk.iap.lib2.listener.OnGetOwnedListListener mOnGetOwnedListListener = null;
|
||||||
private static String mProductType = "";
|
private static String mProductType = "";
|
||||||
protected ArrayList<OwnedProductVo> mOwnedList = null;
|
protected ArrayList<com.samsung.android.sdk.iap.lib2.vo.OwnedProductVo> mOwnedList = null;
|
||||||
|
|
||||||
public OwnedProduct(IapHelper _iapHelper, Context _context, OnGetOwnedListListener _onGetOwnedListListener) {
|
public OwnedProduct(IapHelper _iapHelper, Context _context, OnGetOwnedListListener _onGetOwnedListListener) {
|
||||||
super(_iapHelper, _context);
|
super(_iapHelper, _context);
|
@ -1,13 +1,13 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.service;
|
package com.samsung.android.sdk.iap.lib2.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.R;
|
import com.samsung.android.sdk.iap.lib.R;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
import com.samsung.android.sdk.iap.lib.helper.IapHelper;
|
import com.samsung.android.sdk.iap.lib2.helper.IapHelper;
|
||||||
import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener;
|
import com.samsung.android.sdk.iap.lib2.listener.OnGetProductsDetailsListener;
|
||||||
import com.samsung.android.sdk.iap.lib.vo.ProductVo;
|
import com.samsung.android.sdk.iap.lib2.vo.ProductVo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -18,9 +18,9 @@ import java.util.ArrayList;
|
|||||||
public class ProductsDetails extends BaseService {
|
public class ProductsDetails extends BaseService {
|
||||||
private static final String TAG = ProductsDetails.class.getSimpleName();
|
private static final String TAG = ProductsDetails.class.getSimpleName();
|
||||||
|
|
||||||
private OnGetProductsDetailsListener mOnGetProductsDetailsListener = null;
|
private com.samsung.android.sdk.iap.lib2.listener.OnGetProductsDetailsListener mOnGetProductsDetailsListener = null;
|
||||||
private static String mProductIds = "";
|
private static String mProductIds = "";
|
||||||
protected ArrayList<ProductVo> mProductsDetails = null;
|
protected ArrayList<com.samsung.android.sdk.iap.lib2.vo.ProductVo> mProductsDetails = null;
|
||||||
|
|
||||||
public ProductsDetails(IapHelper _iapHelper, Context _context, OnGetProductsDetailsListener _onGetProductsDetailsListener) {
|
public ProductsDetails(IapHelper _iapHelper, Context _context, OnGetProductsDetailsListener _onGetProductsDetailsListener) {
|
||||||
super(_iapHelper, _context);
|
super(_iapHelper, _context);
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import com.samsung.android.sdk.iap.lib.helper.HelperDefine;
|
import com.samsung.android.sdk.iap.lib2.helper.HelperDefine;
|
||||||
|
|
||||||
public class ErrorVo {
|
public class ErrorVo {
|
||||||
private int mErrorCode = HelperDefine.IAP_PAYMENT_IS_CANCELED;
|
private int mErrorCode = HelperDefine.IAP_PAYMENT_IS_CANCELED;
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
@ -1,4 +1,4 @@
|
|||||||
package com.samsung.android.sdk.iap.lib.vo;
|
package com.samsung.android.sdk.iap.lib2.vo;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
<solid android:color="#252525" />
|
<solid android:color="#252525" />
|
||||||
<corners android:radius="26dp" />
|
<corners android:radius="26dp" />
|
||||||
</shape>
|
</shape>
|
2
SVGAlibrary/.gitignore
vendored
2
SVGAlibrary/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
/build
|
|
||||||
*.iml
|
|
@ -1,37 +0,0 @@
|
|||||||
apply plugin: 'com.android.library'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 28
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion 14
|
|
||||||
targetSdkVersion 28
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
kotlinOptions.freeCompilerArgs += ['-module-name', "com.opensource.svgaplayer"]
|
|
||||||
}
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
packagingOptions {
|
|
||||||
exclude 'META-INF/ASL2.0'
|
|
||||||
exclude 'META-INF/LICENSE'
|
|
||||||
exclude 'META-INF/NOTICE'
|
|
||||||
exclude 'META-INF/NOTICE.txt'
|
|
||||||
exclude 'META-INF/LICENSE.txt'
|
|
||||||
exclude 'META-INF/MANIFEST.MF'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'com.squareup.wire:wire-runtime:4.4.1'
|
|
||||||
}
|
|
17
SVGAlibrary/proguard-rules.pro
vendored
17
SVGAlibrary/proguard-rules.pro
vendored
@ -1,17 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# By default, the flags in this file are appended to flags specified
|
|
||||||
# in /Users/PonyCui_Home/Library/Android/sdk/tools/proguard/proguard-android.txt
|
|
||||||
# You can edit the include path and order by changing the proguardFiles
|
|
||||||
# directive in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# Add any project specific keep options here:
|
|
||||||
|
|
||||||
# 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 *;
|
|
||||||
#}
|
|
@ -1,8 +0,0 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.opensource.svgaplayer">
|
|
||||||
|
|
||||||
<application android:allowBackup="true" android:label="@string/app_name">
|
|
||||||
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,9 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by miaojun on 2019/6/21.
|
|
||||||
* mail:1290846731@qq.com
|
|
||||||
*/
|
|
||||||
interface IClickAreaListener{
|
|
||||||
fun onResponseArea(key : String,x0 : Int, y0 : Int, x1 : Int, y1 : Int)
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.opensource.svgaplayer.utils.log.LogUtils
|
|
||||||
import java.io.File
|
|
||||||
import java.net.URL
|
|
||||||
import java.security.MessageDigest
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SVGA 缓存管理
|
|
||||||
*/
|
|
||||||
object SVGACache {
|
|
||||||
enum class Type {
|
|
||||||
DEFAULT,
|
|
||||||
FILE
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val TAG = "SVGACache"
|
|
||||||
private var type: Type = Type.DEFAULT
|
|
||||||
private var cacheDir: String = "/"
|
|
||||||
get() {
|
|
||||||
if (field != "/") {
|
|
||||||
val dir = File(field)
|
|
||||||
if (!dir.exists()) {
|
|
||||||
dir.mkdirs()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return field
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun onCreate(context: Context?) {
|
|
||||||
onCreate(context, Type.DEFAULT)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onCreate(context: Context?, type: Type) {
|
|
||||||
if (isInitialized()) return
|
|
||||||
context ?: return
|
|
||||||
cacheDir = "${context.cacheDir.absolutePath}/svga/"
|
|
||||||
File(cacheDir).takeIf { !it.exists() }?.mkdirs()
|
|
||||||
this.type = type
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理缓存
|
|
||||||
*/
|
|
||||||
fun clearCache() {
|
|
||||||
if (!isInitialized()) {
|
|
||||||
LogUtils.error(TAG, "SVGACache is not init!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGAParser.threadPoolExecutor.execute {
|
|
||||||
clearDir(cacheDir)
|
|
||||||
LogUtils.info(TAG, "Clear svga cache done!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除目录下的所有文件
|
|
||||||
internal fun clearDir(path: String) {
|
|
||||||
try {
|
|
||||||
val dir = File(path)
|
|
||||||
dir.takeIf { it.exists() }?.let { parentDir ->
|
|
||||||
parentDir.listFiles()?.forEach { file ->
|
|
||||||
if (!file.exists()) {
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
if (file.isDirectory) {
|
|
||||||
clearDir(file.absolutePath)
|
|
||||||
}
|
|
||||||
file.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "Clear svga cache path: $path fail", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInitialized(): Boolean {
|
|
||||||
return "/" != cacheDir && File(cacheDir).exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDefaultCache(): Boolean = type == Type.DEFAULT
|
|
||||||
|
|
||||||
fun isCached(cacheKey: String): Boolean {
|
|
||||||
return if (isDefaultCache()) {
|
|
||||||
buildCacheDir(cacheKey)
|
|
||||||
} else {
|
|
||||||
buildSvgaFile(
|
|
||||||
cacheKey
|
|
||||||
)
|
|
||||||
}.exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildCacheKey(str: String): String {
|
|
||||||
val messageDigest = MessageDigest.getInstance("MD5")
|
|
||||||
messageDigest.update(str.toByteArray(charset("UTF-8")))
|
|
||||||
val digest = messageDigest.digest()
|
|
||||||
var sb = ""
|
|
||||||
for (b in digest) {
|
|
||||||
sb += String.format("%02x", b)
|
|
||||||
}
|
|
||||||
return sb
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildCacheKey(url: URL): String = buildCacheKey(url.toString())
|
|
||||||
|
|
||||||
fun buildCacheDir(cacheKey: String): File {
|
|
||||||
return File("$cacheDir$cacheKey/")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildSvgaFile(cacheKey: String): File {
|
|
||||||
return File("$cacheDir$cacheKey.svga")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildAudioFile(audio: String): File {
|
|
||||||
return File("$cacheDir$audio.mp3")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/30.
|
|
||||||
*/
|
|
||||||
interface SVGACallback {
|
|
||||||
|
|
||||||
fun onPause()
|
|
||||||
fun onFinished()
|
|
||||||
fun onRepeat()
|
|
||||||
fun onStep(frame: Int, percentage: Double)
|
|
||||||
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by miaojun on 2019/6/21.
|
|
||||||
* mail:1290846731@qq.com
|
|
||||||
*/
|
|
||||||
interface SVGAClickAreaListener{
|
|
||||||
fun onClick(clickKey : String)
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.ColorFilter
|
|
||||||
import android.graphics.PixelFormat
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.widget.ImageView
|
|
||||||
import com.opensource.svgaplayer.drawer.SVGACanvasDrawer
|
|
||||||
|
|
||||||
class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicEntity): Drawable() {
|
|
||||||
|
|
||||||
constructor(videoItem: SVGAVideoEntity): this(videoItem, SVGADynamicEntity())
|
|
||||||
|
|
||||||
var cleared = true
|
|
||||||
internal set (value) {
|
|
||||||
if (field == value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
invalidateSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentFrame = 0
|
|
||||||
internal set (value) {
|
|
||||||
if (field == value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
invalidateSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
var scaleType: ImageView.ScaleType = ImageView.ScaleType.MATRIX
|
|
||||||
|
|
||||||
private val drawer = SVGACanvasDrawer(videoItem, dynamicItem)
|
|
||||||
|
|
||||||
override fun draw(canvas: Canvas?) {
|
|
||||||
if (cleared) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
canvas?.let {
|
|
||||||
drawer.drawFrame(it,currentFrame, scaleType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setAlpha(alpha: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpacity(): Int {
|
|
||||||
return PixelFormat.TRANSPARENT
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setColorFilter(colorFilter: ColorFilter?) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resume() {
|
|
||||||
videoItem.audioList.forEach { audio ->
|
|
||||||
audio.playID?.let {
|
|
||||||
if (SVGASoundManager.isInit()){
|
|
||||||
SVGASoundManager.resume(it)
|
|
||||||
}else{
|
|
||||||
videoItem.soundPool?.resume(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pause() {
|
|
||||||
videoItem.audioList.forEach { audio ->
|
|
||||||
audio.playID?.let {
|
|
||||||
if (SVGASoundManager.isInit()){
|
|
||||||
SVGASoundManager.pause(it)
|
|
||||||
}else{
|
|
||||||
videoItem.soundPool?.pause(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stop() {
|
|
||||||
videoItem.audioList.forEach { audio ->
|
|
||||||
audio.playID?.let {
|
|
||||||
if (SVGASoundManager.isInit()){
|
|
||||||
SVGASoundManager.stop(it)
|
|
||||||
}else{
|
|
||||||
videoItem.soundPool?.stop(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
videoItem.audioList.forEach { audio ->
|
|
||||||
audio.playID?.let {
|
|
||||||
if (SVGASoundManager.isInit()){
|
|
||||||
SVGASoundManager.stop(it)
|
|
||||||
}else{
|
|
||||||
videoItem.soundPool?.stop(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audio.playID = null
|
|
||||||
}
|
|
||||||
videoItem.clear()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,153 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.text.BoringLayout
|
|
||||||
import android.text.StaticLayout
|
|
||||||
import android.text.TextPaint
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/30.
|
|
||||||
*/
|
|
||||||
class SVGADynamicEntity {
|
|
||||||
|
|
||||||
internal var dynamicHidden: HashMap<String, Boolean> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicImage: HashMap<String, Bitmap> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicText: HashMap<String, String> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicTextPaint: HashMap<String, TextPaint> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicStaticLayoutText: HashMap<String, StaticLayout> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicBoringLayoutText: HashMap<String, BoringLayout> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicDrawer: HashMap<String, (canvas: Canvas, frameIndex: Int) -> Boolean> = hashMapOf()
|
|
||||||
|
|
||||||
//点击事件回调map
|
|
||||||
internal var mClickMap : HashMap<String, IntArray> = hashMapOf()
|
|
||||||
internal var dynamicIClickArea: HashMap<String, IClickAreaListener> = hashMapOf()
|
|
||||||
|
|
||||||
internal var dynamicDrawerSized: HashMap<String, (canvas: Canvas, frameIndex: Int, width: Int, height: Int) -> Boolean> = hashMapOf()
|
|
||||||
|
|
||||||
|
|
||||||
internal var isTextDirty = false
|
|
||||||
|
|
||||||
fun setHidden(value: Boolean, forKey: String) {
|
|
||||||
this.dynamicHidden.put(forKey, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicImage(bitmap: Bitmap, forKey: String) {
|
|
||||||
this.dynamicImage.put(forKey, bitmap)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicImage(url: String, forKey: String) {
|
|
||||||
val handler = android.os.Handler()
|
|
||||||
SVGAParser.threadPoolExecutor.execute {
|
|
||||||
(URL(url).openConnection() as? HttpURLConnection)?.let {
|
|
||||||
try {
|
|
||||||
it.connectTimeout = 20 * 1000
|
|
||||||
it.requestMethod = "GET"
|
|
||||||
it.connect()
|
|
||||||
it.inputStream.use { stream ->
|
|
||||||
BitmapFactory.decodeStream(stream)?.let {
|
|
||||||
handler.post { setDynamicImage(it, forKey) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
it.disconnect()
|
|
||||||
} catch (disconnectException: Throwable) {
|
|
||||||
// ignored here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicText(text: String, textPaint: TextPaint, forKey: String) {
|
|
||||||
this.isTextDirty = true
|
|
||||||
this.dynamicText.put(forKey, text)
|
|
||||||
this.dynamicTextPaint.put(forKey, textPaint)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicText(layoutText: StaticLayout, forKey: String) {
|
|
||||||
this.isTextDirty = true
|
|
||||||
this.dynamicStaticLayoutText.put(forKey, layoutText)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicText(layoutText: BoringLayout, forKey: String) {
|
|
||||||
this.isTextDirty = true
|
|
||||||
BoringLayout.isBoring(layoutText.text,layoutText.paint)?.let {
|
|
||||||
this.dynamicBoringLayoutText.put(forKey,layoutText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicDrawer(drawer: (canvas: Canvas, frameIndex: Int) -> Boolean, forKey: String) {
|
|
||||||
this.dynamicDrawer.put(forKey, drawer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setClickArea(clickKey: List<String>) {
|
|
||||||
for(itemKey in clickKey){
|
|
||||||
dynamicIClickArea.put(itemKey,object : IClickAreaListener {
|
|
||||||
override fun onResponseArea(key: String, x0: Int, y0: Int, x1: Int, y1: Int) {
|
|
||||||
mClickMap.let {
|
|
||||||
if(it.get(key) == null){
|
|
||||||
it.put(key, intArrayOf(x0,y0,x1,y1))
|
|
||||||
}else{
|
|
||||||
it.get(key)?.let {
|
|
||||||
it[0] = x0
|
|
||||||
it[1] = y0
|
|
||||||
it[2] = x1
|
|
||||||
it[3] = y1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setClickArea(clickKey: String) {
|
|
||||||
dynamicIClickArea.put(clickKey, object : IClickAreaListener {
|
|
||||||
override fun onResponseArea(key: String, x0: Int, y0: Int, x1: Int, y1: Int) {
|
|
||||||
mClickMap.let {
|
|
||||||
if (it.get(key) == null) {
|
|
||||||
it.put(key, intArrayOf(x0, y0, x1, y1))
|
|
||||||
} else {
|
|
||||||
it.get(key)?.let {
|
|
||||||
it[0] = x0
|
|
||||||
it[1] = y0
|
|
||||||
it[2] = x1
|
|
||||||
it[3] = y1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDynamicDrawerSized(drawer: (canvas: Canvas, frameIndex: Int, width: Int, height: Int) -> Boolean, forKey: String) {
|
|
||||||
this.dynamicDrawerSized.put(forKey, drawer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearDynamicObjects() {
|
|
||||||
this.isTextDirty = true
|
|
||||||
this.dynamicHidden.clear()
|
|
||||||
this.dynamicImage.clear()
|
|
||||||
this.dynamicText.clear()
|
|
||||||
this.dynamicTextPaint.clear()
|
|
||||||
this.dynamicStaticLayoutText.clear()
|
|
||||||
this.dynamicBoringLayoutText.clear()
|
|
||||||
this.dynamicDrawer.clear()
|
|
||||||
this.dynamicIClickArea.clear()
|
|
||||||
this.mClickMap.clear()
|
|
||||||
this.dynamicDrawerSized.clear()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,329 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.animation.Animator
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.view.animation.LinearInterpolator
|
|
||||||
import android.widget.ImageView
|
|
||||||
import com.opensource.svgaplayer.utils.SVGARange
|
|
||||||
import com.opensource.svgaplayer.utils.log.LogUtils
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by PonyCui on 2017/3/29.
|
|
||||||
*/
|
|
||||||
open class SVGAImageView @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : ImageView(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
private val TAG = "SVGAImageView"
|
|
||||||
|
|
||||||
enum class FillMode {
|
|
||||||
Backward,
|
|
||||||
Forward,
|
|
||||||
Clear,
|
|
||||||
}
|
|
||||||
|
|
||||||
var isAnimating = false
|
|
||||||
private set
|
|
||||||
|
|
||||||
var loops = 0
|
|
||||||
|
|
||||||
@Deprecated(
|
|
||||||
"It is recommended to use clearAfterDetached, or manually call to SVGAVideoEntity#clear." +
|
|
||||||
"If you just consider cleaning up the canvas after playing, you can use FillMode#Clear.",
|
|
||||||
level = DeprecationLevel.WARNING
|
|
||||||
)
|
|
||||||
var clearsAfterStop = false
|
|
||||||
var clearsAfterDetached = false
|
|
||||||
var fillMode: FillMode = FillMode.Forward
|
|
||||||
var callback: SVGACallback? = null
|
|
||||||
|
|
||||||
private var mAnimator: ValueAnimator? = null
|
|
||||||
private var mItemClickAreaListener: SVGAClickAreaListener? = null
|
|
||||||
private var mAntiAlias = true
|
|
||||||
private var mAutoPlay = true
|
|
||||||
private val mAnimatorListener = AnimatorListener(this)
|
|
||||||
private val mAnimatorUpdateListener = AnimatorUpdateListener(this)
|
|
||||||
private var mStartFrame = 0
|
|
||||||
private var mEndFrame = 0
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
||||||
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
|
|
||||||
}
|
|
||||||
attrs?.let { loadAttrs(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadAttrs(attrs: AttributeSet) {
|
|
||||||
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.SVGAImageView, 0, 0)
|
|
||||||
loops = typedArray.getInt(R.styleable.SVGAImageView_loopCount, 0)
|
|
||||||
clearsAfterStop = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterStop, false)
|
|
||||||
clearsAfterDetached = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterDetached, false)
|
|
||||||
mAntiAlias = typedArray.getBoolean(R.styleable.SVGAImageView_antiAlias, true)
|
|
||||||
mAutoPlay = typedArray.getBoolean(R.styleable.SVGAImageView_autoPlay, true)
|
|
||||||
typedArray.getString(R.styleable.SVGAImageView_fillMode)?.let {
|
|
||||||
when (it) {
|
|
||||||
"0" -> {
|
|
||||||
fillMode = FillMode.Backward
|
|
||||||
}
|
|
||||||
"1" -> {
|
|
||||||
fillMode = FillMode.Forward
|
|
||||||
}
|
|
||||||
"2" -> {
|
|
||||||
fillMode = FillMode.Clear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedArray.getString(R.styleable.SVGAImageView_source)?.let {
|
|
||||||
parserSource(it)
|
|
||||||
}
|
|
||||||
typedArray.recycle()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parserSource(source: String) {
|
|
||||||
val refImgView = WeakReference<SVGAImageView>(this)
|
|
||||||
val parser = SVGAParser(context)
|
|
||||||
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
||||||
parser.decodeFromURL(URL(source), createParseCompletion(refImgView))
|
|
||||||
} else {
|
|
||||||
parser.decodeFromAssets(source, createParseCompletion(refImgView))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createParseCompletion(ref: WeakReference<SVGAImageView>): SVGAParser.ParseCompletion {
|
|
||||||
return object : SVGAParser.ParseCompletion {
|
|
||||||
override fun onComplete(videoItem: SVGAVideoEntity) {
|
|
||||||
ref.get()?.startAnimation(videoItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startAnimation(videoItem: SVGAVideoEntity) {
|
|
||||||
this@SVGAImageView.post {
|
|
||||||
videoItem.antiAlias = mAntiAlias
|
|
||||||
setVideoItem(videoItem)
|
|
||||||
getSVGADrawable()?.scaleType = scaleType
|
|
||||||
if (mAutoPlay) {
|
|
||||||
startAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startAnimation() {
|
|
||||||
startAnimation(null, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startAnimation(range: SVGARange?, reverse: Boolean = false) {
|
|
||||||
stopAnimation(false)
|
|
||||||
play(range, reverse)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun play(range: SVGARange?, reverse: Boolean) {
|
|
||||||
LogUtils.info(TAG, "================ start animation ================")
|
|
||||||
val drawable = getSVGADrawable() ?: return
|
|
||||||
setupDrawable()
|
|
||||||
mStartFrame = Math.max(0, range?.location ?: 0)
|
|
||||||
val videoItem = drawable.videoItem
|
|
||||||
mEndFrame = Math.min(videoItem.frames - 1, ((range?.location ?: 0) + (range?.length ?: Int.MAX_VALUE) - 1))
|
|
||||||
val animator = ValueAnimator.ofInt(mStartFrame, mEndFrame)
|
|
||||||
animator.interpolator = LinearInterpolator()
|
|
||||||
animator.duration = ((mEndFrame - mStartFrame + 1) * (1000 / videoItem.FPS) / generateScale()).toLong()
|
|
||||||
animator.repeatCount = if (loops <= 0) 99999 else loops - 1
|
|
||||||
animator.addUpdateListener(mAnimatorUpdateListener)
|
|
||||||
animator.addListener(mAnimatorListener)
|
|
||||||
if (reverse) {
|
|
||||||
animator.reverse()
|
|
||||||
} else {
|
|
||||||
animator.start()
|
|
||||||
}
|
|
||||||
mAnimator = animator
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupDrawable() {
|
|
||||||
val drawable = getSVGADrawable() ?: return
|
|
||||||
drawable.cleared = false
|
|
||||||
drawable.scaleType = scaleType
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSVGADrawable(): SVGADrawable? {
|
|
||||||
return drawable as? SVGADrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNNECESSARY_SAFE_CALL")
|
|
||||||
private fun generateScale(): Double {
|
|
||||||
var scale = 1.0
|
|
||||||
try {
|
|
||||||
val animatorClass = Class.forName("android.animation.ValueAnimator") ?: return scale
|
|
||||||
val getMethod = animatorClass.getDeclaredMethod("getDurationScale") ?: return scale
|
|
||||||
scale = (getMethod.invoke(animatorClass) as Float).toDouble()
|
|
||||||
if (scale == 0.0) {
|
|
||||||
val setMethod = animatorClass.getDeclaredMethod("setDurationScale",Float::class.java) ?: return scale
|
|
||||||
setMethod.isAccessible = true
|
|
||||||
setMethod.invoke(animatorClass,1.0f)
|
|
||||||
scale = 1.0
|
|
||||||
LogUtils.info(TAG,
|
|
||||||
"The animation duration scale has been reset to" +
|
|
||||||
" 1.0x, because you closed it on developer options.")
|
|
||||||
}
|
|
||||||
} catch (ignore: Exception) {
|
|
||||||
ignore.printStackTrace()
|
|
||||||
}
|
|
||||||
return scale
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onAnimatorUpdate(animator: ValueAnimator?) {
|
|
||||||
val drawable = getSVGADrawable() ?: return
|
|
||||||
drawable.currentFrame = animator?.animatedValue as Int
|
|
||||||
val percentage = (drawable.currentFrame + 1).toDouble() / drawable.videoItem.frames.toDouble()
|
|
||||||
callback?.onStep(drawable.currentFrame, percentage)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onAnimationEnd(animation: Animator?) {
|
|
||||||
isAnimating = false
|
|
||||||
stopAnimation()
|
|
||||||
val drawable = getSVGADrawable()
|
|
||||||
if (drawable != null) {
|
|
||||||
when (fillMode) {
|
|
||||||
FillMode.Backward -> {
|
|
||||||
drawable.currentFrame = mStartFrame
|
|
||||||
}
|
|
||||||
FillMode.Forward -> {
|
|
||||||
drawable.currentFrame = mEndFrame
|
|
||||||
}
|
|
||||||
FillMode.Clear -> {
|
|
||||||
drawable.cleared = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback?.onFinished()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
getSVGADrawable()?.cleared = true
|
|
||||||
getSVGADrawable()?.clear()
|
|
||||||
// 清除对 drawable 的引用
|
|
||||||
setImageDrawable(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pauseAnimation() {
|
|
||||||
stopAnimation(false)
|
|
||||||
callback?.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stopAnimation() {
|
|
||||||
stopAnimation(clear = clearsAfterStop)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stopAnimation(clear: Boolean) {
|
|
||||||
mAnimator?.cancel()
|
|
||||||
mAnimator?.removeAllListeners()
|
|
||||||
mAnimator?.removeAllUpdateListeners()
|
|
||||||
getSVGADrawable()?.stop()
|
|
||||||
getSVGADrawable()?.cleared = clear
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setVideoItem(videoItem: SVGAVideoEntity?) {
|
|
||||||
setVideoItem(videoItem, SVGADynamicEntity())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setVideoItem(videoItem: SVGAVideoEntity?, dynamicItem: SVGADynamicEntity?) {
|
|
||||||
if (videoItem == null) {
|
|
||||||
setImageDrawable(null)
|
|
||||||
} else {
|
|
||||||
val drawable = SVGADrawable(videoItem, dynamicItem ?: SVGADynamicEntity())
|
|
||||||
drawable.cleared = true
|
|
||||||
setImageDrawable(drawable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stepToFrame(frame: Int, andPlay: Boolean) {
|
|
||||||
pauseAnimation()
|
|
||||||
val drawable = getSVGADrawable() ?: return
|
|
||||||
drawable.currentFrame = frame
|
|
||||||
if (andPlay) {
|
|
||||||
startAnimation()
|
|
||||||
mAnimator?.let {
|
|
||||||
it.currentPlayTime = (Math.max(0.0f, Math.min(1.0f, (frame.toFloat() / drawable.videoItem.frames.toFloat()))) * it.duration).toLong()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stepToPercentage(percentage: Double, andPlay: Boolean) {
|
|
||||||
val drawable = drawable as? SVGADrawable ?: return
|
|
||||||
var frame = (drawable.videoItem.frames * percentage).toInt()
|
|
||||||
if (frame >= drawable.videoItem.frames && frame > 0) {
|
|
||||||
frame = drawable.videoItem.frames - 1
|
|
||||||
}
|
|
||||||
stepToFrame(frame, andPlay)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnAnimKeyClickListener(clickListener : SVGAClickAreaListener){
|
|
||||||
mItemClickAreaListener = clickListener
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
|
||||||
if (event?.action != MotionEvent.ACTION_DOWN) {
|
|
||||||
return super.onTouchEvent(event)
|
|
||||||
}
|
|
||||||
val drawable = getSVGADrawable() ?: return super.onTouchEvent(event)
|
|
||||||
for ((key, value) in drawable.dynamicItem.mClickMap) {
|
|
||||||
if (event.x >= value[0] && event.x <= value[2] && event.y >= value[1] && event.y <= value[3]) {
|
|
||||||
mItemClickAreaListener?.let {
|
|
||||||
it.onClick(key)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onTouchEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromWindow() {
|
|
||||||
super.onDetachedFromWindow()
|
|
||||||
stopAnimation(clearsAfterDetached)
|
|
||||||
if (clearsAfterDetached) {
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener {
|
|
||||||
private val weakReference = WeakReference<SVGAImageView>(view)
|
|
||||||
|
|
||||||
override fun onAnimationRepeat(animation: Animator?) {
|
|
||||||
weakReference.get()?.callback?.onRepeat()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAnimationEnd(animation: Animator?) {
|
|
||||||
weakReference.get()?.onAnimationEnd(animation)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAnimationCancel(animation: Animator?) {
|
|
||||||
weakReference.get()?.isAnimating = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
|
||||||
weakReference.get()?.isAnimating = true
|
|
||||||
}
|
|
||||||
} // end of AnimatorListener
|
|
||||||
|
|
||||||
|
|
||||||
private class AnimatorUpdateListener(view: SVGAImageView) : ValueAnimator.AnimatorUpdateListener {
|
|
||||||
private val weakReference = WeakReference<SVGAImageView>(view)
|
|
||||||
|
|
||||||
override fun onAnimationUpdate(animation: ValueAnimator?) {
|
|
||||||
weakReference.get()?.onAnimatorUpdate(animation)
|
|
||||||
}
|
|
||||||
} // end of AnimatorUpdateListener
|
|
||||||
}
|
|
@ -1,565 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.http.HttpResponseCache
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import com.opensource.svgaplayer.proto.MovieEntity
|
|
||||||
import com.opensource.svgaplayer.utils.log.LogUtils
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.io.*
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URL
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
import java.util.zip.Inflater
|
|
||||||
import java.util.zip.ZipInputStream
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by PonyCui 16/6/18.
|
|
||||||
*/
|
|
||||||
private var fileLock: Int = 0
|
|
||||||
private var isUnzipping = false
|
|
||||||
|
|
||||||
class SVGAParser(context: Context?) {
|
|
||||||
private var mContext = context?.applicationContext
|
|
||||||
|
|
||||||
init {
|
|
||||||
SVGACache.onCreate(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var mFrameWidth: Int = 0
|
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var mFrameHeight: Int = 0
|
|
||||||
|
|
||||||
interface ParseCompletion {
|
|
||||||
fun onComplete(videoItem: SVGAVideoEntity)
|
|
||||||
fun onError()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PlayCallback{
|
|
||||||
fun onPlay(file: List<File>)
|
|
||||||
}
|
|
||||||
|
|
||||||
open class FileDownloader {
|
|
||||||
|
|
||||||
var noCache = false
|
|
||||||
|
|
||||||
open fun resume(url: URL, complete: (inputStream: InputStream) -> Unit, failure: (e: Exception) -> Unit): () -> Unit {
|
|
||||||
var cancelled = false
|
|
||||||
val cancelBlock = {
|
|
||||||
cancelled = true
|
|
||||||
}
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
try {
|
|
||||||
LogUtils.info(TAG, "================ svga file download start ================")
|
|
||||||
if (HttpResponseCache.getInstalled() == null && !noCache) {
|
|
||||||
LogUtils.error(TAG, "SVGAParser can not handle cache before install HttpResponseCache. see https://github.com/yyued/SVGAPlayer-Android#cache")
|
|
||||||
LogUtils.error(TAG, "在配置 HttpResponseCache 前 SVGAParser 无法缓存. 查看 https://github.com/yyued/SVGAPlayer-Android#cache ")
|
|
||||||
}
|
|
||||||
(url.openConnection() as? HttpURLConnection)?.let {
|
|
||||||
it.connectTimeout = 20 * 1000
|
|
||||||
it.requestMethod = "GET"
|
|
||||||
it.setRequestProperty("Connection", "close")
|
|
||||||
it.connect()
|
|
||||||
it.inputStream.use { inputStream ->
|
|
||||||
ByteArrayOutputStream().use { outputStream ->
|
|
||||||
val buffer = ByteArray(4096)
|
|
||||||
var count: Int
|
|
||||||
while (true) {
|
|
||||||
if (cancelled) {
|
|
||||||
LogUtils.warn(TAG, "================ svga file download canceled ================")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
count = inputStream.read(buffer, 0, 4096)
|
|
||||||
if (count == -1) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
outputStream.write(buffer, 0, count)
|
|
||||||
}
|
|
||||||
if (cancelled) {
|
|
||||||
LogUtils.warn(TAG, "================ svga file download canceled ================")
|
|
||||||
return@execute
|
|
||||||
}
|
|
||||||
ByteArrayInputStream(outputStream.toByteArray()).use {
|
|
||||||
LogUtils.info(TAG, "================ svga file download complete ================")
|
|
||||||
complete(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "================ svga file download fail ================")
|
|
||||||
LogUtils.error(TAG, "error: ${e.message}")
|
|
||||||
e.printStackTrace()
|
|
||||||
failure(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cancelBlock
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDownloader = FileDownloader()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "SVGAParser"
|
|
||||||
|
|
||||||
private val threadNum = AtomicInteger(0)
|
|
||||||
private var mShareParser = SVGAParser(null)
|
|
||||||
|
|
||||||
internal var threadPoolExecutor = Executors.newCachedThreadPool { r ->
|
|
||||||
Thread(r, "SVGAParser-Thread-${threadNum.getAndIncrement()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setThreadPoolExecutor(executor: ThreadPoolExecutor) {
|
|
||||||
threadPoolExecutor = executor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shareParser(): SVGAParser {
|
|
||||||
return mShareParser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun init(context: Context) {
|
|
||||||
mContext = context.applicationContext
|
|
||||||
SVGACache.onCreate(mContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setFrameSize(frameWidth: Int, frameHeight: Int) {
|
|
||||||
mFrameWidth = frameWidth
|
|
||||||
mFrameHeight = frameHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decodeFromAssets(
|
|
||||||
name: String,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
playCallback: PlayCallback? = null
|
|
||||||
) {
|
|
||||||
if (mContext == null) {
|
|
||||||
LogUtils.error(TAG, "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LogUtils.info(TAG, "================ decode $name from assets ================")
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
try {
|
|
||||||
mContext?.assets?.open(name)?.let {
|
|
||||||
this.decodeFromInputStream(
|
|
||||||
it,
|
|
||||||
SVGACache.buildCacheKey("file:///assets/$name"),
|
|
||||||
callback,
|
|
||||||
true,
|
|
||||||
playCallback,
|
|
||||||
alias = name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
this.invokeErrorCallback(e, callback, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decodeFromURL(
|
|
||||||
url: URL,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
playCallback: PlayCallback? = null
|
|
||||||
): (() -> Unit)? {
|
|
||||||
if (mContext == null) {
|
|
||||||
LogUtils.error(TAG, "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val urlPath = url.toString()
|
|
||||||
LogUtils.info(TAG, "================ decode from url: $urlPath ================")
|
|
||||||
val cacheKey = SVGACache.buildCacheKey(url);
|
|
||||||
return if (SVGACache.isCached(cacheKey)) {
|
|
||||||
LogUtils.info(TAG, "this url cached")
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
if (SVGACache.isDefaultCache()) {
|
|
||||||
this.decodeFromCacheKey(cacheKey, callback, alias = urlPath)
|
|
||||||
} else {
|
|
||||||
this.decodeFromSVGAFileCacheKey(cacheKey, callback, playCallback, alias = urlPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
} else {
|
|
||||||
LogUtils.info(TAG, "no cached, prepare to download")
|
|
||||||
fileDownloader.resume(url, {
|
|
||||||
this.decodeFromInputStream(
|
|
||||||
it,
|
|
||||||
cacheKey,
|
|
||||||
callback,
|
|
||||||
false,
|
|
||||||
playCallback,
|
|
||||||
alias = urlPath
|
|
||||||
)
|
|
||||||
}, {
|
|
||||||
LogUtils.error(
|
|
||||||
TAG,
|
|
||||||
"================ svga file: $url download fail ================"
|
|
||||||
)
|
|
||||||
this.invokeErrorCallback(it, callback, alias = urlPath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取解析本地缓存的 svga 文件.
|
|
||||||
*/
|
|
||||||
fun decodeFromSVGAFileCacheKey(
|
|
||||||
cacheKey: String,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
playCallback: PlayCallback?,
|
|
||||||
alias: String? = null
|
|
||||||
) {
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
try {
|
|
||||||
LogUtils.info(TAG, "================ decode $alias from svga cachel file to entity ================")
|
|
||||||
FileInputStream(SVGACache.buildSvgaFile(cacheKey)).use { inputStream ->
|
|
||||||
readAsBytes(inputStream)?.let { bytes ->
|
|
||||||
if (isZipFile(bytes)) {
|
|
||||||
this.decodeFromCacheKey(cacheKey, callback, alias)
|
|
||||||
} else {
|
|
||||||
LogUtils.info(TAG, "inflate start")
|
|
||||||
inflate(bytes)?.let {
|
|
||||||
LogUtils.info(TAG, "inflate complete")
|
|
||||||
val videoItem = SVGAVideoEntity(
|
|
||||||
MovieEntity.ADAPTER.decode(it),
|
|
||||||
File(cacheKey),
|
|
||||||
mFrameWidth,
|
|
||||||
mFrameHeight
|
|
||||||
)
|
|
||||||
LogUtils.info(TAG, "SVGAVideoEntity prepare start")
|
|
||||||
videoItem.prepare({
|
|
||||||
LogUtils.info(TAG, "SVGAVideoEntity prepare success")
|
|
||||||
this.invokeCompleteCallback(videoItem, callback, alias)
|
|
||||||
},playCallback)
|
|
||||||
|
|
||||||
} ?: this.invokeErrorCallback(
|
|
||||||
Exception("inflate(bytes) cause exception"),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} ?: this.invokeErrorCallback(
|
|
||||||
Exception("readAsBytes(inputStream) cause exception"),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e: java.lang.Exception) {
|
|
||||||
this.invokeErrorCallback(e, callback, alias)
|
|
||||||
} finally {
|
|
||||||
LogUtils.info(TAG, "================ decode $alias from svga cachel file to entity end ================")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decodeFromInputStream(
|
|
||||||
inputStream: InputStream,
|
|
||||||
cacheKey: String,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
closeInputStream: Boolean = false,
|
|
||||||
playCallback: PlayCallback? = null,
|
|
||||||
alias: String? = null
|
|
||||||
) {
|
|
||||||
if (mContext == null) {
|
|
||||||
LogUtils.error(TAG, "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LogUtils.info(TAG, "================ decode $alias from input stream ================")
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
try {
|
|
||||||
readAsBytes(inputStream)?.let { bytes ->
|
|
||||||
if (isZipFile(bytes)) {
|
|
||||||
LogUtils.info(TAG, "decode from zip file")
|
|
||||||
if (!SVGACache.buildCacheDir(cacheKey).exists() || isUnzipping) {
|
|
||||||
synchronized(fileLock) {
|
|
||||||
if (!SVGACache.buildCacheDir(cacheKey).exists()) {
|
|
||||||
isUnzipping = true
|
|
||||||
LogUtils.info(TAG, "no cached, prepare to unzip")
|
|
||||||
ByteArrayInputStream(bytes).use {
|
|
||||||
unzip(it, cacheKey)
|
|
||||||
isUnzipping = false
|
|
||||||
LogUtils.info(TAG, "unzip success")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.decodeFromCacheKey(cacheKey, callback, alias)
|
|
||||||
} else {
|
|
||||||
if (!SVGACache.isDefaultCache()) {
|
|
||||||
// 如果 SVGACache 设置类型为 FILE
|
|
||||||
threadPoolExecutor.execute {
|
|
||||||
SVGACache.buildSvgaFile(cacheKey).let { cacheFile ->
|
|
||||||
try {
|
|
||||||
cacheFile.takeIf { !it.exists() }?.createNewFile()
|
|
||||||
FileOutputStream(cacheFile).write(bytes)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "create cache file fail.", e)
|
|
||||||
cacheFile.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogUtils.info(TAG, "inflate start")
|
|
||||||
inflate(bytes)?.let {
|
|
||||||
LogUtils.info(TAG, "inflate complete")
|
|
||||||
val videoItem = SVGAVideoEntity(
|
|
||||||
MovieEntity.ADAPTER.decode(it),
|
|
||||||
File(cacheKey),
|
|
||||||
mFrameWidth,
|
|
||||||
mFrameHeight
|
|
||||||
)
|
|
||||||
LogUtils.info(TAG, "SVGAVideoEntity prepare start")
|
|
||||||
videoItem.prepare({
|
|
||||||
LogUtils.info(TAG, "SVGAVideoEntity prepare success")
|
|
||||||
this.invokeCompleteCallback(videoItem, callback, alias)
|
|
||||||
},playCallback)
|
|
||||||
|
|
||||||
} ?: this.invokeErrorCallback(
|
|
||||||
Exception("inflate(bytes) cause exception"),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} ?: this.invokeErrorCallback(
|
|
||||||
Exception("readAsBytes(inputStream) cause exception"),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
} catch (e: java.lang.Exception) {
|
|
||||||
this.invokeErrorCallback(e, callback, alias)
|
|
||||||
} finally {
|
|
||||||
if (closeInputStream) {
|
|
||||||
inputStream.close()
|
|
||||||
}
|
|
||||||
LogUtils.info(TAG, "================ decode $alias from input stream end ================")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated from 2.4.0
|
|
||||||
*/
|
|
||||||
@Deprecated("This method has been deprecated from 2.4.0.", ReplaceWith("this.decodeFromAssets(assetsName, callback)"))
|
|
||||||
fun parse(assetsName: String, callback: ParseCompletion?) {
|
|
||||||
this.decodeFromAssets(assetsName, callback,null)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated from 2.4.0
|
|
||||||
*/
|
|
||||||
@Deprecated("This method has been deprecated from 2.4.0.", ReplaceWith("this.decodeFromURL(url, callback)"))
|
|
||||||
fun parse(url: URL, callback: ParseCompletion?) {
|
|
||||||
this.decodeFromURL(url, callback,null)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated from 2.4.0
|
|
||||||
*/
|
|
||||||
@Deprecated("This method has been deprecated from 2.4.0.", ReplaceWith("this.decodeFromInputStream(inputStream, cacheKey, callback, closeInputStream)"))
|
|
||||||
fun parse(
|
|
||||||
inputStream: InputStream,
|
|
||||||
cacheKey: String,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
closeInputStream: Boolean = false
|
|
||||||
) {
|
|
||||||
this.decodeFromInputStream(inputStream, cacheKey, callback, closeInputStream,null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invokeCompleteCallback(
|
|
||||||
videoItem: SVGAVideoEntity,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
alias: String?
|
|
||||||
) {
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
LogUtils.info(TAG, "================ $alias parser complete ================")
|
|
||||||
callback?.onComplete(videoItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invokeErrorCallback(
|
|
||||||
e: Exception,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
alias: String?
|
|
||||||
) {
|
|
||||||
e.printStackTrace()
|
|
||||||
LogUtils.error(TAG, "================ $alias parser error ================")
|
|
||||||
LogUtils.error(TAG, "$alias parse error", e)
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
callback?.onError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun decodeFromCacheKey(
|
|
||||||
cacheKey: String,
|
|
||||||
callback: ParseCompletion?,
|
|
||||||
alias: String?
|
|
||||||
) {
|
|
||||||
LogUtils.info(TAG, "================ decode $alias from cache ================")
|
|
||||||
LogUtils.debug(TAG, "decodeFromCacheKey called with cacheKey : $cacheKey")
|
|
||||||
if (mContext == null) {
|
|
||||||
LogUtils.error(TAG, "在配置 SVGAParser context 前, 无法解析 SVGA 文件。")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
val cacheDir = SVGACache.buildCacheDir(cacheKey)
|
|
||||||
File(cacheDir, "movie.binary").takeIf { it.isFile }?.let { binaryFile ->
|
|
||||||
try {
|
|
||||||
LogUtils.info(TAG, "binary change to entity")
|
|
||||||
FileInputStream(binaryFile).use {
|
|
||||||
LogUtils.info(TAG, "binary change to entity success")
|
|
||||||
this.invokeCompleteCallback(
|
|
||||||
SVGAVideoEntity(
|
|
||||||
MovieEntity.ADAPTER.decode(it),
|
|
||||||
cacheDir,
|
|
||||||
mFrameWidth,
|
|
||||||
mFrameHeight
|
|
||||||
),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "binary change to entity fail", e)
|
|
||||||
cacheDir.delete()
|
|
||||||
binaryFile.delete()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File(cacheDir, "movie.spec").takeIf { it.isFile }?.let { jsonFile ->
|
|
||||||
try {
|
|
||||||
LogUtils.info(TAG, "spec change to entity")
|
|
||||||
FileInputStream(jsonFile).use { fileInputStream ->
|
|
||||||
ByteArrayOutputStream().use { byteArrayOutputStream ->
|
|
||||||
val buffer = ByteArray(2048)
|
|
||||||
while (true) {
|
|
||||||
val size = fileInputStream.read(buffer, 0, buffer.size)
|
|
||||||
if (size == -1) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
byteArrayOutputStream.write(buffer, 0, size)
|
|
||||||
}
|
|
||||||
byteArrayOutputStream.toString().let {
|
|
||||||
JSONObject(it).let {
|
|
||||||
LogUtils.info(TAG, "spec change to entity success")
|
|
||||||
this.invokeCompleteCallback(
|
|
||||||
SVGAVideoEntity(
|
|
||||||
it,
|
|
||||||
cacheDir,
|
|
||||||
mFrameWidth,
|
|
||||||
mFrameHeight
|
|
||||||
),
|
|
||||||
callback,
|
|
||||||
alias
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "$alias movie.spec change to entity fail", e)
|
|
||||||
cacheDir.delete()
|
|
||||||
jsonFile.delete()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
this.invokeErrorCallback(e, callback, alias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readAsBytes(inputStream: InputStream): ByteArray? {
|
|
||||||
ByteArrayOutputStream().use { byteArrayOutputStream ->
|
|
||||||
val byteArray = ByteArray(2048)
|
|
||||||
while (true) {
|
|
||||||
val count = inputStream.read(byteArray, 0, 2048)
|
|
||||||
if (count <= 0) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
byteArrayOutputStream.write(byteArray, 0, count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return byteArrayOutputStream.toByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun inflate(byteArray: ByteArray): ByteArray? {
|
|
||||||
val inflater = Inflater()
|
|
||||||
inflater.setInput(byteArray, 0, byteArray.size)
|
|
||||||
val inflatedBytes = ByteArray(2048)
|
|
||||||
ByteArrayOutputStream().use { inflatedOutputStream ->
|
|
||||||
while (true) {
|
|
||||||
val count = inflater.inflate(inflatedBytes, 0, 2048)
|
|
||||||
if (count <= 0) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
inflatedOutputStream.write(inflatedBytes, 0, count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inflater.end()
|
|
||||||
return inflatedOutputStream.toByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否是 zip 文件
|
|
||||||
private fun isZipFile(bytes: ByteArray): Boolean {
|
|
||||||
return bytes.size > 4 && bytes[0].toInt() == 80 && bytes[1].toInt() == 75 && bytes[2].toInt() == 3 && bytes[3].toInt() == 4
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解压
|
|
||||||
private fun unzip(inputStream: InputStream, cacheKey: String) {
|
|
||||||
LogUtils.info(TAG, "================ unzip prepare ================")
|
|
||||||
val cacheDir = SVGACache.buildCacheDir(cacheKey)
|
|
||||||
cacheDir.mkdirs()
|
|
||||||
try {
|
|
||||||
BufferedInputStream(inputStream).use {
|
|
||||||
ZipInputStream(it).use { zipInputStream ->
|
|
||||||
while (true) {
|
|
||||||
val zipItem = zipInputStream.nextEntry ?: break
|
|
||||||
if (zipItem.name.contains("../")) {
|
|
||||||
// 解压路径存在路径穿越问题,直接过滤
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (zipItem.name.contains("/")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val file = File(cacheDir, zipItem.name)
|
|
||||||
ensureUnzipSafety(file, cacheDir.absolutePath)
|
|
||||||
FileOutputStream(file).use { fileOutputStream ->
|
|
||||||
val buff = ByteArray(2048)
|
|
||||||
while (true) {
|
|
||||||
val readBytes = zipInputStream.read(buff)
|
|
||||||
if (readBytes <= 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fileOutputStream.write(buff, 0, readBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogUtils.error(TAG, "================ unzip complete ================")
|
|
||||||
zipInputStream.closeEntry()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, "================ unzip error ================")
|
|
||||||
LogUtils.error(TAG, "error", e)
|
|
||||||
SVGACache.clearDir(cacheDir.absolutePath)
|
|
||||||
cacheDir.delete()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 zip 路径穿透
|
|
||||||
private fun ensureUnzipSafety(outputFile: File, dstDirPath: String) {
|
|
||||||
val dstDirCanonicalPath = File(dstDirPath).canonicalPath
|
|
||||||
val outputFileCanonicalPath = outputFile.canonicalPath
|
|
||||||
if (!outputFileCanonicalPath.startsWith(dstDirCanonicalPath)) {
|
|
||||||
throw IOException("Found Zip Path Traversal Vulnerability with $dstDirCanonicalPath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/30.
|
|
||||||
* @deprecated from 2.4.0
|
|
||||||
*/
|
|
||||||
@Deprecated("This class has been deprecated from 2.4.0. We don't recommend you to use it.")
|
|
||||||
class SVGAPlayer: SVGAImageView {
|
|
||||||
|
|
||||||
constructor(context: Context) : super(context) {}
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
|
|
||||||
|
|
||||||
}
|
|
@ -1,194 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Devin
|
|
||||||
*
|
|
||||||
* Created on 2/24/21.
|
|
||||||
*/
|
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.AudioManager
|
|
||||||
import android.media.SoundPool
|
|
||||||
import android.os.Build
|
|
||||||
import com.opensource.svgaplayer.utils.log.LogUtils
|
|
||||||
import java.io.FileDescriptor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Author : llk
|
|
||||||
* Time : 2020/10/24
|
|
||||||
* Description : svga 音频加载管理类
|
|
||||||
* 将 SoundPool 抽取到单例里边,规避 load 资源之后不回调 onLoadComplete 的问题。
|
|
||||||
*
|
|
||||||
* 需要对 SVGASoundManager 进行初始化
|
|
||||||
*
|
|
||||||
* 相关文章:Android SoundPool 崩溃问题研究
|
|
||||||
* https://zhuanlan.zhihu.com/p/29985198
|
|
||||||
*/
|
|
||||||
object SVGASoundManager {
|
|
||||||
|
|
||||||
private val TAG = SVGASoundManager::class.java.simpleName
|
|
||||||
|
|
||||||
private var soundPool: SoundPool? = null
|
|
||||||
|
|
||||||
private val soundCallBackMap: MutableMap<Int, SVGASoundCallBack> = mutableMapOf()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音量设置,范围在 [0, 1] 之间
|
|
||||||
*/
|
|
||||||
private var volume: Float = 1f
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频回调
|
|
||||||
*/
|
|
||||||
internal interface SVGASoundCallBack {
|
|
||||||
|
|
||||||
// 音量发生变化
|
|
||||||
fun onVolumeChange(value: Float)
|
|
||||||
|
|
||||||
// 音频加载完成
|
|
||||||
fun onComplete()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun init() {
|
|
||||||
init(20)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun init(maxStreams: Int) {
|
|
||||||
LogUtils.debug(TAG, "**************** init **************** $maxStreams")
|
|
||||||
if (soundPool != null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
soundPool = getSoundPool(maxStreams)
|
|
||||||
soundPool?.setOnLoadCompleteListener { _, soundId, status ->
|
|
||||||
LogUtils.debug(TAG, "SoundPool onLoadComplete soundId=$soundId status=$status")
|
|
||||||
if (status == 0) { //加载该声音成功
|
|
||||||
if (soundCallBackMap.containsKey(soundId)) {
|
|
||||||
soundCallBackMap[soundId]?.onComplete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun release() {
|
|
||||||
LogUtils.debug(TAG, "**************** release ****************")
|
|
||||||
if (soundCallBackMap.isNotEmpty()) {
|
|
||||||
soundCallBackMap.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据当前播放实体,设置音量
|
|
||||||
*
|
|
||||||
* @param volume 范围在 [0, 1]
|
|
||||||
* @param entity 根据需要控制对应 entity 音量大小,若为空则控制所有正在播放的音频音量
|
|
||||||
*/
|
|
||||||
fun setVolume(volume: Float, entity: SVGAVideoEntity? = null) {
|
|
||||||
if (!checkInit()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (volume < 0f || volume > 1f) {
|
|
||||||
LogUtils.error(TAG, "The volume level is in the range of 0 to 1 ")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == null) {
|
|
||||||
this.volume = volume
|
|
||||||
val iterator = soundCallBackMap.entries.iterator()
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val e = iterator.next()
|
|
||||||
e.value.onVolumeChange(volume)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val soundPool = soundPool ?: return
|
|
||||||
|
|
||||||
entity.audioList.forEach { audio ->
|
|
||||||
val streamId = audio.playID ?: return
|
|
||||||
soundPool.setVolume(streamId, volume, volume)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否初始化
|
|
||||||
* 如果没有初始化,就使用原来SvgaPlayer库的音频加载逻辑。
|
|
||||||
* @return true 则已初始化, 否则为 false
|
|
||||||
*/
|
|
||||||
internal fun isInit(): Boolean {
|
|
||||||
return soundPool != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkInit(): Boolean {
|
|
||||||
val isInit = isInit()
|
|
||||||
if (!isInit) {
|
|
||||||
LogUtils.error(TAG, "soundPool is null, you need call init() !!!")
|
|
||||||
}
|
|
||||||
return isInit
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSoundPool(maxStreams: Int) = if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
val attributes = AudioAttributes.Builder()
|
|
||||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
|
||||||
.build()
|
|
||||||
SoundPool.Builder().setAudioAttributes(attributes)
|
|
||||||
.setMaxStreams(maxStreams)
|
|
||||||
.build()
|
|
||||||
} else {
|
|
||||||
SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun load(callBack: SVGASoundCallBack?,
|
|
||||||
fd: FileDescriptor?,
|
|
||||||
offset: Long,
|
|
||||||
length: Long,
|
|
||||||
priority: Int): Int {
|
|
||||||
if (!checkInit()) return -1
|
|
||||||
|
|
||||||
val soundId = soundPool!!.load(fd, offset, length, priority)
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "load soundId=$soundId callBack=$callBack")
|
|
||||||
|
|
||||||
if (callBack != null && !soundCallBackMap.containsKey(soundId)) {
|
|
||||||
soundCallBackMap[soundId] = callBack
|
|
||||||
}
|
|
||||||
return soundId
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unload(soundId: Int) {
|
|
||||||
if (!checkInit()) return
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "unload soundId=$soundId")
|
|
||||||
|
|
||||||
soundPool!!.unload(soundId)
|
|
||||||
|
|
||||||
soundCallBackMap.remove(soundId)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun play(soundId: Int): Int {
|
|
||||||
if (!checkInit()) return -1
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "play soundId=$soundId")
|
|
||||||
return soundPool!!.play(soundId, volume, volume, 1, 0, 1.0f)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun stop(soundId: Int) {
|
|
||||||
if (!checkInit()) return
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "stop soundId=$soundId")
|
|
||||||
soundPool!!.stop(soundId)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun resume(soundId: Int) {
|
|
||||||
if (!checkInit()) return
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "stop soundId=$soundId")
|
|
||||||
soundPool!!.resume(soundId)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun pause(soundId: Int) {
|
|
||||||
if (!checkInit()) return
|
|
||||||
|
|
||||||
LogUtils.debug(TAG, "pause soundId=$soundId")
|
|
||||||
soundPool!!.pause(soundId)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,347 +0,0 @@
|
|||||||
package com.opensource.svgaplayer
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.AudioManager
|
|
||||||
import android.media.SoundPool
|
|
||||||
import android.os.Build
|
|
||||||
import com.opensource.svgaplayer.bitmap.SVGABitmapByteArrayDecoder
|
|
||||||
import com.opensource.svgaplayer.bitmap.SVGABitmapFileDecoder
|
|
||||||
import com.opensource.svgaplayer.entities.SVGAAudioEntity
|
|
||||||
import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity
|
|
||||||
import com.opensource.svgaplayer.proto.AudioEntity
|
|
||||||
import com.opensource.svgaplayer.proto.MovieEntity
|
|
||||||
import com.opensource.svgaplayer.proto.MovieParams
|
|
||||||
import com.opensource.svgaplayer.utils.SVGARect
|
|
||||||
import com.opensource.svgaplayer.utils.log.LogUtils
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by PonyCui on 16/6/18.
|
|
||||||
*/
|
|
||||||
class SVGAVideoEntity {
|
|
||||||
|
|
||||||
private val TAG = "SVGAVideoEntity"
|
|
||||||
|
|
||||||
var antiAlias = true
|
|
||||||
var movieItem: MovieEntity? = null
|
|
||||||
|
|
||||||
var videoSize = SVGARect(0.0, 0.0, 0.0, 0.0)
|
|
||||||
private set
|
|
||||||
|
|
||||||
var FPS = 15
|
|
||||||
private set
|
|
||||||
|
|
||||||
var frames: Int = 0
|
|
||||||
private set
|
|
||||||
|
|
||||||
internal var spriteList: List<SVGAVideoSpriteEntity> = emptyList()
|
|
||||||
internal var audioList: List<SVGAAudioEntity> = emptyList()
|
|
||||||
internal var soundPool: SoundPool? = null
|
|
||||||
private var soundCallback: SVGASoundManager.SVGASoundCallBack? = null
|
|
||||||
internal var imageMap = HashMap<String, Bitmap>()
|
|
||||||
private var mCacheDir: File
|
|
||||||
private var mFrameHeight = 0
|
|
||||||
private var mFrameWidth = 0
|
|
||||||
private var mPlayCallback: SVGAParser.PlayCallback?=null
|
|
||||||
private lateinit var mCallback: () -> Unit
|
|
||||||
|
|
||||||
constructor(json: JSONObject, cacheDir: File) : this(json, cacheDir, 0, 0)
|
|
||||||
|
|
||||||
constructor(json: JSONObject, cacheDir: File, frameWidth: Int, frameHeight: Int) {
|
|
||||||
mFrameWidth = frameWidth
|
|
||||||
mFrameHeight = frameHeight
|
|
||||||
mCacheDir = cacheDir
|
|
||||||
val movieJsonObject = json.optJSONObject("movie") ?: return
|
|
||||||
setupByJson(movieJsonObject)
|
|
||||||
try {
|
|
||||||
parserImages(json)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
resetSprites(json)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupByJson(movieObject: JSONObject) {
|
|
||||||
movieObject.optJSONObject("viewBox")?.let { viewBoxObject ->
|
|
||||||
val width = viewBoxObject.optDouble("width", 0.0)
|
|
||||||
val height = viewBoxObject.optDouble("height", 0.0)
|
|
||||||
videoSize = SVGARect(0.0, 0.0, width, height)
|
|
||||||
}
|
|
||||||
FPS = movieObject.optInt("fps", 20)
|
|
||||||
frames = movieObject.optInt("frames", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(entity: MovieEntity, cacheDir: File) : this(entity, cacheDir, 0, 0)
|
|
||||||
|
|
||||||
constructor(entity: MovieEntity, cacheDir: File, frameWidth: Int, frameHeight: Int) {
|
|
||||||
this.mFrameWidth = frameWidth
|
|
||||||
this.mFrameHeight = frameHeight
|
|
||||||
this.mCacheDir = cacheDir
|
|
||||||
this.movieItem = entity
|
|
||||||
entity.params?.let(this::setupByMovie)
|
|
||||||
try {
|
|
||||||
parserImages(entity)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
resetSprites(entity)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupByMovie(movieParams: MovieParams) {
|
|
||||||
val width = (movieParams.viewBoxWidth ?: 0.0f).toDouble()
|
|
||||||
val height = (movieParams.viewBoxHeight ?: 0.0f).toDouble()
|
|
||||||
videoSize = SVGARect(0.0, 0.0, width, height)
|
|
||||||
FPS = movieParams.fps ?: 20
|
|
||||||
frames = movieParams.frames ?: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun prepare(callback: () -> Unit, playCallback: SVGAParser.PlayCallback?) {
|
|
||||||
mCallback = callback
|
|
||||||
mPlayCallback = playCallback
|
|
||||||
if (movieItem == null) {
|
|
||||||
mCallback()
|
|
||||||
} else {
|
|
||||||
setupAudios(movieItem!!) {
|
|
||||||
mCallback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parserImages(json: JSONObject) {
|
|
||||||
val imgJson = json.optJSONObject("images") ?: return
|
|
||||||
imgJson.keys().forEach { imgKey ->
|
|
||||||
val filePath = generateBitmapFilePath(imgJson[imgKey].toString(), imgKey)
|
|
||||||
if (filePath.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val bitmapKey = imgKey.replace(".matte", "")
|
|
||||||
val bitmap = createBitmap(filePath)
|
|
||||||
if (bitmap != null) {
|
|
||||||
imageMap[bitmapKey] = bitmap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateBitmapFilePath(imgName: String, imgKey: String): String {
|
|
||||||
val path = mCacheDir.absolutePath + "/" + imgName
|
|
||||||
val path1 = "$path.png"
|
|
||||||
val path2 = mCacheDir.absolutePath + "/" + imgKey + ".png"
|
|
||||||
|
|
||||||
return when {
|
|
||||||
File(path).exists() -> path
|
|
||||||
File(path1).exists() -> path1
|
|
||||||
File(path2).exists() -> path2
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createBitmap(filePath: String): Bitmap? {
|
|
||||||
return SVGABitmapFileDecoder.decodeBitmapFrom(filePath, mFrameWidth, mFrameHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parserImages(obj: MovieEntity) {
|
|
||||||
obj.images?.entries?.forEach { entry ->
|
|
||||||
val byteArray = entry.value.toByteArray()
|
|
||||||
if (byteArray.count() < 4) {
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
val fileTag = byteArray.slice(IntRange(0, 3))
|
|
||||||
if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) {
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key)
|
|
||||||
createBitmap(byteArray, filePath)?.let { bitmap ->
|
|
||||||
imageMap[entry.key] = bitmap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? {
|
|
||||||
val bitmap = SVGABitmapByteArrayDecoder.decodeBitmapFrom(byteArray, mFrameWidth, mFrameHeight)
|
|
||||||
return bitmap ?: createBitmap(filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetSprites(json: JSONObject) {
|
|
||||||
val mutableList: MutableList<SVGAVideoSpriteEntity> = mutableListOf()
|
|
||||||
json.optJSONArray("sprites")?.let { item ->
|
|
||||||
for (i in 0 until item.length()) {
|
|
||||||
item.optJSONObject(i)?.let { entryJson ->
|
|
||||||
mutableList.add(SVGAVideoSpriteEntity(entryJson))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spriteList = mutableList.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetSprites(entity: MovieEntity) {
|
|
||||||
spriteList = entity.sprites?.map {
|
|
||||||
return@map SVGAVideoSpriteEntity(it)
|
|
||||||
} ?: listOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupAudios(entity: MovieEntity, completionBlock: () -> Unit) {
|
|
||||||
if (entity.audios == null || entity.audios.isEmpty()) {
|
|
||||||
run(completionBlock)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setupSoundPool(entity, completionBlock)
|
|
||||||
val audiosFileMap = generateAudioFileMap(entity)
|
|
||||||
//repair when audioEntity error can not callback
|
|
||||||
//如果audiosFileMap为空 soundPool?.load 不会走 导致 setOnLoadCompleteListener 不会回调 导致外层prepare不回调卡住
|
|
||||||
if (audiosFileMap.size == 0) {
|
|
||||||
run(completionBlock)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.audioList = entity.audios.map { audio ->
|
|
||||||
return@map createSvgaAudioEntity(audio, audiosFileMap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createSvgaAudioEntity(audio: AudioEntity, audiosFileMap: HashMap<String, File>): SVGAAudioEntity {
|
|
||||||
val item = SVGAAudioEntity(audio)
|
|
||||||
val startTime = (audio.startTime ?: 0).toDouble()
|
|
||||||
val totalTime = (audio.totalTime ?: 0).toDouble()
|
|
||||||
if (totalTime.toInt() == 0) {
|
|
||||||
// 除数不能为 0
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
// 直接回调文件,后续播放都不走
|
|
||||||
mPlayCallback?.let {
|
|
||||||
val fileList: MutableList<File> = ArrayList()
|
|
||||||
audiosFileMap.forEach { entity ->
|
|
||||||
fileList.add(entity.value)
|
|
||||||
}
|
|
||||||
it.onPlay(fileList)
|
|
||||||
mCallback()
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
audiosFileMap[audio.audioKey]?.let { file ->
|
|
||||||
FileInputStream(file).use {
|
|
||||||
val length = it.available().toDouble()
|
|
||||||
val offset = ((startTime / totalTime) * length).toLong()
|
|
||||||
if (SVGASoundManager.isInit()) {
|
|
||||||
item.soundID = SVGASoundManager.load(soundCallback,
|
|
||||||
it.fd,
|
|
||||||
offset,
|
|
||||||
length.toLong(),
|
|
||||||
1)
|
|
||||||
} else {
|
|
||||||
item.soundID = soundPool?.load(it.fd, offset, length.toLong(), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateAudioFile(audioCache: File, value: ByteArray): File {
|
|
||||||
audioCache.createNewFile()
|
|
||||||
FileOutputStream(audioCache).write(value)
|
|
||||||
return audioCache
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateAudioFileMap(entity: MovieEntity): HashMap<String, File> {
|
|
||||||
val audiosDataMap = generateAudioMap(entity)
|
|
||||||
val audiosFileMap = HashMap<String, File>()
|
|
||||||
if (audiosDataMap.count() > 0) {
|
|
||||||
audiosDataMap.forEach {
|
|
||||||
val audioCache = SVGACache.buildAudioFile(it.key)
|
|
||||||
audiosFileMap[it.key] =
|
|
||||||
audioCache.takeIf { file -> file.exists() } ?: generateAudioFile(
|
|
||||||
audioCache,
|
|
||||||
it.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return audiosFileMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateAudioMap(entity: MovieEntity): HashMap<String, ByteArray> {
|
|
||||||
val audiosDataMap = HashMap<String, ByteArray>()
|
|
||||||
entity.images?.entries?.forEach {
|
|
||||||
val imageKey = it.key
|
|
||||||
val byteArray = it.value.toByteArray()
|
|
||||||
if (byteArray.count() < 4) {
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
val fileTag = byteArray.slice(IntRange(0, 3))
|
|
||||||
if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) {
|
|
||||||
audiosDataMap[imageKey] = byteArray
|
|
||||||
}else if(fileTag[0].toInt() == -1 && fileTag[1].toInt() == -5 && fileTag[2].toInt() == -108){
|
|
||||||
audiosDataMap[imageKey] = byteArray
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return audiosDataMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupSoundPool(entity: MovieEntity, completionBlock: () -> Unit) {
|
|
||||||
var soundLoaded = 0
|
|
||||||
if (SVGASoundManager.isInit()) {
|
|
||||||
soundCallback = object : SVGASoundManager.SVGASoundCallBack {
|
|
||||||
override fun onVolumeChange(value: Float) {
|
|
||||||
SVGASoundManager.setVolume(value, this@SVGAVideoEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {
|
|
||||||
soundLoaded++
|
|
||||||
if (soundLoaded >= entity.audios.count()) {
|
|
||||||
completionBlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
soundPool = generateSoundPool(entity)
|
|
||||||
LogUtils.info("SVGAParser", "pool_start")
|
|
||||||
soundPool?.setOnLoadCompleteListener { _, _, _ ->
|
|
||||||
LogUtils.info("SVGAParser", "pool_complete")
|
|
||||||
soundLoaded++
|
|
||||||
if (soundLoaded >= entity.audios.count()) {
|
|
||||||
completionBlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateSoundPool(entity: MovieEntity): SoundPool? {
|
|
||||||
return try {
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
val attributes = AudioAttributes.Builder()
|
|
||||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
|
||||||
.build()
|
|
||||||
SoundPool.Builder().setAudioAttributes(attributes)
|
|
||||||
.setMaxStreams(12.coerceAtMost(entity.audios.count()))
|
|
||||||
.build()
|
|
||||||
} else {
|
|
||||||
SoundPool(12.coerceAtMost(entity.audios.count()), AudioManager.STREAM_MUSIC, 0)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtils.error(TAG, e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
if (SVGASoundManager.isInit()) {
|
|
||||||
this.audioList.forEach {
|
|
||||||
it.soundID?.let { id -> SVGASoundManager.unload(id) }
|
|
||||||
}
|
|
||||||
soundCallback = null
|
|
||||||
}
|
|
||||||
soundPool?.release()
|
|
||||||
soundPool = null
|
|
||||||
audioList = emptyList()
|
|
||||||
spriteList = emptyList()
|
|
||||||
imageMap.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.bitmap
|
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Create by im_dsd 2020/7/7 17:59
|
|
||||||
*/
|
|
||||||
internal object BitmapSampleSizeCalculator {
|
|
||||||
|
|
||||||
fun calculate(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
|
|
||||||
// Raw height and width of image
|
|
||||||
val (height: Int, width: Int) = options.run { outHeight to outWidth }
|
|
||||||
var inSampleSize = 1
|
|
||||||
|
|
||||||
if (reqHeight <= 0 || reqWidth <= 0) {
|
|
||||||
return inSampleSize
|
|
||||||
}
|
|
||||||
if (height > reqHeight || width > reqWidth) {
|
|
||||||
|
|
||||||
val halfHeight: Int = height / 2
|
|
||||||
val halfWidth: Int = width / 2
|
|
||||||
|
|
||||||
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
|
||||||
// height and width larger than the requested height and width.
|
|
||||||
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
|
|
||||||
inSampleSize *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return inSampleSize
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.bitmap
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过字节码解码 Bitmap
|
|
||||||
*
|
|
||||||
* Create by im_dsd 2020/7/7 17:50
|
|
||||||
*/
|
|
||||||
internal object SVGABitmapByteArrayDecoder : SVGABitmapDecoder<ByteArray>() {
|
|
||||||
|
|
||||||
override fun onDecode(data: ByteArray, ops: BitmapFactory.Options): Bitmap? {
|
|
||||||
return BitmapFactory.decodeByteArray(data, 0, data.count(), ops)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.bitmap
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bitmap 解码器
|
|
||||||
*
|
|
||||||
* <T> 需要加载的数据类型
|
|
||||||
*
|
|
||||||
* Create by im_dsd 2020/7/7 17:39
|
|
||||||
*/
|
|
||||||
internal abstract class SVGABitmapDecoder<T> {
|
|
||||||
|
|
||||||
fun decodeBitmapFrom(data: T, reqWidth: Int, reqHeight: Int): Bitmap? {
|
|
||||||
return BitmapFactory.Options().run {
|
|
||||||
// 如果期望的宽高是合法的, 则开启检测尺寸模式
|
|
||||||
inJustDecodeBounds = (reqWidth > 0 && reqHeight > 0)
|
|
||||||
inPreferredConfig = Bitmap.Config.RGB_565
|
|
||||||
|
|
||||||
val bitmap = onDecode(data, this)
|
|
||||||
if (!inJustDecodeBounds) {
|
|
||||||
return bitmap
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate inSampleSize
|
|
||||||
inSampleSize = BitmapSampleSizeCalculator.calculate(this, reqWidth, reqHeight)
|
|
||||||
// Decode bitmap with inSampleSize set
|
|
||||||
inJustDecodeBounds = false
|
|
||||||
onDecode(data, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun onDecode(data: T, ops: BitmapFactory.Options): Bitmap?
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.bitmap
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过文件解码 Bitmap
|
|
||||||
*
|
|
||||||
* Create by im_dsd 2020/7/7 17:50
|
|
||||||
*/
|
|
||||||
internal object SVGABitmapFileDecoder : SVGABitmapDecoder<String>() {
|
|
||||||
|
|
||||||
override fun onDecode(data: String, ops: BitmapFactory.Options): Bitmap? {
|
|
||||||
return BitmapFactory.decodeFile(data, ops)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.drawer
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.widget.ImageView
|
|
||||||
import com.opensource.svgaplayer.SVGAVideoEntity
|
|
||||||
import com.opensource.svgaplayer.entities.SVGAVideoSpriteFrameEntity
|
|
||||||
import com.opensource.svgaplayer.utils.Pools
|
|
||||||
import com.opensource.svgaplayer.utils.SVGAScaleInfo
|
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
open internal class SGVADrawer(val videoItem: SVGAVideoEntity) {
|
|
||||||
|
|
||||||
val scaleInfo = SVGAScaleInfo()
|
|
||||||
|
|
||||||
private val spritePool = Pools.SimplePool<SVGADrawerSprite>(max(1, videoItem.spriteList.size))
|
|
||||||
|
|
||||||
inner class SVGADrawerSprite(var _matteKey: String? = null, var _imageKey: String? = null, var _frameEntity: SVGAVideoSpriteFrameEntity? = null) {
|
|
||||||
val matteKey get() = _matteKey
|
|
||||||
val imageKey get() = _imageKey
|
|
||||||
val frameEntity get() = _frameEntity!!
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun requestFrameSprites(frameIndex: Int): List<SVGADrawerSprite> {
|
|
||||||
return videoItem.spriteList.mapNotNull {
|
|
||||||
if (frameIndex >= 0 && frameIndex < it.frames.size) {
|
|
||||||
it.imageKey?.let { imageKey ->
|
|
||||||
if (!imageKey.endsWith(".matte") && it.frames[frameIndex].alpha <= 0.0) {
|
|
||||||
return@mapNotNull null
|
|
||||||
}
|
|
||||||
return@mapNotNull (spritePool.acquire() ?: SVGADrawerSprite()).apply {
|
|
||||||
_matteKey = it.matteKey
|
|
||||||
_imageKey = it.imageKey
|
|
||||||
_frameEntity = it.frames[frameIndex]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return@mapNotNull null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun releaseFrameSprites(sprites: List<SVGADrawerSprite>) {
|
|
||||||
sprites.forEach { spritePool.release(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun drawFrame(canvas : Canvas, frameIndex: Int, scaleType: ImageView.ScaleType) {
|
|
||||||
scaleInfo.performScaleType(canvas.width.toFloat(),canvas.height.toFloat(), videoItem.videoSize.width.toFloat(), videoItem.videoSize.height.toFloat(), scaleType)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,559 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.drawer
|
|
||||||
|
|
||||||
import android.graphics.*
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.StaticLayout
|
|
||||||
import android.text.TextUtils
|
|
||||||
import android.widget.ImageView
|
|
||||||
import com.opensource.svgaplayer.SVGADynamicEntity
|
|
||||||
import com.opensource.svgaplayer.SVGASoundManager
|
|
||||||
import com.opensource.svgaplayer.SVGAVideoEntity
|
|
||||||
import com.opensource.svgaplayer.entities.SVGAVideoShapeEntity
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
internal class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicEntity) : SGVADrawer(videoItem) {
|
|
||||||
|
|
||||||
private val sharedValues = ShareValues()
|
|
||||||
private val drawTextCache: HashMap<String, Bitmap> = hashMapOf()
|
|
||||||
private val pathCache = PathCache()
|
|
||||||
|
|
||||||
private var beginIndexList: Array<Boolean>? = null
|
|
||||||
private var endIndexList: Array<Boolean>? = null
|
|
||||||
|
|
||||||
override fun drawFrame(canvas: Canvas, frameIndex: Int, scaleType: ImageView.ScaleType) {
|
|
||||||
super.drawFrame(canvas, frameIndex, scaleType)
|
|
||||||
playAudio(frameIndex)
|
|
||||||
this.pathCache.onSizeChanged(canvas)
|
|
||||||
val sprites = requestFrameSprites(frameIndex)
|
|
||||||
// Filter null sprites
|
|
||||||
if (sprites.count() <= 0) return
|
|
||||||
val matteSprites = mutableMapOf<String, SVGADrawerSprite>()
|
|
||||||
var saveID = -1
|
|
||||||
beginIndexList = null
|
|
||||||
endIndexList = null
|
|
||||||
|
|
||||||
// Filter no matte layer
|
|
||||||
var hasMatteLayer = false
|
|
||||||
sprites.get(0).imageKey?.let {
|
|
||||||
if (it.endsWith(".matte")) {
|
|
||||||
hasMatteLayer = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sprites.forEachIndexed { index, svgaDrawerSprite ->
|
|
||||||
|
|
||||||
// Save matte sprite
|
|
||||||
svgaDrawerSprite.imageKey?.let {
|
|
||||||
/// No matte layer included or VERSION Unsopport matte
|
|
||||||
if (!hasMatteLayer || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// Normal sprite
|
|
||||||
drawSprite(svgaDrawerSprite, canvas, frameIndex)
|
|
||||||
// Continue
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
/// Cache matte sprite
|
|
||||||
if (it.endsWith(".matte")) {
|
|
||||||
matteSprites.put(it, svgaDrawerSprite)
|
|
||||||
// Continue
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Is matte begin
|
|
||||||
if (isMatteBegin(index, sprites)) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
saveID = canvas.saveLayer(0f, 0f, canvas.width.toFloat(), canvas.height.toFloat(), null)
|
|
||||||
} else {
|
|
||||||
canvas.save()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Normal matte
|
|
||||||
drawSprite(svgaDrawerSprite, canvas, frameIndex)
|
|
||||||
|
|
||||||
/// Is matte end
|
|
||||||
if (isMatteEnd(index, sprites)) {
|
|
||||||
matteSprites.get(svgaDrawerSprite.matteKey)?.let {
|
|
||||||
drawSprite(it, this.sharedValues.shareMatteCanvas(canvas.width, canvas.height), frameIndex)
|
|
||||||
canvas.drawBitmap(this.sharedValues.sharedMatteBitmap(), 0f, 0f, this.sharedValues.shareMattePaint())
|
|
||||||
if (saveID != -1) {
|
|
||||||
canvas.restoreToCount(saveID)
|
|
||||||
} else {
|
|
||||||
canvas.restore()
|
|
||||||
}
|
|
||||||
// Continue
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
releaseFrameSprites(sprites)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isMatteBegin(spriteIndex: Int, sprites: List<SVGADrawerSprite>): Boolean {
|
|
||||||
if (beginIndexList == null) {
|
|
||||||
val boolArray = Array(sprites.count()) { false }
|
|
||||||
sprites.forEachIndexed { index, svgaDrawerSprite ->
|
|
||||||
svgaDrawerSprite.imageKey?.let {
|
|
||||||
/// Filter matte sprite
|
|
||||||
if (it.endsWith(".matte")) {
|
|
||||||
// Continue
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
svgaDrawerSprite.matteKey?.let {
|
|
||||||
if (it.length > 0) {
|
|
||||||
sprites.get(index - 1)?.let { lastSprite ->
|
|
||||||
if (lastSprite.matteKey.isNullOrEmpty()) {
|
|
||||||
boolArray[index] = true
|
|
||||||
} else {
|
|
||||||
if (lastSprite.matteKey != svgaDrawerSprite.matteKey) {
|
|
||||||
boolArray[index] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
beginIndexList = boolArray
|
|
||||||
}
|
|
||||||
return beginIndexList?.get(spriteIndex) ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isMatteEnd(spriteIndex: Int, sprites: List<SVGADrawerSprite>): Boolean {
|
|
||||||
if (endIndexList == null) {
|
|
||||||
val boolArray = Array(sprites.count()) { false }
|
|
||||||
sprites.forEachIndexed { index, svgaDrawerSprite ->
|
|
||||||
svgaDrawerSprite.imageKey?.let {
|
|
||||||
/// Filter matte sprite
|
|
||||||
if (it.endsWith(".matte")) {
|
|
||||||
// Continue
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
svgaDrawerSprite.matteKey?.let {
|
|
||||||
if (it.length > 0) {
|
|
||||||
// Last one
|
|
||||||
if (index == sprites.count() - 1) {
|
|
||||||
boolArray[index] = true
|
|
||||||
} else {
|
|
||||||
sprites.get(index + 1)?.let { nextSprite ->
|
|
||||||
if (nextSprite.matteKey.isNullOrEmpty()) {
|
|
||||||
boolArray[index] = true
|
|
||||||
} else {
|
|
||||||
if (nextSprite.matteKey != svgaDrawerSprite.matteKey) {
|
|
||||||
boolArray[index] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endIndexList = boolArray
|
|
||||||
}
|
|
||||||
return endIndexList?.get(spriteIndex) ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun playAudio(frameIndex: Int) {
|
|
||||||
this.videoItem.audioList.forEach { audio ->
|
|
||||||
if (audio.startFrame == frameIndex) {
|
|
||||||
if (SVGASoundManager.isInit()) {
|
|
||||||
audio.soundID?.let { soundID ->
|
|
||||||
audio.playID = SVGASoundManager.play(soundID)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.videoItem.soundPool?.let { soundPool ->
|
|
||||||
audio.soundID?.let { soundID ->
|
|
||||||
audio.playID = soundPool.play(soundID, 1.0f, 1.0f, 1, 0, 1.0f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (audio.endFrame <= frameIndex) {
|
|
||||||
audio.playID?.let {
|
|
||||||
if (SVGASoundManager.isInit()) {
|
|
||||||
SVGASoundManager.stop(it)
|
|
||||||
} else {
|
|
||||||
this.videoItem.soundPool?.stop(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audio.playID = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun shareFrameMatrix(transform: Matrix): Matrix {
|
|
||||||
val matrix = this.sharedValues.sharedMatrix()
|
|
||||||
matrix.postScale(scaleInfo.scaleFx, scaleInfo.scaleFy)
|
|
||||||
matrix.postTranslate(scaleInfo.tranFx, scaleInfo.tranFy)
|
|
||||||
matrix.preConcat(transform)
|
|
||||||
return matrix
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawSprite(sprite: SVGADrawerSprite, canvas: Canvas, frameIndex: Int) {
|
|
||||||
drawImage(sprite, canvas)
|
|
||||||
drawShape(sprite, canvas)
|
|
||||||
drawDynamic(sprite, canvas, frameIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawImage(sprite: SVGADrawerSprite, canvas: Canvas) {
|
|
||||||
val imageKey = sprite.imageKey ?: return
|
|
||||||
val isHidden = dynamicItem.dynamicHidden[imageKey] == true
|
|
||||||
if (isHidden) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val bitmapKey = if (imageKey.endsWith(".matte")) imageKey.substring(0, imageKey.length - 6) else imageKey
|
|
||||||
val drawingBitmap = (dynamicItem.dynamicImage[bitmapKey] ?: videoItem.imageMap[bitmapKey])
|
|
||||||
?: return
|
|
||||||
val frameMatrix = shareFrameMatrix(sprite.frameEntity.transform)
|
|
||||||
val paint = this.sharedValues.sharedPaint()
|
|
||||||
paint.isAntiAlias = videoItem.antiAlias
|
|
||||||
paint.isFilterBitmap = videoItem.antiAlias
|
|
||||||
paint.alpha = (sprite.frameEntity.alpha * 255).toInt()
|
|
||||||
if (sprite.frameEntity.maskPath != null) {
|
|
||||||
val maskPath = sprite.frameEntity.maskPath ?: return
|
|
||||||
canvas.save()
|
|
||||||
val path = this.sharedValues.sharedPath()
|
|
||||||
maskPath.buildPath(path)
|
|
||||||
path.transform(frameMatrix)
|
|
||||||
canvas.clipPath(path)
|
|
||||||
frameMatrix.preScale((sprite.frameEntity.layout.width / drawingBitmap.width).toFloat(), (sprite.frameEntity.layout.height / drawingBitmap.height).toFloat())
|
|
||||||
if (!drawingBitmap.isRecycled) {
|
|
||||||
canvas.drawBitmap(drawingBitmap, frameMatrix, paint)
|
|
||||||
}
|
|
||||||
canvas.restore()
|
|
||||||
} else {
|
|
||||||
frameMatrix.preScale((sprite.frameEntity.layout.width / drawingBitmap.width).toFloat(), (sprite.frameEntity.layout.height / drawingBitmap.height).toFloat())
|
|
||||||
if (!drawingBitmap.isRecycled) {
|
|
||||||
canvas.drawBitmap(drawingBitmap, frameMatrix, paint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dynamicItem.dynamicIClickArea.let {
|
|
||||||
it.get(imageKey)?.let { listener ->
|
|
||||||
val matrixArray = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
|
|
||||||
frameMatrix.getValues(matrixArray)
|
|
||||||
listener.onResponseArea(imageKey, matrixArray[2].toInt()
|
|
||||||
, matrixArray[5].toInt()
|
|
||||||
, (drawingBitmap.width * matrixArray[0] + matrixArray[2]).toInt()
|
|
||||||
, (drawingBitmap.height * matrixArray[4] + matrixArray[5]).toInt())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawTextOnBitmap(canvas, drawingBitmap, sprite, frameMatrix)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawTextOnBitmap(canvas: Canvas, drawingBitmap: Bitmap, sprite: SVGADrawerSprite, frameMatrix: Matrix) {
|
|
||||||
if (dynamicItem.isTextDirty) {
|
|
||||||
this.drawTextCache.clear()
|
|
||||||
dynamicItem.isTextDirty = false
|
|
||||||
}
|
|
||||||
val imageKey = sprite.imageKey ?: return
|
|
||||||
var textBitmap: Bitmap? = null
|
|
||||||
dynamicItem.dynamicText[imageKey]?.let { drawingText ->
|
|
||||||
dynamicItem.dynamicTextPaint[imageKey]?.let { drawingTextPaint ->
|
|
||||||
drawTextCache[imageKey]?.let {
|
|
||||||
textBitmap = it
|
|
||||||
} ?: kotlin.run {
|
|
||||||
textBitmap = Bitmap.createBitmap(drawingBitmap.width, drawingBitmap.height, Bitmap.Config.ARGB_8888)
|
|
||||||
val drawRect = Rect(0, 0, drawingBitmap.width, drawingBitmap.height)
|
|
||||||
val textCanvas = Canvas(textBitmap)
|
|
||||||
drawingTextPaint.isAntiAlias = true
|
|
||||||
val fontMetrics = drawingTextPaint.getFontMetrics();
|
|
||||||
val top = fontMetrics.top
|
|
||||||
val bottom = fontMetrics.bottom
|
|
||||||
val baseLineY = drawRect.centerY() - top / 2 - bottom / 2
|
|
||||||
textCanvas.drawText(drawingText, drawRect.centerX().toFloat(), baseLineY, drawingTextPaint);
|
|
||||||
drawTextCache.put(imageKey, textBitmap as Bitmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dynamicItem.dynamicBoringLayoutText[imageKey]?.let {
|
|
||||||
drawTextCache[imageKey]?.let {
|
|
||||||
textBitmap = it
|
|
||||||
} ?: kotlin.run {
|
|
||||||
it.paint.isAntiAlias = true
|
|
||||||
|
|
||||||
textBitmap = Bitmap.createBitmap(drawingBitmap.width, drawingBitmap.height, Bitmap.Config.ARGB_8888)
|
|
||||||
val textCanvas = Canvas(textBitmap)
|
|
||||||
textCanvas.translate(0f, ((drawingBitmap.height - it.height) / 2).toFloat())
|
|
||||||
it.draw(textCanvas)
|
|
||||||
drawTextCache.put(imageKey, textBitmap as Bitmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dynamicItem.dynamicStaticLayoutText[imageKey]?.let {
|
|
||||||
drawTextCache[imageKey]?.let {
|
|
||||||
textBitmap = it
|
|
||||||
} ?: kotlin.run {
|
|
||||||
it.paint.isAntiAlias = true
|
|
||||||
var layout = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
var lineMax = try {
|
|
||||||
val field = StaticLayout::class.java.getDeclaredField("mMaximumVisibleLineCount")
|
|
||||||
field.isAccessible = true
|
|
||||||
field.getInt(it)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Int.MAX_VALUE
|
|
||||||
}
|
|
||||||
StaticLayout.Builder
|
|
||||||
.obtain(it.text, 0, it.text.length, it.paint, drawingBitmap.width)
|
|
||||||
.setAlignment(it.alignment)
|
|
||||||
.setMaxLines(lineMax)
|
|
||||||
.setEllipsize(TextUtils.TruncateAt.END)
|
|
||||||
.build()
|
|
||||||
} else {
|
|
||||||
StaticLayout(it.text, 0, it.text.length, it.paint, drawingBitmap.width, it.alignment, it.spacingMultiplier, it.spacingAdd, false)
|
|
||||||
}
|
|
||||||
textBitmap = Bitmap.createBitmap(drawingBitmap.width, drawingBitmap.height, Bitmap.Config.ARGB_8888)
|
|
||||||
val textCanvas = Canvas(textBitmap)
|
|
||||||
textCanvas.translate(0f, ((drawingBitmap.height - layout.height) / 2).toFloat())
|
|
||||||
layout.draw(textCanvas)
|
|
||||||
drawTextCache.put(imageKey, textBitmap as Bitmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
textBitmap?.let { textBitmap ->
|
|
||||||
val paint = this.sharedValues.sharedPaint()
|
|
||||||
paint.isAntiAlias = videoItem.antiAlias
|
|
||||||
paint.alpha = (sprite.frameEntity.alpha * 255).toInt()
|
|
||||||
if (sprite.frameEntity.maskPath != null) {
|
|
||||||
val maskPath = sprite.frameEntity.maskPath ?: return@let
|
|
||||||
canvas.save()
|
|
||||||
canvas.concat(frameMatrix)
|
|
||||||
canvas.clipRect(0, 0, drawingBitmap.width, drawingBitmap.height)
|
|
||||||
val bitmapShader = BitmapShader(textBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
|
|
||||||
paint.shader = bitmapShader
|
|
||||||
val path = this.sharedValues.sharedPath()
|
|
||||||
maskPath.buildPath(path)
|
|
||||||
canvas.drawPath(path, paint)
|
|
||||||
canvas.restore()
|
|
||||||
} else {
|
|
||||||
paint.isFilterBitmap = videoItem.antiAlias
|
|
||||||
canvas.drawBitmap(textBitmap, frameMatrix, paint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawShape(sprite: SVGADrawerSprite, canvas: Canvas) {
|
|
||||||
val frameMatrix = shareFrameMatrix(sprite.frameEntity.transform)
|
|
||||||
sprite.frameEntity.shapes.forEach { shape ->
|
|
||||||
shape.buildPath()
|
|
||||||
shape.shapePath?.let {
|
|
||||||
val paint = this.sharedValues.sharedPaint()
|
|
||||||
paint.reset()
|
|
||||||
paint.isAntiAlias = videoItem.antiAlias
|
|
||||||
paint.alpha = (sprite.frameEntity.alpha * 255).toInt()
|
|
||||||
val path = this.sharedValues.sharedPath()
|
|
||||||
path.reset()
|
|
||||||
path.addPath(this.pathCache.buildPath(shape))
|
|
||||||
val shapeMatrix = this.sharedValues.sharedMatrix2()
|
|
||||||
shapeMatrix.reset()
|
|
||||||
shape.transform?.let {
|
|
||||||
shapeMatrix.postConcat(it)
|
|
||||||
}
|
|
||||||
shapeMatrix.postConcat(frameMatrix)
|
|
||||||
path.transform(shapeMatrix)
|
|
||||||
shape.styles?.fill?.let {
|
|
||||||
if (it != 0x00000000) {
|
|
||||||
paint.style = Paint.Style.FILL
|
|
||||||
paint.color = it
|
|
||||||
val alpha = Math.min(255, Math.max(0, (sprite.frameEntity.alpha * 255).toInt()))
|
|
||||||
if (alpha != 255) {
|
|
||||||
paint.alpha = alpha
|
|
||||||
}
|
|
||||||
if (sprite.frameEntity.maskPath !== null) canvas.save()
|
|
||||||
sprite.frameEntity.maskPath?.let { maskPath ->
|
|
||||||
val path2 = this.sharedValues.sharedPath2()
|
|
||||||
maskPath.buildPath(path2)
|
|
||||||
path2.transform(frameMatrix)
|
|
||||||
canvas.clipPath(path2)
|
|
||||||
}
|
|
||||||
canvas.drawPath(path, paint)
|
|
||||||
if (sprite.frameEntity.maskPath !== null) canvas.restore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shape.styles?.strokeWidth?.let {
|
|
||||||
if (it > 0) {
|
|
||||||
paint.alpha = (sprite.frameEntity.alpha * 255).toInt()
|
|
||||||
paint.style = Paint.Style.STROKE
|
|
||||||
shape.styles?.stroke?.let {
|
|
||||||
paint.color = it
|
|
||||||
val alpha = Math.min(255, Math.max(0, (sprite.frameEntity.alpha * 255).toInt()))
|
|
||||||
if (alpha != 255) {
|
|
||||||
paint.alpha = alpha
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val scale = matrixScale(frameMatrix)
|
|
||||||
shape.styles?.strokeWidth?.let {
|
|
||||||
paint.strokeWidth = it * scale
|
|
||||||
}
|
|
||||||
shape.styles?.lineCap?.let {
|
|
||||||
when {
|
|
||||||
it.equals("butt", true) -> paint.strokeCap = Paint.Cap.BUTT
|
|
||||||
it.equals("round", true) -> paint.strokeCap = Paint.Cap.ROUND
|
|
||||||
it.equals("square", true) -> paint.strokeCap = Paint.Cap.SQUARE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shape.styles?.lineJoin?.let {
|
|
||||||
when {
|
|
||||||
it.equals("miter", true) -> paint.strokeJoin = Paint.Join.MITER
|
|
||||||
it.equals("round", true) -> paint.strokeJoin = Paint.Join.ROUND
|
|
||||||
it.equals("bevel", true) -> paint.strokeJoin = Paint.Join.BEVEL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shape.styles?.miterLimit?.let {
|
|
||||||
paint.strokeMiter = it.toFloat() * scale
|
|
||||||
}
|
|
||||||
shape.styles?.lineDash?.let {
|
|
||||||
if (it.size == 3 && (it[0] > 0 || it[1] > 0)) {
|
|
||||||
paint.pathEffect = DashPathEffect(floatArrayOf(
|
|
||||||
(if (it[0] < 1.0f) 1.0f else it[0]) * scale,
|
|
||||||
(if (it[1] < 0.1f) 0.1f else it[1]) * scale
|
|
||||||
), it[2] * scale)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sprite.frameEntity.maskPath !== null) canvas.save()
|
|
||||||
sprite.frameEntity.maskPath?.let { maskPath ->
|
|
||||||
val path2 = this.sharedValues.sharedPath2()
|
|
||||||
maskPath.buildPath(path2)
|
|
||||||
path2.transform(frameMatrix)
|
|
||||||
canvas.clipPath(path2)
|
|
||||||
}
|
|
||||||
canvas.drawPath(path, paint)
|
|
||||||
if (sprite.frameEntity.maskPath !== null) canvas.restore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val matrixScaleTempValues = FloatArray(16)
|
|
||||||
|
|
||||||
private fun matrixScale(matrix: Matrix): Float {
|
|
||||||
matrix.getValues(matrixScaleTempValues)
|
|
||||||
if (matrixScaleTempValues[0] == 0f) {
|
|
||||||
return 0f
|
|
||||||
}
|
|
||||||
var A = matrixScaleTempValues[0].toDouble()
|
|
||||||
var B = matrixScaleTempValues[3].toDouble()
|
|
||||||
var C = matrixScaleTempValues[1].toDouble()
|
|
||||||
var D = matrixScaleTempValues[4].toDouble()
|
|
||||||
if (A * D == B * C) return 0f
|
|
||||||
var scaleX = Math.sqrt(A * A + B * B)
|
|
||||||
A /= scaleX
|
|
||||||
B /= scaleX
|
|
||||||
var skew = A * C + B * D
|
|
||||||
C -= A * skew
|
|
||||||
D -= B * skew
|
|
||||||
var scaleY = Math.sqrt(C * C + D * D)
|
|
||||||
C /= scaleY
|
|
||||||
D /= scaleY
|
|
||||||
skew /= scaleY
|
|
||||||
if (A * D < B * C) {
|
|
||||||
scaleX = -scaleX
|
|
||||||
}
|
|
||||||
return if (scaleInfo.ratioX) Math.abs(scaleX.toFloat()) else Math.abs(scaleY.toFloat())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawDynamic(sprite: SVGADrawerSprite, canvas: Canvas, frameIndex: Int) {
|
|
||||||
val imageKey = sprite.imageKey ?: return
|
|
||||||
dynamicItem.dynamicDrawer[imageKey]?.let {
|
|
||||||
val frameMatrix = shareFrameMatrix(sprite.frameEntity.transform)
|
|
||||||
canvas.save()
|
|
||||||
canvas.concat(frameMatrix)
|
|
||||||
it.invoke(canvas, frameIndex)
|
|
||||||
canvas.restore()
|
|
||||||
}
|
|
||||||
dynamicItem.dynamicDrawerSized[imageKey]?.let {
|
|
||||||
val frameMatrix = shareFrameMatrix(sprite.frameEntity.transform)
|
|
||||||
canvas.save()
|
|
||||||
canvas.concat(frameMatrix)
|
|
||||||
it.invoke(canvas, frameIndex, sprite.frameEntity.layout.width.toInt(), sprite.frameEntity.layout.height.toInt())
|
|
||||||
canvas.restore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ShareValues {
|
|
||||||
|
|
||||||
private val sharedPaint = Paint()
|
|
||||||
private val sharedPath = Path()
|
|
||||||
private val sharedPath2 = Path()
|
|
||||||
private val sharedMatrix = Matrix()
|
|
||||||
private val sharedMatrix2 = Matrix()
|
|
||||||
|
|
||||||
private val shareMattePaint = Paint()
|
|
||||||
private var shareMatteCanvas: Canvas? = null
|
|
||||||
private var sharedMatteBitmap: Bitmap? = null
|
|
||||||
|
|
||||||
fun sharedPaint(): Paint {
|
|
||||||
sharedPaint.reset()
|
|
||||||
return sharedPaint
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sharedPath(): Path {
|
|
||||||
sharedPath.reset()
|
|
||||||
return sharedPath
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sharedPath2(): Path {
|
|
||||||
sharedPath2.reset()
|
|
||||||
return sharedPath2
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sharedMatrix(): Matrix {
|
|
||||||
sharedMatrix.reset()
|
|
||||||
return sharedMatrix
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sharedMatrix2(): Matrix {
|
|
||||||
sharedMatrix2.reset()
|
|
||||||
return sharedMatrix2
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shareMattePaint(): Paint {
|
|
||||||
shareMattePaint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_IN))
|
|
||||||
return shareMattePaint
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sharedMatteBitmap(): Bitmap {
|
|
||||||
return sharedMatteBitmap as Bitmap
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shareMatteCanvas(width: Int, height: Int): Canvas {
|
|
||||||
if (shareMatteCanvas == null) {
|
|
||||||
sharedMatteBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
|
|
||||||
// shareMatteCanvas = Canvas(sharedMatteBitmap)
|
|
||||||
}
|
|
||||||
// val matteCanvas = shareMatteCanvas as Canvas
|
|
||||||
// matteCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
|
|
||||||
// return matteCanvas
|
|
||||||
return Canvas(sharedMatteBitmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PathCache {
|
|
||||||
|
|
||||||
private var canvasWidth: Int = 0
|
|
||||||
private var canvasHeight: Int = 0
|
|
||||||
private val cache = HashMap<SVGAVideoShapeEntity, Path>()
|
|
||||||
|
|
||||||
fun onSizeChanged(canvas: Canvas) {
|
|
||||||
if (this.canvasWidth != canvas.width || this.canvasHeight != canvas.height) {
|
|
||||||
this.cache.clear()
|
|
||||||
}
|
|
||||||
this.canvasWidth = canvas.width
|
|
||||||
this.canvasHeight = canvas.height
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildPath(shape: SVGAVideoShapeEntity): Path {
|
|
||||||
if (!this.cache.containsKey(shape)) {
|
|
||||||
val path = Path()
|
|
||||||
path.set(shape.shapePath)
|
|
||||||
this.cache[shape] = path
|
|
||||||
}
|
|
||||||
return this.cache[shape]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.entities
|
|
||||||
|
|
||||||
import com.opensource.svgaplayer.proto.AudioEntity
|
|
||||||
import java.io.FileInputStream
|
|
||||||
|
|
||||||
internal class SVGAAudioEntity {
|
|
||||||
|
|
||||||
val audioKey: String?
|
|
||||||
val startFrame: Int
|
|
||||||
val endFrame: Int
|
|
||||||
val startTime: Int
|
|
||||||
val totalTime: Int
|
|
||||||
var soundID: Int? = null
|
|
||||||
var playID: Int? = null
|
|
||||||
|
|
||||||
constructor(audioItem: AudioEntity) {
|
|
||||||
this.audioKey = audioItem.audioKey
|
|
||||||
this.startFrame = audioItem.startFrame ?: 0
|
|
||||||
this.endFrame = audioItem.endFrame ?: 0
|
|
||||||
this.startTime = audioItem.startTime ?: 0
|
|
||||||
this.totalTime = audioItem.totalTime ?: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.entities
|
|
||||||
|
|
||||||
import android.graphics.Path
|
|
||||||
import com.opensource.svgaplayer.utils.SVGAPoint
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
private val VALID_METHODS: Set<String> = setOf("M", "L", "H", "V", "C", "S", "Q", "R", "A", "Z", "m", "l", "h", "v", "c", "s", "q", "r", "a", "z")
|
|
||||||
|
|
||||||
class SVGAPathEntity(originValue: String) {
|
|
||||||
|
|
||||||
private val replacedValue: String = if (originValue.contains(",")) originValue.replace(",", " ") else originValue
|
|
||||||
|
|
||||||
private var cachedPath: Path? = null
|
|
||||||
|
|
||||||
fun buildPath(toPath: Path) {
|
|
||||||
cachedPath?.let {
|
|
||||||
toPath.set(it)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val cachedPath = Path()
|
|
||||||
val segments = StringTokenizer(this.replacedValue, "MLHVCSQRAZmlhvcsqraz", true)
|
|
||||||
var currentMethod = ""
|
|
||||||
while (segments.hasMoreTokens()) {
|
|
||||||
val segment = segments.nextToken()
|
|
||||||
if (segment.isEmpty()) { continue }
|
|
||||||
if (VALID_METHODS.contains(segment)) {
|
|
||||||
currentMethod = segment
|
|
||||||
if (currentMethod == "Z" || currentMethod == "z") { operate(cachedPath, currentMethod, StringTokenizer("", "")) }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
operate(cachedPath, currentMethod, StringTokenizer(segment, " "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.cachedPath = cachedPath
|
|
||||||
toPath.set(cachedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun operate(finalPath: Path, method: String, args: StringTokenizer) {
|
|
||||||
var x0 = 0.0f
|
|
||||||
var y0 = 0.0f
|
|
||||||
var x1 = 0.0f
|
|
||||||
var y1 = 0.0f
|
|
||||||
var x2 = 0.0f
|
|
||||||
var y2 = 0.0f
|
|
||||||
try {
|
|
||||||
var index = 0
|
|
||||||
while (args.hasMoreTokens()) {
|
|
||||||
val s = args.nextToken()
|
|
||||||
if (s.isEmpty()) {continue}
|
|
||||||
if (index == 0) { x0 = s.toFloat() }
|
|
||||||
if (index == 1) { y0 = s.toFloat() }
|
|
||||||
if (index == 2) { x1 = s.toFloat() }
|
|
||||||
if (index == 3) { y1 = s.toFloat() }
|
|
||||||
if (index == 4) { x2 = s.toFloat() }
|
|
||||||
if (index == 5) { y2 = s.toFloat() }
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {}
|
|
||||||
var currentPoint = SVGAPoint(0.0f, 0.0f, 0.0f)
|
|
||||||
if (method == "M") {
|
|
||||||
finalPath.moveTo(x0, y0)
|
|
||||||
currentPoint = SVGAPoint(x0, y0, 0.0f)
|
|
||||||
} else if (method == "m") {
|
|
||||||
finalPath.rMoveTo(x0, y0)
|
|
||||||
currentPoint = SVGAPoint(currentPoint.x + x0, currentPoint.y + y0, 0.0f)
|
|
||||||
}
|
|
||||||
if (method == "L") {
|
|
||||||
finalPath.lineTo(x0, y0)
|
|
||||||
} else if (method == "l") {
|
|
||||||
finalPath.rLineTo(x0, y0)
|
|
||||||
}
|
|
||||||
if (method == "C") {
|
|
||||||
finalPath.cubicTo(x0, y0, x1, y1, x2, y2)
|
|
||||||
} else if (method == "c") {
|
|
||||||
finalPath.rCubicTo(x0, y0, x1, y1, x2, y2)
|
|
||||||
}
|
|
||||||
if (method == "Q") {
|
|
||||||
finalPath.quadTo(x0, y0, x1, y1)
|
|
||||||
} else if (method == "q") {
|
|
||||||
finalPath.rQuadTo(x0, y0, x1, y1)
|
|
||||||
}
|
|
||||||
if (method == "H") {
|
|
||||||
finalPath.lineTo(x0, currentPoint.y)
|
|
||||||
} else if (method == "h") {
|
|
||||||
finalPath.rLineTo(x0, 0f)
|
|
||||||
}
|
|
||||||
if (method == "V") {
|
|
||||||
finalPath.lineTo(currentPoint.x, x0)
|
|
||||||
} else if (method == "v") {
|
|
||||||
finalPath.rLineTo(0f, x0)
|
|
||||||
}
|
|
||||||
if (method == "Z") {
|
|
||||||
finalPath.close()
|
|
||||||
}
|
|
||||||
else if (method == "z") {
|
|
||||||
finalPath.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,356 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.entities
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Matrix
|
|
||||||
import android.graphics.Path
|
|
||||||
import android.graphics.RectF
|
|
||||||
import com.opensource.svgaplayer.proto.ShapeEntity
|
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/2/22.
|
|
||||||
*/
|
|
||||||
|
|
||||||
val sharedPath = Path()
|
|
||||||
|
|
||||||
internal class SVGAVideoShapeEntity {
|
|
||||||
|
|
||||||
enum class Type {
|
|
||||||
shape,
|
|
||||||
rect,
|
|
||||||
ellipse,
|
|
||||||
keep
|
|
||||||
}
|
|
||||||
|
|
||||||
class Styles {
|
|
||||||
|
|
||||||
var fill = 0x00000000
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var stroke = 0x00000000
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var strokeWidth = 0.0f
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var lineCap = "butt"
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var lineJoin = "miter"
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var miterLimit = 0
|
|
||||||
internal set
|
|
||||||
|
|
||||||
var lineDash = FloatArray(0)
|
|
||||||
internal set
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = Type.shape
|
|
||||||
private set
|
|
||||||
|
|
||||||
var args: Map<String, Any>? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
var styles: Styles? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
var transform: Matrix? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
constructor(obj: JSONObject) {
|
|
||||||
parseType(obj)
|
|
||||||
parseArgs(obj)
|
|
||||||
parseStyles(obj)
|
|
||||||
parseTransform(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(obj: ShapeEntity) {
|
|
||||||
parseType(obj)
|
|
||||||
parseArgs(obj)
|
|
||||||
parseStyles(obj)
|
|
||||||
parseTransform(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
val isKeep: Boolean
|
|
||||||
get() = type == Type.keep
|
|
||||||
|
|
||||||
var shapePath: Path? = null
|
|
||||||
|
|
||||||
private fun parseType(obj: JSONObject) {
|
|
||||||
obj.optString("type")?.let {
|
|
||||||
when {
|
|
||||||
it.equals("shape", ignoreCase = true) -> type = Type.shape
|
|
||||||
it.equals("rect", ignoreCase = true) -> type = Type.rect
|
|
||||||
it.equals("ellipse", ignoreCase = true) -> type = Type.ellipse
|
|
||||||
it.equals("keep", ignoreCase = true) -> type = Type.keep
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseType(obj: ShapeEntity) {
|
|
||||||
obj.type?.let {
|
|
||||||
type = when (it) {
|
|
||||||
ShapeEntity.ShapeType.SHAPE -> Type.shape
|
|
||||||
ShapeEntity.ShapeType.RECT -> Type.rect
|
|
||||||
ShapeEntity.ShapeType.ELLIPSE -> Type.ellipse
|
|
||||||
ShapeEntity.ShapeType.KEEP -> Type.keep
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseArgs(obj: JSONObject) {
|
|
||||||
val args = HashMap<String, Any>()
|
|
||||||
obj.optJSONObject("args")?.let { values ->
|
|
||||||
values.keys().forEach { key ->
|
|
||||||
values.get(key)?.let {
|
|
||||||
args.put(key, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.args = args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseArgs(obj: ShapeEntity) {
|
|
||||||
val args = HashMap<String, Any>()
|
|
||||||
obj.shape?.let {
|
|
||||||
it.d?.let { args.put("d", it) }
|
|
||||||
}
|
|
||||||
obj.ellipse?.let {
|
|
||||||
args.put("x", it.x ?: 0.0f)
|
|
||||||
args.put("y", it.y ?: 0.0f)
|
|
||||||
args.put("radiusX", it.radiusX ?: 0.0f)
|
|
||||||
args.put("radiusY", it.radiusY ?: 0.0f)
|
|
||||||
}
|
|
||||||
obj.rect?.let {
|
|
||||||
args.put("x", it.x ?: 0.0f)
|
|
||||||
args.put("y", it.y ?: 0.0f)
|
|
||||||
args.put("width", it.width ?: 0.0f)
|
|
||||||
args.put("height", it.height ?: 0.0f)
|
|
||||||
args.put("cornerRadius", it.cornerRadius ?: 0.0f)
|
|
||||||
}
|
|
||||||
this.args = args
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查色域范围是否是 [0f, 1f],或者是 [0f, 255f]
|
|
||||||
private fun checkValueRange(obj: JSONArray): Float {
|
|
||||||
return if (
|
|
||||||
obj.optDouble(0) <= 1 &&
|
|
||||||
obj.optDouble(1) <= 1 &&
|
|
||||||
obj.optDouble(2) <= 1
|
|
||||||
) {
|
|
||||||
255f
|
|
||||||
} else {
|
|
||||||
1f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 alpha 的范围是否是 [0f, 1f],或者是 [0f, 255f]
|
|
||||||
private fun checkAlphaValueRange(obj: JSONArray): Float {
|
|
||||||
return if (obj.optDouble(3) <= 1) {
|
|
||||||
255f
|
|
||||||
} else {
|
|
||||||
1f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseStyles(obj: JSONObject) {
|
|
||||||
obj.optJSONObject("styles")?.let {
|
|
||||||
val styles = Styles()
|
|
||||||
it.optJSONArray("fill")?.let {
|
|
||||||
if (it.length() == 4) {
|
|
||||||
val mulValue = checkValueRange(it)
|
|
||||||
val alphaRangeValue = checkAlphaValueRange(it)
|
|
||||||
styles.fill = Color.argb(
|
|
||||||
(it.optDouble(3) * alphaRangeValue).toInt(),
|
|
||||||
(it.optDouble(0) * mulValue).toInt(),
|
|
||||||
(it.optDouble(1) * mulValue).toInt(),
|
|
||||||
(it.optDouble(2) * mulValue).toInt()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it.optJSONArray("stroke")?.let {
|
|
||||||
if (it.length() == 4) {
|
|
||||||
val mulValue = checkValueRange(it)
|
|
||||||
val alphaRangeValue = checkAlphaValueRange(it)
|
|
||||||
styles.stroke = Color.argb(
|
|
||||||
(it.optDouble(3) * alphaRangeValue).toInt(),
|
|
||||||
(it.optDouble(0) * mulValue).toInt(),
|
|
||||||
(it.optDouble(1) * mulValue).toInt(),
|
|
||||||
(it.optDouble(2) * mulValue).toInt()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
styles.strokeWidth = it.optDouble("strokeWidth", 0.0).toFloat()
|
|
||||||
styles.lineCap = it.optString("lineCap", "butt")
|
|
||||||
styles.lineJoin = it.optString("lineJoin", "miter")
|
|
||||||
styles.miterLimit = it.optInt("miterLimit", 0)
|
|
||||||
it.optJSONArray("lineDash")?.let {
|
|
||||||
styles.lineDash = FloatArray(it.length())
|
|
||||||
for (i in 0 until it.length()) {
|
|
||||||
styles.lineDash[i] = it.optDouble(i, 0.0).toFloat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.styles = styles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查色域范围是否是 [0f, 1f],或者是 [0f, 255f]
|
|
||||||
private fun checkValueRange(color: ShapeEntity.ShapeStyle.RGBAColor): Float {
|
|
||||||
return if (
|
|
||||||
(color.r ?: 0f) <= 1 &&
|
|
||||||
(color.g ?: 0f) <= 1 &&
|
|
||||||
(color.b ?: 0f) <= 1
|
|
||||||
) {
|
|
||||||
255f
|
|
||||||
} else {
|
|
||||||
1f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 alpha 范围是否是 [0f, 1f],有可能是 [0f, 255f]
|
|
||||||
private fun checkAlphaValueRange(color: ShapeEntity.ShapeStyle.RGBAColor): Float {
|
|
||||||
return if (color.a <= 1f) {
|
|
||||||
255f
|
|
||||||
} else {
|
|
||||||
1f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseStyles(obj: ShapeEntity) {
|
|
||||||
obj.styles?.let {
|
|
||||||
val styles = Styles()
|
|
||||||
it.fill?.let {
|
|
||||||
val mulValue = checkValueRange(it)
|
|
||||||
val alphaRangeValue = checkAlphaValueRange(it)
|
|
||||||
styles.fill = Color.argb(
|
|
||||||
((it.a ?: 0f) * alphaRangeValue).toInt(),
|
|
||||||
((it.r ?: 0f) * mulValue).toInt(),
|
|
||||||
((it.g ?: 0f) * mulValue).toInt(),
|
|
||||||
((it.b ?: 0f) * mulValue).toInt()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
it.stroke?.let {
|
|
||||||
val mulValue = checkValueRange(it)
|
|
||||||
val alphaRangeValue = checkAlphaValueRange(it)
|
|
||||||
styles.stroke = Color.argb(
|
|
||||||
((it.a ?: 0f) * alphaRangeValue).toInt(),
|
|
||||||
((it.r ?: 0f) * mulValue).toInt(),
|
|
||||||
((it.g ?: 0f) * mulValue).toInt(),
|
|
||||||
((it.b ?: 0f) * mulValue).toInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
styles.strokeWidth = it.strokeWidth ?: 0.0f
|
|
||||||
it.lineCap?.let {
|
|
||||||
when (it) {
|
|
||||||
ShapeEntity.ShapeStyle.LineCap.LineCap_BUTT -> styles.lineCap = "butt"
|
|
||||||
ShapeEntity.ShapeStyle.LineCap.LineCap_ROUND -> styles.lineCap = "round"
|
|
||||||
ShapeEntity.ShapeStyle.LineCap.LineCap_SQUARE -> styles.lineCap = "square"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it.lineJoin?.let {
|
|
||||||
when (it) {
|
|
||||||
ShapeEntity.ShapeStyle.LineJoin.LineJoin_BEVEL -> styles.lineJoin = "bevel"
|
|
||||||
ShapeEntity.ShapeStyle.LineJoin.LineJoin_MITER -> styles.lineJoin = "miter"
|
|
||||||
ShapeEntity.ShapeStyle.LineJoin.LineJoin_ROUND -> styles.lineJoin = "round"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
styles.miterLimit = (it.miterLimit ?: 0.0f).toInt()
|
|
||||||
styles.lineDash = kotlin.FloatArray(3)
|
|
||||||
it.lineDashI?.let { styles.lineDash[0] = it }
|
|
||||||
it.lineDashII?.let { styles.lineDash[1] = it }
|
|
||||||
it.lineDashIII?.let { styles.lineDash[2] = it }
|
|
||||||
this.styles = styles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseTransform(obj: JSONObject) {
|
|
||||||
obj.optJSONObject("transform")?.let {
|
|
||||||
val transform = Matrix()
|
|
||||||
val arr = FloatArray(9)
|
|
||||||
val a = it.optDouble("a", 1.0)
|
|
||||||
val b = it.optDouble("b", 0.0)
|
|
||||||
val c = it.optDouble("c", 0.0)
|
|
||||||
val d = it.optDouble("d", 1.0)
|
|
||||||
val tx = it.optDouble("tx", 0.0)
|
|
||||||
val ty = it.optDouble("ty", 0.0)
|
|
||||||
arr[0] = a.toFloat() // a
|
|
||||||
arr[1] = c.toFloat() // c
|
|
||||||
arr[2] = tx.toFloat() // tx
|
|
||||||
arr[3] = b.toFloat() // b
|
|
||||||
arr[4] = d.toFloat() // d
|
|
||||||
arr[5] = ty.toFloat() // ty
|
|
||||||
arr[6] = 0.0.toFloat()
|
|
||||||
arr[7] = 0.0.toFloat()
|
|
||||||
arr[8] = 1.0.toFloat()
|
|
||||||
transform.setValues(arr)
|
|
||||||
this.transform = transform
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseTransform(obj: ShapeEntity) {
|
|
||||||
obj.transform?.let {
|
|
||||||
val transform = Matrix()
|
|
||||||
val arr = FloatArray(9)
|
|
||||||
val a = it.a ?: 1.0f
|
|
||||||
val b = it.b ?: 0.0f
|
|
||||||
val c = it.c ?: 0.0f
|
|
||||||
val d = it.d ?: 1.0f
|
|
||||||
val tx = it.tx ?: 0.0f
|
|
||||||
val ty = it.ty ?: 0.0f
|
|
||||||
arr[0] = a
|
|
||||||
arr[1] = c
|
|
||||||
arr[2] = tx
|
|
||||||
arr[3] = b
|
|
||||||
arr[4] = d
|
|
||||||
arr[5] = ty
|
|
||||||
arr[6] = 0.0f
|
|
||||||
arr[7] = 0.0f
|
|
||||||
arr[8] = 1.0f
|
|
||||||
transform.setValues(arr)
|
|
||||||
this.transform = transform
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun buildPath() {
|
|
||||||
if (this.shapePath != null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sharedPath.reset()
|
|
||||||
if (this.type == Type.shape) {
|
|
||||||
(this.args?.get("d") as? String)?.let {
|
|
||||||
SVGAPathEntity(it).buildPath(sharedPath)
|
|
||||||
}
|
|
||||||
} else if (this.type == Type.ellipse) {
|
|
||||||
val xv = this.args?.get("x") as? Number ?: return
|
|
||||||
val yv = this.args?.get("y") as? Number ?: return
|
|
||||||
val rxv = this.args?.get("radiusX") as? Number ?: return
|
|
||||||
val ryv = this.args?.get("radiusY") as? Number ?: return
|
|
||||||
val x = xv.toFloat()
|
|
||||||
val y = yv.toFloat()
|
|
||||||
val rx = rxv.toFloat()
|
|
||||||
val ry = ryv.toFloat()
|
|
||||||
sharedPath.addOval(RectF(x - rx, y - ry, x + rx, y + ry), Path.Direction.CW)
|
|
||||||
} else if (this.type == Type.rect) {
|
|
||||||
val xv = this.args?.get("x") as? Number ?: return
|
|
||||||
val yv = this.args?.get("y") as? Number ?: return
|
|
||||||
val wv = this.args?.get("width") as? Number ?: return
|
|
||||||
val hv = this.args?.get("height") as? Number ?: return
|
|
||||||
val crv = this.args?.get("cornerRadius") as? Number ?: return
|
|
||||||
val x = xv.toFloat()
|
|
||||||
val y = yv.toFloat()
|
|
||||||
val width = wv.toFloat()
|
|
||||||
val height = hv.toFloat()
|
|
||||||
val cornerRadius = crv.toFloat()
|
|
||||||
sharedPath.addRoundRect(RectF(x, y, x + width, y + height), cornerRadius, cornerRadius, Path.Direction.CW)
|
|
||||||
}
|
|
||||||
this.shapePath = Path()
|
|
||||||
this.shapePath?.set(sharedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.entities
|
|
||||||
|
|
||||||
import com.opensource.svgaplayer.proto.SpriteEntity
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2016/10/17.
|
|
||||||
*/
|
|
||||||
internal class SVGAVideoSpriteEntity {
|
|
||||||
|
|
||||||
val imageKey: String?
|
|
||||||
|
|
||||||
val matteKey: String?
|
|
||||||
|
|
||||||
val frames: List<SVGAVideoSpriteFrameEntity>
|
|
||||||
|
|
||||||
constructor(obj: JSONObject) {
|
|
||||||
this.imageKey = obj.optString("imageKey")
|
|
||||||
this.matteKey = obj.optString("matteKey")
|
|
||||||
val mutableFrames: MutableList<SVGAVideoSpriteFrameEntity> = mutableListOf()
|
|
||||||
obj.optJSONArray("frames")?.let {
|
|
||||||
for (i in 0 until it.length()) {
|
|
||||||
it.optJSONObject(i)?.let {
|
|
||||||
val frameItem = SVGAVideoSpriteFrameEntity(it)
|
|
||||||
if (frameItem.shapes.isNotEmpty()) {
|
|
||||||
frameItem.shapes.first().let {
|
|
||||||
if (it.isKeep && mutableFrames.size > 0) {
|
|
||||||
frameItem.shapes = mutableFrames.last().shapes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutableFrames.add(frameItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frames = mutableFrames.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(obj: SpriteEntity) {
|
|
||||||
this.imageKey = obj.imageKey
|
|
||||||
this.matteKey = obj.matteKey
|
|
||||||
var lastFrame: SVGAVideoSpriteFrameEntity? = null
|
|
||||||
frames = obj.frames?.map {
|
|
||||||
val frameItem = SVGAVideoSpriteFrameEntity(it)
|
|
||||||
if (frameItem.shapes.isNotEmpty()) {
|
|
||||||
frameItem.shapes.first().let {
|
|
||||||
if (it.isKeep) {
|
|
||||||
lastFrame?.let {
|
|
||||||
frameItem.shapes = it.shapes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastFrame = frameItem
|
|
||||||
return@map frameItem
|
|
||||||
} ?: listOf()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.entities
|
|
||||||
|
|
||||||
import android.graphics.Matrix
|
|
||||||
import com.opensource.svgaplayer.proto.FrameEntity
|
|
||||||
import com.opensource.svgaplayer.utils.SVGARect
|
|
||||||
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2016/10/17.
|
|
||||||
*/
|
|
||||||
internal class SVGAVideoSpriteFrameEntity {
|
|
||||||
|
|
||||||
var alpha: Double
|
|
||||||
var layout = SVGARect(0.0, 0.0, 0.0, 0.0)
|
|
||||||
var transform = Matrix()
|
|
||||||
var maskPath: SVGAPathEntity? = null
|
|
||||||
var shapes: List<SVGAVideoShapeEntity> = listOf()
|
|
||||||
|
|
||||||
constructor(obj: JSONObject) {
|
|
||||||
this.alpha = obj.optDouble("alpha", 0.0)
|
|
||||||
obj.optJSONObject("layout")?.let {
|
|
||||||
layout = SVGARect(it.optDouble("x", 0.0), it.optDouble("y", 0.0), it.optDouble("width", 0.0), it.optDouble("height", 0.0))
|
|
||||||
}
|
|
||||||
obj.optJSONObject("transform")?.let {
|
|
||||||
val arr = FloatArray(9)
|
|
||||||
val a = it.optDouble("a", 1.0)
|
|
||||||
val b = it.optDouble("b", 0.0)
|
|
||||||
val c = it.optDouble("c", 0.0)
|
|
||||||
val d = it.optDouble("d", 1.0)
|
|
||||||
val tx = it.optDouble("tx", 0.0)
|
|
||||||
val ty = it.optDouble("ty", 0.0)
|
|
||||||
arr[0] = a.toFloat()
|
|
||||||
arr[1] = c.toFloat()
|
|
||||||
arr[2] = tx.toFloat()
|
|
||||||
arr[3] = b.toFloat()
|
|
||||||
arr[4] = d.toFloat()
|
|
||||||
arr[5] = ty.toFloat()
|
|
||||||
arr[6] = 0.0.toFloat()
|
|
||||||
arr[7] = 0.0.toFloat()
|
|
||||||
arr[8] = 1.0.toFloat()
|
|
||||||
transform.setValues(arr)
|
|
||||||
}
|
|
||||||
obj.optString("clipPath")?.let { d ->
|
|
||||||
if (d.isNotEmpty()) {
|
|
||||||
maskPath = SVGAPathEntity(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj.optJSONArray("shapes")?.let {
|
|
||||||
val mutableList: MutableList<SVGAVideoShapeEntity> = mutableListOf()
|
|
||||||
for (i in 0 until it.length()) {
|
|
||||||
it.optJSONObject(i)?.let {
|
|
||||||
mutableList.add(SVGAVideoShapeEntity(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shapes = mutableList.toList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(obj: FrameEntity) {
|
|
||||||
this.alpha = (obj.alpha ?: 0.0f).toDouble()
|
|
||||||
obj.layout?.let {
|
|
||||||
this.layout = SVGARect((it.x ?: 0.0f).toDouble(), (it.y
|
|
||||||
?: 0.0f).toDouble(), (it.width ?: 0.0f).toDouble(), (it.height
|
|
||||||
?: 0.0f).toDouble())
|
|
||||||
}
|
|
||||||
obj.transform?.let {
|
|
||||||
val arr = FloatArray(9)
|
|
||||||
val a = it.a ?: 1.0f
|
|
||||||
val b = it.b ?: 0.0f
|
|
||||||
val c = it.c ?: 0.0f
|
|
||||||
val d = it.d ?: 1.0f
|
|
||||||
val tx = it.tx ?: 0.0f
|
|
||||||
val ty = it.ty ?: 0.0f
|
|
||||||
arr[0] = a
|
|
||||||
arr[1] = c
|
|
||||||
arr[2] = tx
|
|
||||||
arr[3] = b
|
|
||||||
arr[4] = d
|
|
||||||
arr[5] = ty
|
|
||||||
arr[6] = 0.0f
|
|
||||||
arr[7] = 0.0f
|
|
||||||
arr[8] = 1.0f
|
|
||||||
transform.setValues(arr)
|
|
||||||
}
|
|
||||||
obj.clipPath?.takeIf { it.isNotEmpty() }?.let {
|
|
||||||
maskPath = SVGAPathEntity(it)
|
|
||||||
}
|
|
||||||
this.shapes = obj.shapes.map {
|
|
||||||
return@map SVGAVideoShapeEntity(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,258 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 19:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class AudioEntity extends Message<AudioEntity, AudioEntity.Builder> {
|
|
||||||
public static final ProtoAdapter<AudioEntity> ADAPTER = new ProtoAdapter_AudioEntity();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final String DEFAULT_AUDIOKEY = "";
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_STARTFRAME = 0;
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_ENDFRAME = 0;
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_STARTTIME = 0;
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_TOTALTIME = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频文件名
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#STRING"
|
|
||||||
)
|
|
||||||
public final String audioKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放起始帧
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer startFrame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放结束帧
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer endFrame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放起始时间(相对音频长度)
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer startTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频总长度
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 5,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer totalTime;
|
|
||||||
|
|
||||||
public AudioEntity(String audioKey, Integer startFrame, Integer endFrame, Integer startTime, Integer totalTime) {
|
|
||||||
this(audioKey, startFrame, endFrame, startTime, totalTime, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioEntity(String audioKey, Integer startFrame, Integer endFrame, Integer startTime, Integer totalTime, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.audioKey = audioKey;
|
|
||||||
this.startFrame = startFrame;
|
|
||||||
this.endFrame = endFrame;
|
|
||||||
this.startTime = startTime;
|
|
||||||
this.totalTime = totalTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.audioKey = audioKey;
|
|
||||||
builder.startFrame = startFrame;
|
|
||||||
builder.endFrame = endFrame;
|
|
||||||
builder.startTime = startTime;
|
|
||||||
builder.totalTime = totalTime;
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof AudioEntity)) return false;
|
|
||||||
AudioEntity o = (AudioEntity) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(audioKey, o.audioKey)
|
|
||||||
&& Internal.equals(startFrame, o.startFrame)
|
|
||||||
&& Internal.equals(endFrame, o.endFrame)
|
|
||||||
&& Internal.equals(startTime, o.startTime)
|
|
||||||
&& Internal.equals(totalTime, o.totalTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (audioKey != null ? audioKey.hashCode() : 0);
|
|
||||||
result = result * 37 + (startFrame != null ? startFrame.hashCode() : 0);
|
|
||||||
result = result * 37 + (endFrame != null ? endFrame.hashCode() : 0);
|
|
||||||
result = result * 37 + (startTime != null ? startTime.hashCode() : 0);
|
|
||||||
result = result * 37 + (totalTime != null ? totalTime.hashCode() : 0);
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (audioKey != null) builder.append(", audioKey=").append(audioKey);
|
|
||||||
if (startFrame != null) builder.append(", startFrame=").append(startFrame);
|
|
||||||
if (endFrame != null) builder.append(", endFrame=").append(endFrame);
|
|
||||||
if (startTime != null) builder.append(", startTime=").append(startTime);
|
|
||||||
if (totalTime != null) builder.append(", totalTime=").append(totalTime);
|
|
||||||
return builder.replace(0, 2, "AudioEntity{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<AudioEntity, Builder> {
|
|
||||||
public String audioKey;
|
|
||||||
|
|
||||||
public Integer startFrame;
|
|
||||||
|
|
||||||
public Integer endFrame;
|
|
||||||
|
|
||||||
public Integer startTime;
|
|
||||||
|
|
||||||
public Integer totalTime;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频文件名
|
|
||||||
*/
|
|
||||||
public Builder audioKey(String audioKey) {
|
|
||||||
this.audioKey = audioKey;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放起始帧
|
|
||||||
*/
|
|
||||||
public Builder startFrame(Integer startFrame) {
|
|
||||||
this.startFrame = startFrame;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放结束帧
|
|
||||||
*/
|
|
||||||
public Builder endFrame(Integer endFrame) {
|
|
||||||
this.endFrame = endFrame;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频播放起始时间(相对音频长度)
|
|
||||||
*/
|
|
||||||
public Builder startTime(Integer startTime) {
|
|
||||||
this.startTime = startTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频总长度
|
|
||||||
*/
|
|
||||||
public Builder totalTime(Integer totalTime) {
|
|
||||||
this.totalTime = totalTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioEntity build() {
|
|
||||||
return new AudioEntity(audioKey, startFrame, endFrame, startTime, totalTime, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_AudioEntity extends ProtoAdapter<AudioEntity> {
|
|
||||||
ProtoAdapter_AudioEntity() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, AudioEntity.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(AudioEntity value) {
|
|
||||||
return (value.audioKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.audioKey) : 0)
|
|
||||||
+ (value.startFrame != null ? ProtoAdapter.INT32.encodedSizeWithTag(2, value.startFrame) : 0)
|
|
||||||
+ (value.endFrame != null ? ProtoAdapter.INT32.encodedSizeWithTag(3, value.endFrame) : 0)
|
|
||||||
+ (value.startTime != null ? ProtoAdapter.INT32.encodedSizeWithTag(4, value.startTime) : 0)
|
|
||||||
+ (value.totalTime != null ? ProtoAdapter.INT32.encodedSizeWithTag(5, value.totalTime) : 0)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, AudioEntity value) throws IOException {
|
|
||||||
if (value.audioKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.audioKey);
|
|
||||||
if (value.startFrame != null) ProtoAdapter.INT32.encodeWithTag(writer, 2, value.startFrame);
|
|
||||||
if (value.endFrame != null) ProtoAdapter.INT32.encodeWithTag(writer, 3, value.endFrame);
|
|
||||||
if (value.startTime != null) ProtoAdapter.INT32.encodeWithTag(writer, 4, value.startTime);
|
|
||||||
if (value.totalTime != null) ProtoAdapter.INT32.encodeWithTag(writer, 5, value.totalTime);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioEntity decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.audioKey(ProtoAdapter.STRING.decode(reader)); break;
|
|
||||||
case 2: builder.startFrame(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
case 3: builder.endFrame(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
case 4: builder.startTime(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
case 5: builder.totalTime(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioEntity redact(AudioEntity value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,259 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 115:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Float;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import java.util.List;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class FrameEntity extends Message<FrameEntity, FrameEntity.Builder> {
|
|
||||||
public static final ProtoAdapter<FrameEntity> ADAPTER = new ProtoAdapter_FrameEntity();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_ALPHA = 0.0f;
|
|
||||||
|
|
||||||
public static final String DEFAULT_CLIPPATH = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 透明度
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float alpha;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始约束大小
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.Layout#ADAPTER"
|
|
||||||
)
|
|
||||||
public final Layout layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2D 变换矩阵
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.Transform#ADAPTER"
|
|
||||||
)
|
|
||||||
public final Transform transform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遮罩路径,使用 SVG 标准 Path 绘制图案进行 Mask 遮罩。
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#STRING"
|
|
||||||
)
|
|
||||||
public final String clipPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 矢量元素列表
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 5,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.ShapeEntity#ADAPTER",
|
|
||||||
label = WireField.Label.REPEATED
|
|
||||||
)
|
|
||||||
public final List<ShapeEntity> shapes;
|
|
||||||
|
|
||||||
public FrameEntity(Float alpha, Layout layout, Transform transform, String clipPath, List<ShapeEntity> shapes) {
|
|
||||||
this(alpha, layout, transform, clipPath, shapes, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FrameEntity(Float alpha, Layout layout, Transform transform, String clipPath, List<ShapeEntity> shapes, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.alpha = alpha;
|
|
||||||
this.layout = layout;
|
|
||||||
this.transform = transform;
|
|
||||||
this.clipPath = clipPath;
|
|
||||||
this.shapes = Internal.immutableCopyOf("shapes", shapes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.alpha = alpha;
|
|
||||||
builder.layout = layout;
|
|
||||||
builder.transform = transform;
|
|
||||||
builder.clipPath = clipPath;
|
|
||||||
builder.shapes = Internal.copyOf("shapes", shapes);
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof FrameEntity)) return false;
|
|
||||||
FrameEntity o = (FrameEntity) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(alpha, o.alpha)
|
|
||||||
&& Internal.equals(layout, o.layout)
|
|
||||||
&& Internal.equals(transform, o.transform)
|
|
||||||
&& Internal.equals(clipPath, o.clipPath)
|
|
||||||
&& shapes.equals(o.shapes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (alpha != null ? alpha.hashCode() : 0);
|
|
||||||
result = result * 37 + (layout != null ? layout.hashCode() : 0);
|
|
||||||
result = result * 37 + (transform != null ? transform.hashCode() : 0);
|
|
||||||
result = result * 37 + (clipPath != null ? clipPath.hashCode() : 0);
|
|
||||||
result = result * 37 + shapes.hashCode();
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (alpha != null) builder.append(", alpha=").append(alpha);
|
|
||||||
if (layout != null) builder.append(", layout=").append(layout);
|
|
||||||
if (transform != null) builder.append(", transform=").append(transform);
|
|
||||||
if (clipPath != null) builder.append(", clipPath=").append(clipPath);
|
|
||||||
if (!shapes.isEmpty()) builder.append(", shapes=").append(shapes);
|
|
||||||
return builder.replace(0, 2, "FrameEntity{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<FrameEntity, Builder> {
|
|
||||||
public Float alpha;
|
|
||||||
|
|
||||||
public Layout layout;
|
|
||||||
|
|
||||||
public Transform transform;
|
|
||||||
|
|
||||||
public String clipPath;
|
|
||||||
|
|
||||||
public List<ShapeEntity> shapes;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
shapes = Internal.newMutableList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 透明度
|
|
||||||
*/
|
|
||||||
public Builder alpha(Float alpha) {
|
|
||||||
this.alpha = alpha;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始约束大小
|
|
||||||
*/
|
|
||||||
public Builder layout(Layout layout) {
|
|
||||||
this.layout = layout;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2D 变换矩阵
|
|
||||||
*/
|
|
||||||
public Builder transform(Transform transform) {
|
|
||||||
this.transform = transform;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遮罩路径,使用 SVG 标准 Path 绘制图案进行 Mask 遮罩。
|
|
||||||
*/
|
|
||||||
public Builder clipPath(String clipPath) {
|
|
||||||
this.clipPath = clipPath;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 矢量元素列表
|
|
||||||
*/
|
|
||||||
public Builder shapes(List<ShapeEntity> shapes) {
|
|
||||||
Internal.checkElementsNotNull(shapes);
|
|
||||||
this.shapes = shapes;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FrameEntity build() {
|
|
||||||
return new FrameEntity(alpha, layout, transform, clipPath, shapes, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_FrameEntity extends ProtoAdapter<FrameEntity> {
|
|
||||||
ProtoAdapter_FrameEntity() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, FrameEntity.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(FrameEntity value) {
|
|
||||||
return (value.alpha != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.alpha) : 0)
|
|
||||||
+ (value.layout != null ? Layout.ADAPTER.encodedSizeWithTag(2, value.layout) : 0)
|
|
||||||
+ (value.transform != null ? Transform.ADAPTER.encodedSizeWithTag(3, value.transform) : 0)
|
|
||||||
+ (value.clipPath != null ? ProtoAdapter.STRING.encodedSizeWithTag(4, value.clipPath) : 0)
|
|
||||||
+ ShapeEntity.ADAPTER.asRepeated().encodedSizeWithTag(5, value.shapes)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, FrameEntity value) throws IOException {
|
|
||||||
if (value.alpha != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.alpha);
|
|
||||||
if (value.layout != null) Layout.ADAPTER.encodeWithTag(writer, 2, value.layout);
|
|
||||||
if (value.transform != null) Transform.ADAPTER.encodeWithTag(writer, 3, value.transform);
|
|
||||||
if (value.clipPath != null) ProtoAdapter.STRING.encodeWithTag(writer, 4, value.clipPath);
|
|
||||||
ShapeEntity.ADAPTER.asRepeated().encodeWithTag(writer, 5, value.shapes);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FrameEntity decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.alpha(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 2: builder.layout(Layout.ADAPTER.decode(reader)); break;
|
|
||||||
case 3: builder.transform(Transform.ADAPTER.decode(reader)); break;
|
|
||||||
case 4: builder.clipPath(ProtoAdapter.STRING.decode(reader)); break;
|
|
||||||
case 5: builder.shapes.add(ShapeEntity.ADAPTER.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FrameEntity redact(FrameEntity value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
if (builder.layout != null) builder.layout = Layout.ADAPTER.redact(builder.layout);
|
|
||||||
if (builder.transform != null) builder.transform = Transform.ADAPTER.redact(builder.transform);
|
|
||||||
Internal.redactElements(builder.shapes, ShapeEntity.ADAPTER);
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,205 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 27:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Float;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class Layout extends Message<Layout, Layout.Builder> {
|
|
||||||
public static final ProtoAdapter<Layout> ADAPTER = new ProtoAdapter_Layout();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_X = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_Y = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_WIDTH = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_HEIGHT = 0.0f;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float x;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float y;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float width;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float height;
|
|
||||||
|
|
||||||
public Layout(Float x, Float y, Float width, Float height) {
|
|
||||||
this(x, y, width, height, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Layout(Float x, Float y, Float width, Float height, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.x = x;
|
|
||||||
builder.y = y;
|
|
||||||
builder.width = width;
|
|
||||||
builder.height = height;
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof Layout)) return false;
|
|
||||||
Layout o = (Layout) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(x, o.x)
|
|
||||||
&& Internal.equals(y, o.y)
|
|
||||||
&& Internal.equals(width, o.width)
|
|
||||||
&& Internal.equals(height, o.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (x != null ? x.hashCode() : 0);
|
|
||||||
result = result * 37 + (y != null ? y.hashCode() : 0);
|
|
||||||
result = result * 37 + (width != null ? width.hashCode() : 0);
|
|
||||||
result = result * 37 + (height != null ? height.hashCode() : 0);
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (x != null) builder.append(", x=").append(x);
|
|
||||||
if (y != null) builder.append(", y=").append(y);
|
|
||||||
if (width != null) builder.append(", width=").append(width);
|
|
||||||
if (height != null) builder.append(", height=").append(height);
|
|
||||||
return builder.replace(0, 2, "Layout{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<Layout, Builder> {
|
|
||||||
public Float x;
|
|
||||||
|
|
||||||
public Float y;
|
|
||||||
|
|
||||||
public Float width;
|
|
||||||
|
|
||||||
public Float height;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder x(Float x) {
|
|
||||||
this.x = x;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder y(Float y) {
|
|
||||||
this.y = y;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder width(Float width) {
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder height(Float height) {
|
|
||||||
this.height = height;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Layout build() {
|
|
||||||
return new Layout(x, y, width, height, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_Layout extends ProtoAdapter<Layout> {
|
|
||||||
ProtoAdapter_Layout() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, Layout.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(Layout value) {
|
|
||||||
return (value.x != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.x) : 0)
|
|
||||||
+ (value.y != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.y) : 0)
|
|
||||||
+ (value.width != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(3, value.width) : 0)
|
|
||||||
+ (value.height != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(4, value.height) : 0)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, Layout value) throws IOException {
|
|
||||||
if (value.x != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.x);
|
|
||||||
if (value.y != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.y);
|
|
||||||
if (value.width != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 3, value.width);
|
|
||||||
if (value.height != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 4, value.height);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Layout decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.x(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 2: builder.y(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 3: builder.width(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 4: builder.height(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Layout redact(Layout value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,265 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 123:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class MovieEntity extends Message<MovieEntity, MovieEntity.Builder> {
|
|
||||||
public static final ProtoAdapter<MovieEntity> ADAPTER = new ProtoAdapter_MovieEntity();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final String DEFAULT_VERSION = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SVGA 格式版本号
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#STRING"
|
|
||||||
)
|
|
||||||
public final String version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画参数
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.MovieParams#ADAPTER"
|
|
||||||
)
|
|
||||||
public final MovieParams params;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key 是位图键名,Value 是位图文件名或二进制 PNG 数据。
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
keyAdapter = "com.squareup.wire.ProtoAdapter#STRING",
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#BYTES"
|
|
||||||
)
|
|
||||||
public final Map<String, ByteString> images;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 元素列表
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.SpriteEntity#ADAPTER",
|
|
||||||
label = WireField.Label.REPEATED
|
|
||||||
)
|
|
||||||
public final List<SpriteEntity> sprites;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频列表
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 5,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.AudioEntity#ADAPTER",
|
|
||||||
label = WireField.Label.REPEATED
|
|
||||||
)
|
|
||||||
public final List<AudioEntity> audios;
|
|
||||||
|
|
||||||
public MovieEntity(String version, MovieParams params, Map<String, ByteString> images, List<SpriteEntity> sprites, List<AudioEntity> audios) {
|
|
||||||
this(version, params, images, sprites, audios, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MovieEntity(String version, MovieParams params, Map<String, ByteString> images, List<SpriteEntity> sprites, List<AudioEntity> audios, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.version = version;
|
|
||||||
this.params = params;
|
|
||||||
this.images = Internal.immutableCopyOf("images", images);
|
|
||||||
this.sprites = Internal.immutableCopyOf("sprites", sprites);
|
|
||||||
this.audios = Internal.immutableCopyOf("audios", audios);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.version = version;
|
|
||||||
builder.params = params;
|
|
||||||
builder.images = Internal.copyOf("images", images);
|
|
||||||
builder.sprites = Internal.copyOf("sprites", sprites);
|
|
||||||
builder.audios = Internal.copyOf("audios", audios);
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof MovieEntity)) return false;
|
|
||||||
MovieEntity o = (MovieEntity) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(version, o.version)
|
|
||||||
&& Internal.equals(params, o.params)
|
|
||||||
&& images.equals(o.images)
|
|
||||||
&& sprites.equals(o.sprites)
|
|
||||||
&& audios.equals(o.audios);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (version != null ? version.hashCode() : 0);
|
|
||||||
result = result * 37 + (params != null ? params.hashCode() : 0);
|
|
||||||
result = result * 37 + images.hashCode();
|
|
||||||
result = result * 37 + sprites.hashCode();
|
|
||||||
result = result * 37 + audios.hashCode();
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (version != null) builder.append(", version=").append(version);
|
|
||||||
if (params != null) builder.append(", params=").append(params);
|
|
||||||
if (!images.isEmpty()) builder.append(", images=").append(images);
|
|
||||||
if (!sprites.isEmpty()) builder.append(", sprites=").append(sprites);
|
|
||||||
if (!audios.isEmpty()) builder.append(", audios=").append(audios);
|
|
||||||
return builder.replace(0, 2, "MovieEntity{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<MovieEntity, Builder> {
|
|
||||||
public String version;
|
|
||||||
|
|
||||||
public MovieParams params;
|
|
||||||
|
|
||||||
public Map<String, ByteString> images;
|
|
||||||
|
|
||||||
public List<SpriteEntity> sprites;
|
|
||||||
|
|
||||||
public List<AudioEntity> audios;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
images = Internal.newMutableMap();
|
|
||||||
sprites = Internal.newMutableList();
|
|
||||||
audios = Internal.newMutableList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SVGA 格式版本号
|
|
||||||
*/
|
|
||||||
public Builder version(String version) {
|
|
||||||
this.version = version;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画参数
|
|
||||||
*/
|
|
||||||
public Builder params(MovieParams params) {
|
|
||||||
this.params = params;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key 是位图键名,Value 是位图文件名或二进制 PNG 数据。
|
|
||||||
*/
|
|
||||||
public Builder images(Map<String, ByteString> images) {
|
|
||||||
Internal.checkElementsNotNull(images);
|
|
||||||
this.images = images;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 元素列表
|
|
||||||
*/
|
|
||||||
public Builder sprites(List<SpriteEntity> sprites) {
|
|
||||||
Internal.checkElementsNotNull(sprites);
|
|
||||||
this.sprites = sprites;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音频列表
|
|
||||||
*/
|
|
||||||
public Builder audios(List<AudioEntity> audios) {
|
|
||||||
Internal.checkElementsNotNull(audios);
|
|
||||||
this.audios = audios;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieEntity build() {
|
|
||||||
return new MovieEntity(version, params, images, sprites, audios, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_MovieEntity extends ProtoAdapter<MovieEntity> {
|
|
||||||
private final ProtoAdapter<Map<String, ByteString>> images = ProtoAdapter.newMapAdapter(ProtoAdapter.STRING, ProtoAdapter.BYTES);
|
|
||||||
|
|
||||||
ProtoAdapter_MovieEntity() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, MovieEntity.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(MovieEntity value) {
|
|
||||||
return (value.version != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.version) : 0)
|
|
||||||
+ (value.params != null ? MovieParams.ADAPTER.encodedSizeWithTag(2, value.params) : 0)
|
|
||||||
+ images.encodedSizeWithTag(3, value.images)
|
|
||||||
+ SpriteEntity.ADAPTER.asRepeated().encodedSizeWithTag(4, value.sprites)
|
|
||||||
+ AudioEntity.ADAPTER.asRepeated().encodedSizeWithTag(5, value.audios)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, MovieEntity value) throws IOException {
|
|
||||||
if (value.version != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.version);
|
|
||||||
if (value.params != null) MovieParams.ADAPTER.encodeWithTag(writer, 2, value.params);
|
|
||||||
images.encodeWithTag(writer, 3, value.images);
|
|
||||||
SpriteEntity.ADAPTER.asRepeated().encodeWithTag(writer, 4, value.sprites);
|
|
||||||
AudioEntity.ADAPTER.asRepeated().encodeWithTag(writer, 5, value.audios);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieEntity decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.version(ProtoAdapter.STRING.decode(reader)); break;
|
|
||||||
case 2: builder.params(MovieParams.ADAPTER.decode(reader)); break;
|
|
||||||
case 3: builder.images.putAll(images.decode(reader)); break;
|
|
||||||
case 4: builder.sprites.add(SpriteEntity.ADAPTER.decode(reader)); break;
|
|
||||||
case 5: builder.audios.add(AudioEntity.ADAPTER.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieEntity redact(MovieEntity value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
if (builder.params != null) builder.params = MovieParams.ADAPTER.redact(builder.params);
|
|
||||||
Internal.redactElements(builder.sprites, SpriteEntity.ADAPTER);
|
|
||||||
Internal.redactElements(builder.audios, AudioEntity.ADAPTER);
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,230 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 6:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Float;
|
|
||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class MovieParams extends Message<MovieParams, MovieParams.Builder> {
|
|
||||||
public static final ProtoAdapter<MovieParams> ADAPTER = new ProtoAdapter_MovieParams();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_VIEWBOXWIDTH = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_VIEWBOXHEIGHT = 0.0f;
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_FPS = 0;
|
|
||||||
|
|
||||||
public static final Integer DEFAULT_FRAMES = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 画布宽
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float viewBoxWidth;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 画布高
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float viewBoxHeight;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画每秒播放帧数,合法值是 [1, 2, 3, 5, 6, 10, 12, 15, 20, 30, 60] 中的任意一个。
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer fps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画总帧数
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#INT32"
|
|
||||||
)
|
|
||||||
public final Integer frames;
|
|
||||||
|
|
||||||
public MovieParams(Float viewBoxWidth, Float viewBoxHeight, Integer fps, Integer frames) {
|
|
||||||
this(viewBoxWidth, viewBoxHeight, fps, frames, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MovieParams(Float viewBoxWidth, Float viewBoxHeight, Integer fps, Integer frames, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.viewBoxWidth = viewBoxWidth;
|
|
||||||
this.viewBoxHeight = viewBoxHeight;
|
|
||||||
this.fps = fps;
|
|
||||||
this.frames = frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.viewBoxWidth = viewBoxWidth;
|
|
||||||
builder.viewBoxHeight = viewBoxHeight;
|
|
||||||
builder.fps = fps;
|
|
||||||
builder.frames = frames;
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof MovieParams)) return false;
|
|
||||||
MovieParams o = (MovieParams) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(viewBoxWidth, o.viewBoxWidth)
|
|
||||||
&& Internal.equals(viewBoxHeight, o.viewBoxHeight)
|
|
||||||
&& Internal.equals(fps, o.fps)
|
|
||||||
&& Internal.equals(frames, o.frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (viewBoxWidth != null ? viewBoxWidth.hashCode() : 0);
|
|
||||||
result = result * 37 + (viewBoxHeight != null ? viewBoxHeight.hashCode() : 0);
|
|
||||||
result = result * 37 + (fps != null ? fps.hashCode() : 0);
|
|
||||||
result = result * 37 + (frames != null ? frames.hashCode() : 0);
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (viewBoxWidth != null) builder.append(", viewBoxWidth=").append(viewBoxWidth);
|
|
||||||
if (viewBoxHeight != null) builder.append(", viewBoxHeight=").append(viewBoxHeight);
|
|
||||||
if (fps != null) builder.append(", fps=").append(fps);
|
|
||||||
if (frames != null) builder.append(", frames=").append(frames);
|
|
||||||
return builder.replace(0, 2, "MovieParams{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<MovieParams, Builder> {
|
|
||||||
public Float viewBoxWidth;
|
|
||||||
|
|
||||||
public Float viewBoxHeight;
|
|
||||||
|
|
||||||
public Integer fps;
|
|
||||||
|
|
||||||
public Integer frames;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 画布宽
|
|
||||||
*/
|
|
||||||
public Builder viewBoxWidth(Float viewBoxWidth) {
|
|
||||||
this.viewBoxWidth = viewBoxWidth;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 画布高
|
|
||||||
*/
|
|
||||||
public Builder viewBoxHeight(Float viewBoxHeight) {
|
|
||||||
this.viewBoxHeight = viewBoxHeight;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画每秒播放帧数,合法值是 [1, 2, 3, 5, 6, 10, 12, 15, 20, 30, 60] 中的任意一个。
|
|
||||||
*/
|
|
||||||
public Builder fps(Integer fps) {
|
|
||||||
this.fps = fps;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动画总帧数
|
|
||||||
*/
|
|
||||||
public Builder frames(Integer frames) {
|
|
||||||
this.frames = frames;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieParams build() {
|
|
||||||
return new MovieParams(viewBoxWidth, viewBoxHeight, fps, frames, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_MovieParams extends ProtoAdapter<MovieParams> {
|
|
||||||
ProtoAdapter_MovieParams() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, MovieParams.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(MovieParams value) {
|
|
||||||
return (value.viewBoxWidth != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.viewBoxWidth) : 0)
|
|
||||||
+ (value.viewBoxHeight != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.viewBoxHeight) : 0)
|
|
||||||
+ (value.fps != null ? ProtoAdapter.INT32.encodedSizeWithTag(3, value.fps) : 0)
|
|
||||||
+ (value.frames != null ? ProtoAdapter.INT32.encodedSizeWithTag(4, value.frames) : 0)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, MovieParams value) throws IOException {
|
|
||||||
if (value.viewBoxWidth != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.viewBoxWidth);
|
|
||||||
if (value.viewBoxHeight != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.viewBoxHeight);
|
|
||||||
if (value.fps != null) ProtoAdapter.INT32.encodeWithTag(writer, 3, value.fps);
|
|
||||||
if (value.frames != null) ProtoAdapter.INT32.encodeWithTag(writer, 4, value.frames);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieParams decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.viewBoxWidth(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 2: builder.viewBoxHeight(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 3: builder.fps(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
case 4: builder.frames(ProtoAdapter.INT32.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MovieParams redact(MovieParams value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,202 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 13:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import java.util.List;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class SpriteEntity extends Message<SpriteEntity, SpriteEntity.Builder> {
|
|
||||||
public static final ProtoAdapter<SpriteEntity> ADAPTER = new ProtoAdapter_SpriteEntity();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final String DEFAULT_IMAGEKEY = "";
|
|
||||||
|
|
||||||
public static final String DEFAULT_MATTEKEY = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 元件所对应的位图键名, 如果 imageKey 含有 .vector 后缀,该 sprite 为矢量图层 含有 .matte 后缀,该 sprite 为遮罩图层。
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#STRING"
|
|
||||||
)
|
|
||||||
public final String imageKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 帧列表
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.opensource.svgaplayer.proto.FrameEntity#ADAPTER",
|
|
||||||
label = WireField.Label.REPEATED
|
|
||||||
)
|
|
||||||
public final List<FrameEntity> frames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 被遮罩图层的 matteKey 对应的是其遮罩图层的 imageKey.
|
|
||||||
*/
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#STRING"
|
|
||||||
)
|
|
||||||
public final String matteKey;
|
|
||||||
|
|
||||||
public SpriteEntity(String imageKey, List<FrameEntity> frames, String matteKey) {
|
|
||||||
this(imageKey, frames, matteKey, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpriteEntity(String imageKey, List<FrameEntity> frames, String matteKey, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.imageKey = imageKey;
|
|
||||||
this.frames = Internal.immutableCopyOf("frames", frames);
|
|
||||||
this.matteKey = matteKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.imageKey = imageKey;
|
|
||||||
builder.frames = Internal.copyOf("frames", frames);
|
|
||||||
builder.matteKey = matteKey;
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof SpriteEntity)) return false;
|
|
||||||
SpriteEntity o = (SpriteEntity) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(imageKey, o.imageKey)
|
|
||||||
&& frames.equals(o.frames)
|
|
||||||
&& Internal.equals(matteKey, o.matteKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (imageKey != null ? imageKey.hashCode() : 0);
|
|
||||||
result = result * 37 + frames.hashCode();
|
|
||||||
result = result * 37 + (matteKey != null ? matteKey.hashCode() : 0);
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (imageKey != null) builder.append(", imageKey=").append(imageKey);
|
|
||||||
if (!frames.isEmpty()) builder.append(", frames=").append(frames);
|
|
||||||
if (matteKey != null) builder.append(", matteKey=").append(matteKey);
|
|
||||||
return builder.replace(0, 2, "SpriteEntity{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<SpriteEntity, Builder> {
|
|
||||||
public String imageKey;
|
|
||||||
|
|
||||||
public List<FrameEntity> frames;
|
|
||||||
|
|
||||||
public String matteKey;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
frames = Internal.newMutableList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 元件所对应的位图键名, 如果 imageKey 含有 .vector 后缀,该 sprite 为矢量图层 含有 .matte 后缀,该 sprite 为遮罩图层。
|
|
||||||
*/
|
|
||||||
public Builder imageKey(String imageKey) {
|
|
||||||
this.imageKey = imageKey;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 帧列表
|
|
||||||
*/
|
|
||||||
public Builder frames(List<FrameEntity> frames) {
|
|
||||||
Internal.checkElementsNotNull(frames);
|
|
||||||
this.frames = frames;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 被遮罩图层的 matteKey 对应的是其遮罩图层的 imageKey.
|
|
||||||
*/
|
|
||||||
public Builder matteKey(String matteKey) {
|
|
||||||
this.matteKey = matteKey;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpriteEntity build() {
|
|
||||||
return new SpriteEntity(imageKey, frames, matteKey, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_SpriteEntity extends ProtoAdapter<SpriteEntity> {
|
|
||||||
ProtoAdapter_SpriteEntity() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, SpriteEntity.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(SpriteEntity value) {
|
|
||||||
return (value.imageKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.imageKey) : 0)
|
|
||||||
+ FrameEntity.ADAPTER.asRepeated().encodedSizeWithTag(2, value.frames)
|
|
||||||
+ (value.matteKey != null ? ProtoAdapter.STRING.encodedSizeWithTag(3, value.matteKey) : 0)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, SpriteEntity value) throws IOException {
|
|
||||||
if (value.imageKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.imageKey);
|
|
||||||
FrameEntity.ADAPTER.asRepeated().encodeWithTag(writer, 2, value.frames);
|
|
||||||
if (value.matteKey != null) ProtoAdapter.STRING.encodeWithTag(writer, 3, value.matteKey);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpriteEntity decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.imageKey(ProtoAdapter.STRING.decode(reader)); break;
|
|
||||||
case 2: builder.frames.add(FrameEntity.ADAPTER.decode(reader)); break;
|
|
||||||
case 3: builder.matteKey(ProtoAdapter.STRING.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpriteEntity redact(SpriteEntity value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
Internal.redactElements(builder.frames, FrameEntity.ADAPTER);
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,251 +0,0 @@
|
|||||||
// Code generated by Wire protocol buffer compiler, do not edit.
|
|
||||||
// Source file: svga.proto at 34:1
|
|
||||||
package com.opensource.svgaplayer.proto;
|
|
||||||
|
|
||||||
import com.squareup.wire.FieldEncoding;
|
|
||||||
import com.squareup.wire.Message;
|
|
||||||
import com.squareup.wire.ProtoAdapter;
|
|
||||||
import com.squareup.wire.ProtoReader;
|
|
||||||
import com.squareup.wire.ProtoWriter;
|
|
||||||
import com.squareup.wire.WireField;
|
|
||||||
import com.squareup.wire.internal.Internal;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.Float;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.lang.Override;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.lang.StringBuilder;
|
|
||||||
import okio.ByteString;
|
|
||||||
|
|
||||||
public final class Transform extends Message<Transform, Transform.Builder> {
|
|
||||||
public static final ProtoAdapter<Transform> ADAPTER = new ProtoAdapter_Transform();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_A = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_B = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_C = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_D = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_TX = 0.0f;
|
|
||||||
|
|
||||||
public static final Float DEFAULT_TY = 0.0f;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 1,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float a;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 2,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float b;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 3,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float c;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 4,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float d;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 5,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float tx;
|
|
||||||
|
|
||||||
@WireField(
|
|
||||||
tag = 6,
|
|
||||||
adapter = "com.squareup.wire.ProtoAdapter#FLOAT"
|
|
||||||
)
|
|
||||||
public final Float ty;
|
|
||||||
|
|
||||||
public Transform(Float a, Float b, Float c, Float d, Float tx, Float ty) {
|
|
||||||
this(a, b, c, d, tx, ty, ByteString.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transform(Float a, Float b, Float c, Float d, Float tx, Float ty, ByteString unknownFields) {
|
|
||||||
super(ADAPTER, unknownFields);
|
|
||||||
this.a = a;
|
|
||||||
this.b = b;
|
|
||||||
this.c = c;
|
|
||||||
this.d = d;
|
|
||||||
this.tx = tx;
|
|
||||||
this.ty = ty;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder newBuilder() {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
builder.a = a;
|
|
||||||
builder.b = b;
|
|
||||||
builder.c = c;
|
|
||||||
builder.d = d;
|
|
||||||
builder.tx = tx;
|
|
||||||
builder.ty = ty;
|
|
||||||
builder.addUnknownFields(unknownFields());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other == this) return true;
|
|
||||||
if (!(other instanceof Transform)) return false;
|
|
||||||
Transform o = (Transform) other;
|
|
||||||
return unknownFields().equals(o.unknownFields())
|
|
||||||
&& Internal.equals(a, o.a)
|
|
||||||
&& Internal.equals(b, o.b)
|
|
||||||
&& Internal.equals(c, o.c)
|
|
||||||
&& Internal.equals(d, o.d)
|
|
||||||
&& Internal.equals(tx, o.tx)
|
|
||||||
&& Internal.equals(ty, o.ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = super.hashCode;
|
|
||||||
if (result == 0) {
|
|
||||||
result = unknownFields().hashCode();
|
|
||||||
result = result * 37 + (a != null ? a.hashCode() : 0);
|
|
||||||
result = result * 37 + (b != null ? b.hashCode() : 0);
|
|
||||||
result = result * 37 + (c != null ? c.hashCode() : 0);
|
|
||||||
result = result * 37 + (d != null ? d.hashCode() : 0);
|
|
||||||
result = result * 37 + (tx != null ? tx.hashCode() : 0);
|
|
||||||
result = result * 37 + (ty != null ? ty.hashCode() : 0);
|
|
||||||
super.hashCode = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (a != null) builder.append(", a=").append(a);
|
|
||||||
if (b != null) builder.append(", b=").append(b);
|
|
||||||
if (c != null) builder.append(", c=").append(c);
|
|
||||||
if (d != null) builder.append(", d=").append(d);
|
|
||||||
if (tx != null) builder.append(", tx=").append(tx);
|
|
||||||
if (ty != null) builder.append(", ty=").append(ty);
|
|
||||||
return builder.replace(0, 2, "Transform{").append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends Message.Builder<Transform, Builder> {
|
|
||||||
public Float a;
|
|
||||||
|
|
||||||
public Float b;
|
|
||||||
|
|
||||||
public Float c;
|
|
||||||
|
|
||||||
public Float d;
|
|
||||||
|
|
||||||
public Float tx;
|
|
||||||
|
|
||||||
public Float ty;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder a(Float a) {
|
|
||||||
this.a = a;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder b(Float b) {
|
|
||||||
this.b = b;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder c(Float c) {
|
|
||||||
this.c = c;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder d(Float d) {
|
|
||||||
this.d = d;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder tx(Float tx) {
|
|
||||||
this.tx = tx;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder ty(Float ty) {
|
|
||||||
this.ty = ty;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Transform build() {
|
|
||||||
return new Transform(a, b, c, d, tx, ty, super.buildUnknownFields());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ProtoAdapter_Transform extends ProtoAdapter<Transform> {
|
|
||||||
ProtoAdapter_Transform() {
|
|
||||||
super(FieldEncoding.LENGTH_DELIMITED, Transform.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int encodedSize(Transform value) {
|
|
||||||
return (value.a != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(1, value.a) : 0)
|
|
||||||
+ (value.b != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(2, value.b) : 0)
|
|
||||||
+ (value.c != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(3, value.c) : 0)
|
|
||||||
+ (value.d != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(4, value.d) : 0)
|
|
||||||
+ (value.tx != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(5, value.tx) : 0)
|
|
||||||
+ (value.ty != null ? ProtoAdapter.FLOAT.encodedSizeWithTag(6, value.ty) : 0)
|
|
||||||
+ value.unknownFields().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(ProtoWriter writer, Transform value) throws IOException {
|
|
||||||
if (value.a != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 1, value.a);
|
|
||||||
if (value.b != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 2, value.b);
|
|
||||||
if (value.c != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 3, value.c);
|
|
||||||
if (value.d != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 4, value.d);
|
|
||||||
if (value.tx != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 5, value.tx);
|
|
||||||
if (value.ty != null) ProtoAdapter.FLOAT.encodeWithTag(writer, 6, value.ty);
|
|
||||||
writer.writeBytes(value.unknownFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Transform decode(ProtoReader reader) throws IOException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
long token = reader.beginMessage();
|
|
||||||
for (int tag; (tag = reader.nextTag()) != -1;) {
|
|
||||||
switch (tag) {
|
|
||||||
case 1: builder.a(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 2: builder.b(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 3: builder.c(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 4: builder.d(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 5: builder.tx(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
case 6: builder.ty(ProtoAdapter.FLOAT.decode(reader)); break;
|
|
||||||
default: {
|
|
||||||
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
|
|
||||||
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
|
|
||||||
builder.addUnknownField(tag, fieldEncoding, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endMessage(token);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Transform redact(Transform value) {
|
|
||||||
Builder builder = value.newBuilder();
|
|
||||||
builder.clearUnknownFields();
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for creating pools of objects. An example use looks like this:
|
|
||||||
* <pre>
|
|
||||||
* public class MyPooledClass {
|
|
||||||
*
|
|
||||||
* private static final SynchronizedPool<MyPooledClass> sPool =
|
|
||||||
* new SynchronizedPool<MyPooledClass>(10);
|
|
||||||
*
|
|
||||||
* public static MyPooledClass obtain() {
|
|
||||||
* MyPooledClass instance = sPool.acquire();
|
|
||||||
* return (instance != null) ? instance : new MyPooledClass();
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* public void recycle() {
|
|
||||||
* // Clear state if needed.
|
|
||||||
* sPool.release(this);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* . . .
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Pools private constructor() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for managing a pool of objects.
|
|
||||||
*
|
|
||||||
* @param <T> The pooled type.
|
|
||||||
*/
|
|
||||||
interface Pool<T> {
|
|
||||||
/**
|
|
||||||
* @return An instance from the pool if such, null otherwise.
|
|
||||||
*/
|
|
||||||
fun acquire(): T?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release an instance to the pool.
|
|
||||||
*
|
|
||||||
* @param instance The instance to release.
|
|
||||||
* @return Whether the instance was put in the pool.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException If the instance is already in the pool.
|
|
||||||
*/
|
|
||||||
fun release(instance: T): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple (non-synchronized) pool of objects.
|
|
||||||
*
|
|
||||||
* @param maxPoolSize The max pool size.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException If the max pool size is less than zero.
|
|
||||||
*
|
|
||||||
* @param <T> The pooled type.
|
|
||||||
*/
|
|
||||||
open class SimplePool<T>(maxPoolSize: Int) : Pool<T> {
|
|
||||||
private val mPool: Array<Any?>
|
|
||||||
private var mPoolSize = 0
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(maxPoolSize > 0) { "The max pool size must be > 0" }
|
|
||||||
mPool = arrayOfNulls(maxPoolSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun acquire(): T? {
|
|
||||||
if (mPoolSize > 0) {
|
|
||||||
val lastPooledIndex = mPoolSize - 1
|
|
||||||
val instance = mPool[lastPooledIndex] as T?
|
|
||||||
mPool[lastPooledIndex] = null
|
|
||||||
mPoolSize--
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun release(instance: T): Boolean {
|
|
||||||
check(!isInPool(instance)) { "Already in the pool!" }
|
|
||||||
if (mPoolSize < mPool.size) {
|
|
||||||
mPool[mPoolSize] = instance
|
|
||||||
mPoolSize++
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isInPool(instance: T): Boolean {
|
|
||||||
for (i in 0 until mPoolSize) {
|
|
||||||
if (mPool[i] === instance) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils
|
|
||||||
|
|
||||||
import android.widget.ImageView
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by ubt on 2018/1/19.
|
|
||||||
*/
|
|
||||||
class SVGAScaleInfo {
|
|
||||||
|
|
||||||
var tranFx : Float = 0.0f
|
|
||||||
var tranFy : Float = 0.0f
|
|
||||||
var scaleFx : Float = 1.0f
|
|
||||||
var scaleFy : Float = 1.0f
|
|
||||||
var ratio = 1.0f
|
|
||||||
var ratioX = false
|
|
||||||
|
|
||||||
private fun resetVar(){
|
|
||||||
tranFx = 0.0f
|
|
||||||
tranFy = 0.0f
|
|
||||||
scaleFx = 1.0f
|
|
||||||
scaleFy = 1.0f
|
|
||||||
ratio = 1.0f
|
|
||||||
ratioX = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun performScaleType(canvasWidth : Float, canvasHeight: Float, videoWidth : Float, videoHeight : Float, scaleType: ImageView.ScaleType) {
|
|
||||||
if (canvasWidth == 0.0f || canvasHeight == 0.0f || videoWidth == 0.0f || videoHeight == 0.0f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resetVar()
|
|
||||||
val canW_vidW_f = (canvasWidth - videoWidth) / 2.0f
|
|
||||||
val canH_vidH_f = (canvasHeight - videoHeight) / 2.0f
|
|
||||||
|
|
||||||
val videoRatio = videoWidth / videoHeight
|
|
||||||
val canvasRatio = canvasWidth / canvasHeight
|
|
||||||
|
|
||||||
val canH_d_vidH = canvasHeight / videoHeight
|
|
||||||
val canW_d_vidW = canvasWidth / videoWidth
|
|
||||||
|
|
||||||
when (scaleType) {
|
|
||||||
ImageView.ScaleType.CENTER -> {
|
|
||||||
tranFx = canW_vidW_f
|
|
||||||
tranFy = canH_vidH_f
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.CENTER_CROP -> {
|
|
||||||
if (videoRatio > canvasRatio) {
|
|
||||||
ratio = canH_d_vidH
|
|
||||||
ratioX = false
|
|
||||||
scaleFx = canH_d_vidH
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.CENTER_INSIDE -> {
|
|
||||||
if (videoWidth < canvasWidth && videoHeight < canvasHeight) {
|
|
||||||
tranFx = canW_vidW_f
|
|
||||||
tranFy = canH_vidH_f
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (videoRatio > canvasRatio) {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ratio = canH_d_vidH
|
|
||||||
ratioX = false
|
|
||||||
scaleFx = canH_d_vidH
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.FIT_CENTER -> {
|
|
||||||
if (videoRatio > canvasRatio) {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
tranFy = (canvasHeight - videoHeight * (canW_d_vidW)) / 2.0f
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ratio = canH_d_vidH
|
|
||||||
ratioX = false
|
|
||||||
scaleFx = canH_d_vidH
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
tranFx = (canvasWidth - videoWidth * (canH_d_vidH)) / 2.0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.FIT_START -> {
|
|
||||||
if (videoRatio > canvasRatio) {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ratio = canH_d_vidH
|
|
||||||
ratioX = false
|
|
||||||
scaleFx = canH_d_vidH
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.FIT_END -> {
|
|
||||||
if (videoRatio > canvasRatio) {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
tranFy= canvasHeight - videoHeight * (canW_d_vidW)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ratio = canH_d_vidH
|
|
||||||
ratioX = false
|
|
||||||
scaleFx = canH_d_vidH
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
tranFx = canvasWidth - videoWidth * (canH_d_vidH)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView.ScaleType.FIT_XY -> {
|
|
||||||
ratio = Math.max(canW_d_vidW, canH_d_vidH)
|
|
||||||
ratioX = canW_d_vidW > canH_d_vidH
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canH_d_vidH
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
ratio = canW_d_vidW
|
|
||||||
ratioX = true
|
|
||||||
scaleFx = canW_d_vidW
|
|
||||||
scaleFy = canW_d_vidW
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cuiminghui on 2017/3/29.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class SVGAPoint(val x: Float, val y: Float, val value: Float)
|
|
||||||
|
|
||||||
class SVGARect(val x: Double, val y: Double, val width: Double, val height: Double)
|
|
||||||
|
|
||||||
class SVGARange(val location: Int, val length: Int)
|
|
@ -1,28 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils.log
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内部默认 ILogger 接口实现
|
|
||||||
*/
|
|
||||||
class DefaultLogCat : ILogger {
|
|
||||||
override fun verbose(tag: String, msg: String) {
|
|
||||||
Log.v(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun info(tag: String, msg: String) {
|
|
||||||
Log.i(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun debug(tag: String, msg: String) {
|
|
||||||
Log.d(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun warn(tag: String, msg: String) {
|
|
||||||
Log.w(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(tag: String, msg: String?, error: Throwable?) {
|
|
||||||
Log.e(tag, msg, error)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils.log
|
|
||||||
|
|
||||||
/**
|
|
||||||
* log 外部接管接口
|
|
||||||
**/
|
|
||||||
interface ILogger {
|
|
||||||
fun verbose(tag: String, msg: String)
|
|
||||||
fun info(tag: String, msg: String)
|
|
||||||
fun debug(tag: String, msg: String)
|
|
||||||
fun warn(tag: String, msg: String)
|
|
||||||
fun error(tag: String, msg: String?, error: Throwable?)
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils.log
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志输出
|
|
||||||
*/
|
|
||||||
internal object LogUtils {
|
|
||||||
private const val TAG = "SVGALog"
|
|
||||||
|
|
||||||
fun verbose(tag: String = TAG, msg: String) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.verbose(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun info(tag: String = TAG, msg: String) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.info(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun debug(tag: String = TAG, msg: String) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.debug(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun warn(tag: String = TAG, msg: String) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.warn(tag, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun error(tag: String = TAG, msg: String) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.error(tag, msg, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun error(tag: String, error: Throwable) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.error(tag, error.message, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun error(tag: String = TAG, msg: String, error: Throwable) {
|
|
||||||
if (!SVGALogger.isLogEnabled()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SVGALogger.getSVGALogger()?.error(tag, msg, error)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package com.opensource.svgaplayer.utils.log
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SVGA logger 配置管理
|
|
||||||
**/
|
|
||||||
object SVGALogger {
|
|
||||||
|
|
||||||
private var mLogger: ILogger? = DefaultLogCat()
|
|
||||||
private var isLogEnabled = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* log 接管注入
|
|
||||||
*/
|
|
||||||
fun injectSVGALoggerImp(logImp: ILogger): SVGALogger {
|
|
||||||
mLogger = logImp
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置是否开启 log
|
|
||||||
*/
|
|
||||||
fun setLogEnabled(isEnabled: Boolean): SVGALogger {
|
|
||||||
isLogEnabled = isEnabled
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前 ILogger 实现类
|
|
||||||
*/
|
|
||||||
fun getSVGALogger(): ILogger? {
|
|
||||||
return mLogger
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启 log
|
|
||||||
*/
|
|
||||||
fun isLogEnabled(): Boolean {
|
|
||||||
return isLogEnabled
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<declare-styleable name="SVGAImageView">
|
|
||||||
<attr name="source" format="string" />
|
|
||||||
<attr name="autoPlay" format="boolean" />
|
|
||||||
<attr name="antiAlias" format="boolean" />
|
|
||||||
<attr name="loopCount" format="integer" />
|
|
||||||
<attr name="clearsAfterStop" format="boolean" />
|
|
||||||
<attr name="clearsAfterDetached" format="boolean" />
|
|
||||||
<attr name="fillMode" format="enum">
|
|
||||||
<enum name="Backward" value="0" />
|
|
||||||
<enum name="Forward" value="1" />
|
|
||||||
<enum name="Clear" value="2"/>
|
|
||||||
</attr>
|
|
||||||
</declare-styleable>
|
|
||||||
</resources>
|
|
@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">SVGAPlayer</string>
|
|
||||||
</resources>
|
|
@ -1,13 +1,18 @@
|
|||||||
apply plugin: 'com.android.library'
|
//apply plugin: 'com.android.library'
|
||||||
apply plugin: 'img-optimizer'
|
//apply plugin: 'img-optimizer'
|
||||||
apply plugin: 'kotlin-android'
|
//apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-parcelize'
|
//apply plugin: 'kotlin-android-extensions'
|
||||||
apply from: "../package_config.gradle"
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'kotlin-android'
|
||||||
|
id 'kotlin-parcelize'
|
||||||
|
id 'img-optimizer'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace "com.pdlive.shayu"
|
namespace "com.pdlive.shayu"
|
||||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
compileSdk rootProject.ext.android.compileSdkVersion
|
||||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
pickFirst "lib/armeabi/libyuvutils.so"
|
pickFirst "lib/armeabi/libyuvutils.so"
|
||||||
pickFirst "lib/arm64-v8a/libyuvutils.so"
|
pickFirst "lib/arm64-v8a/libyuvutils.so"
|
||||||
@ -34,7 +39,7 @@ android {
|
|||||||
versionName rootProject.ext.android.versionName
|
versionName rootProject.ext.android.versionName
|
||||||
manifestPlaceholders = rootProject.ext.manifestPlaceholders
|
manifestPlaceholders = rootProject.ext.manifestPlaceholders
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "armeabi-v7a", "arm64-v8a","x86","x86_64"
|
abiFilters "armeabi-v7a", "arm64-v8a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
@ -49,8 +54,11 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_18
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_18
|
||||||
|
}
|
||||||
|
buildFeatures {
|
||||||
|
buildConfig = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
>
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<package android:name="com.pdlive.shayu"/>
|
<package android:name="com.pandoralive.shayu"/>
|
||||||
<package android:name="com.facebook.orca"/>
|
<package android:name="com.facebook.orca"/>
|
||||||
|
|
||||||
<package
|
<package
|
||||||
@ -18,7 +19,7 @@
|
|||||||
tools:ignore="ExportedContentProvider" />
|
tools:ignore="ExportedContentProvider" />
|
||||||
|
|
||||||
</queries>
|
</queries>
|
||||||
<application android:allowBackup="true">
|
<application>
|
||||||
<activity
|
<activity
|
||||||
android:name="com.facebook.FacebookActivity"
|
android:name="com.facebook.FacebookActivity"
|
||||||
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
|
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
|
||||||
@ -27,7 +28,7 @@
|
|||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="com.facebook.FacebookContentProvider"
|
android:name="com.facebook.FacebookContentProvider"
|
||||||
android:authorities="com.facebook.app.FacebookContentProvider2011402032399020"
|
android:authorities="com.facebook.app.FacebookContentProvider5476953575716796"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.yunbao.share.receiver.TwitterResultReceiver"
|
android:name="com.yunbao.share.receiver.TwitterResultReceiver"
|
||||||
|
@ -7,7 +7,7 @@ import android.net.Uri;
|
|||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import com.twitter.sdk.android.tweetcomposer.TweetUploadService;
|
import com.twitter.sdk.android.tweetcomposer.TweetUploadService;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
import com.yunbao.share.receiver.TwitterResultReceiver;
|
import com.yunbao.share.receiver.TwitterResultReceiver;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -23,7 +23,7 @@ public abstract class AbsShareInterface {
|
|||||||
context.registerReceiver(new TwitterResultReceiver(), filter);
|
context.registerReceiver(new TwitterResultReceiver(), filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void share(ShareBuilder builder, ICallback callback);
|
public abstract void share(ShareBean builder, ICallback callback);
|
||||||
|
|
||||||
public Uri fileToUri(File file){
|
public Uri fileToUri(File file){
|
||||||
return FileProvider.getUriForFile(mContext,
|
return FileProvider.getUriForFile(mContext,
|
||||||
|
@ -0,0 +1,128 @@
|
|||||||
|
package com.yunbao.share.adapters;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.pdlive.shayu.R;
|
||||||
|
import com.yunbao.common.glide.ImgLoader;
|
||||||
|
import com.yunbao.common.utils.ViewUtils;
|
||||||
|
import com.yunbao.common.views.weight.ClipPathCircleImage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.rong.imkit.conversationlist.model.SingleConversation;
|
||||||
|
import io.rong.imlib.model.Conversation;
|
||||||
|
|
||||||
|
public class InternalShareAdapter extends RecyclerView.Adapter<InternalShareAdapter.ViewHolder> {
|
||||||
|
List<SingleConversation> listData = new ArrayList<>();
|
||||||
|
int selectPosition = -1;
|
||||||
|
private int isEmpty = -233;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
public InternalShareAdapter(Context mContext) {
|
||||||
|
this.mContext = mContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
if (viewType == isEmpty) {
|
||||||
|
return new EmptyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_layout_msg, parent, false));
|
||||||
|
}
|
||||||
|
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_internal_user, parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
if (getItemViewType(position) == isEmpty) return;
|
||||||
|
holder.bind(listData.get(position), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (listData.get(position).mCore.getTargetId().equals("isEmpty_-233-pdl-5YK76YC8")) {
|
||||||
|
return isEmpty;
|
||||||
|
}
|
||||||
|
return super.getItemViewType(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return listData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<SingleConversation> listData) {
|
||||||
|
if (listData == null) {
|
||||||
|
listData = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (listData.isEmpty()) {
|
||||||
|
Conversation conversation = new Conversation();
|
||||||
|
conversation.setTargetId("isEmpty_-233-pdl-5YK76YC8");
|
||||||
|
listData.add(new SingleConversation(mContext, conversation));
|
||||||
|
}
|
||||||
|
this.listData = listData;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectPosition() {
|
||||||
|
return selectPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SingleConversation> getListData() {
|
||||||
|
return listData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmptyViewHolder extends ViewHolder {
|
||||||
|
|
||||||
|
public EmptyViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ViewUtils.findViewById(itemView, R.id.imageView, ImageView.class).setImageResource(R.mipmap.ic_addressbook_not_search);
|
||||||
|
ViewUtils.findViewById(itemView, R.id.textView, TextView.class).setText(R.string.not_data_message_address_book_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
ClipPathCircleImage mAvatar;
|
||||||
|
TextView userName;
|
||||||
|
TextView content;
|
||||||
|
RadioButton radioButton;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
mAvatar = itemView.findViewById(R.id.rc_conversation_portrait);
|
||||||
|
userName = itemView.findViewById(R.id.rc_conversation_title);
|
||||||
|
content = itemView.findViewById(R.id.rc_conversation_content);
|
||||||
|
radioButton = itemView.findViewById(R.id.btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(SingleConversation item, int position) {
|
||||||
|
ImgLoader.display(itemView.getContext(), item.mCore.getPortraitUrl(), mAvatar);
|
||||||
|
userName.setText(item.mCore.getConversationTitle());
|
||||||
|
content.setText("");
|
||||||
|
if (selectPosition == position) {
|
||||||
|
radioButton.setChecked(true);
|
||||||
|
} else {
|
||||||
|
radioButton.setChecked(false);
|
||||||
|
}
|
||||||
|
radioButton.setOnClickListener(view -> {
|
||||||
|
selectPosition = position;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
itemView.setOnClickListener(view -> {
|
||||||
|
selectPosition = position;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.yunbao.share.adapters;
|
package com.yunbao.share.adapters;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Environment;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -15,28 +14,39 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import com.pdlive.shayu.R;
|
import com.pdlive.shayu.R;
|
||||||
import com.yunbao.share.ICallback;
|
import com.yunbao.share.ICallback;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
import com.yunbao.share.platform.FacebookShare;
|
import com.yunbao.share.platform.FacebookShare;
|
||||||
import com.yunbao.share.platform.Instagram;
|
import com.yunbao.share.platform.Instagram;
|
||||||
|
import com.yunbao.share.platform.Internal;
|
||||||
import com.yunbao.share.platform.Line;
|
import com.yunbao.share.platform.Line;
|
||||||
import com.yunbao.share.platform.MessengerShare;
|
import com.yunbao.share.platform.MessengerShare;
|
||||||
import com.yunbao.share.platform.TwitterShare;
|
import com.yunbao.share.platform.TwitterShare;
|
||||||
import com.yunbao.share.platform.WhatsApp;
|
import com.yunbao.share.platform.WhatsApp;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppViewHolder> {
|
public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppViewHolder> {
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private List<ShareBuilder> list;
|
private List<ShareBean> list;
|
||||||
|
ShareCallback shareCallback;
|
||||||
|
|
||||||
|
private onShareListener onShareListener;
|
||||||
|
|
||||||
|
public ShareAppAdapter.onShareListener getOnShareListener() {
|
||||||
|
return onShareListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnShareListener(ShareAppAdapter.onShareListener onShareListener) {
|
||||||
|
this.onShareListener = onShareListener;
|
||||||
|
}
|
||||||
|
|
||||||
public ShareAppAdapter(Context mContext) {
|
public ShareAppAdapter(Context mContext) {
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
this.mContext = mContext;
|
this.mContext = mContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setList(List<ShareBuilder> list) {
|
public void setList(List<ShareBean> list) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@ -49,26 +59,30 @@ public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppVie
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull AppViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull AppViewHolder holder, int position) {
|
||||||
ShareBuilder builder = list.get(position);
|
ShareBean builder = list.get(position);
|
||||||
|
System.out.println("------type------>" + builder.getType());
|
||||||
switch (builder.getType()) {
|
switch (builder.getType()) {
|
||||||
case ShareBuilder.APP_FACEBOOK:
|
case ShareBean.APP_FACEBOOK:
|
||||||
holder.setData(builder, R.mipmap.icon_share_facebook, R.string.dialog_share_app_facebook);
|
holder.setData(builder, R.mipmap.icon_share_facebook, R.string.dialog_share_app_facebook);
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_LINE:
|
case ShareBean.APP_LINE:
|
||||||
holder.setData(builder, R.mipmap.icon_share_line, R.string.dialog_share_app_line);
|
holder.setData(builder, R.mipmap.icon_share_line, R.string.dialog_share_app_line);
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_TWITTER:
|
case ShareBean.APP_TWITTER:
|
||||||
holder.setData(builder, R.mipmap.icon_share_twitter, R.string.dialog_share_app_twitter);
|
holder.setData(builder, R.mipmap.icon_share_twitter, R.string.dialog_share_app_twitter);
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_WHATSAPP:
|
case ShareBean.APP_WHATSAPP:
|
||||||
holder.setData(builder, R.mipmap.icon_share_whatsapp, R.string.dialog_share_app_whatsapp);
|
holder.setData(builder, R.mipmap.icon_share_whatsapp, R.string.dialog_share_app_whatsapp);
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_MESSENGER:
|
case ShareBean.APP_MESSENGER:
|
||||||
holder.setData(builder, R.mipmap.icon_share_messenger, R.string.dialog_share_app_messenger);
|
holder.setData(builder, R.mipmap.icon_share_messenger, R.string.dialog_share_app_messenger);
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_INSTAGRAM:
|
case ShareBean.APP_INSTAGRAM:
|
||||||
holder.setData(builder, R.mipmap.icon_share_instagram, R.string.dialog_share_app_instagram);
|
holder.setData(builder, R.mipmap.icon_share_instagram, R.string.dialog_share_app_instagram);
|
||||||
break;
|
break;
|
||||||
|
case ShareBean.APP_INTERNAL:
|
||||||
|
holder.setData(builder, R.mipmap.ic_share_friend, R.string.dialog_share_app_internal);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +91,14 @@ public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppVie
|
|||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AppViewHolder extends RecyclerView.ViewHolder {
|
public void setOnShareStatusListener(ShareCallback shareCallback) {
|
||||||
|
this.shareCallback = shareCallback;
|
||||||
|
if (this.shareCallback == null) {
|
||||||
|
this.shareCallback = new ShareCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppViewHolder extends RecyclerView.ViewHolder {
|
||||||
ImageView icon;
|
ImageView icon;
|
||||||
TextView title;
|
TextView title;
|
||||||
|
|
||||||
@ -87,34 +108,45 @@ public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppVie
|
|||||||
title = itemView.findViewById(R.id.share_app_name);
|
title = itemView.findViewById(R.id.share_app_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(ShareBuilder bean, @DrawableRes int iconId, @StringRes int appName) {
|
public void setData(ShareBean bean, @DrawableRes int iconId, @StringRes int appName) {
|
||||||
icon.setImageResource(iconId);
|
icon.setImageResource(iconId);
|
||||||
title.setText(appName);
|
title.setText(appName);
|
||||||
itemView.setOnClickListener(v -> {
|
itemView.setOnClickListener(v -> {
|
||||||
switch (bean.getType()) {
|
switch (bean.getType()) {
|
||||||
case ShareBuilder.APP_FACEBOOK:
|
case ShareBean.APP_FACEBOOK:
|
||||||
new FacebookShare(itemView.getContext()).share(bean, new ShareCallback());
|
new FacebookShare(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_LINE:
|
case ShareBean.APP_LINE:
|
||||||
new Line(itemView.getContext()).share(bean, new ShareCallback());
|
new Line(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_TWITTER:
|
case ShareBean.APP_TWITTER:
|
||||||
new TwitterShare(itemView.getContext()).share(bean, new ShareCallback());
|
new TwitterShare(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_WHATSAPP:
|
case ShareBean.APP_WHATSAPP:
|
||||||
new WhatsApp(itemView.getContext()).share(bean, new ShareCallback());
|
new WhatsApp(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_MESSENGER:
|
case ShareBean.APP_MESSENGER:
|
||||||
new MessengerShare(itemView.getContext()).share(bean, new ShareCallback());
|
new MessengerShare(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
case ShareBuilder.APP_INSTAGRAM:
|
case ShareBean.APP_INSTAGRAM:
|
||||||
new Instagram(itemView.getContext()).share(bean, new ShareCallback());
|
new Instagram(itemView.getContext()).share(bean, new ShareCallback());
|
||||||
break;
|
break;
|
||||||
|
case ShareBean.APP_INTERNAL:
|
||||||
|
new Internal(itemView.getContext()).share(bean, shareCallback);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (onShareListener != null) {
|
||||||
|
onShareListener.onAddShareCount();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ShareCallback implements ICallback {
|
public interface onShareListener {
|
||||||
|
void onAddShareCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ShareCallback implements ICallback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
@ -127,4 +159,3 @@ public class ShareAppAdapter extends RecyclerView.Adapter<ShareAppAdapter.AppVie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
276
Share/src/main/java/com/yunbao/share/bean/ShareBean.java
Normal file
276
Share/src/main/java/com/yunbao/share/bean/ShareBean.java
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package com.yunbao.share.bean;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.yunbao.common.CommonAppConfig;
|
||||||
|
import com.yunbao.common.utils.StringUtil;
|
||||||
|
import com.yunbao.common.utils.WordUtil;
|
||||||
|
import com.yunbao.share.ui.SharePopDialog;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class ShareBean {
|
||||||
|
public static final int APP_FACEBOOK = 0;
|
||||||
|
public static final int APP_LINE = 1;
|
||||||
|
public static final int APP_TWITTER = 2;
|
||||||
|
public static final int APP_WHATSAPP = 3;
|
||||||
|
public static final int APP_MESSENGER = 4;
|
||||||
|
public static final int APP_INSTAGRAM = 5;
|
||||||
|
public static final int APP_INTERNAL = 6;
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
private String link;
|
||||||
|
private File file;
|
||||||
|
private int type;
|
||||||
|
private String uid;
|
||||||
|
private String anchorId;
|
||||||
|
private String anchorName;
|
||||||
|
private String anchorAvatar;
|
||||||
|
private int shareType;
|
||||||
|
private String cover;
|
||||||
|
private String title;
|
||||||
|
private String extraData;
|
||||||
|
|
||||||
|
|
||||||
|
public static String createLiveShareLink(String shareUid, String anchorId, String anchorName, String anchorAvatar) {
|
||||||
|
return String.format(CommonAppConfig.HOST +
|
||||||
|
"/index.php?g=Appapi&m=home&a=share&uid=%s&user_id=%s&isGoogle=%s",
|
||||||
|
anchorId,
|
||||||
|
shareUid,
|
||||||
|
CommonAppConfig.IS_GOOGLE_PLAY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createInviteLink(String shareUid) {
|
||||||
|
return String.format("https://www.pdlive.com/public/app/download/index.html?user_id=%s&isGoogle=%s",
|
||||||
|
shareUid,
|
||||||
|
CommonAppConfig.IS_GOOGLE_PLAY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShareBean builder(int type) {
|
||||||
|
return new ShareBean(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShareBean(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getShareType() {
|
||||||
|
return shareType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShareType(int shareType) {
|
||||||
|
this.shareType = shareType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCover() {
|
||||||
|
return cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCover(String cover) {
|
||||||
|
this.cover = cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUid() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUid(String uid) {
|
||||||
|
this.uid = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAnchorId() {
|
||||||
|
return anchorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchorId(String anchorId) {
|
||||||
|
this.anchorId = anchorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAnchorName() {
|
||||||
|
return anchorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchorName(String anchorName) {
|
||||||
|
this.anchorName = anchorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAnchorAvatar() {
|
||||||
|
return anchorAvatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchorAvatar(String anchorAvatar) {
|
||||||
|
this.anchorAvatar = anchorAvatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtraData() {
|
||||||
|
return extraData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtraData(String extraData) {
|
||||||
|
this.extraData = extraData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBean setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBean setLink(String link) {
|
||||||
|
this.link = link;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBean setFile(File file) {
|
||||||
|
this.file = file;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
if (StringUtil.isEmpty(text)) {
|
||||||
|
return getLink();
|
||||||
|
}
|
||||||
|
return text + "\n" + getLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLink() {
|
||||||
|
if (StringUtil.isEmpty(link)) {
|
||||||
|
link = createLiveShareLink(uid, anchorId, anchorName, anchorAvatar);
|
||||||
|
}
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ShareBuilder{" +
|
||||||
|
"text='" + text + '\'' +
|
||||||
|
", link='" + link + '\'' +
|
||||||
|
", file=" + file +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* private String text;
|
||||||
|
* private String link;
|
||||||
|
* private File file;
|
||||||
|
* private int type;
|
||||||
|
* private String uid;
|
||||||
|
* private String anchorId;
|
||||||
|
* private String anchorName;
|
||||||
|
* private String anchorAvatar;
|
||||||
|
* private int shareType;
|
||||||
|
* private String cover;
|
||||||
|
* private String title;
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ShareBean clone() {
|
||||||
|
ShareBean bean = new ShareBean(type);
|
||||||
|
bean.anchorId = anchorId;
|
||||||
|
bean.anchorName = anchorName;
|
||||||
|
bean.anchorAvatar = anchorAvatar;
|
||||||
|
bean.text = text;
|
||||||
|
bean.link = link;
|
||||||
|
bean.file = file;
|
||||||
|
bean.uid = uid;
|
||||||
|
bean.shareType = shareType;
|
||||||
|
bean.cover = cover;
|
||||||
|
bean.title = title;
|
||||||
|
bean.extraData = extraData;
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ShareBuilder {
|
||||||
|
ShareBean bean;
|
||||||
|
|
||||||
|
public ShareBuilder() {
|
||||||
|
bean = new ShareBean(APP_FACEBOOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setShareType(int shareType) {
|
||||||
|
bean.setShareType(shareType);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setCover(String cover) {
|
||||||
|
bean.setCover(cover);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setTitle(String title) {
|
||||||
|
bean.setTitle(title);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setUid(String uid) {
|
||||||
|
bean.setUid(uid);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setAnchorId(String anchorId) {
|
||||||
|
bean.setAnchorId(anchorId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setAnchorName(String anchorName) {
|
||||||
|
bean.setAnchorName(anchorName);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setAnchorAvatar(String anchorAvatar) {
|
||||||
|
bean.setAnchorAvatar(anchorAvatar);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setText(String text) {
|
||||||
|
bean.setText(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setLink(String link) {
|
||||||
|
bean.setLink(link);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setFile(File file) {
|
||||||
|
bean.setFile(file);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBuilder setExtraData(String extraData) {
|
||||||
|
bean.setExtraData(extraData);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShareBean build() {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ShareBuilder create() {
|
||||||
|
return new ShareBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,134 +0,0 @@
|
|||||||
package com.yunbao.share.bean;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.yunbao.common.CommonAppConfig;
|
|
||||||
import com.yunbao.common.CommonAppContext;
|
|
||||||
import com.yunbao.common.manager.IMLoginManager;
|
|
||||||
import com.yunbao.common.utils.StringUtil;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class ShareBuilder {
|
|
||||||
public static final int APP_FACEBOOK = 0;
|
|
||||||
public static final int APP_LINE = 1;
|
|
||||||
public static final int APP_TWITTER = 2;
|
|
||||||
public static final int APP_WHATSAPP = 3;
|
|
||||||
public static final int APP_MESSENGER = 4;
|
|
||||||
public static final int APP_INSTAGRAM = 5;
|
|
||||||
|
|
||||||
private String text;
|
|
||||||
private String link;
|
|
||||||
private File file;
|
|
||||||
private int type;
|
|
||||||
private String uid;
|
|
||||||
private String anchorId;
|
|
||||||
private String anchorName;
|
|
||||||
private String anchorAvatar;
|
|
||||||
|
|
||||||
public static String createLiveShareLink(String shareUid, String anchorId, String anchorName, String anchorAvatar) {
|
|
||||||
return String.format(CommonAppConfig.HOST +
|
|
||||||
"/index.php?g=Appapi&m=home&a=share&uid=%s&user_id=%s&isGoogle=%s",
|
|
||||||
anchorId,
|
|
||||||
shareUid,
|
|
||||||
CommonAppConfig.IS_GOOGLE_PLAY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String createInviteLink(String shareUid) {
|
|
||||||
return String.format("https://www.pdlive.com/public/app/download/index.html?user_id=%s&isGoogle=%s",
|
|
||||||
shareUid,
|
|
||||||
CommonAppConfig.IS_GOOGLE_PLAY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ShareBuilder builder(int type) {
|
|
||||||
return new ShareBuilder(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ShareBuilder(int type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUid() {
|
|
||||||
return uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUid(String uid) {
|
|
||||||
this.uid = uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAnchorId() {
|
|
||||||
return anchorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnchorId(String anchorId) {
|
|
||||||
this.anchorId = anchorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAnchorName() {
|
|
||||||
return anchorName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnchorName(String anchorName) {
|
|
||||||
this.anchorName = anchorName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAnchorAvatar() {
|
|
||||||
return anchorAvatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnchorAvatar(String anchorAvatar) {
|
|
||||||
this.anchorAvatar = anchorAvatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShareBuilder setText(String text) {
|
|
||||||
this.text = text;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShareBuilder setLink(String link) {
|
|
||||||
this.link = link;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShareBuilder setFile(File file) {
|
|
||||||
this.file = file;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
if (StringUtil.isEmpty(text)) {
|
|
||||||
return getLink();
|
|
||||||
}
|
|
||||||
return text + "\n" + getLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLink() {
|
|
||||||
if (StringUtil.isEmpty(link)) {
|
|
||||||
link = createLiveShareLink(uid, anchorId, anchorName, anchorAvatar);
|
|
||||||
}
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getFile() {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ShareBuilder{" +
|
|
||||||
"text='" + text + '\'' +
|
|
||||||
", link='" + link + '\'' +
|
|
||||||
", file=" + file +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,10 +12,9 @@ import com.facebook.FacebookException;
|
|||||||
import com.facebook.share.Sharer;
|
import com.facebook.share.Sharer;
|
||||||
import com.facebook.share.model.ShareLinkContent;
|
import com.facebook.share.model.ShareLinkContent;
|
||||||
import com.facebook.share.widget.ShareDialog;
|
import com.facebook.share.widget.ShareDialog;
|
||||||
import com.yunbao.common.utils.ToastUtil;
|
|
||||||
import com.yunbao.share.AbsShareInterface;
|
import com.yunbao.share.AbsShareInterface;
|
||||||
import com.yunbao.share.ICallback;
|
import com.yunbao.share.ICallback;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
|
|
||||||
public class FacebookShare extends AbsShareInterface {
|
public class FacebookShare extends AbsShareInterface {
|
||||||
public static CallbackManager callbackManager;
|
public static CallbackManager callbackManager;
|
||||||
@ -24,7 +23,7 @@ public class FacebookShare extends AbsShareInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(ShareBuilder builder, ICallback callback) {
|
public void share(ShareBean builder, ICallback callback) {
|
||||||
callbackManager= CallbackManager.Factory.create();
|
callbackManager= CallbackManager.Factory.create();
|
||||||
ShareLinkContent content = new ShareLinkContent.Builder()
|
ShareLinkContent content = new ShareLinkContent.Builder()
|
||||||
.setContentUrl(Uri.parse(builder.getLink()))
|
.setContentUrl(Uri.parse(builder.getLink()))
|
||||||
|
@ -6,7 +6,7 @@ import android.net.Uri;
|
|||||||
|
|
||||||
import com.yunbao.share.AbsShareInterface;
|
import com.yunbao.share.AbsShareInterface;
|
||||||
import com.yunbao.share.ICallback;
|
import com.yunbao.share.ICallback;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
|
|
||||||
public class Instagram extends AbsShareInterface {
|
public class Instagram extends AbsShareInterface {
|
||||||
public Instagram(Context context) {
|
public Instagram(Context context) {
|
||||||
@ -14,7 +14,7 @@ public class Instagram extends AbsShareInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(ShareBuilder builder, ICallback callback) {
|
public void share(ShareBean builder, ICallback callback) {
|
||||||
String type = "image/*";
|
String type = "image/*";
|
||||||
Intent share = new Intent(Intent.ACTION_SEND);
|
Intent share = new Intent(Intent.ACTION_SEND);
|
||||||
Uri uri = fileToUri(builder.getFile());
|
Uri uri = fileToUri(builder.getFile());
|
||||||
|
65
Share/src/main/java/com/yunbao/share/platform/Internal.java
Normal file
65
Share/src/main/java/com/yunbao/share/platform/Internal.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package com.yunbao.share.platform;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.yunbao.common.interfaces.OnItemClickListener;
|
||||||
|
import com.yunbao.common.interfaces.OnSendMessageListener;
|
||||||
|
import com.yunbao.common.message.content.MessageChatCardContent;
|
||||||
|
import com.yunbao.share.AbsShareInterface;
|
||||||
|
import com.yunbao.share.ICallback;
|
||||||
|
import com.yunbao.share.bean.ShareBean;
|
||||||
|
import com.yunbao.share.ui.AppInternalShareDialog;
|
||||||
|
import com.yunbao.share.ui.SharePopDialog;
|
||||||
|
import com.yunbao.share.ui.ShareSuccessNotifyDialog;
|
||||||
|
|
||||||
|
import io.rong.imlib.model.Conversation;
|
||||||
|
|
||||||
|
public class Internal extends AbsShareInterface {
|
||||||
|
public Internal(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void share(ShareBean builder, ICallback callback) {
|
||||||
|
new AppInternalShareDialog(mContext)
|
||||||
|
.setOnItemClickListener(new OnItemClickListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(String toUid, int position) {
|
||||||
|
if (position == -1) {
|
||||||
|
callback.onFailure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
builder.setUid(toUid);
|
||||||
|
sendMessage(builder);
|
||||||
|
new ShareSuccessNotifyDialog(mContext, builder)
|
||||||
|
.showDialog();
|
||||||
|
callback.onSuccess();
|
||||||
|
}
|
||||||
|
}).showDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(ShareBean builder) {
|
||||||
|
MessageChatCardContent.sendMessage(Conversation.ConversationType.PRIVATE, builder.getUid(),
|
||||||
|
MessageChatCardContent.obtain(
|
||||||
|
builder.getCover(),
|
||||||
|
builder.getTitle(),
|
||||||
|
builder.getAnchorAvatar(),
|
||||||
|
builder.getAnchorName(),
|
||||||
|
builder.getAnchorId(),
|
||||||
|
builder.getShareType() + "",
|
||||||
|
builder.getExtraData()
|
||||||
|
),
|
||||||
|
new OnSendMessageListener<Object>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String token, Object bean) {
|
||||||
|
super.onSuccess(token, bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int status, String msg) {
|
||||||
|
super.onError(status, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import android.net.Uri;
|
|||||||
|
|
||||||
import com.yunbao.share.AbsShareInterface;
|
import com.yunbao.share.AbsShareInterface;
|
||||||
import com.yunbao.share.ICallback;
|
import com.yunbao.share.ICallback;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ public class Line extends AbsShareInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(ShareBuilder builder, ICallback callback) {
|
public void share(ShareBean builder, ICallback callback) {
|
||||||
try {
|
try {
|
||||||
Intent share = new Intent(Intent.ACTION_VIEW, Uri.parse("https://line.me/R/share?text=" + URLEncoder.encode(builder.getText(), "UTF-8")));
|
Intent share = new Intent(Intent.ACTION_VIEW, Uri.parse("https://line.me/R/share?text=" + URLEncoder.encode(builder.getText(), "UTF-8")));
|
||||||
mContext.startActivity(share);
|
mContext.startActivity(share);
|
||||||
|
@ -13,10 +13,9 @@ import com.facebook.FacebookSdk;
|
|||||||
import com.facebook.share.Sharer;
|
import com.facebook.share.Sharer;
|
||||||
import com.facebook.share.model.ShareLinkContent;
|
import com.facebook.share.model.ShareLinkContent;
|
||||||
import com.facebook.share.widget.MessageDialog;
|
import com.facebook.share.widget.MessageDialog;
|
||||||
import com.yunbao.common.utils.ToastUtil;
|
|
||||||
import com.yunbao.share.AbsShareInterface;
|
import com.yunbao.share.AbsShareInterface;
|
||||||
import com.yunbao.share.ICallback;
|
import com.yunbao.share.ICallback;
|
||||||
import com.yunbao.share.bean.ShareBuilder;
|
import com.yunbao.share.bean.ShareBean;
|
||||||
|
|
||||||
public class MessengerShare extends AbsShareInterface {
|
public class MessengerShare extends AbsShareInterface {
|
||||||
public static CallbackManager callbackManager;
|
public static CallbackManager callbackManager;
|
||||||
@ -27,7 +26,7 @@ public class MessengerShare extends AbsShareInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(ShareBuilder builder, ICallback callback) {
|
public void share(ShareBean builder, ICallback callback) {
|
||||||
callbackManager = CallbackManager.Factory.create();
|
callbackManager = CallbackManager.Factory.create();
|
||||||
ShareLinkContent content = new ShareLinkContent.Builder()
|
ShareLinkContent content = new ShareLinkContent.Builder()
|
||||||
.setContentUrl(Uri.parse(builder.getLink()))
|
.setContentUrl(Uri.parse(builder.getLink()))
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user