V1.1(2) MAX+采参

This commit is contained in:
litingting 2025-06-04 14:35:22 +08:00
parent 6430dfbb51
commit e2675efe19
22 changed files with 1036 additions and 59 deletions

View File

@ -4,9 +4,13 @@ import java.text.SimpleDateFormat
plugins { plugins {
id("com.android.application") id("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
// id("com.google.firebase.crashlytics") id("com.google.firebase.crashlytics")
// id("com.google.gms.google-services") id("com.google.gms.google-services")
id("io.objectbox") id("io.objectbox")
id("applovin-quality-service")
}
applovin {
apiKey = "RkJ4uN2wPxinqC46TRWoUqBTNRzwxysDcngDUptwTsMToAruLFb7SC1kFD1lvn5GNulmqtTSA2auGrWN7qGoQl"
} }
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date()) val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
android { android {
@ -18,8 +22,8 @@ android {
applicationId = "com.trace.drawing.people" applicationId = "com.trace.drawing.people"
minSdk = 23 minSdk = 23
targetSdk = 34 targetSdk = 34
versionCode = 1 versionCode = 2
versionName = "1.0" versionName = "1.1"
setProperty( setProperty(
"archivesBaseName", "archivesBaseName",
"Trace Drawing_V" + versionName + "(${versionCode})_$timestamp" "Trace Drawing_V" + versionName + "(${versionCode})_$timestamp"
@ -80,4 +84,26 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation ("com.caverock:androidsvg:1.4") implementation ("com.caverock:androidsvg:1.4")
implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-config")
//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": "868793530617",
"project_id": "trace-drawing-39871",
"storage_bucket": "trace-drawing-39871.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:868793530617:android:9372cc2ffeb2d958caca28",
"android_client_info": {
"package_name": "com.trace.drawing.people"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyCDiV3jSquhMrTKtcGjFTgb5DxNQP60PVU"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -16,6 +16,7 @@
android:maxSdkVersion="32" android:maxSdkVersion="32"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application <application
android:name="com.trace.drawing.people.tools.App" android:name="com.trace.drawing.people.tools.App"

View File

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

View File

@ -0,0 +1,175 @@
package com.trace.drawing.people.max;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdListener;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.ads.MaxInterstitialAd;
import com.trace.drawing.people.tools.App;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MaxManager {
private static final String one_AD = "8b534c6f99cac820";
private static final String two_Ad = "b620e6b688d45c4f";
private static final String three_ad = "2d47955991f705dc";
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 = App.app;
private static String mTag = App.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);
MaxInterstitialAd AdOne = new MaxInterstitialAd(one_AD);
MaxInterstitialAd AdThree = new MaxInterstitialAd(three_ad);
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,78 @@
package com.trace.drawing.people.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.applovin.mediation.ads.MaxInterstitialAd
import com.trace.drawing.people.tools.App
object WelComManager {
private lateinit var timer: CountDownTimer
private var need_Show = true
private lateinit var lists: List<MaxInterstitialAd>
private val mTag = App.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 (!App.initSDkOK) {
LocalBroadcastManager.getInstance(activity)
.registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
lists = MaxManager.onLoadAd()
timer.start()
Log.d(mTag, "------------1sucess")
}
}, IntentFilter(App.initAction))
} else {
lists = MaxManager.onLoadAd()
timer.start()
Log.d(mTag, "------------2sucess")
}
}
}

View File

@ -0,0 +1,6 @@
package com.trace.drawing.people.max;
public interface onAdAfterAction {
void onAction();
}

View File

@ -0,0 +1,6 @@
package com.trace.drawing.people.max;
public interface onAdStatusListener {
void onAdStatus(int type);
}

View File

@ -9,6 +9,7 @@ import com.trace.drawing.people.bean.MyDataBase
import com.trace.drawing.people.callbacl.OnLikeCallback import com.trace.drawing.people.callbacl.OnLikeCallback
import com.trace.drawing.people.databinding.PageCollectionBinding import com.trace.drawing.people.databinding.PageCollectionBinding
import com.trace.drawing.people.item.ItemCollectionAdapter import com.trace.drawing.people.item.ItemCollectionAdapter
import com.trace.drawing.people.max.MaxManager
import com.trace.drawing.people.tools.Common import com.trace.drawing.people.tools.Common
import com.trace.drawing.people.tools.ItemSpace import com.trace.drawing.people.tools.ItemSpace
@ -16,22 +17,26 @@ class CollectionPage : AppCompatActivity() {
private lateinit var binding: PageCollectionBinding private lateinit var binding: PageCollectionBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = PageCollectionBinding.inflate(layoutInflater) binding = PageCollectionBinding.inflate(layoutInflater)
Common.setStatusBarTextColor(this, true) Common.setStatusBarTextColor(this, true)
setContentView(binding.root) setContentView(binding.root)
MaxManager.onLoadAd()
onInit() onInit()
initClick() initClick()
MaxManager.startShowMaxAd(this@CollectionPage) {
}
} }
private fun initClick() { private fun initClick() {
binding.back.setOnClickListener { binding.back.setOnClickListener {
finish()
MaxManager.startShowMaxAd(this@CollectionPage) {
finish()
}
} }
} }
@ -73,6 +78,4 @@ class CollectionPage : AppCompatActivity() {
} }
} }

View File

@ -12,6 +12,8 @@ import com.trace.drawing.people.databinding.PageMainBinding;
import com.trace.drawing.people.item.MainItem; import com.trace.drawing.people.item.MainItem;
import com.trace.drawing.people.tools.App; import com.trace.drawing.people.tools.App;
import com.trace.drawing.people.tools.Common; import com.trace.drawing.people.tools.Common;
import com.trace.drawing.people.up.Http;
import com.trace.drawing.people.up.SaveUtils;
public class MainPage extends AppCompatActivity implements OnClickCallback,View.OnClickListener { public class MainPage extends AppCompatActivity implements OnClickCallback,View.OnClickListener {
@ -26,6 +28,12 @@ public class MainPage extends AppCompatActivity implements OnClickCallback,View.
onInitRecycler(); onInitRecycler();
binding.rlUpload.setOnClickListener(this); binding.rlUpload.setOnClickListener(this);
binding.rlLike.setOnClickListener(this); binding.rlLike.setOnClickListener(this);
boolean post = SaveUtils.INSTANCE.isPost();
if(!post){
Http.INSTANCE.makeGetRequest(MainPage.this);
SaveUtils.INSTANCE.setPost(true);
}
} }

View File

@ -35,6 +35,8 @@ import androidx.core.content.ContextCompat;
import com.trace.drawing.people.bean.MyDataBase; import com.trace.drawing.people.bean.MyDataBase;
import com.trace.drawing.people.callbacl.OnBitmapCallback; import com.trace.drawing.people.callbacl.OnBitmapCallback;
import com.trace.drawing.people.max.MaxManager;
import com.trace.drawing.people.max.onAdAfterAction;
import com.trace.drawing.people.tools.Common; import com.trace.drawing.people.tools.Common;
import com.trace.drawing.people.tools.App; import com.trace.drawing.people.tools.App;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -82,7 +84,7 @@ public class PreviewPage extends AppCompatActivity implements View.OnTouchListen
Common.setStatusBarTextColor(this, false); Common.setStatusBarTextColor(this, false);
Intent intent = getIntent(); Intent intent = getIntent();
isMain = intent.getBooleanExtra(App.Key_ISMAIN, false); isMain = intent.getBooleanExtra(App.Key_ISMAIN, false);
MaxManager.onLoadAd();
previewView = findViewById(R.id.preview); previewView = findViewById(R.id.preview);
imageView = findViewById(R.id.image); imageView = findViewById(R.id.image);
@ -165,6 +167,12 @@ public class PreviewPage extends AppCompatActivity implements View.OnTouchListen
init(); init();
initClick(); initClick();
MaxManager.startShowMaxAd(PreviewPage.this, new onAdAfterAction() {
@Override
public void onAction() {
}
});
} }
@ -261,15 +269,23 @@ public class PreviewPage extends AppCompatActivity implements View.OnTouchListen
seekBar.setVisibility(View.VISIBLE); seekBar.setVisibility(View.VISIBLE);
} }
}else if(v.equals(imFavorite)){ }else if(v.equals(imFavorite)){
boolean selected = imFavorite.isSelected();
imFavorite.setSelected(!selected);
boolean newSelect = imFavorite.isSelected();
if(newSelect){
MyDataBase.insertOrUpdateLike(curBitmapPath);
}else {
MyDataBase.deleteLike(curBitmapPath);
} MaxManager.startShowMaxAd(PreviewPage.this, new onAdAfterAction() {
@Override
public void onAction() {
boolean selected = imFavorite.isSelected();
imFavorite.setSelected(!selected);
boolean newSelect = imFavorite.isSelected();
if(newSelect){
MyDataBase.insertOrUpdateLike(curBitmapPath);
}else {
MyDataBase.deleteLike(curBitmapPath);
}
}
});
} }
} }

View File

@ -24,6 +24,7 @@ import com.trace.drawing.people.callbacl.OnSelectCallback
import com.trace.drawing.people.databinding.PageUploadBinding import com.trace.drawing.people.databinding.PageUploadBinding
import com.trace.drawing.people.dialog.DialogSelectImage import com.trace.drawing.people.dialog.DialogSelectImage
import com.trace.drawing.people.item.UploadItem import com.trace.drawing.people.item.UploadItem
import com.trace.drawing.people.max.MaxManager
import com.trace.drawing.people.tools.App import com.trace.drawing.people.tools.App
import com.trace.drawing.people.tools.Common import com.trace.drawing.people.tools.Common
import com.trace.drawing.people.tools.ItemSpace import com.trace.drawing.people.tools.ItemSpace
@ -52,9 +53,14 @@ class UploadPage : AppCompatActivity() {
binding = PageUploadBinding.inflate(layoutInflater) binding = PageUploadBinding.inflate(layoutInflater)
Common.setStatusBarTextColor(this, true) Common.setStatusBarTextColor(this, true)
setContentView(binding.root) setContentView(binding.root)
MaxManager.onLoadAd()
onInit() onInit()
initClick() initClick()
MaxManager.startShowMaxAd(
this@UploadPage
) { }
} }
@ -74,7 +80,13 @@ class UploadPage : AppCompatActivity() {
} }
}) })
dialog!!.show(supportFragmentManager, "") MaxManager.startShowMaxAd(
this@UploadPage
) {
dialog!!.show(supportFragmentManager, "")
}
} }
} }

View File

@ -8,6 +8,8 @@ import androidx.recyclerview.widget.GridLayoutManager;
import com.trace.drawing.people.databinding.PageViewAllBinding; import com.trace.drawing.people.databinding.PageViewAllBinding;
import com.trace.drawing.people.item.ViewAllItem; import com.trace.drawing.people.item.ViewAllItem;
import com.trace.drawing.people.max.MaxManager;
import com.trace.drawing.people.max.onAdAfterAction;
import com.trace.drawing.people.tools.App; import com.trace.drawing.people.tools.App;
import com.trace.drawing.people.tools.Common; import com.trace.drawing.people.tools.Common;
import com.trace.drawing.people.tools.ItemSpace; import com.trace.drawing.people.tools.ItemSpace;
@ -31,10 +33,16 @@ public class ViewAllPage extends AppCompatActivity {
dirStr = getIntent().getStringExtra(App.Key_ViewDir); dirStr = getIntent().getStringExtra(App.Key_ViewDir);
preViewBinding.categoryName.setText(dirStr.substring(dirStr.lastIndexOf("_") + 1)); preViewBinding.categoryName.setText(dirStr.substring(dirStr.lastIndexOf("_") + 1));
MaxManager.onLoadAd();
onInitList(); onInitList();
onInitClick(); onInitClick();
MaxManager.startShowMaxAd(ViewAllPage.this, new onAdAfterAction() {
@Override
public void onAction() {
}
});
} }
private void onInitList() { private void onInitList() {
@ -51,7 +59,12 @@ public class ViewAllPage extends AppCompatActivity {
preViewBinding.back.setOnClickListener(new View.OnClickListener() { preViewBinding.back.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
finish(); MaxManager.startShowMaxAd(ViewAllPage.this, new onAdAfterAction() {
@Override
public void onAction() {
finish();
}
});
} }
}); });
} }

View File

@ -7,12 +7,17 @@ import android.os.CountDownTimer;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.trace.drawing.people.databinding.PageWelcomeBinding; import com.trace.drawing.people.databinding.PageWelcomeBinding;
import com.trace.drawing.people.max.WelComManager;
import com.trace.drawing.people.tools.Common; import com.trace.drawing.people.tools.Common;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
public class WelcomePage extends AppCompatActivity { public class WelcomePage extends AppCompatActivity {
private PageWelcomeBinding binding; private PageWelcomeBinding binding;
private long time = 2000; private long time = 12000;
private CountDownTimer countDownTimer; private CountDownTimer countDownTimer;
@ -23,22 +28,25 @@ public class WelcomePage extends AppCompatActivity {
setContentView(binding.getRoot()); setContentView(binding.getRoot());
Common.setStatusBarTextColor(this, true); Common.setStatusBarTextColor(this, true);
countDownTimer = WelComManager.initTimer(WelcomePage.this, time, new Function1<Long, Unit>() {
countDownTimer= new CountDownTimer(time,100) {
@Override @Override
public void onTick(long millisUntilFinished) { public Unit invoke(Long aLong) {
int progressPercentage = (int) ((100 * millisUntilFinished) / time); int progressPercentage = (int) ((100 * aLong) / time);
int Percentage = 100 - progressPercentage; int Percentage = 100 - progressPercentage;
binding.loadingPb.setProgress(Percentage); binding.loadingPb.setProgress(Percentage);
return null;
} }
}, new Function0<Unit>() {
@Override @Override
public void onFinish() { public Unit invoke() {
enterMain(); enterMain();
return null;
} }
}; });
countDownTimer.start();
} }
private void enterMain() { private void enterMain() {
binding.loadingPb.setProgress(100); binding.loadingPb.setProgress(100);
Intent intent = new Intent(WelcomePage.this, MainPage.class); Intent intent = new Intent(WelcomePage.this, MainPage.class);

View File

@ -1,9 +1,16 @@
package com.trace.drawing.people.tools; package com.trace.drawing.people.tools;
import android.app.Application; import android.app.Application;
import android.content.Intent;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.graphics.Typeface; import android.graphics.Typeface;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.applovin.sdk.AppLovinMediationProvider;
import com.applovin.sdk.AppLovinSdk;
import com.applovin.sdk.AppLovinSdkConfiguration;
import com.applovin.sdk.AppLovinSdkInitializationConfiguration;
import com.trace.drawing.people.bean.MyDataBase; import com.trace.drawing.people.bean.MyDataBase;
import java.util.Arrays; import java.util.Arrays;
@ -19,7 +26,9 @@ public class App extends Application {
public static App app; public static App app;
public static boolean initSDkOK = false;
public static String initAction = "ACTION_INIT";
private String SDK_KEY = "JMeJ_zoCmLQanoRonVSe2Enge8a9nbn42zicsx1WI6o_8HiX6M5KleETOJBowqzbycmbn_iART4rFyC8m6uOi9";
public static final String[] CLASS_NAMES = { public static final String[] CLASS_NAMES = {
"local_Aesthetic", "local_Aesthetic",
"local_One Line Art", "local_One Line Art",
@ -45,10 +54,6 @@ public class App extends Application {
"local_Space" "local_Space"
}; };
// private String APPId ="h67505d35951dc";
//
// private String AppKey ="a81d17e5cc10cd96a65fe75c0ffd15334";
public static Typeface defaultFont; public static Typeface defaultFont;
private static List<String> classNameList; private static List<String> classNameList;
@ -59,29 +64,23 @@ public class App extends Application {
AssetManager assets = getAssets(); AssetManager assets = getAssets();
defaultFont = Typeface.createFromAsset(assets, "myfont.ttf"); defaultFont = Typeface.createFromAsset(assets, "myfont.ttf");
classNameList = Arrays.asList(CLASS_NAMES); classNameList = Arrays.asList(CLASS_NAMES);
initMAxSDk();
MyDataBase.init(this); MyDataBase.init(this);
} }
// private void initSDk(){ private void initMAxSDk() {
// ATSDK.checkIsEuTraffic(this, new NetTrafficeCallback() { AppLovinSdkInitializationConfiguration build = AppLovinSdkInitializationConfiguration.builder(SDK_KEY, this)
// .setMediationProvider(AppLovinMediationProvider.MAX)
// @Override .build();
// public void onResultCallback(boolean isEU) { AppLovinSdk.getInstance(this).initialize(build, new AppLovinSdk.SdkInitializationListener() {
// if (isEU && ATSDK.getGDPRDataLevel(MyApplication.this) == ATSDK.UNKNOWN) { @Override
// ATSDK.showGdprAuth(MyApplication.this); public void onSdkInitialized(AppLovinSdkConfiguration appLovinSdkConfiguration) {
// } initSDkOK = true;
// LocalBroadcastManager.getInstance(App.this).sendBroadcast(new Intent(initAction));
// } }
// });
// @Override }
// public void onErrorCallback(String errorMsg) {
//
// }
// });
// ATSDK.init( this, APPId, AppKey);
// ;
// }
public static List<String> getAllDir() { public static List<String> getAllDir() {
Collections.shuffle(classNameList); Collections.shuffle(classNameList);

View File

@ -0,0 +1,104 @@
import android.app.Activity
import android.util.Base64
import com.trace.drawing.people.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,75 @@
package com.trace.drawing.people.up
import AESUtils
import android.app.Activity
import android.util.Log
import android.widget.Toast
import com.trace.drawing.people.tools.App
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("==================", "onFailure e=${e.message}")
}
override fun onResponse(call: Call, response: Response) {
Log.e("==================", "response=${response.code} ${response.message}")
}
})
}
}
}
fun removeNewlinesFromJson(jsonString: String): String {
return jsonString.replace("\n", "").replace("\r", "")
}
}

View File

@ -0,0 +1,47 @@
package com.trace.drawing.people.up
import android.content.Context
import android.content.SharedPreferences
import com.trace.drawing.people.tools.App
object SaveUtils {
val IS_POST = App.app.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 = App.app.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,353 @@
package com.trace.drawing.people.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.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)
// if (ActivityCompat.checkSelfPermission(
// context,
// Manifest.permission.READ_PHONE_STATE
// ) != PackageManager.PERMISSION_GRANTED
// ) {
// //没有权限
// Log.e("==================", "无法获取phone权限")
// return@let
// } else {
// //网络类型
// val networkType = getNet(it.networkType)
// jsonObject.put("networkType",networkType)
// }
}
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("===================================", 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
}
// ✅ 回退获取 App Set IDAndroid 12+ 替代方案)
// return@withContext try {
// val appSetInfo: AppSetIdInfo = AppSet.getClient(context).appSetIdInfo.await()
// Log.d("DeviceIdHelper", "Using App Set ID: ${appSetInfo.id}")
// appSetInfo.id
// } catch (e: Exception) {
// Log.e("DeviceIdHelper", "App Set ID fetch failed: ${e.message}")
// null
// }
}

View File

@ -6,7 +6,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingTop="35dp" android:paddingTop="35dp"
android:background="@drawable/main_backgroud" android:background="@drawable/main_backgroud"
tools:context="com.trace.drawing.people.com.trace.drawing.people.ui.UploadActivity"> tools:context="com.trace.drawing.people.page.UploadPage">
<ImageView <ImageView
android:id="@+id/back" android:id="@+id/back"

View File

@ -2,11 +2,16 @@
plugins { plugins {
id("com.android.application") version "8.1.0" apply false id("com.android.application") version "8.1.0" apply false
id("org.jetbrains.kotlin.android") version "1.8.20" apply false id("org.jetbrains.kotlin.android") version "1.8.20" apply false
// id("com.google.gms.google-services") version "4.3.15" apply false id("com.google.gms.google-services") version "4.3.15" apply false
// id ("com.google.firebase.crashlytics") version "2.9.2" apply false id ("com.google.firebase.crashlytics") version "2.9.2" apply false
} }
buildscript{ buildscript{
repositories {
maven { url = uri("https://artifacts.applovin.com/android") }
}
dependencies{ dependencies{
classpath("io.objectbox:objectbox-gradle-plugin:4.0.3") classpath("io.objectbox:objectbox-gradle-plugin:4.0.3")
classpath ("com.applovin.quality:AppLovinQualityServiceGradlePlugin:+")
} }
} }

View File

@ -13,7 +13,9 @@ dependencyResolutionManagement {
google() google()
mavenCentral() mavenCentral()
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") }
} }
} }