首次提交

This commit is contained in:
2025-11-20 17:48:34 +08:00
commit 94baa16c92
61 changed files with 375904 additions and 0 deletions

1
app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

145
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,145 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Date
import java.util.Locale
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
flavorDimensions += "company"
namespace = "com.app.systemadsolution"
compileSdk = 36
defaultConfig {
applicationId = "com.media.systemadsolution"
minSdk = 23
targetSdk = 36
versionCode = 1
versionName = "1.0"
ndk {
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a"))
}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
create("rockchip") {
// storeFile = file("../sign/rockchip_platform.keystore")
// keyAlias = "rockchipdebugkey"
// storePassword = "android"
// keyPassword = "android"
// storeFile = file("../sign/platform_rk.keystore")
// keyAlias = "platform"
// storePassword = "android"
// keyPassword = "android"
storeFile = file("../sign/platform.keystore")
keyAlias = "platform"
storePassword = "android"
keyPassword = "android"
}
}
buildTypes {
release {
isMinifyEnabled = project.properties["MINIFY_ENABLE"]?.toString()?.toBoolean() ?: false
signingConfig = signingConfigs.getByName("rockchip")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
file("${rootDir}/proguard/common-library-proguard-rules.pro")
)
}
debug {
signingConfig = signingConfigs.getByName("rockchip")
}
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_11
}
}
buildFeatures {
viewBinding = true
aidl = true
}
productFlavors {
//aike
create("custom") {
dimension = "company"
// applicationIdSuffix = ".custom" //rk包名版本号2开头
applicationIdSuffix = ".custom.aw" //全志包名版本号1开头
versionCode = 111
versionName = "1.1.1" //三位格式,不能改变,否则影响广告获取
}
create("aosp") {
dimension = "company"
}
}
android.applicationVariants.all {
outputs.all {
if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
val config = project.android.defaultConfig
val formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm")
val createTime = LocalDateTime.now().format(formatter)
//this.outputFileName = "${project.name}_${this.name}_${versionName}_$createTime.apk"
this.outputFileName = "AppAd_${this.name}_${versionName}_$createTime.apk"
}
}
}
}
dependencies {
implementation(libs.material)
implementation(libs.androidx.constraintlayout)
coreLibraryDesugaring(libs.desugar.jdk.libs)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
//implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.lifecycle.service)
implementation(libs.interactivemedia)
//1.2.1 miniSdk=16 1.3.0 miniSDK=19,1.5.0 miniSDK=21
val media3_version = "1.2.1"
//def media3_version = "1.5.1"
// For media playback using ExoPlayer
implementation(libs.androidx.media3.exoplayer)
// For DASH playback support with ExoPlayer
implementation(libs.androidx.media3.exoplayer.dash)
// For HLS playback support with ExoPlayer
implementation(libs.androidx.media3.exoplayer.hls)
// For SmoothStreaming playback support with ExoPlayer
implementation(libs.androidx.media3.exoplayer.smoothstreaming)
// For RTSP playback support with ExoPlayer
implementation(libs.androidx.media3.exoplayer.rtsp)
implementation(libs.retrofit)
implementation(libs.converter.gson)
implementation(libs.okhttp)
implementation(libs.logging.interceptor)
implementation(libs.iqiyi.xcrash)
api(project(":sensorSDK"))
api(project(":adcore"))
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}

65
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,65 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-printmapping proguardMapping.txt
-dontwarn com.media.systemadsolution.util.SkyLog
-keep class android.app.** { *; }
-keep class com.media.systemadsolution.** { *; }
-keep class com.google.ads.interactivemedia.** { *; }
-keep class com.sensorsdata.analytics.android.** { *; }
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnBufferingUpdateListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnCompletionListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnErrorListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnInfoListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnPreparedListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnSeekCompleteListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnVideoDarSizeChangedListener
-dontwarn tv.danmaku.ijk.media.player.IMediaPlayer$OnVideoSizeChangedListener
-dontwarn tv.danmaku.ijk.media.player.IjkMediaPlayer
-dontwarn com.media.systemadsolution.util.DeviceHelper
-dontwarn com.media.systemadsolution.util.DeviceInfoImpl
-dontwarn xcrash.ICrashCallback
-dontwarn xcrash.ILogger
-dontwarn xcrash.TombstoneManager
-dontwarn xcrash.TombstoneParser
-dontwarn xcrash.XCrash$InitParameters
-dontwarn xcrash.XCrash
-dontoptimize
-dontwarn retrofit2.**
-dontwarn okhttp3.**
-keep class retrofit2.** { *; }
-keep class okhttp3.** { *; }
-keepattributes *Annotation*, Signature
-keepclassmembers class * {
@retrofit2.http.* <methods>;
}
-keep class * implements java.io.Serializable { *; }
-keep class * implements retrofit2.CallAdapter$Factory { *; }
-keep class * implements retrofit2.Converter$Factory { *; }
-keep class com.app.systemadsolution.utils.** { *; }

373500
app/proguardMapping.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
package com.coolita.systemadsolution
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.coolita.systemadsolution", appContext.packageName)
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".custom.CustomerAPP"
tools:replace="android:name">
<activity
android:name=".custom.TransparentActivity"
android:theme="@style/TranslucentStyle"
android:exported="true" >
<intent-filter>
<action android:name="media.tv.intent.action.APP_AD_PUSH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,16 @@
package com.app.systemadsolution.custom
import com.app.systemadsolution.App
import com.app.systemadsolution.custom.sal.DeviceInfo
import com.media.systemadsolution.util.DeviceHelper
/**
* @author Mai Wenhao
* @date 2025/8/15
*/
class CustomerAPP: App() {
override fun onCreate() {
super.onCreate()
DeviceHelper.delegate = DeviceInfo(this)
}
}

View File

@@ -0,0 +1,17 @@
package com.app.systemadsolution.custom
import android.os.Bundle
import android.os.Handler
import com.app.systemadsolution.R
import com.media.systemadsolution.BaseActivity
import com.media.systemadsolution.util.SkyLog
class TransparentActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.TranslucentStyle)
Handler().postDelayed({
finish()
}, 1500)
}
}

View File

@@ -0,0 +1,27 @@
package com.app.systemadsolution.custom.sal
import android.content.Context
import com.media.systemadsolution.util.DeviceInfoImpl
/**
* @author Mai Wenhao
* @date 2025/8/15
*/
class DeviceInfo(context: Context): DeviceInfoImpl(context) {
override fun getCustomer(): String {
return "AIKE"
}
override fun getBrand(): String {
return "WhiteBrand"
}
override fun getChip(): String {
return "AOSP"
}
override fun getModel(): String {
return "STB"
}
}

View File

@@ -0,0 +1 @@
<resources></resources>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TranslucentStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item> <!-- 背景色透明 -->
<item name="android:windowIsTranslucent">true</item> <!-- 是否有透明属性 -->
<item name="android:backgroundDimEnabled">false</item> <!-- 背景是否半透明 -->
<!-- <item name="android:statusBarColor">@android:color/transparent</item> &lt;!&ndash; 状态栏透明 &ndash;&gt;-->
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item> <!-- activity窗口切换效果 -->
<item name="android:windowNoTitle">true</item>
<!-- 隐藏状态栏 -->
<item name="android:windowFullscreen">true</item>
</style>
</resources>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!--
coreApp="true"
android:sharedUserId="android.uid.system"
android:supportsRtl="true"
android:usesCleartextTraffic="true"-->
<!-- 普通权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application
android:name=".App"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
<provider
android:name="com.app.systemadsolution.provider.ConfigurationProvider"
android:authorities="com.app.systemadsolution.provider.ConfigurationProvider"
android:enabled="true"
android:exported="true"
android:syncable="true">
<meta-data
android:name="android.content.ContactDirectory"
android:value="true" />
</provider>
<receiver
android:name=".broadcast.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,201 @@
package com.app.systemadsolution
import android.annotation.SuppressLint
import android.app.Application
import android.content.pm.PackageManager
import android.os.Handler
import android.text.TextUtils
import com.app.systemadsolution.utils.AdInfoEntity
import com.app.systemadsolution.utils.DeviceUtils
import com.app.systemadsolution.utils.IndexPlayInfo
import com.app.systemadsolution.utils.LogManager
import com.app.systemadsolution.utils.LogUtils
import com.app.systemadsolution.utils.NetUtils.netApi
import com.media.systemadsolution.BaseConfig
import com.media.systemadsolution.ad.AdListener
import com.media.systemadsolution.ad.AdManager
import com.media.systemadsolution.ad.AdSpace
import com.media.systemadsolution.ad.AdStatus
import com.media.systemadsolution.util.SkyLog
import com.media.systemadsolution.util.getAppVersionCode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/**
* @author Mai Wenhao
* @date 2025/8/4
*/
open class App : Application() {
private var currentPackage: String = ""
@SuppressLint("SuspiciousIndentation")
override fun onCreate() {
super.onCreate()
val check =
packageManager.checkSignatures(packageName, "android") == PackageManager.SIGNATURE_MATCH
LogUtils.loge("signature match: $check")
//签名不匹配时,禁用服务,防止应用崩溃
BaseConfig.init(this, !check)
Handler().postDelayed({
postAdInfo("serviceStart")
AdManager.getAdController(AdSpace.AVOD010).adListener = object : AdListener {
override fun onAdDownload(isSucceed: Boolean) {
LogUtils.loge(
"广告播放素材下载${if (isSucceed) "成功" else "失败"}"
)
// if (!isSucceed) {
// postAdInfo("adDownloadFailure")
// }
}
override fun onAdPlayEnd(adStatus: AdStatus) {
LogUtils.loge(
"广告播放结束(${
when (adStatus) {
AdStatus.CLICK -> "播放跳转用户点击learn more"
AdStatus.ERROR -> "播放错误"
AdStatus.SKIP -> "播放跳过用户点击skip"
AdStatus.COMPLETE -> "播放完成"
}
}"
)
// postAdInfo(adStatus.name)
}
override fun onAdPlayStart() {
LogUtils.loge("广告播放开始")
}
override fun onAdRequest(isSucceed: Boolean) {
LogUtils.loge("广告请求${if (isSucceed) "成功" else "失败"}")
if (!isSucceed) {
postAdInfo("adRequestFailure")
} else {
postAdInfo("adRequestSuccess")
}
}
override fun onAppStart(packageName: String) {
currentPackage = packageName
// SkyLog.e("logSwitch:", "${LogManager.getmInstance().getLogSwitch()}")
postAdInfo("appStart")
LogUtils.loge(
"广告播放当前app包名:$packageName"
)
}
}
}, 1000)
/* AdManager.adListener = object : AdListener {
override fun onAdRequest(isSucceed: Boolean) {
SkyLog.e(
"Application",
"systemadservice--->广告请求${if (isSucceed) "成功" else "失败"}"
)
if (!isSucceed) {
postAdInfo("adRequestFailure")
}
}
override fun onAdPlayStart() {
SkyLog.e("Application", "systemadservice--->广告播放开始")
}
override fun onAdPlayEnd(adStatus: AdStatus) {
SkyLog.e(
"Application", "systemadservice--->广告播放结束(${
when (adStatus) {
AdStatus.CLICK -> "播放跳转用户点击learn more"
AdStatus.ERROR -> "播放错误"
AdStatus.SKIP -> "播放跳过用户点击skip"
AdStatus.COMPLETE -> "播放完成"
}
}"
)
postAdInfo(adStatus.name)
}
}
}, 1000)*/
}
private fun postAdInfo(type: String) {
CoroutineScope(Dispatchers.IO).launch {
runCatching {
netApi.postAdInfo(
AdInfoEntity(
mac = DeviceUtils.getEthernetMac(),
cpu = DeviceUtils.getCpu(),
createTime = "${System.currentTimeMillis()}",
type = 1, // 0:默认分类1:三方(德国时区)
indexPlayInfos = arrayListOf<IndexPlayInfo>().apply {
add(
IndexPlayInfo(
playDuration = 0,
playCount = 0,
packageName = currentPackage,
versionCode = getAppVersionCode(packageName),
dateTime = "",
adIndexId = when (type) {
"serviceStart" -> 10009
"adRequestSuccess" -> 10008
"appStart" -> 10007
"adDownloadFailure" -> 10006
"CLICK" -> 10005
"SKIP" -> 10004
"ERROR" -> 10003
"COMPLETE" -> 10002
else -> 10001
}
)
)
}
).apply {
LogUtils.loge("${type.logType}:${this.toString()}")
}
)
}.onSuccess {
LogUtils.loge(
"${type.logType}上传${if (it.code == 200) "成功" else "失败"}:${it.msg},上传类型:${
getAdType(
type
)
}"
)
}.onFailure {
LogUtils.loge(
"${type.logType}上传失败:${it.message},上传类型:${
getAdType(
type
)
}"
)
}
}
}
private fun getAdType(type: String): String = when (type) {
"serviceStart" -> "广告播放统计服务开启10009"
"adRequestSuccess" -> "广告请求成功10008"
"appStart" -> "应用打开10007"
"adDownloadFailure" -> "广告素材下载失败10006"
"CLICK" -> "播放跳转用户点击learn more10005"
"SKIP" -> "播放跳过用户点击skip10004)"
"ERROR" -> "播放错误10003"
"COMPLETE" -> "播放完成10002)"
else -> "广告请求失败(10001)"
}
val String.logType: String
get() = if (TextUtils.equals(
this,
"serviceStart"
)
) "服务开启数据" else "广告播放数据"
}

View File

@@ -0,0 +1,21 @@
package com.app.systemadsolution.broadcast
import android.content.ActivityNotFoundException
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.util.Log
import com.media.systemadsolution.ad.AdListener
import com.media.systemadsolution.ad.AdManager
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// SkyLog.i("BootReceiver", "onReceive:" + intent.action)
//什么也不干,目的就是拉起进程
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
}
}
}

View File

@@ -0,0 +1,75 @@
package com.app.systemadsolution.provider
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.ContentProvider
import android.content.ContentValues
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import com.app.systemadsolution.utils.LogManager
import com.app.systemadsolution.utils.LogUtils
import com.media.systemadsolution.util.SkyLog
class ConfigurationProvider : ContentProvider() {
override fun onCreate(): Boolean {
if (context == null) {
return false
}
LogManager.init(context)
try {
LogUtils.loge("start TransparentActivity")
val intent = Intent().apply {
component = ComponentName(
"com.media.systemadsolution.custom.aw", //全志:com.media.systemadsolution.custom.aw , rk:com.media.systemadsolution.custom
"com.app.systemadsolution.custom.TransparentActivity"
)
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context!!.startActivity(intent)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
LogUtils.loge("exception:" + e.message)
}
return true
}
override fun query(
p0: Uri,
p1: Array<out String?>?,
p2: String?,
p3: Array<out String?>?,
p4: String?
): Cursor? {
return null
}
override fun update(
p0: Uri,
p1: ContentValues?,
p2: String?,
p3: Array<out String?>?
): Int {
return 0
}
override fun delete(
p0: Uri,
p1: String?,
p2: Array<out String?>?
): Int {
return 0
}
override fun getType(p0: Uri): String? {
return null
}
override fun insert(p0: Uri, p1: ContentValues?): Uri? {
return null
}
}

View File

@@ -0,0 +1,188 @@
package com.app.systemadsolution.utils;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.NetworkInterface;
import java.net.SocketException;
public class DeviceUtils {
private static final String platform = "allwinner"; //allwinner、rockchip、amlogic
public static String getCpu() {
if (TextUtils.equals(platform, "allwinner")) {
String platform = getAllwinnerPlatform();
if ("sun8iw7".equals(platform)) {
return getH3CPUinfo();
}
return getH616And313CPUinfo();
} else if (TextUtils.equals(platform, "rockchip") || TextUtils.equals(platform, "amlogic")) {
return getCPUinfo();
}
return "";
}
private static String getAllwinnerPlatform() {
String platform = "";
String line = null;
String cmd = "cat /sys/class/sunxi_info/sys_info";
try {
Process p = Runtime.getRuntime().exec(cmd);
// BufferedReader ie = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
// String error = null;
// while ((error = ie.readLine()) != null && !error.equals("null")) {
// Log.d("===========", "========error="+error);
// }
while ((line = in.readLine()) != null && !line.equals("null")) {
if (line.contains("sunxi_platform")) {
String[] SerialStr = line.split(":");
if (SerialStr.length == 2) {
String mSerial = SerialStr[1];
platform = mSerial.trim();
return platform;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return platform;
}
private static String getH3CPUinfo() {
String cpuAddress = "";
String line = null;
String cmd = "cat /sys/class/sunxi_info/sys_info";
try {
Process p = Runtime.getRuntime().exec(cmd);
// BufferedReader ie = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
// String error = null;
// while ((error = ie.readLine()) != null && !error.equals("null")) {
// Log.d("===========", "========error="+error);
// }
while ((line = in.readLine()) != null && !line.equals("null")) {
if (line.contains("sunxi_chipid")) {
String[] SerialStr = line.split(":");
if (SerialStr.length == 2) {
String mSerial = SerialStr[1];
cpuAddress = mSerial.trim();
return cpuAddress;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return cpuAddress;
}
private static String getH616And313CPUinfo() {
String cpuAddress = "";
String line = null;
String cmd = "cat /sys/class/sunxi_info/sys_info";
try {
Process p = Runtime.getRuntime().exec(cmd);
// BufferedReader ie = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
// String error = null;
// while ((error = ie.readLine()) != null && !error.equals("null")) {
// Log.d("===========", "========error="+error);
// }
while ((line = in.readLine()) != null && !line.equals("null")) {
if (line.contains("sunxi_serial")) {
String[] SerialStr = line.split(":");
if (SerialStr.length == 2) {
String mSerial = SerialStr[1];
cpuAddress = mSerial.trim();
return cpuAddress;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return cpuAddress;
}
private static String getCPUinfo() {
String cpuAddress = "";
String line = null;
String cmd = "cat /proc/cpuinfo";
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = in.readLine()) != null && !line.equals("null")) {
if (line.contains("Serial")) {
String[] SerialStr = line.split(":");
if (SerialStr.length == 2) {
String mSerial = SerialStr[1];
cpuAddress = mSerial.trim();
return cpuAddress;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return cpuAddress;
}
public static String getEthernetMac() {
String ethernetMac = null;
try {
NetworkInterface NIC = NetworkInterface.getByName("eth0");
byte[] buf = NIC.getHardwareAddress();
ethernetMac = byteHexString(buf);
} catch (Exception e) {
e.printStackTrace();
}
if (ethernetMac == null) { //获取不到以太网mac时就获取wifi mac
ethernetMac = getWifiMac();
}
return ethernetMac;
}
private static String byteHexString(byte[] array) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < array.length; i++) {
String hex = Integer.toHexString(array[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
if (i < array.length - 1) {
builder.append(hex + ":");
} else {
builder.append(hex);
}
}
return builder.toString().toUpperCase();
}
private static String getWifiMac() {
String wifiMac = null;
try {
NetworkInterface NIC = NetworkInterface.getByName("wlan0");
byte[] buf = NIC.getHardwareAddress();
wifiMac = byteHexString(buf);
} catch (SocketException e) {
e.printStackTrace();
}
return wifiMac;
}
}

View File

@@ -0,0 +1,130 @@
package com.app.systemadsolution.utils;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GsonUtil {
private static Gson gson = null;
static {
if (gson == null) {
gson = new Gson();
}
}
private GsonUtil() {
}
/**
* 转成json
*
* @param object
* @return
*/
public static String GsonString(Object object) {
String gsonString = null;
if (gson != null) {
gsonString = gson.toJson(object);
}
return gsonString;
}
/**
* 转成bean
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
T t = null;
if (gson != null) {
t = gson.fromJson(gsonString, cls);
}
return t;
}
/**
* 转成带list的bean
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToListBean(String gsonString, Class<T> cls) {
T t = null;
if (gson != null) {
t = gson.fromJson(gsonString, cls);
}
return t;
}
/**
* 转成list
*
* @param gsonString
* @param cls
* @return
*/
public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
ArrayList<T> mList = new ArrayList<>();
JsonArray array = new JsonParser().parse(gsonString).getAsJsonArray();
for (final JsonElement elem : array) {
mList.add(gson.fromJson(elem, cls));
}
return mList;
}
/**
* 转成list中有map的
*
* @param gsonString
* @return
*/
public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(gsonString,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
}
/**
* 转成map的
*
* @param gsonString
* @return
*/
public static <T> Map<String, T> GsonToMaps(String gsonString) {
Map<String, T> map = null;
if (gson != null) {
map = gson.fromJson(gsonString, new TypeToken<Map<String, T>>() {
}.getType());
}
return map;
}
public static boolean isJson(String content){
try {
JSONObject jsonStr= new JSONObject(content);
return true;
} catch (Exception e) {
return false;
}
}
}

View File

@@ -0,0 +1,213 @@
package com.app.systemadsolution.utils;
import android.content.Context;
import android.text.TextUtils;
import com.media.systemadsolution.util.SkyLog;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Map;
public class LogManager {
private Context mContext;
/**
* 文件名称
*/
private static final String FILE_NALE = "nebula_log.txt";
/**
* 文件路径
*/
private String LOG_FILE_PATH = null;
private FileOutputStream mFileOutputStream;
private FileInputStream mFileInputStream;
private static LogManager mInstance = null;
private ReadLogCallBack mReadLogCallBack;
private boolean isReadLog = true;
private static final String LOGCONFIG = "/system/logconfig.json";
private LogManager(Context context) {
this.mContext = context;
this.LOG_FILE_PATH = context.getExternalCacheDir().getPath() + File.separator + FILE_NALE;
mFileOutputStream = createWriterStream();
mFileInputStream = createReadStream();
isReadLog = getLogSwitch();
}
public static void init(Context context) {
if (mInstance == null) {
mInstance = new LogManager(context);
}
}
public static LogManager getmInstance() {
return mInstance;
}
public boolean isReadLog() {
return isReadLog;
// return true;
}
public boolean getLogSwitch() {
String json = getAssertData(mContext, LOGCONFIG);
if (json == null) {
return false;
}
try {
// Map<String, Boolean> logConfigMap = GsonUtil.GsonToMaps(json);
// logConfigMap.get("Logswitch");
// return logConfigMap.get("Logswitch");
String value = json.substring(json.indexOf(":") + 1, json.indexOf("}")).trim();
return TextUtils.equals(value, "true");
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static String getAssertData(Context context, String filepath) {
File file = new File(filepath);
if (!file.exists()) {
return null;
}
// InputStream is = context.getResources().openRawResource(R.raw.setting_system_update);
// if (Build.MODEL.equals("Z10Plus")||Build.MODEL.equals("Z10Pro")){
// is = context.getResources().openRawResource(R.raw.setting_system_update_z10pro);
// }
String resultString = "";
try {
InputStream is = new FileInputStream(file);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
String jsonString = "";
while ((jsonString = bufferedReader.readLine()) != null) {
resultString += jsonString;
}
} catch (Exception e) {
e.printStackTrace();
}
return resultString;
}
/**
* 读日志
*/
public void logReadMsg(ReadLogCallBack readLogCallBack) {
mReadLogCallBack = readLogCallBack;
isReadLog = true;
}
public void stopRecordLogMsg() {
isReadLog = false;
}
private FileOutputStream createWriterStream() {
try {
File file = new File(LOG_FILE_PATH);
if (!file.exists()) {
file.createNewFile();
}
mFileOutputStream = new FileOutputStream(LOG_FILE_PATH);
return mFileOutputStream;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private FileInputStream createReadStream() {
try {
mFileInputStream = new FileInputStream(LOG_FILE_PATH);
return mFileInputStream;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public interface ReadLogCallBack {
public void onLogMsg(String msg);
}
// class ReadMsgThread extends Thread{
//
//
// private boolean isRuning=false;
// private ReadLogCallBack mReadLogCallBack;
//
// public ReadMsgThread(ReadLogCallBack readLogCallBack){
// this.mReadLogCallBack = readLogCallBack;
// }
//
// @Override
// public void run() {
// super.run();
// isRuning =true;
// byte[] bytes = new byte[1024];
// try {
// while (isRuning){
// int len= mFileInputStream.read(bytes);
// if(len>0) {
// if (mReadLogCallBack != null) {
// String msg = new String(bytes, "utf-8");
// mReadLogCallBack.onLogMsg(msg);
// }
// try {
// sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// }else {
// try {
// sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
//
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// }
//
//
// public void stopThread(){
// isRuning = false;
// }
// }
}

View File

@@ -0,0 +1,16 @@
package com.app.systemadsolution.utils;
import android.util.Log;
import com.media.systemadsolution.util.SkyLog;
public class LogUtils {
private static final String TAG = "systemadservice";
public static void loge(String msg) {
if (LogManager.getmInstance().isReadLog()) {
Log.e(TAG, msg);
}
}
}

View File

@@ -0,0 +1,72 @@
package com.app.systemadsolution.utils
import com.media.systemadsolution.util.SkyLog
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body
import retrofit2.http.POST
import java.util.concurrent.TimeUnit
object NetUtils {
val netApi by lazy { createApi<NetApi>("http://third.ad.akrdinfo.cn:30133/app-api/") }
// val netApi by lazy { createApi<NetApi>("http://imptor.top:8742/app-api/") }
inline fun <reified T> createApi(baseUrl: String): T {
val loggingInterceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
LogUtils.loge("HttpLoggingInterceptor:${message}")
}
}).setLevel(HttpLoggingInterceptor.Level.NONE)
val okHttpClientBuilder =
OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.readTimeout(15000, TimeUnit.MILLISECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
val retrofit = Retrofit.Builder()
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.build()
return retrofit.create(T::class.java)
}
interface NetApi {
@POST("launcher/ad/play/callback/v2")
suspend fun postAdInfo(
@Body adInfoEntity: AdInfoEntity
): AdResultEntity
}
}
data class AdInfoEntity(
val mac: String,
val cpu: String,
val createTime: String,
val type: Int,
val indexPlayInfos: List<IndexPlayInfo>
)
data class IndexPlayInfo(
val playDuration: Int,
val playCount: Int,
val packageName: String,
val versionCode: Int,
val dateTime: String,
val adIndexId: Int
)
data class AdResultEntity(
val code: Int,
val data: Boolean,
val msg: String,
)

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,3 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">SmartService</string>
</resources>

View File

@@ -0,0 +1,3 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

View File

@@ -0,0 +1,17 @@
package com.coolita.systemadsolution
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}