Max+参数采集

This commit is contained in:
litingting 2025-06-25 14:32:24 +08:00
parent 75e7412a8e
commit f7fb0ca050
21 changed files with 990 additions and 99 deletions

View File

@ -5,10 +5,14 @@ import java.text.SimpleDateFormat
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
// id("com.google.gms.google-services")
// id("com.google.firebase.crashlytics")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
kotlin("kapt")
id ("kotlin-android")
id("applovin-quality-service")
}
applovin {
apiKey = "Ln9ZBkOoNWDdTK3a4iHGH4XW1scCVDW14WRkncTTQHC1AIOkNRUT8OUAkEQOSHFrWp5Mn3eRrrnmT3dWmw41zD"
}
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
@ -21,8 +25,8 @@ android {
applicationId = "com.app.keyboard.colorful"
minSdk = 23
targetSdk = 34
versionCode = 1
versionName = "1.0"
versionCode = 2
versionName = "1.1"
setProperty(
"archivesBaseName",
"Colorful Keyboard_V" + versionName + "(${versionCode})_$timestamp"
@ -74,69 +78,27 @@ dependencies {
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")
// implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
// implementation("com.google.firebase:firebase-crashlytics")
// implementation("com.google.firebase:firebase-analytics")
// implementation("com.google.firebase:firebase-config")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-config")
//-----------------------------------------------TopOn(pangle、IronSource、mintegral、unityads、liftoff(vungle)、Bigo)
//Anythink (Necessary)
// implementation("com.anythink.sdk:core-tpn:6.3.68")
// implementation("com.anythink.sdk:nativead-tpn:6.3.68")
// implementation("com.anythink.sdk:banner-tpn:6.3.68")
// implementation("com.anythink.sdk:interstitial-tpn:6.3.68")
// implementation("com.anythink.sdk:rewardedvideo-tpn:6.3.68")
// implementation("com.anythink.sdk:splash-tpn:6.3.68")
//
// //Androidx (Necessary)
// implementation("androidx.appcompat:appcompat:1.1.0")
// implementation("androidx.browser:browser:1.4.0")
//
// //Vungle
// implementation("com.anythink.sdk:adapter-tpn-vungle:6.3.68")
// implementation("com.vungle:vungle-ads:7.3.2")
// implementation("com.google.android.gms:play-services-basement:18.1.0")
// implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
//
// //UnityAds
// implementation("com.anythink.sdk:adapter-tpn-unityads:6.3.68")
// implementation("com.unity3d.ads:unity-ads:4.9.3")
//
// //Ironsource
// implementation("com.anythink.sdk:adapter-tpn-ironsource:6.3.68")
// implementation("com.ironsource.sdk:mediationsdk:8.1.0")
// implementation("com.google.android.gms:play-services-appset:16.0.2")
// implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
// implementation("com.google.android.gms:play-services-basement:18.1.0")
//
// //Bigo
// implementation("com.anythink.sdk:adapter-tpn-bigo:6.3.68")
// implementation("com.bigossp:bigo-ads:4.7.4")
//
// //Pangle
// implementation("com.anythink.sdk:adapter-tpn-pangle-nonchina:6.3.68.1")
// implementation( "com.pangle.global:ads-sdk:6.0.0.3")
// implementation( "com.google.android.gms:play-services-ads-identifier:18.0.1")
//
// //Mintegral
// implementation("com.anythink.sdk:adapter-tpn-mintegral-nonchina:6.3.68")
// implementation("com.mbridge.msdk.oversea:reward:16.7.51")
// implementation("com.mbridge.msdk.oversea:newinterstitial:16.7.51")
// implementation("com.mbridge.msdk.oversea:mbnative:16.7.51")
// implementation("com.mbridge.msdk.oversea:mbnativeadvanced:16.7.51")
// implementation("com.mbridge.msdk.oversea:mbsplash:16.7.51")
// implementation("com.mbridge.msdk.oversea:mbbanner:16.7.51")
// implementation("com.mbridge.msdk.oversea:mbbid:16.7.51")
// implementation("androidx.recyclerview:recyclerview:1.1.0")
//
// //Tramini
// implementation("com.anythink.sdk:tramini-plugin-tpn:6.3.68")
//
// // Debugger UI Tools
// implementation ("com.anythink.sdk:debugger-ui:1.0.7")
//----------------------------------------------TopOn
//Max(BIGO Ads、Chartboost、DT Exchange、InMobi、ironSource、Liftoff Monetize、Mintegral、Pangle)
implementation("com.applovin:applovin-sdk:+")
implementation("com.applovin.mediation:bigoads-adapter:+")
implementation("com.applovin.mediation:chartboost-adapter:+")
implementation("com.google.android.gms:play-services-base:16.1.0")
implementation("com.applovin.mediation:fyber-adapter:+")
implementation("com.applovin.mediation:inmobi-adapter:+")
implementation("com.squareup.picasso:picasso:2.8")
implementation("androidx.recyclerview:recyclerview:1.1.0")
implementation("com.applovin.mediation:ironsource-adapter:+")
implementation("com.applovin.mediation:vungle-adapter:+")
implementation("com.applovin.mediation:mintegral-adapter:+")
implementation("com.applovin.mediation:bytedance-adapter:+")
}

29
app/google-services.json Normal file
View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "57413153295",
"project_id": "colorful-keyboard-14488",
"storage_bucket": "colorful-keyboard-14488.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:57413153295:android:e27a2700ec70668a21697a",
"android_client_info": {
"package_name": "com.app.keyboard.colorful"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAlufDnsZ4Faf0nIgXVvzoEpzXtnXOduXw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -12,6 +12,7 @@
android:roundIcon="@mipmap/icon"
android:supportsRtl="true"
android:theme="@style/MyKeyBoard"
android:networkSecurityConfig="@xml/net"
tools:targetApi="31">
<activity
android:name=".activity.ActivityAll"

View File

@ -1,10 +1,16 @@
package com.app.keyboard.colorful
//import com.pretty.keyboard.theme.keyboard.helper.ObjectBox
import android.app.Application
import android.content.Intent
import android.graphics.Typeface
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.app.keyboard.colorful.data.ChildBean
import com.app.keyboard.colorful.data.ClassBean
//import com.pretty.keyboard.theme.keyboard.helper.ObjectBox
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import org.json.JSONArray
import java.io.BufferedReader
import java.io.IOException
@ -12,6 +18,7 @@ import java.io.InputStream
import java.io.InputStreamReader
import java.io.StringWriter
class MyApp : Application() {
companion object {
lateinit var myAppInstance: MyApp
@ -22,12 +29,15 @@ class MyApp : Application() {
var defaultFont: Typeface? = null
const val DB_VERSION = 1
const val DB_NAME = "db_name"
var initSDkOK = false
var initAction = "ACTION_INIT"
}
override fun onCreate() {
super.onCreate()
myAppInstance = this
defaultFont = Typeface.createFromAsset(assets, "font.ttf")
initMAxSDk()
dealFile()
@ -119,4 +129,16 @@ class MyApp : Application() {
private val SDK_KEY = "yhOU4TgSF10NVhdOBNZy6VbUxFc25c78nh_LA3905OB6rHVXJdsa0DVUhsIA6DWqJaHKDkimoBWXD5CktvrVXg"
private fun initMAxSDk() {
val initConfig = AppLovinSdkInitializationConfiguration.builder(SDK_KEY, this)
.setMediationProvider(AppLovinMediationProvider.MAX)
.build()
AppLovinSdk.getInstance(this).initialize(initConfig) {
initSDkOK = true
LocalBroadcastManager.getInstance(this@MyApp).sendBroadcast(Intent(initAction))
}
}
}

View File

@ -13,6 +13,8 @@ import com.app.keyboard.colorful.data.ClassBean;
import com.app.keyboard.colorful.ada.AdaOther;
import com.app.keyboard.colorful.helper.CommonUtils;
import com.app.keyboard.colorful.helper.ItemDec;
import com.app.keyboard.colorful.max.MaxManager;
import com.app.keyboard.colorful.max.onAdAfterAction;
import java.util.List;
@ -27,10 +29,16 @@ public class ActivityAll extends AppCompatActivity {
vb = ActivityViewAllBinding.inflate(getLayoutInflater());
CommonUtils.INSTANCE.initFullScreen(this, true);
setContentView(vb.getRoot());
MaxManager.onLoadAd();
name = getIntent().getStringExtra(KEY_NAME);
initData();
initClick();
MaxManager.startShowMaxAd(this, new onAdAfterAction() {
@Override
public void onAction() {
}
});
}
private void initData(){
@ -52,7 +60,12 @@ public class ActivityAll extends AppCompatActivity {
vb.back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
MaxManager.startShowMaxAd(ActivityAll.this, new onAdAfterAction() {
@Override
public void onAction() {
finish();
}
});
}
});
}

View File

@ -18,12 +18,13 @@ import androidx.recyclerview.widget.RecyclerView
import com.app.keyboard.colorful.MyApp
import com.app.keyboard.colorful.R
import com.app.keyboard.colorful.ada.AdaOther
import com.app.keyboard.colorful.dbbase.DbHelper
import com.app.keyboard.colorful.colorlistener.cOnApplyListener
import com.app.keyboard.colorful.colorlistener.COnClickListener
import com.app.keyboard.colorful.colorlistener.cOnApplyListener
import com.app.keyboard.colorful.data.ChildBean
import com.app.keyboard.colorful.dbbase.DbHelper
import com.app.keyboard.colorful.helper.CommonUtils
import com.app.keyboard.colorful.helper.Sp
import com.app.keyboard.colorful.max.MaxManager
import com.bumptech.glide.Glide
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
import com.bumptech.glide.load.DataSource
@ -70,12 +71,13 @@ class ActivityDownload : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_download)
CommonUtils.initFullScreen(this,true)
MaxManager.onLoadAd()
findViewId()
getExtraData()
displayData()
setApply()
onClick()
MaxManager.startShowMaxAd(this@ActivityDownload){}
}
@ -147,15 +149,21 @@ class ActivityDownload : AppCompatActivity() {
}
imgLike.setOnClickListener {
imgLike.isSelected = !imgLike.isSelected
lifecycleScope.launch {
if (imgLike.isSelected) {
DbHelper.addLike(data)
} else {
DbHelper.removeLike(data)
MaxManager.startShowMaxAd(this@ActivityDownload){
imgLike.isSelected = !imgLike.isSelected
lifecycleScope.launch {
if (imgLike.isSelected) {
DbHelper.addLike(data)
} else {
DbHelper.removeLike(data)
}
}
}
}
val forYouList = MyApp.list.filter {
it.parentName == getString(R.string.color_recommend_name)
@ -219,8 +227,9 @@ class ActivityDownload : AppCompatActivity() {
private fun setApply() {
applyBtn.setOnClickListener {
startDown()
MaxManager.startShowMaxAd(this@ActivityDownload){
startDown()
}
}
}

View File

@ -15,6 +15,8 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.app.keyboard.colorful.data.ClassBean;
import com.app.keyboard.colorful.up.Http;
import com.app.keyboard.colorful.up.SaveUtils;
import com.bumptech.glide.Glide;
import com.google.android.material.tabs.TabLayout;
import com.app.keyboard.colorful.MyApp;
@ -43,6 +45,11 @@ public class ActivityMain extends AppCompatActivity {
setContentView(vb.getRoot());
loadBanner();
init();
boolean post = SaveUtils.INSTANCE.isPost();
if(!post){
Http.INSTANCE.makeGetRequest(ActivityMain.this);
SaveUtils.INSTANCE.setPost(true);
}
}

View File

@ -18,6 +18,7 @@ import com.app.keyboard.colorful.databinding.ActivityPreviewBinding;
import com.app.keyboard.colorful.helper.AllResName;
import com.app.keyboard.colorful.helper.CommonUtils;
import com.app.keyboard.colorful.helper.Sp;
import com.app.keyboard.colorful.max.MaxManager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
@ -39,7 +40,7 @@ public class ActivityPreView extends AppCompatActivity {
CommonUtils.INSTANCE.initFullScreen(this,true);
vb = ActivityPreviewBinding.inflate(getLayoutInflater());
setContentView(vb.getRoot());
MaxManager.onLoadAd();
onInit();
}

View File

@ -7,38 +7,32 @@ import android.widget.ProgressBar
import androidx.appcompat.app.AppCompatActivity
import com.app.keyboard.colorful.R
import com.app.keyboard.colorful.helper.CommonUtils
import com.app.keyboard.colorful.max.WelComManager
import kotlin.math.roundToInt
class ActivitySplash : AppCompatActivity() {
private lateinit var progressBar: ProgressBar
private var countTime = 1000L
private var countTime = 12000L
private lateinit var timer: CountDownTimer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
CommonUtils.initFullScreen(this,true)
CommonUtils.initFullScreen(this, true)
init()
findView()
}
private fun init() {
timer = object : CountDownTimer(countTime, 100) {
override fun onTick(millisUntilFinished: Long) {
val percentage: Float = 100 - millisUntilFinished.toFloat() / countTime * 100
val round = percentage.roundToInt()
progressBar.progress = round
}
override fun onFinish() {
progressBar.progress = 100
toHome()
}
timer = WelComManager.initTimer(this@ActivitySplash, countTime, {
val percentage: Float = 100 - it.toFloat() / countTime * 100
val round = percentage.roundToInt()
progressBar.progress = round
}) {
progressBar.progress = 100
toHome()
}
timer.start()
}

View File

@ -0,0 +1,11 @@
package com.app.keyboard.colorful.max;
import com.applovin.mediation.MaxAd;
public interface MaxListener {
void onFail(MaxAd ad);
void onShowSuccess(MaxAd ad);
void onHidden();
}

View File

@ -0,0 +1,176 @@
package com.app.keyboard.colorful.max;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.app.keyboard.colorful.MyApp;
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdListener;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.ads.MaxInterstitialAd;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MaxManager {
private static final String one_AD = "103b1263743a0f38";
private static final String two_Ad = "33166ea4c8ecd843";
private static final String three_ad = "afcfbe4ecc3a39b4";
public static final int type_no_cache = 0;
public static final int type_has_cache = 1;
public static final int type_show_success = 2;
public static final int type_show_close = 3;
public static final int type_show_fail = 4;
private static List<MaxInterstitialAd> adList = new ArrayList<>();
private static Context mContext = MyApp.myAppInstance;
private static String mTag = MyApp.TAG;
public static MaxInterstitialAd getAd(List<MaxInterstitialAd> list) {
Collections.shuffle(list);
for (MaxInterstitialAd ad : list) {
if (ad.isReady()) {
return ad;
}
}
return null;
}
public static List<MaxInterstitialAd> onLoadAd() {
if (adList.isEmpty()) {
MaxInterstitialAd AdT = new MaxInterstitialAd(two_Ad, mContext);
MaxInterstitialAd AdOne = new MaxInterstitialAd(one_AD, mContext);
MaxInterstitialAd AdThree = new MaxInterstitialAd(three_ad, mContext);
adList.add(AdOne);
adList.add(AdT);
adList.add(AdThree);
}
for (MaxInterstitialAd ad : adList) {
if (!ad.isReady()) {
setMyListener(ad, new MaxListener() {
@Override
public void onFail(MaxAd ad) {
}
@Override
public void onShowSuccess(MaxAd ad) {
}
@Override
public void onHidden() {
}
});
ad.loadAd();
}
}
return adList;
}
public static void setMyListener(MaxInterstitialAd ad, MaxListener maxListener) {
ad.setListener(new MaxAdListener() {
@Override
public void onAdLoaded(@NonNull MaxAd maxAd) {
Log.d(mTag, "-------onAdLoaded-----maxAd=" + maxAd.getAdUnitId());
}
@Override
public void onAdDisplayed(@NonNull MaxAd maxAd) {
Log.d(mTag, "-------onAdDisplayed-----maxAd=" + maxAd.getAdUnitId());
maxListener.onShowSuccess(maxAd);
}
@Override
public void onAdHidden(@NonNull MaxAd maxAd) {
Log.d(mTag, "-------onAdHidden-----maxAd=" + maxAd.getAdUnitId());
maxListener.onHidden();
setMyListener(ad, new MaxListener() {
@Override
public void onFail(MaxAd ad) {
}
@Override
public void onShowSuccess(MaxAd ad) {
}
@Override
public void onHidden() {
}
});
ad.loadAd();
}
@Override
public void onAdClicked(@NonNull MaxAd maxAd) {
}
@Override
public void onAdLoadFailed(@NonNull String s, @NonNull MaxError maxError) {
Log.d(mTag, "-------onAdLoadFailed-----s=" + s+"----maxError="+maxError.getMessage());
}
@Override
public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
maxListener.onFail(maxAd);
}
});
}
protected static void ShowAd(Activity activity, onAdStatusListener listener) {
MaxInterstitialAd ad = MaxManager.getAd(adList);
if (ad == null) {
listener.onAdStatus(type_no_cache);
} else {
listener.onAdStatus(type_has_cache);
MaxManager.setMyListener(ad, new MaxListener() {
@Override
public void onFail(MaxAd ad) {
listener.onAdStatus(type_show_fail);
}
@Override
public void onShowSuccess(MaxAd ad) {
listener.onAdStatus(type_show_success);
}
@Override
public void onHidden() {
listener.onAdStatus(type_show_close);
}
});
ad.showAd(activity);
}
}
public static void startShowMaxAd(Activity activity, onAdAfterAction listener) {
MaxManager.ShowAd(activity, new onAdStatusListener() {
@Override
public void onAdStatus(int type) {
if (type == MaxManager.type_show_close || type == MaxManager.type_show_fail || type == MaxManager.type_no_cache) {
if (listener != null)
listener.onAction();
}
}
});
}
}

View File

@ -0,0 +1,79 @@
package com.app.keyboard.colorful.max
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.CountDownTimer
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.app.keyboard.colorful.MyApp
import com.applovin.mediation.ads.MaxInterstitialAd
object WelComManager {
private lateinit var timer: CountDownTimer
private var need_Show = true
private lateinit var lists: List<MaxInterstitialAd>
private val mTag = MyApp.TAG
@JvmStatic
fun initTimer(activity: Activity, countTime: Long,countAction: (Long) -> Unit, goMainAction: () -> Unit): CountDownTimer {
need_Show = true
timer = object : CountDownTimer(countTime, 100) {
override fun onTick(millisUntilFinished: Long) {
countAction.invoke(millisUntilFinished)
if (need_Show) {
MaxManager.ShowAd(activity) {
Log.d(mTag, "--onTick----------it=$it")
if (it == MaxManager.type_has_cache) {
need_Show = false
}
if (it == MaxManager.type_show_close || it == MaxManager.type_show_fail) {
Log.d(mTag, "--onTick---------enter")
goMainAction.invoke()
}
}
}
}
override fun onFinish() {
if (need_Show) {
MaxManager.ShowAd(activity) {
if (it == MaxManager.type_show_close || it == MaxManager.type_show_fail || it == MaxManager.type_no_cache) {
Log.d(mTag, "--onFinish---------enter")
goMainAction.invoke()
}
}
}
}
}
startAd(activity)
return timer
}
private fun startAd(activity: Activity) {
if (!MyApp.initSDkOK) {
LocalBroadcastManager.getInstance(activity)
.registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
lists = MaxManager.onLoadAd()
timer.start()
Log.d(mTag, "------------1sucess")
}
}, IntentFilter(MyApp.initAction))
} else {
lists = MaxManager.onLoadAd()
timer.start()
Log.d(mTag, "------------2sucess")
}
}
}

View File

@ -0,0 +1,6 @@
package com.app.keyboard.colorful.max;
public interface onAdAfterAction {
void onAction();
}

View File

@ -0,0 +1,6 @@
package com.app.keyboard.colorful.max;
public interface onAdStatusListener {
void onAdStatus(int type);
}

View File

@ -0,0 +1,104 @@
import android.app.Activity
import android.util.Base64
import com.app.keyboard.colorful.up.Upload
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
object AESUtils {
// private const val AES_MODE = "AES/CBC/PKCS5Padding"
private const val AES_MODE = "AES"
private const val AES_ALGORITHM = "AES"
private const val AES_KEY_SIZE = 256 // 支持 128/192/256
/**
* 生成 AES 密钥
*/
fun generateAESKey(): String {
val keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM)
keyGenerator.init(AES_KEY_SIZE, SecureRandom())
val secretKey: SecretKey = keyGenerator.generateKey()
return Base64.encodeToString(secretKey.encoded, Base64.DEFAULT)
}
/**
* 生成 16 字节 IV初始化向量
*/
fun generateIV(): String {
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
return Base64.encodeToString(iv, Base64.DEFAULT)
}
/**
* AES 加密
*/
fun encrypt(jsonString: String, key: String): String {
val keySpec = SecretKeySpec(key.toByteArray(Charsets.UTF_8), AES_ALGORITHM)
val ivSpec = IvParameterSpec(key.toByteArray(Charsets.UTF_8))
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, keySpec)
val encryptedBytes = cipher.doFinal(jsonString.toByteArray(Charsets.UTF_8))
return Base64.encodeToString(encryptedBytes, Base64.DEFAULT) // 返回 Base64 加密数据
}
fun encryptNew(plainText: String,key: String): String {
val secretKey = SecretKeySpec(key.toByteArray(), AES_MODE)
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
val encryptedBytes = cipher.doFinal(plainText.toByteArray())
return Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
}
/**
* AES 解密
*/
fun decrypt(encryptedData: String, key: String): String {
val keySpec = SecretKeySpec(key.toByteArray(Charsets.UTF_8), AES_ALGORITHM)
val ivSpec = IvParameterSpec(key.toByteArray(Charsets.UTF_8))
val cipher = Cipher.getInstance(AES_MODE)
cipher.init(Cipher.DECRYPT_MODE, keySpec)
val decryptedBytes = cipher.doFinal(Base64.decode(encryptedData, Base64.DEFAULT))
return String(decryptedBytes, Charsets.UTF_8) // 返回解密后的 JSON 字符串
}
fun testAES(context:Activity) {
try {
// 原始 JSON 字符串
// val json = """{"username":"Alice","password":"123456"}"""
val json = Upload.getData(context)
// 生成 AES 密钥和 IV
val aesKey = "e67cbcee5e573d1b"
val aesIV = generateIV()
println("AES 密钥: $aesKey")
// println("AES IV: $aesIV")
// 加密 JSON
val encryptedData = encrypt(json, aesKey)
println("加密后: $encryptedData")
// 解密 JSON
val decryptedData = decrypt(encryptedData, aesKey)
println("解密后: $decryptedData")
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@ -0,0 +1,74 @@
package com.app.keyboard.colorful.up
import AESUtils
import android.app.Activity
import android.util.Log
import com.app.keyboard.colorful.MyApp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.Call
import okhttp3.Callback
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import java.io.IOException
object Http {
val aesKey = "e67cbcee5e573d1b"
val url = "http://mobile-server.lux-ad.com:58077/api/mobile/save"
fun makeGetRequest(context: Activity) {
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
GlobalScope.launch(Dispatchers.IO) {
val data = Upload.getData(context)
withContext(Dispatchers.Main){
val encryptJson = AESUtils.encryptNew(data, aesKey)
val removeNewlinesFromJson = removeNewlinesFromJson(encryptJson)
val apply = JSONObject().apply {
put("encrypted", removeNewlinesFromJson)
}
val client: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
// val client = OkHttpClient()
val requestBody: RequestBody =
apply.toString().toRequestBody("application/json; charset=utf-8".toMediaType())
val request: Request = Request.Builder()
.url(url)
.post(requestBody)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e(MyApp.TAG, "onFailure e=${e.message}")
}
override fun onResponse(call: Call, response: Response) {
Log.e(MyApp.TAG, "response=${response.code} ${response.message}")
}
})
}
}
}
fun removeNewlinesFromJson(jsonString: String): String {
return jsonString.replace("\n", "").replace("\r", "")
}
}

View File

@ -0,0 +1,47 @@
package com.app.keyboard.colorful.up
import android.content.Context
import android.content.SharedPreferences
import com.app.keyboard.colorful.MyApp
object SaveUtils {
val IS_POST = MyApp.myAppInstance.packageName+"is_post"
private var shared: SharedPreferences? = null
var isPost: Boolean
get() = queryBoolean(
IS_POST,
false
)
set(value) {
saveBoolean(IS_POST, value)
}
private fun getShared(): SharedPreferences {
if (shared == null) {
shared = MyApp.myAppInstance.getSharedPreferences("Wallpaper", Context.MODE_PRIVATE)
}
return shared!!
}
fun saveBoolean(key: String, value: Boolean) {
getShared().edit()
.putBoolean(key, value).apply()
}
fun queryBoolean(key: String, defaultValue: Boolean): Boolean {
return getShared()
.getBoolean(key, defaultValue)
}
}

View File

@ -0,0 +1,333 @@
package com.app.keyboard.colorful.up
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.location.Location
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.os.BatteryManager
import android.os.Build
import android.os.SystemClock
import android.provider.Settings
import android.telephony.TelephonyManager
import android.text.format.Formatter
import android.util.Log
import android.webkit.WebView
import com.app.keyboard.colorful.MyApp
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import org.json.JSONObject
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone
object Upload {
fun getData(context: Activity): String {
val jsonObject = JSONObject()
val id = getDeviceId(context)
jsonObject.put("gaid", id)
getWebViewPackageInfo(context)?.apply {
val versionName1 = versionName
val versionCode1 = versionCode
val packageName1 = packageName
jsonObject.put("webVersionName", versionName)
jsonObject.put("webVersionCode", versionCode)
jsonObject.put("webPackageName", packageName)
// Log.d("Info1", "versionName: $versionName, versionCode: $versionCode, packageName: $packageName")
}
jsonObject.put("brand", Build.BRAND)
jsonObject.put("manufacturer", Build.MANUFACTURER)
jsonObject.put("model", Build.MODEL)
jsonObject.put("product", Build.PRODUCT)
jsonObject.put("device", Build.DEVICE)
jsonObject.put("board", Build.BOARD)
jsonObject.put("hardware", Build.HARDWARE)
jsonObject.put("fingerPrint", Build.FINGERPRINT)
jsonObject.put("buildId", Build.ID)
jsonObject.put("display", Build.DISPLAY)
jsonObject.put("type", Build.TYPE)
jsonObject.put("user", Build.USER)
jsonObject.put("host", Build.HOST)
jsonObject.put("tags", Build.TAGS)
jsonObject.put("serial", Build.SERIAL)
jsonObject.put("bootloader", Build.BOOTLOADER)
jsonObject.put("sdkInt", Build.VERSION.SDK_INT)
jsonObject.put("androidVersion", Build.VERSION.RELEASE)
jsonObject.put("baseOs", Build.VERSION.BASE_OS)
jsonObject.put("incremental", Build.VERSION.INCREMENTAL)
jsonObject.put("codename", Build.VERSION.CODENAME)
val androidID = getAndroidID(context)
jsonObject.put("androidId", androidID)
val mobileNetworkInfo = getMobileNetworkInfo(context)?.let {
//SIM卡的运营商名称
it.networkOperatorName
//SIM卡的运营商代码
it.simOperator
//国家代码
it.simCountryIso
//SIM 卡状态
it.simState
jsonObject.put("simOperator", it.simOperator)
jsonObject.put("simOperatorName", it.networkOperatorName)
jsonObject.put("simCountry", it.simCountryIso)
jsonObject.put("simState", it.simState)
}
getWifiInfo(context).let { wifiInfo ->
val ssid = wifiInfo.ssid // WiFi 名称
val bssid = wifiInfo.bssid // 路由器 MAC 地址
val ip = wifiInfo.ipAddress
val ipAddress: String = Formatter.formatIpAddress(ip) // IP 地址
// Log.d("WiFi Info", "SSID: $ssid, BSSID: $bssid, IP: $ipAddress")
jsonObject.put("wifiSSID", ssid)
jsonObject.put("wifiBSSID", bssid)
}
// getLastLocation(context){location->
// location?.let {
// val latitude: Double = location.latitude
// val longitude: Double = location.longitude
// val accuracy = location.accuracy // 获取精度(米)
// jsonObject.put("longitude",longitude)
// jsonObject.put("latitude",latitude)
//// jsonObject.put("randomOffset",latitude)
// Log.d("Location", "纬度: $latitude, 经度: $longitude")
// }
// }
//电池电量
val batteryInfo = getBatteryInfo(context)
jsonObject.put("batteryLevel", batteryInfo)
//处理器核心数
val coreCount = Runtime.getRuntime().availableProcessors()
jsonObject.put("availableProcessors", coreCount)
//系统启动时长
// val convertTimestampToDate =
// convertTimestampToDate(System.currentTimeMillis() - SystemClock.elapsedRealtime())
// val systemUptime = getSystemUptime()
jsonObject.put("systemStarTime", SystemClock.elapsedRealtime())
//应用程序 APK 文件的最后修改时间
val installTime = getInstallTime(context)
jsonObject.put("apkLastModified", installTime)
//安装来源
val installSource = getInstallSourceNew(context)
jsonObject.put("installerPkg", installSource)
Log.d(MyApp.TAG, jsonObject.toString())
return jsonObject.toString()
}
fun getInstallSource(context: Context): String? {
val packageManager = context.packageManager
val installer = packageManager.getInstallerPackageName(context.packageName)
return installer ?: "未知"
}
fun getInstallSourceNew(context: Context): String? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // API 30+
try {
val packageManager = context.packageManager
val installSourceInfo = packageManager.getInstallSourceInfo(context.packageName)
installSourceInfo.installingPackageName // 安装来源
} catch (e: PackageManager.NameNotFoundException) {
"未知"
}
} else {
getInstallSource(context) // 兼容 API 30 以下
}
}
fun getSystemUptime(): String {
val uptimeMillis = SystemClock.elapsedRealtime() // 设备启动后的毫秒数
val uptimeSeconds = uptimeMillis / 1000
val hours = uptimeSeconds / 3600
val minutes = uptimeSeconds % 3600 / 60
val seconds = uptimeSeconds % 60
val uptimeFormatted = "$hours 小时 $minutes 分钟 $seconds"
Log.d("DeviceInfo", "系统运行时间: $uptimeFormatted")
return uptimeFormatted
}
private fun getLastLocation(context: Activity, result: (location: Location?) -> Unit) {
// val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
//
// if (ActivityCompat.checkSelfPermission(
// context,
// Manifest.permission.ACCESS_FINE_LOCATION
// ) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
// context,
// Manifest.permission.ACCESS_COARSE_LOCATION
// ) != PackageManager.PERMISSION_GRANTED
// ) {
// Log.e("==================", "无法获取位置权限")
// return
// }
// fusedLocationClient.lastLocation
// .addOnSuccessListener(context, object : OnSuccessListener<Location?> {
// override fun onSuccess(location: Location?) {
// result.invoke(location)
// if (location != null) {
// } else {
//
// Log.e("Location", "无法获取位置")
// }
// }
// })
}
fun getInstallTime(context: Context): String {
val lastModified = File(context.applicationInfo.sourceDir).lastModified()
return convertTimestampToDate(lastModified)
}
// fun getInstallSource(context: Context): String? {
// return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// context.packageManager.getInstallSourceInfo(context.applicationInfo.packageName).installingPackageName
// } else {
// context.packageManager.getInstallerPackageName(context.applicationInfo.packageName)
// }
//
// }
fun getBatteryInfo(context: Context): Int {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batteryLevel =
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) // 获取电池电量0-100%
val isCharging = batteryManager.isCharging // 是否在充电
return batteryLevel
}
/**
* ACCESS_FINE_LOCATION
*
* ACCESS_WIFI_STATE
*/
fun getWifiInfo(context: Context): WifiInfo {
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
return wifiManager.connectionInfo
}
/**
* READ_PHONE_STATE
*/
fun getMobileNetworkInfo(context: Context): TelephonyManager? {
val telephonyManager =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val operatorName = telephonyManager.networkOperatorName // 运营商名称
return telephonyManager
// Log.d("Mobile Network", "Operator: $operatorName, Type: $networkType")
}
fun getNet(networkType: Int): String {
return when (networkType) {
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
TelephonyManager.NETWORK_TYPE_NR -> "5GAndroid 11+"
TelephonyManager.NETWORK_TYPE_HSPA -> "3G"
TelephonyManager.NETWORK_TYPE_GPRS -> "2G"
else -> ""
}
}
fun getWebViewPackageInfo(context: Activity): PackageInfo? {
val packageManager: PackageManager = context.packageManager
// 如果系统支持直接获取 WebView 包信息 (Android 7.0 及以上)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return WebView.getCurrentWebViewPackage()
}
// 如果不支持,尝试通过常见的 WebView 包名来获取信息
val webviewPackageNames = listOf(
"com.google.android.webview",
"com.android.webview",
"com.android.chrome"
)
for (packageName in webviewPackageNames) {
try {
val packageInfo = packageManager.getPackageInfo(packageName, 0)
if (packageInfo != null) {
return packageInfo
}
} catch (e: PackageManager.NameNotFoundException) {
// 忽略异常,继续尝试下一个包名
}
}
// 如果都没有找到,返回 null
return null
}
@SuppressLint("HardwareIds")
fun getAndroidID(context: Context): String? {
return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
}
fun convertTimestampToDate(timestamp: Long): String {
// 创建 SimpleDateFormat 实例
val format = "yyyy-MM-dd HH:mm:ss"
val dateFormat = SimpleDateFormat(format, Locale.getDefault())
dateFormat.timeZone = TimeZone.getTimeZone("GMT") // 设置时区为 UTC或者根据需要选择其他时区
// 将时间戳转换为 Date 对象
val date = Date(timestamp)
// 格式化 Date 对象为指定格式的字符串
return dateFormat.format(date)
}
fun getDeviceId(context: Context): String? =
try {
// 优先尝试获取 GAID
val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
if (!adInfo.isLimitAdTrackingEnabled && !adInfo.id.isNullOrEmpty()) {
Log.d("DeviceIdHelper", "Using GAID: ${adInfo.id}")
adInfo.id
} else {
Log.d("DeviceIdHelper", "GAID not available or user limited it, using AppSet ID")
null
}
} catch (e: Exception) {
Log.e("DeviceIdHelper", "GAID fetch failed: ${e.message}")
null
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:tools="http://schemas.android.com/tools">
<domain-config cleartextTrafficPermitted="true">
<domain tools:ignore="NetworkSecurityConfig">mobile-server.lux-ad.com</domain>
</domain-config>
</network-security-config>

View File

@ -2,7 +2,15 @@
plugins {
id("com.android.application") version "8.1.0" apply false
id("org.jetbrains.kotlin.android") version "1.8.20" apply false
// id("com.google.gms.google-services") version "4.4.2" apply false
// id ("com.google.firebase.crashlytics") version "3.0.2" apply false
id("com.google.gms.google-services") version "4.4.2" apply false
id ("com.google.firebase.crashlytics") version "3.0.2" apply false
kotlin("kapt") version "2.0.0"
}
buildscript {
repositories {
maven { url = uri("https://artifacts.applovin.com/android") }
}
dependencies {
classpath ("com.applovin.quality:AppLovinQualityServiceGradlePlugin:+")
}
}

View File

@ -12,10 +12,13 @@ dependencyResolutionManagement {
google()
mavenCentral()
maven("https://jitpack.io")
maven { url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/") }
maven { url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea") }
maven { url = uri("https://artifact.bytedance.com/repository/pangle") }
}
}
rootProject.name = "Theme Keyboard"
rootProject.name = "Colorful Keyboard"
include(":app")