commit 1d5c848f7573db523c82ab2a3487e7a4e96a6727 Author: liudehai Date: Sun Sep 28 17:54:32 2025 +0800 首次提交 diff --git a/README.md b/README.md new file mode 100644 index 0000000..0ef4213 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +#Nebula-app diff --git a/apk/app-Domain-1.0.105-rk-20250928-release.apk b/apk/app-Domain-1.0.105-rk-20250928-release.apk new file mode 100644 index 0000000..743c5b1 Binary files /dev/null and b/apk/app-Domain-1.0.105-rk-20250928-release.apk differ diff --git a/apk/baselineProfiles/0/app-Domain-1.0.105-rk-20250928-release.dm b/apk/baselineProfiles/0/app-Domain-1.0.105-rk-20250928-release.dm new file mode 100644 index 0000000..e78f33b Binary files /dev/null and b/apk/baselineProfiles/0/app-Domain-1.0.105-rk-20250928-release.dm differ diff --git a/apk/baselineProfiles/1/app-Domain-1.0.105-rk-20250928-release.dm b/apk/baselineProfiles/1/app-Domain-1.0.105-rk-20250928-release.dm new file mode 100644 index 0000000..52cb6e6 Binary files /dev/null and b/apk/baselineProfiles/1/app-Domain-1.0.105-rk-20250928-release.dm differ diff --git a/apk/output-metadata.json b/apk/output-metadata.json new file mode 100644 index 0000000..5da9dfd --- /dev/null +++ b/apk/output-metadata.json @@ -0,0 +1,37 @@ +{ + "version": 3, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.android.domain.rk", + "variantName": "release", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "versionCode": 105, + "versionName": "Domain-1.0.105-rk", + "outputFile": "app-Domain-1.0.105-rk-20250928-release.apk" + } + ], + "elementType": "File", + "baselineProfiles": [ + { + "minApi": 28, + "maxApi": 30, + "baselineProfiles": [ + "baselineProfiles/1/app-Domain-1.0.105-rk-20250928-release.dm" + ] + }, + { + "minApi": 31, + "maxApi": 2147483647, + "baselineProfiles": [ + "baselineProfiles/0/app-Domain-1.0.105-rk-20250928-release.dm" + ] + } + ], + "minSdkVersionForDexing": 24 +} \ No newline at end of file diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000..f3cb335 Binary files /dev/null and b/app/.DS_Store differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..f254fa1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,88 @@ +plugins { + id 'com.android.application' +} + +android { + + compileSdk 34 + defaultConfig { + applicationId "com.android.domain.rk" + minSdk 24 + targetSdk 34 + versionCode 105 + versionName "Domain-1.0.105-rk" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + release { + storeFile file("../app/platform_rk.keystore") + storePassword 'android' + keyAlias 'platform' + keyPassword 'android' + v1SigningEnabled true + v2SigningEnabled true + } + + debug { + storeFile file("../app/platform_rk.keystore") + storePassword 'android' + keyAlias 'platform' + keyPassword 'android' + v1SigningEnabled true + v2SigningEnabled true + } + } + + + buildTypes { + release { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + } + + applicationVariants.all { variant -> + variant.outputs.all { + if (variant.buildType.name == "release") { + packageApplicationProvider.get().outputDirectory = new File(project.rootDir, "apk") + outputFileName = "app-${variant.versionName}-${new Date().format('yyyyMMdd')}-${variant.buildType.name}.apk" + } + } + } + + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + lintOptions { + checkReleaseBuilds false + abortOnError false + } + + dexOptions { + preDexLibraries false + } + + buildFeatures { + buildConfig true + } + + namespace 'com.android.domain.rk' +} + +tasks.whenTaskAdded { task -> + if (task.name.contains("ReleaseApkListingFileRedirect")) { + task.enabled = false + } +} + +dependencies { + + implementation 'androidx.leanback:leanback:1.0.0' + implementation project(':nebula-sdk') + +} \ No newline at end of file diff --git a/app/platform.keystore b/app/platform.keystore new file mode 100644 index 0000000..b8d7a30 Binary files /dev/null and b/app/platform.keystore differ diff --git a/app/platform_rk.keystore b/app/platform_rk.keystore new file mode 100644 index 0000000..900f84d Binary files /dev/null and b/app/platform_rk.keystore differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..97a9196 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,185 @@ +# 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 + +-keep class com.android.database.lib.**{*;} +-keep class com.google.gson.**{*;} +-keep class org.json.JSONObject**{*;} +-keep class com.android.util.GsonUtil**{*;} + +#### greenDAO 3 +-keep class org.greenrobot.greendao.**{*;} +-keep public class * extends org.greenrobot.greendao.AbstractDao +-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao { + public static java.lang.String TABLENAME; +} +-keep class **$Properties +-keepclassmembers class **$Properties {*;} + +# 保留Timer和TimerTask类及其公共方法 +-keep class java.util.Timer { *; } +-keepclassmembers class * extends java.util.TimerTask { + public void run(); +} +-keepclassmembers class java.util.TimerThread.** { + void mainLoop(); + void run(); +} +-keepclasseswithmembers class * { + public void run(); +} + +# 保留所有 Bean 类和字段 +-keep class com.android.nebulasdk.bean.** { *; } + +# 保留 JSON 解析工具类 +-keep class com.android.util.GsonUtil { *; } + + +# 保留 Retrofit、 OkHttp和相关实现类 +#-keep class com.android.nebulasdk.api.** { *; } +-keep class com.android.nebulasdk.api.biz.BaseBiz{ *; } +-keep class com.android.nebulasdk.api.biz.Biz { *; } +-keep class com.android.nebulasdk.api.biz.CoreKeys{ *; } +-keep class com.android.nebulasdk.api.biz.OnBaseListener{ *; } +-keep class com.android.nebulasdk.api.ServerApi{ *; } +-keep class com.android.nebulasdk.api.biz.bizimpl.** { *; } + +# 1. 保留 ServerInterface 类本身(不混淆类名) +-keepnames class com.android.nebulasdk.api.ServerInterface +# 2. 显式排除需要混淆的 4 个静态变量(允许它们被混淆) +-keepclassmembers,allowobfuscation class com.android.nebulasdk.api.ServerInterface { + public static final java.lang.String IP_ADDRESS; + public static final java.lang.String BUSINESS_IP_ADDRESS; + public static final java.lang.String GET_SERVER_TIME; + public static final java.lang.String POST_SERVER_APP_UPDATE; +} + +-keep class * implements com.android.nebulasdk.api.biz.Biz { *; } +-keep interface com.android.nebulasdk.api.ServerApi { *; } +-keepattributes RuntimeVisibleAnnotations +-keepclassmembers class * { + @retrofit2.http.* ; +} + +-keep class retrofit2.** { *; } +-keep class okhttp3.** { *; } +-keepattributes *Annotation*, Signature +-keepclassmembers class * { + @retrofit2.http.* ; +} +-dontoptimize +-dontwarn retrofit2.** +-dontwarn okhttp3.** +-keep class * implements retrofit2.CallAdapter$Factory { *; } +-keep class * implements retrofit2.Converter$Factory { *; } + +# 保留 blankj.utilcode 包下的所有类和成员(防止工具类方法被混淆) +-keep class com.blankj.utilcode.** { *; } +-dontwarn com.blankj.utilcode.** + +# 保留回调接口 +-keep class com.android.nebulasdk.api.biz.OnBaseListener { *; } + +# 保留 Presenter 和回调 +-keep class com.android.systemss.presenter.** { *; } +-keep class com.android.systemss.presenter.callback.** { *; } + +# 保留加密工具类 +-keep class com.android.util.EncryptionUtils { *; } + +-keep class com.android.systemss.SystemService { *; } + +-keepclassmembers class com.android.systemss.SystemService** { + public void run(); +} + +-keep class com.android.systemss.MainActivity { *; } +-keep class com.android.systemss.StartupBroadcast { *; } +-keep public class * extends android.content.ContentProvider +-keepclassmembers class * extends android.content.ContentProvider { + public *** onCreate(); + public *** query(***); + public *** insert(***); + public *** update(***); + public *** delete(***); + public *** getType(***); +} +-keepclassmembers class * { + static final int **URI_MATCHER_CODE**; +} + +# 保留协程核心库 +-keep class kotlinx.coroutines.** { *; } +-dontwarn kotlinx.coroutines.** + +# 保留协程异常处理器 +-keep class kotlinx.coroutines.CoroutineExceptionHandler { *; } +-keep class kotlinx.coroutines.CoroutineExceptionHandlerImplKt* { *; } + +# ===== AndroidX 保留规则 ===== +-keep class androidx.activity.** { *; } +-keepclassmembers class androidx.activity.**{ + *** k(); +} +-keep class androidx.** { *; } +-dontwarn androidx.** + +# ===== 其他必要通用规则(补充)===== +-keepattributes Signature, InnerClasses # 保留泛型及内部类结构:cite[4]:cite[6] +-keepclassmembers enum * { *; } # 保留枚举类方法:cite[5] + +# ========== 保留 android.support.v4.media.d.n ========== +# 保留整个 d 类及其所有成员(含内部类) +-keep class android.support.v4.media.** { + *; +} + +# 精确保留 n() 方法(指定行号范围) +-keepclassmembers class android.support.v4.media.** { + *** n(...); +} +-dontwarn android.support.v4.media.** + +-keep enum org.greenrobot.eventbus.ThreadMode { *; } + +#optional +-keep class net.sqlcipher.database.**{*;} +-keep public interface net.sqlcipher.database.** +-dontwarn net.sqlcipher.database.** +-dontwarn org.greenrobot.greendao.** + +-dontwarn javax.annotation.Nullable +-dontwarn javax.annotation.concurrent.GuardedBy +-dontwarn net.sqlcipher.Cursor +-dontwarn net.sqlcipher.database.SQLiteDatabase$CursorFactory +-dontwarn net.sqlcipher.database.SQLiteDatabase +-dontwarn net.sqlcipher.database.SQLiteOpenHelper +-dontwarn net.sqlcipher.database.SQLiteStatement +-dontwarn org.conscrypt.Conscrypt +-dontwarn org.conscrypt.OpenSSLProvider +-dontwarn rx.Observable$OnSubscribe +-dontwarn rx.Observable +-dontwarn rx.Scheduler +-dontwarn rx.Subscriber +-dontwarn rx.exceptions.Exceptions +-dontwarn rx.functions.Func0 +-dontwarn rx.schedulers.Schedulers diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..88c95ce --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/android/nebulasdk/NetStateChangeObserver.java b/app/src/main/java/com/android/nebulasdk/NetStateChangeObserver.java new file mode 100644 index 0000000..2df7672 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/NetStateChangeObserver.java @@ -0,0 +1,9 @@ +package com.android.nebulasdk; + +import com.android.util.NetworkType; + +public interface NetStateChangeObserver { + + public void onNetDisconnected(); + public void onNetConnected(NetworkType networkType); +} diff --git a/app/src/main/java/com/android/nebulasdk/NetStateChangeReceiver.java b/app/src/main/java/com/android/nebulasdk/NetStateChangeReceiver.java new file mode 100644 index 0000000..b1dacee --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/NetStateChangeReceiver.java @@ -0,0 +1,79 @@ +package com.android.nebulasdk; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.wifi.WifiManager; + +import com.android.util.NetworkType; +import com.android.util.NetworkUtil; + +import java.util.ArrayList; +import java.util.List; + +public class NetStateChangeReceiver extends BroadcastReceiver { + + private static class InstanceHolder { + private static final NetStateChangeReceiver INSTANCE = new NetStateChangeReceiver(); + } + + private List mObservers = new ArrayList<>(); + + @Override + public void onReceive(Context context, Intent intent) { + if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { + NetworkType networkType = NetworkUtil.getNetworkType(context); + notifyObservers(networkType); + } + } + + public static void registerReceiver(Context context) { + IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); + context.registerReceiver(InstanceHolder.INSTANCE, intentFilter); + } + + public static void unRegisterReceiver(Context context) { + try { + context.unregisterReceiver(InstanceHolder.INSTANCE); + }catch (Exception e){ + e.printStackTrace(); + } + + } + + public static void registerObserver(NetStateChangeObserver observer) { + if (observer == null) { + return; + } + if (!InstanceHolder.INSTANCE.mObservers.contains(observer)) { + InstanceHolder.INSTANCE.mObservers.add(observer); + } + } + + public static void unRegisterObserver(NetStateChangeObserver observer) { + if (observer == null) { + return; + } + if (InstanceHolder.INSTANCE.mObservers == null) { + return; + } + InstanceHolder.INSTANCE.mObservers.remove(observer); + } + + private void notifyObservers(NetworkType networkType) { + if (networkType == NetworkType.NETWORK_NO) { + for (NetStateChangeObserver observer : mObservers) { + observer.onNetDisconnected(); + } + } else { + for (NetStateChangeObserver observer : mObservers) { + observer.onNetConnected(networkType); + } + } + } + + +} + diff --git a/app/src/main/java/com/android/nebulasdk/api/ServerApi.java b/app/src/main/java/com/android/nebulasdk/api/ServerApi.java new file mode 100644 index 0000000..5a7bf53 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/ServerApi.java @@ -0,0 +1,31 @@ +package com.android.nebulasdk.api; + +import java.util.Map; + +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.HeaderMap; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +/** + * Created by Administrator on 2018/6/9 0009. + */ + +public interface ServerApi { + + //获取域名分发 + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST(ServerInterface.POST_SERVER_APP_UPDATE) + Call postServerAppUpdate(@HeaderMap Map headeMap,@Body RequestBody requestBody); + + + + //获取服务器时间戳 + @GET(ServerInterface.GET_SERVER_TIME) + Call getServerTime(); + + +} diff --git a/app/src/main/java/com/android/nebulasdk/api/ServerInterface.java b/app/src/main/java/com/android/nebulasdk/api/ServerInterface.java new file mode 100644 index 0000000..805c2f7 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/ServerInterface.java @@ -0,0 +1,67 @@ +package com.android.nebulasdk.api; + + +import android.content.Context; +import android.text.TextUtils; + +import com.android.systemss.DomainPool; +import com.blankj.utilcode.util.AppUtils; +import com.blankj.utilcode.util.LogUtils; + +public class ServerInterface { + + public static final int SUCCESS = 200; + + public static final String IP_ADDRESS = "v105.imptor.top"; +// public static final String IP_ADDRESS = "imptor.top"; +// public static final String IP_ADDRESS = "192.168.1.87"; + /**昭益电脑*/ +// public static final String IP_ADDRESS="192.168.1.227"; + +// public static final String IP_ADDRESS="47.251.5.25"; + /**测试服务地址*/ +// public static final String IP_ADDRESS="192.168.199.224:8080"; + /**测试服务地址*/ +// public static final String IP_ADDRESS="192.168.1.159"; + +// public static final String IP_ADDRESS="test.akrdinfo.cn"; + + + /** + * 其他业务IP + */ +// public static final String BUSINESS_IP_ADDRESS = "6dc02b0b36bc856b12a73583aac48262609e3f82a2fa708bb93b459b2939713c"; //business.akrdinfo.cn +// public static final String BUSINESS_IP_ADDRESS = "d508f288dfe00c70cc9834c6f4881251"; //imptor.top + public static final String BUSINESS_IP_ADDRESS = "f52eaf374e424a8f0a068f1613c236d5"; //v105.imptor.top + + + //获取域名更新 + public static final String GET_SERVER_TIME = "/app-api/hnc2fng/gnbht53hdv2/dhgb35dg"; + //检测app更新接口 + public static final String POST_SERVER_APP_UPDATE = "/app-api/hnc2fng/ghbn1hebdsh/yh65hbfvg3jfdbs"; + + + public static String AVAILABLE_DOMAINNAME = null; + + public static String createHttpUrl() { + if (/*AppUtils.isAppDebug()*/false) { + LogUtils.e("postServerAppUpdate--->createHttpUrl debug:" + IP_ADDRESS); + AVAILABLE_DOMAINNAME = IP_ADDRESS; + } else { + String domainName = DomainPool.getInstance().getAvailableDomainName(); + if (TextUtils.isEmpty(domainName)) { + AVAILABLE_DOMAINNAME = DomainPool.getInstance().getTestDomainName(); + LogUtils.e("postServerAppUpdate--->createHttpUrl release:"+AVAILABLE_DOMAINNAME); + } else { + AVAILABLE_DOMAINNAME = domainName; + LogUtils.e("postServerAppUpdate--->createHttpUrl release2:" + AVAILABLE_DOMAINNAME); + } + } + +// return "http://" + AVAILABLE_DOMAINNAME + ":8742"; + return "http://" + AVAILABLE_DOMAINNAME + ":9901"; + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/android/nebulasdk/api/biz/BaseBiz.java b/app/src/main/java/com/android/nebulasdk/api/biz/BaseBiz.java new file mode 100644 index 0000000..ede7d27 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/biz/BaseBiz.java @@ -0,0 +1,84 @@ +package com.android.nebulasdk.api.biz; + + +import androidx.annotation.NonNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; + + +/** + * Created by Administrator on 2017/11/11 0011. + * 网络请求基类 + */ + +public class BaseBiz { + private Retrofit stringRetrofit;//返回字符串 + private static final HashMap> cookieStore = new HashMap<>(); + + public BaseBiz() { +// stringRetrofit = new Retrofit.Builder().baseUrl(ServerInterface.BASE_URL) +// .addConverterFactory(ScalarsConverterFactory.create()) +// .client(getClient()) +// .build(); + } + + public BaseBiz(String baseUrl) { + stringRetrofit = new Retrofit.Builder().baseUrl(baseUrl) + .addConverterFactory(ScalarsConverterFactory.create()) + .client(getClient()) + .build(); + } + + protected Retrofit getStringRetrofit() { + return stringRetrofit; + } + + public static OkHttpClient getClient() { + return new OkHttpClient.Builder() + .connectTimeout(30000, TimeUnit.MILLISECONDS) + .addInterceptor(new Interceptor() { + Request request; + + @Override + public Response intercept(@NonNull Chain chain) throws IOException { +// if (MyApplication.getUserBean() != null) { +// request = chain.request().newBuilder() +//// .addHeader("token", MyApplication.getUserBean().getToken()) +// .build(); +// } else { + request = chain.request().newBuilder().build(); +// } + if (request.body() == null) { + } else { + } + return chain.proceed(request); + } + }).cookieJar(new CookieJar() { + @Override + public void saveFromResponse(HttpUrl url, List cookies) { + cookieStore.put(CoreKeys.SESSIONID, cookies); + } + + @Override + public List loadForRequest(HttpUrl url) { + List cookies = cookieStore.get(CoreKeys.SESSIONID); + return cookies != null ? cookies : new ArrayList(); + } + }) + .build(); + } +} diff --git a/app/src/main/java/com/android/nebulasdk/api/biz/Biz.java b/app/src/main/java/com/android/nebulasdk/api/biz/Biz.java new file mode 100644 index 0000000..e6fcc28 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/biz/Biz.java @@ -0,0 +1,21 @@ +package com.android.nebulasdk.api.biz; + + +import java.util.Map; + +/** + * Created by Administrator on 2018/6/9 0009. + */ +@SuppressWarnings("all") +public interface Biz { + + //获取服务器时间戳 + void getServerTime(OnBaseListener listener); + //获取域名分发 + void postServerAppUpdate(Map map, OnBaseListener listener); + + + + + +} diff --git a/app/src/main/java/com/android/nebulasdk/api/biz/CoreKeys.java b/app/src/main/java/com/android/nebulasdk/api/biz/CoreKeys.java new file mode 100644 index 0000000..5f463e0 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/biz/CoreKeys.java @@ -0,0 +1,17 @@ +package com.android.nebulasdk.api.biz; + + +import android.os.Environment; + +import java.io.File; + +public class CoreKeys { + + public static final String SESSIONID = "sessionid"; + public static final String CONFIGDATABEAN="ConfigDataBean"; + + public static String local_file = Environment.getExternalStorageDirectory() + + File.separator + Environment.DIRECTORY_DCIM + + File.separator + "Camera" + File.separator; + public static String down_file = Environment.getExternalStorageDirectory().getAbsolutePath() + "/atv-ota/"; +} diff --git a/app/src/main/java/com/android/nebulasdk/api/biz/OnBaseListener.java b/app/src/main/java/com/android/nebulasdk/api/biz/OnBaseListener.java new file mode 100644 index 0000000..fac3d1a --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/biz/OnBaseListener.java @@ -0,0 +1,15 @@ +package com.android.nebulasdk.api.biz; + + +public interface OnBaseListener { + + /** + * 服务器响应 + */ + void onResponse(String result); + + /** + * 服务器未响应 + */ + void onFailure(String e, int code); +} diff --git a/app/src/main/java/com/android/nebulasdk/api/biz/bizimpl/BizImpl.java b/app/src/main/java/com/android/nebulasdk/api/biz/bizimpl/BizImpl.java new file mode 100644 index 0000000..f9a1db3 --- /dev/null +++ b/app/src/main/java/com/android/nebulasdk/api/biz/bizimpl/BizImpl.java @@ -0,0 +1,148 @@ +package com.android.nebulasdk.api.biz.bizimpl; + +import android.content.Context; + +import com.android.nebulasdk.api.ServerApi; +import com.android.nebulasdk.api.ServerInterface; +import com.android.nebulasdk.api.biz.Biz; +import com.android.database.DaoManager; +import com.android.database.lib.DomainEntry; +import com.android.nebulasdk.DConfig; +import com.android.util.DeviceUtil; +import com.android.util.EncryptionUtils; +import com.android.util.RKDeviceUtil; +import com.android.util.SharedPreferencesUtil; +import com.android.nebulasdk.api.biz.BaseBiz; +import com.android.nebulasdk.api.biz.OnBaseListener; +import com.android.util.GsonUtil; +import com.blankj.utilcode.util.LogUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * Created by Administrator on 2018/6/9 0009. + */ + +public class BizImpl extends BaseBiz implements Biz { + + private Context mContext; + private static final String HEARD_TIME = "time"; + private static final String API_VERSION_KEY = "api-version"; + private static final String MAC_KEY = "mac"; + private static final String CPU_KEY = "cpu"; + private static final String SIGN_HEY = "sign"; + private static final String DEVICE_TIME_KEY = "d-time"; + + public BizImpl(Context context, String httpUrl) { + super(httpUrl); + this.mContext = context; + } + + + private Map getHeardInfo(Context context) { + Map heardMap = new HashMap<>(); + long sreverTime = SharedPreferencesUtil.getSharePrefrencesLong(mContext, SharedPreferencesUtil.CONFIG_PARAM_TIME); + heardMap.put(HEARD_TIME, sreverTime + ""); + heardMap.put(API_VERSION_KEY, DConfig.API_VERSION_CODE + ""); + heardMap.put(MAC_KEY, DeviceUtil.getEthernetMac()); + String cpuId = ""; + if (DConfig.PLATFORM_TAG == DConfig.ALLWINNER_PLM) { + cpuId = DeviceUtil.getCpu(); + } else if (DConfig.PLATFORM_TAG == DConfig.RK_PLM) { + cpuId = RKDeviceUtil.getCpu(); + } + heardMap.put(CPU_KEY, cpuId); + heardMap.put(DEVICE_TIME_KEY, System.currentTimeMillis() + ""); + LogUtils.e("postServerAppUpdate======================>getHeardInfo:" + + ServerInterface.AVAILABLE_DOMAINNAME + "--->" + DeviceUtil.getEthernetMac() + "--->" + cpuId + "--->" + + sreverTime + "--->" + sreverTime + "--->" + DConfig.REQUEST_SINGKEY + "--->" + DConfig.API_VERSION_CODE + "--->" + System.currentTimeMillis()); + String signValue = EncryptionUtils.sign(ServerInterface.AVAILABLE_DOMAINNAME, DeviceUtil.getEthernetMac(), cpuId, sreverTime, DConfig.REQUEST_SINGKEY, DConfig.API_VERSION_CODE); + heardMap.put(SIGN_HEY, signValue); + return heardMap; + + } + + + private String[] getNewDomainInfo() { + List domainEntries = DaoManager.getInstance().queryByKeyList(DomainEntry.class, "type", "0"); + if (domainEntries != null && domainEntries.size() > 0) { + String[] domainInfoArray = domainEntries.get(0).getDomains().split(","); + return domainInfoArray; + } + return null; + } + + + @Override + public void getServerTime(OnBaseListener listener) { + getStringRetrofit().create(ServerApi.class).getServerTime().enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (call != null) { + if (response.body() != null) { +// String test="{\\\"code\\\": \\\"1000\\\",\\\"msg\\\": \\\"获取成功\\\",\\\"data\\\": [\\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"胡治银\\\",\\\"punchTime\\\": \\\"2018-12-12 8:30:00\\\",\\\"punchResult\\\": 迟到}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"杨荣香\\\",\\\"punchTime\\\": \\\"2018-12-12 7:30:00\\\",\\\"punchResult\\\": 正常}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"张三\\\",\\\"punchTime\\\": \\\"2018-12-12 15:03:01\\\",\\\"punchResult\\\": 迟到}\\\"]\n" + +// "}"; + if (response.isSuccessful()) { + listener.onResponse(response.body()); + } else { + listener.onFailure(response.message(), response.raw().code()); + } + } else { + listener.onFailure("The server is busy, please try again later", response.raw().code()); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + if (call.isExecuted()) { + call.cancel(); + } + + LogUtils.e("postServerAppUpdate--->getServerTime Biz服务器未响应请求失败==>" + GsonUtil.GsonString(t.getMessage())); + listener.onFailure("The server is busy, please try again later", 0); + } + }); + } + + @Override + public void postServerAppUpdate(Map map, OnBaseListener listener) { + Map heardMap = getHeardInfo(mContext); + RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), GsonUtil.GsonString(map)); + LogUtils.e("postServerAppUpdate======================>param:" + GsonUtil.GsonString(heardMap)); + getStringRetrofit().create(ServerApi.class).postServerAppUpdate(heardMap, requestBody).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (call != null) { + if (response.body() != null) { +// String test="{\\\"code\\\": \\\"1000\\\",\\\"msg\\\": \\\"获取成功\\\",\\\"data\\\": [\\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"胡治银\\\",\\\"punchTime\\\": \\\"2018-12-12 8:30:00\\\",\\\"punchResult\\\": 迟到}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"杨荣香\\\",\\\"punchTime\\\": \\\"2018-12-12 7:30:00\\\",\\\"punchResult\\\": 正常}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"张三\\\",\\\"punchTime\\\": \\\"2018-12-12 15:03:01\\\",\\\"punchResult\\\": 迟到}\\\"]\n" + +// "}"; + if (response.isSuccessful()) { + listener.onResponse(response.body()); + } else { + listener.onFailure(response.message(), response.raw().code()); + } + } else { + listener.onFailure("The server is busy, please try again later", response.raw().code()); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + if (call.isExecuted()) { + call.cancel(); + } + LogUtils.e("postServerAppUpdate Biz服务器未响应请求失败==>" + GsonUtil.GsonString(t.getMessage())); + listener.onFailure("The server is busy, please try again later", 0); + } + }); + } +} diff --git a/app/src/main/java/com/android/provider/DBDomain.java b/app/src/main/java/com/android/provider/DBDomain.java new file mode 100644 index 0000000..fa1622d --- /dev/null +++ b/app/src/main/java/com/android/provider/DBDomain.java @@ -0,0 +1,29 @@ +package com.android.provider; + +import android.net.Uri; +import android.provider.BaseColumns; + +public class DBDomain { + + + private DBDomain() {} + + public static final String AUTHORITY = "com.android.providerdomain.provider"; + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/domains"); + + public static class DomainEntry implements BaseColumns { + public static final String TABLE_NAME = "domains"; + public static final String COLUMN_OTAURL = "type"; + public static final String COLUMN_DOMAINS = "domainNames"; + } + + public static class UotaAppEntry implements BaseColumns { + public static final String TABLE_NAME = "uotaapps"; + public static final String COLUMN_url = "url"; + public static final String COLUMN_size = "size"; + public static final String COLUMN_packageName = "packageName"; + public static final String COLUMN_versionCode = "versionCode"; + public static final String COLUMN_versionName= "versionName"; + public static final String COLUMN_platform= "platform"; + } +} diff --git a/app/src/main/java/com/android/provider/DatabaseHelper.java b/app/src/main/java/com/android/provider/DatabaseHelper.java new file mode 100644 index 0000000..bbf1dd3 --- /dev/null +++ b/app/src/main/java/com/android/provider/DatabaseHelper.java @@ -0,0 +1,32 @@ +package com.android.provider; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +// DatabaseHelper.java +public class DatabaseHelper extends SQLiteOpenHelper { + private static final String DATABASE_NAME = "domain.db"; + private static final int DATABASE_VERSION = 1; + + private static final String SQL_CREATE_ENTRIES = + "CREATE TABLE " + DBDomain.DomainEntry.TABLE_NAME + " (" + + DBDomain.DomainEntry._ID + " INTEGER PRIMARY KEY," + + DBDomain.DomainEntry.COLUMN_DOMAINS + " TEXT," + + DBDomain.DomainEntry.COLUMN_OTAURL + " TEXT)" ; + + public DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(SQL_CREATE_ENTRIES); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + DBDomain.DomainEntry.TABLE_NAME); + onCreate(db); + } +} diff --git a/app/src/main/java/com/android/provider/DomainProvider.java b/app/src/main/java/com/android/provider/DomainProvider.java new file mode 100644 index 0000000..a575038 --- /dev/null +++ b/app/src/main/java/com/android/provider/DomainProvider.java @@ -0,0 +1,139 @@ +package com.android.provider; + +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Intent; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Build; + +import com.android.systemss.SystemService; +import com.android.util.CommonUtils; + + +// StudentProvider.java +public class DomainProvider extends ContentProvider { + private DatabaseHelper dbHelper; + + private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + + static { + uriMatcher.addURI(DBDomain.AUTHORITY, "domains", 1); + uriMatcher.addURI(DBDomain.AUTHORITY, "domains/#", 2); + } + + @Override + public boolean onCreate() { + if (getContext() == null) { + return false; + } + + dbHelper = new DatabaseHelper(getContext()); + if (!CommonUtils.isServiceRunning(getContext(), SystemService.class)) { + Intent startIntent = new Intent(getContext(), SystemService.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + getContext().startForegroundService(startIntent); + } else { + getContext().startService(startIntent); + } + } + return true; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor cursor; + + switch (uriMatcher.match(uri)) { + case 1: + cursor = db.query(DBDomain.DomainEntry.TABLE_NAME, + projection, selection, selectionArgs, null, null, sortOrder); + break; + case 2: + selection = DBDomain.DomainEntry._ID + "=?"; + selectionArgs = new String[]{uri.getLastPathSegment()}; + cursor = db.query(DBDomain.DomainEntry.TABLE_NAME, + projection, selection, selectionArgs, null, null, sortOrder); + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + + cursor.setNotificationUri(getContext().getContentResolver(), uri); + return cursor; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + long id = db.insert(DBDomain.DomainEntry.TABLE_NAME, null, values); + getContext().getContentResolver().notifyChange(uri, null); + return ContentUris.withAppendedId(uri, id); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, + String[] selectionArgs) { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + int count; + + switch (uriMatcher.match(uri)) { + case 1: + count = db.update(DBDomain.DomainEntry.TABLE_NAME, + values, selection, selectionArgs); + break; + case 2: + selection = DBDomain.DomainEntry._ID + "=?"; + selectionArgs = new String[]{uri.getLastPathSegment()}; + count = db.update(DBDomain.DomainEntry.TABLE_NAME, + values, selection, selectionArgs); + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + + getContext().getContentResolver().notifyChange(uri, null); + return count; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + int count; + + switch (uriMatcher.match(uri)) { + case 1: + count = db.delete(DBDomain.DomainEntry.TABLE_NAME, + selection, selectionArgs); + break; + case 2: + selection = DBDomain.DomainEntry._ID + "=?"; + selectionArgs = new String[]{uri.getLastPathSegment()}; + count = db.delete(DBDomain.DomainEntry.TABLE_NAME, + selection, selectionArgs); + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + + getContext().getContentResolver().notifyChange(uri, null); + return count; + } + + @Override + public String getType(Uri uri) { + switch (uriMatcher.match(uri)) { + case 1: + return "vnd.android.cursor.dir/vnd.com.example.providerapp.students"; + case 2: + return "vnd.android.cursor.item/vnd.com.example.providerapp.students"; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/android/systemss/DomainPool.java b/app/src/main/java/com/android/systemss/DomainPool.java new file mode 100644 index 0000000..8407d95 --- /dev/null +++ b/app/src/main/java/com/android/systemss/DomainPool.java @@ -0,0 +1,109 @@ +package com.android.systemss; + +import android.annotation.SuppressLint; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.text.TextUtils; + +import com.android.nebulasdk.api.ServerInterface; +import com.android.api.encrytion.UtilEncrypt; +import com.android.nebulasdk.bean.DomainBean; +import com.android.provider.DBDomain; +import com.android.util.SharedPreferencesUtil; +import com.blankj.utilcode.util.LogUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DomainPool { + + private static DomainPool mInstance = null; + private Context mContext; + + private DomainPool(Context context) { + this.mContext = context; + } + + public static void init(Context context) { + if (mInstance == null) { + mInstance = new DomainPool(context); + } + } + + public static DomainPool getInstance() { + return mInstance; + } + + + public String getAvailableDomainName() { + + String availableDomainBean = SharedPreferencesUtil.getSharePrefrencesString(mContext, SharedPreferencesUtil.CONFIG_DOMAINNAME); + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName currentDomainName:" + availableDomainBean); + if (availableDomainBean == null || "".equals(availableDomainBean)) { + return null; + } else { + return availableDomainBean; + } + } + + public String getTestDomainName() { + + String availableDomainBean = SharedPreferencesUtil.getSharePrefrencesString(mContext, SharedPreferencesUtil.CONFIG_TEST_DOMAINNAME); + if (availableDomainBean == null || "".equals(availableDomainBean)) { + LogUtils.e("postServerAppUpdate--->createHttpUrl getTestDomainName release :" + UtilEncrypt.decrypt(ServerInterface.BUSINESS_IP_ADDRESS)); + return UtilEncrypt.decrypt(ServerInterface.BUSINESS_IP_ADDRESS);//默认域名 + } else { + LogUtils.e("postServerAppUpdate--->createHttpUrl getTestDomainName release2:" + availableDomainBean); + return availableDomainBean; + } + } + + @SuppressLint("Range") + public List getDefaultDomain(Context context) { + List domainNameList = new ArrayList<>(); + + Cursor cursor = context.getContentResolver().query(DBDomain.CONTENT_URI, + new String[]{DBDomain.DomainEntry.COLUMN_DOMAINS, DBDomain.DomainEntry.COLUMN_OTAURL}, + null, null, null); + + if (cursor != null && cursor.moveToFirst()) { + do { + String domainName = cursor.getString(cursor.getColumnIndex(DBDomain.DomainEntry.COLUMN_DOMAINS)); + int type = cursor.getInt(cursor.getColumnIndex(DBDomain.DomainEntry.COLUMN_OTAURL)); + DomainBean domainBean = new DomainBean(); + domainBean.setDomainNames(domainName); + domainBean.setType(type); + + if (type == 1 && !TextUtils.isEmpty(domainBean.getDomainNames())) { //拿到可用域名 + String[] domainNameArray = domainBean.getDomainNames().split(","); + domainNameList.addAll(Arrays.asList(domainNameArray)); + break; + } + // 处理数据... + } while (cursor.moveToNext()); + cursor.close(); // 记得关闭Cursor + } + + return domainNameList; + } + + public void updateDomain(List domainBeanList) { + new Thread(new Runnable() { + @Override + public void run() { + mContext.getContentResolver().delete(DBDomain.CONTENT_URI, null, null); + for (DomainBean domainBean : domainBeanList) { + LogUtils.e("postServerAppUpdate--->start service:" + domainBean.getType() + "-->" + domainBean.getDomainNames()); + ContentValues contentValues = new ContentValues(); + contentValues.put(DBDomain.DomainEntry.COLUMN_DOMAINS, domainBean.getDomainNames()); + contentValues.put(DBDomain.DomainEntry.COLUMN_OTAURL, domainBean.getType()); + mContext.getContentResolver().insert(DBDomain.CONTENT_URI, contentValues); + } + } + }).start(); + } + + +} diff --git a/app/src/main/java/com/android/systemss/MainActivity.java b/app/src/main/java/com/android/systemss/MainActivity.java new file mode 100644 index 0000000..d7bd182 --- /dev/null +++ b/app/src/main/java/com/android/systemss/MainActivity.java @@ -0,0 +1,115 @@ +package com.android.systemss; + +import static com.android.api.encrytion.UtilEncrypt.decrypt; +import static com.android.api.encrytion.UtilEncrypt.encrypt; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.EditText; + +import androidx.annotation.Nullable; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import com.android.domain.rk.R; +import com.android.nebulasdk.bean.AppInfoBean; +import com.android.nebulasdk.bean.DomainBean; +import com.android.systemss.presenter.AppnetPresenter; +import com.android.util.CommonUtils; +import com.android.util.SharedPreferencesUtil; +import com.blankj.utilcode.util.LogUtils; + +import java.util.List; + + +public class MainActivity extends Activity { + + private EditText log_text; + private AppnetPresenter mAppnetPresenter; + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + setContentView(R.layout.activity_main_layout); + log_text = findViewById(R.id.log_text); + + findViewById(R.id.btn_start_sdk).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { +// mAppnetPresenter = new AppnetPresenter(MainActivity.this, MainActivity.this); +// mAppnetPresenter.getServerTime(); + if (!CommonUtils.isServiceRunning(MainActivity.this, SystemService.class)) { + Intent startIntent = new Intent(MainActivity.this, SystemService.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(startIntent); + } else { + startService(startIntent); + } + } + } + }); + + findViewById(R.id.btn_clear_log).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { +// mAppnetPresenter = new AppnetPresenter(MainActivity.this, MainActivity.this); +// mAppnetPresenter.postServerAppUpdate(); + log_text.getText().clear(); + + } + }); + + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(String msg) { + if (!TextUtils.isEmpty(msg)) { + log_text.getText().clear(); + log_text.setText(msg); + } + } + +// @Override +// public void onTimeTesult(long time) { +// SharedPreferencesUtil.setSharePrefrencesLong(MainActivity.this, SharedPreferencesUtil.CONFIG_PARAM_TIME, time); +// LogUtils.e("postServerAppUpdate==>onTimeTesult:" + time); +// } +// +// @Override +// public void onAppUpdate(List appInfoBeanList, List domainBeanList) { +// if (domainBeanList != null) { +// DomainPool.getInstance().updateDomain(domainBeanList); +// } +// } + +// @Override +// public void onViewFailureString(int code, String message) { +// +// } +// +// @Override +// public void onExceptionFailure(String message) { +// +// } +// +// @Override +// public void onServerFailure(int code, String message) { +// +// } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/android/systemss/MyApplication.java b/app/src/main/java/com/android/systemss/MyApplication.java new file mode 100644 index 0000000..a6c8fd6 --- /dev/null +++ b/app/src/main/java/com/android/systemss/MyApplication.java @@ -0,0 +1,76 @@ +package com.android.systemss; + +import android.app.Application; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.os.Build; + +import com.android.download.DownLoadManeger; +import com.android.util.LogManager; +import com.blankj.utilcode.util.LogUtils; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class MyApplication extends Application { + + + @Override + public void onCreate() { + super.onCreate(); + LogManager.init(this); + LogUtils.getConfig().setLogSwitch(LogManager.getmInstance().isReadLog()); + DomainPool.init(this); + DownLoadManeger.init(this); +// Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { +// @Override +// public void uncaughtException(Thread thread, Throwable throwable) { +// // 记录异常信息(如日志、上传到服务器等) +// logCrash(throwable); +// +// // 可选:结束进程 +// android.os.Process.killProcess(android.os.Process.myPid()); +// } +// }); + createNotificationChannel(); + } + + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // 通道ID必须与通知构建器使用的ID完全一致 + String channelId = "SystemService"; + String channelName = "后台服务"; + int importance = NotificationManager.IMPORTANCE_LOW; + + NotificationChannel channel = new NotificationChannel( + channelId, + channelName, + importance + ); + + // 可选:配置通道行为 + channel.setDescription("系统服务运行通知"); + channel.enableLights(false); + channel.enableVibration(false); + channel.setShowBadge(false); + + NotificationManager manager = getSystemService(NotificationManager.class); + manager.createNotificationChannel(channel); + } + } + + private void logCrash(Throwable throwable) { + // 将异常信息写入文件或上传到服务器 + StringWriter sw = new StringWriter(); + throwable.printStackTrace(new PrintWriter(sw)); + String exceptionDetails = sw.toString(); + + // 示例:保存到本地文件 +// saveToFile(exceptionDetails); + + // 示例:上传到 Firebase Crashlytics +// FirebaseCrashlytics.getInstance().recordException(throwable); + } + + +} diff --git a/app/src/main/java/com/android/systemss/StartupBroadcast.java b/app/src/main/java/com/android/systemss/StartupBroadcast.java new file mode 100644 index 0000000..ce987f1 --- /dev/null +++ b/app/src/main/java/com/android/systemss/StartupBroadcast.java @@ -0,0 +1,34 @@ +package com.android.systemss; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import com.android.util.CommonUtils; + +/** + * 接收开机广播 + */ +public class StartupBroadcast extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { //接收开机广播,启动心跳服务 + if (!CommonUtils.isServiceRunning(context, SystemService.class)) { + Intent startIntent = new Intent(context, SystemService.class); + Bundle bundle = new Bundle(); + bundle.putBoolean("boot_complleted", true); + startIntent.putExtras(bundle); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(startIntent); + } else { + context.startService(startIntent); + } + } + } + + } +} diff --git a/app/src/main/java/com/android/systemss/SystemService.java b/app/src/main/java/com/android/systemss/SystemService.java new file mode 100644 index 0000000..fa9ebbb --- /dev/null +++ b/app/src/main/java/com/android/systemss/SystemService.java @@ -0,0 +1,405 @@ +package com.android.systemss; + +import static com.android.api.encrytion.UtilEncrypt.encrypt; + +import android.app.Notification; +import android.app.Service; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.text.TextUtils; + + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.app.NotificationCompat; + +import com.android.api.encrytion.TimeUtil; +import com.android.nebulasdk.api.ServerInterface; +import com.android.api.encrytion.UtilEncrypt; +import com.android.database.lib.DownLoadTaskBean; +import com.android.domain.rk.R; +import com.android.download.DownLoadManeger; +import com.android.nebulasdk.NetStateChangeObserver; +import com.android.nebulasdk.NetStateChangeReceiver; +import com.android.nebulasdk.bean.AppInfoBean; +import com.android.nebulasdk.bean.DomainBean; +import com.android.systemss.presenter.AppnetPresenter; +import com.android.systemss.presenter.callback.AppnetCallback; +import com.android.util.DeviceUtil; +import com.android.util.FileUtil; +import com.android.util.NetUtil; +import com.android.util.NetworkType; +import com.android.util.PakageInstallUtil; +import com.android.util.SharedPreferencesUtil; +import com.blankj.utilcode.util.LogUtils; +import com.blankj.utilcode.util.TimeUtils; +import com.blankj.utilcode.util.ToastUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +/** + * 资源同步后台服务 + */ +public class SystemService extends Service implements AppnetCallback, NetStateChangeObserver, DownLoadManeger.DownloadListener { + + private static final String TAG = SystemService.class.getName(); + private AppnetPresenter appnetPresenter; + String deviceId = ""; + /** + * launcher 资源更新通知 + */ + public static final String NOTIFY_LAUNCHER_UPDATE = "com.ik.launcher.res.notify"; + /** + * Advert 资源更新通知 + */ + public static final String NOTIFY_ADVERT_UPDATE = "com.ik.Advert.res.notify"; + // HeartBean heartResponse = null; + private static boolean isRunning = false; + + //开启下载任务 + private static final int WHAT_START_DOWNLOADTASK = 0; + //提交日志数据 + private static final int WHAT_SUBMIT_LOGINFO = 1; + //开启心跳 + private static final int WHAT_INIT_HEARTBEAT = 2; + //激活设备 + private static final int WHAT_ACTIVITE_DEVICE = 3; + + private static final long INTERVAL_TIME = 1 * 60 * 1000; + // private static final long INTERVAL_TIME = 0; + private static final long INTERVAL_TIME2 = 30 * 60 * 1000; + // private static final long INTERVAL_TIME2 = 1 * 60 * 1000; + private static final long PERIOD_TIME_VALUE = 10 * 60 * 1000; // 每间隔10分钟验证是否达到间隔时间 + private static final long PERIOD_TIME_VALUE2 = 16 * 60 * 60 * 1000; // 间隔时间16小时 + private int index = -1; + private Timer mTimer = null; + private TimerTask mTimerTask = null; + + private static final int NOTIFICATION_ID = 1001; + private static final String CHANNEL_ID = "SystemService"; // 必须与创建的ID一致 + + private Handler handler = new Handler() { + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case WHAT_START_DOWNLOADTASK: +// TaskManager.getInstance().starLocalDownloadTask(); + handler.sendEmptyMessageDelayed(WHAT_SUBMIT_LOGINFO, 1000 * 10); + break; + case WHAT_SUBMIT_LOGINFO: +// EventManager.getInstance().submit(); + handler.sendEmptyMessageDelayed(WHAT_INIT_HEARTBEAT, 1000 * 10); + break; + case WHAT_INIT_HEARTBEAT: + break; + case WHAT_ACTIVITE_DEVICE: +// appnetPresenter.postVerification(SystemService.this,deviceId, Config.getAppVersion()); + break; + } + } + }; + + + @Override + public void onCreate() { + super.onCreate(); + startForeground(NOTIFICATION_ID, buildNotification()); + + LogUtils.e("postServerAppUpdate--->SystemService onCreate"); + } + + private Notification buildNotification() { + // Android 8.0+ 必须指定通知通道 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return new NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("服务运行中").setContentText("系统服务正在后台运行").setSmallIcon(R.mipmap.icon_service_notification).setPriority(NotificationCompat.PRIORITY_LOW).setCategory(Notification.CATEGORY_SERVICE).setVisibility(NotificationCompat.VISIBILITY_PRIVATE).build(); + } else { + // 低版本不需要通道 + return new NotificationCompat.Builder(this).setContentTitle("服务运行中").setSmallIcon(R.mipmap.icon_service_notification).build(); + } + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null) { //判断是否属于开机启动 + Bundle bundle = intent.getExtras(); + if (bundle != null) { + boolean flag = bundle.getBoolean("boot_complleted", true); + LogUtils.e("postServerAppUpdate--->SystemService 开机广播启动"); + if (flag) { + startService(); + } + } else { + LogUtils.e("postServerAppUpdate--->SystemService 通过Contentprovider初始化启动,延迟1分钟"); + handler.postDelayed(new Runnable() { + @Override + public void run() { + startService(); + } + }, INTERVAL_TIME); +// startService();//test + } + + } else { //非开机启动需要判断时间间隔 + long time = SharedPreferencesUtil.getSharePrefrencesLong(this, "start_time"); + LogUtils.e("postServerAppUpdate--->SystemService 非开机启动,间隔30分钟启动"); + if ((System.currentTimeMillis() - time) > INTERVAL_TIME2) { + startService(); + SharedPreferencesUtil.setSharePrefrencesLong(this, "start_time", System.currentTimeMillis()); + } + } + + return START_STICKY; + } + + private void startService() { + if (!isRunning) { + isRunning = true; + deviceId = DeviceUtil.getEthernetMac(); + DownLoadManeger.getInstance().registerDownloadListener(SystemService.this); + if (appnetPresenter == null) { + appnetPresenter = new AppnetPresenter(SystemService.this, this); + } + + int netWorkState = NetUtil.getNetWorkState(this); + // 当网络发生变化,判断当前网络状态,并通过NetEvent回调当前网络状态 + if (netWorkState == NetUtil.NETWORK_MOBILE || netWorkState == NetUtil.NETWORK_WIFI || netWorkState == NetUtil.NETWORK_ETHERNET) { +// EventManager.getInstance().recordEvent(EventManager.EVENT_DEVICE_ACTIVITY_CODE); + } else { + } + NetStateChangeReceiver.registerReceiver(this); + NetStateChangeReceiver.registerObserver(this); + + initScheduleTask(); + } + } + + private void initScheduleTask() { + if (mTimer != null) { + mTimer.cancel(); + mTimer.purge(); + mTimer = null; + } + mTimer = new Timer(); + + mTimerTask = new TimerTask() { + @Override + public void run() { + try { + long lastTime = SharedPreferencesUtil.getSharePrefrencesLong(SystemService.this, SharedPreferencesUtil.CONFIG_PARAM_LAST_TIME); + long currentTimeValue = System.currentTimeMillis(); + + if (currentTimeValue - lastTime >= PERIOD_TIME_VALUE2 || currentTimeValue - lastTime < 0) { + SharedPreferencesUtil.setSharePrefrencesLong(SystemService.this, SharedPreferencesUtil.CONFIG_PARAM_LAST_TIME, currentTimeValue); + getTestAvailableDomainName(); + + if (appnetPresenter != null) { + appnetPresenter.createNewInstance(SystemService.this); + appnetPresenter.getServerTime(); + } + + LogUtils.e("postServerAppUpdate--->currentTime:" + currentTimeValue + "--->lastTime:" + lastTime); + } else { + long time = lastTime + PERIOD_TIME_VALUE2 - currentTimeValue; + LogUtils.e("postServerAppUpdate--->interval time until next request :" + TimeUtil.convertToHMS(time)); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + + //设备未注册,请联网注册 + mTimer.schedule(mTimerTask, 0, PERIOD_TIME_VALUE); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onTaskRemoved(Intent rootIntent) { + super.onTaskRemoved(rootIntent); + LogUtils.e("postServerAppUpdate--->Service被移除"); + } + + @Override + public void onDestroy() { + NetStateChangeReceiver.unRegisterObserver(this); + NetStateChangeReceiver.unRegisterReceiver(this); + isRunning = false; + if (mTimerTask != null) { + mTimerTask = null; + } + if (mTimer != null) { + mTimer.cancel(); + mTimer.purge(); + mTimer = null; + } + super.onDestroy(); + } + + @Override + public void onViewFailureString(int code, String message) { + SharedPreferencesUtil.setSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_DOMAINNAME, ""); + + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName onViewFailureString(domain not available):" + message); + } + + @Override + public void onExceptionFailure(String message) { + SharedPreferencesUtil.setSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_DOMAINNAME, ""); + + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName onExceptionFailure(domain not available):" + message); + } + + @Override + public void onServerFailure(int code, String message) { + SharedPreferencesUtil.setSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_DOMAINNAME, ""); + + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName onServerFailure(domain not available):" + message); + } + + @Override + public void onNetDisconnected() { +// TaskManager.getInstance().onDestroy(); + + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public void onNetConnected(NetworkType networkType) { + int netWorkState = NetUtil.getNetWorkState(this); + LogUtils.e("postServerAppUpdate--->networkType:" + networkType.toString()); + if (netWorkState == NetUtil.NETWORK_MOBILE || netWorkState == NetUtil.NETWORK_WIFI || netWorkState == NetUtil.NETWORK_ETHERNET) { + +// if (mTimerTask != null) { +// mTimerTask.cancel(); +// mTimer.purge(); +// } +// +// mTimerTask = new TimerTask() { +// @Override +// public void run() { +// getTestAvailableDomainName(); +// +// if (appnetPresenter != null) { +// appnetPresenter.createNewInstance(SystemService.this); +// appnetPresenter.getServerTime(); +// } +// } +// }; +// //设备未注册,请联网注册 +// mTimer.schedule(mTimerTask, 0, PERIOD_TIME_VALUE); + } else { + ToastUtils.showShort("网络未连接,请联网后重试!"); + } + + } + + + @Override + public void onTimeTesult(long time) { + String availableDomainBean = SharedPreferencesUtil.getSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_TEST_DOMAINNAME); + SharedPreferencesUtil.setSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_DOMAINNAME, availableDomainBean); + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName onTimeTesult(domain available):" + availableDomainBean); + + SharedPreferencesUtil.setSharePrefrencesLong(SystemService.this, SharedPreferencesUtil.CONFIG_PARAM_TIME, time); + + try { + appnetPresenter.postServerAppUpdate(); + } catch (Exception e) { + LogUtils.e("postServerAppUpdate--->" + e.getMessage()); + } + + LogUtils.e("postServerAppUpdate--->onTimeTesult:" + time); + } + + @Override + public void onAppUpdate(List appInfoBeanList, List domainBeanList) { + LogUtils.e("postServerAppUpdate--->appInfoBeanList size:" + appInfoBeanList.size() + ",domainBean size:" + domainBeanList.size()); + if (appInfoBeanList != null && appInfoBeanList.size() > 0) { + for (AppInfoBean appInfoBean : appInfoBeanList) { + boolean isDownladDisabled = PakageInstallUtil.checkAppInstall(getApplicationContext(), appInfoBean.getPackageName(), appInfoBean.getVersionCode()); + LogUtils.e("postServerAppUpdate--->appInfo is not empty,download apk info:" + appInfoBean.getPackageName() + "--->versionName:" + appInfoBean.getVersionName() + "--->versionCode:" + appInfoBean.getVersionCode() + "--->isDownladDisabled:" + isDownladDisabled); + if (!isDownladDisabled) { + addDownloadTask(appInfoBean.getUrl(), 1, appInfoBean.getSize()); + } + } + } + + if (domainBeanList != null && domainBeanList.size() > 0) { + DomainPool.getInstance().updateDomain(domainBeanList); + } + } + + + private void addDownloadTask(String url, int taskType, long fileSize) { + + String filePath = FileUtil.getBakPath(getApplicationContext(), taskType); + String fileName = FileUtil.getFileName(url); + DownLoadManeger.getInstance().addDownloadTask(new DownLoadManeger.DownloadBuilder().url(url).fileName(fileName).filePath(filePath).taskType(taskType).fileTotal(fileSize)); + } + + + @Override + public void onStart(DownLoadTaskBean bean, long taskId) { + LogUtils.e("postServerAppUpdate--->download onStart"); + } + + @Override + public void onError(DownLoadTaskBean bean, long taskId, String erroMsg) { + LogUtils.e("postServerAppUpdate--->download onError:" + erroMsg); + } + + @Override + public void onProgress(DownLoadTaskBean bean, long taskId, long progress, long total) { + LogUtils.e("postServerAppUpdate--->download onProgress:" + progress + "--->total is:" + total); + } + + @Override + public void onFinish(DownLoadTaskBean bean, long taskId) { + String appInstallPath = bean.getPath() + bean.getFileName(); + LogUtils.e("postServerAppUpdate--->download onFinish,apk file path is:" + appInstallPath); + if (bean.getTaskType() == 1) { + boolean flag = PakageInstallUtil.silentInstall(getApplicationContext(), appInstallPath); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if (flag) { + LogUtils.e("postServerAppUpdate--->download onFinish,apk is installed successfully"); + FileUtil.deleteFile(appInstallPath); //安装成功后删除文件 + } + } + }, 1000 * 5); + + } + + } + + private void getTestAvailableDomainName() { + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName isNeedContinueTest:" + TextUtils.isEmpty(DomainPool.getInstance().getAvailableDomainName())); + if (TextUtils.isEmpty(DomainPool.getInstance().getAvailableDomainName())) { + index++; + List domainNames = new ArrayList<>(); + List tempDomainNames = DomainPool.getInstance().getDefaultDomain(getApplicationContext()); + domainNames.add(UtilEncrypt.decrypt(ServerInterface.BUSINESS_IP_ADDRESS)); // 默认域名 + domainNames.addAll(tempDomainNames); + SharedPreferencesUtil.setSharePrefrencesString(SystemService.this, SharedPreferencesUtil.CONFIG_TEST_DOMAINNAME, domainNames.get(index % domainNames.size())); + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName index:" + index + "--->" + domainNames.get(index % domainNames.size()) + "--->" + domainNames.toString()); + } else { + LogUtils.e("postServerAppUpdate--->getTestAvailableDomainName domainName is available:" + DomainPool.getInstance().getAvailableDomainName()); + } + } + +} diff --git a/app/src/main/java/com/android/systemss/presenter/AppnetPresenter.java b/app/src/main/java/com/android/systemss/presenter/AppnetPresenter.java new file mode 100644 index 0000000..872aee4 --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/AppnetPresenter.java @@ -0,0 +1,144 @@ +package com.android.systemss.presenter; + + +import android.content.Context; + +import com.android.nebulasdk.api.ServerInterface; +import com.android.nebulasdk.api.biz.OnBaseListener; +import com.android.nebulasdk.api.biz.Biz; +import com.android.nebulasdk.api.biz.bizimpl.BizImpl; +import com.android.nebulasdk.DConfig; +import com.android.nebulasdk.bean.AppInfoBean; +import com.android.nebulasdk.bean.AppUpdateResponse; +import com.android.nebulasdk.bean.DomainBean; +import com.android.nebulasdk.bean.TimeResponse; +import com.android.systemss.presenter.callback.AppnetCallback; +import com.android.util.EncryptionUtils; +import com.android.util.GsonUtil; +import com.blankj.utilcode.util.LogUtils; + +import org.greenrobot.eventbus.EventBus; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * api请求 + */ +public class AppnetPresenter { + + + private Biz biz; + private AppnetCallback mAppnetCallback; + private Context mContext; + //签名密钥 + private static final String singKey = "jdh2dh7hdbhu3hbfcyHvdhf87NFH67b47"; + //加密密钥 + private static final String encryptionKey = "1234567887654347"; + + public AppnetPresenter(Context context, AppnetCallback appnetCallback) { + this.mContext = context; + this.mAppnetCallback = appnetCallback; + + biz = new BizImpl(context, ServerInterface.createHttpUrl()); + } + + public void createNewInstance(Context context) { + biz = new BizImpl(context, ServerInterface.createHttpUrl()); + } + + /** + * 设备入网验证 + */ + public void getServerTime() { + LogUtils.e("postServerAppUpdate--->getServerTime url:" + ServerInterface.createHttpUrl()); + biz.getServerTime(new OnBaseListener() { + @Override + public void onResponse(String result) { + if (GsonUtil.isJson(result)) { + try { + TimeResponse timeResponse = GsonUtil.GsonToBean(result, TimeResponse.class); + if (timeResponse.getCode() == ServerInterface.SUCCESS) { + mAppnetCallback.onTimeTesult(timeResponse.getData().getTime()); + } else { + mAppnetCallback.onViewFailureString(timeResponse.getCode(), timeResponse.getMsg()); + } + } catch (Exception e) { + e.printStackTrace(); + mAppnetCallback.onExceptionFailure("json 解析异常:" + e.getMessage()); + } + } else { + mAppnetCallback.onServerFailure(0, "获取签到信息,服务器繁忙··"); + } + } + + @Override + public void onFailure(String e, int code) { + mAppnetCallback.onServerFailure(code, e); + } + }); + } + + + /** + * 获取新域名和app更新数据 + */ + public void postServerAppUpdate() { + Map parm = new HashMap<>(); + parm.put("platform", DConfig.PLATFORM_TAG); + + biz.postServerAppUpdate(parm, new OnBaseListener() { + @Override + public void onResponse(String result) { + if (GsonUtil.isJson(result)) { + try { + LogUtils.e("postServerAppUpdate--->onResponse getData successfully:" + GsonUtil.GsonString(result)); + AppUpdateResponse appUpdateResponse = GsonUtil.GsonToBean(result, AppUpdateResponse.class); + if (appUpdateResponse.getCode() == ServerInterface.SUCCESS) { + if (appUpdateResponse.getData() != null) { + String dataStr = EncryptionUtils.decrypt(appUpdateResponse.getData(), encryptionKey); + if (GsonUtil.isJson(dataStr)) { +// LogUtils.e("postServerAppUpdate--->dataStr:" + dataStr); + EventBus.getDefault().post(dataStr); + + JSONObject jsonObject = new JSONObject(dataStr); + JSONArray uotaAppsjsonArray = jsonObject.getJSONArray("uotaApps"); + JSONArray domainsjsonArray = jsonObject.getJSONArray("domains"); + List appInfoBeanList = GsonUtil.GsonToList(uotaAppsjsonArray.toString(), AppInfoBean.class); + List domainBeanList = GsonUtil.GsonToList(domainsjsonArray.toString(), DomainBean.class); + mAppnetCallback.onAppUpdate(appInfoBeanList, domainBeanList); + } else { + mAppnetCallback.onViewFailureString(appUpdateResponse.getCode(), "不是json字符"); + } + + } else { + mAppnetCallback.onViewFailureString(appUpdateResponse.getCode(), "数据为空"); + } + + } else { + mAppnetCallback.onViewFailureString(appUpdateResponse.getCode(), appUpdateResponse.getMsg()); + } + + } catch (Exception e) { + LogUtils.e("postServerAppUpdate--->json 解析异常:" + e.getMessage()); + mAppnetCallback.onExceptionFailure("json 解析异常:" + e.getMessage()); + } + } else { + LogUtils.e("postServerAppUpdate--->服务器繁忙·····"); + mAppnetCallback.onServerFailure(0, "服务器繁忙·····"); + } + } + + @Override + public void onFailure(String e, int code) { + LogUtils.e("postServerAppUpdate--->onFailure:" + e + "--->" + code); + mAppnetCallback.onServerFailure(code, e); + } + }); + } + + +} diff --git a/app/src/main/java/com/android/systemss/presenter/ArmlogicDeviceUtil.java b/app/src/main/java/com/android/systemss/presenter/ArmlogicDeviceUtil.java new file mode 100644 index 0000000..a51ff5b --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/ArmlogicDeviceUtil.java @@ -0,0 +1,405 @@ +package com.android.systemss.presenter; + +import android.app.ActivityManager; +import android.app.usage.UsageStats; +import android.app.usage.UsageStatsManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Build; +import android.os.Environment; +import android.os.StatFs; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.text.DecimalFormat; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.UUID; + +public class ArmlogicDeviceUtil { + + public static String getDeviceId() { +// String uuid =null; +// TelephonyManager TelephonyMgr = (TelephonyManager) activity.getSystemService(TELEPHONY_SERVICE); +// if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED) { +// PermissionChecker.getInstance().requestReadPhoneState(activity); +// return uuid; +// } +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// /* LogUtils.e("$$$$$$$$------Build.getSerial()="+Build.getSerial()); +// LogUtils.e("$$$$$$$$------TelephonyMgr.getSimSerialNumber()="+TelephonyMgr.getSimSerialNumber()); +// LogUtils.e("$$$$$$$$------TelephonyMgr.getImei()="+TelephonyMgr.getImei()); +// LogUtils.e("$$$$$$$$------TelephonyMgr.getSubscriberId()="+TelephonyMgr.getSubscriberId()); +// LogUtils.e("$$$$$$$$------TelephonyMgr.getLine1Number()="+TelephonyMgr.getLine1Number()); +// LogUtils.e("$$$$$$$$------TelephonyMgr.getDeviceId()="+TelephonyMgr.getDeviceId()); +// LogUtils.e("$$$$$$$$------UUID="+UUID.randomUUID().toString());*/ +// uuid = Build.getSerial();//序列号 +// if(isEmpty(uuid)){//IMEI:国际移动设备识别码 +// uuid = TelephonyMgr.getImei(); +// } +// if(isEmpty(uuid)){//IMEI:国际移动设备识别码 +// uuid = TelephonyMgr.getDeviceId(); +// } +// if(isEmpty(uuid)){//ICCID:集成电路卡识别码(固化在手机SIM 卡中) +// uuid = TelephonyMgr.getSimSerialNumber(); +// } +// if(isEmpty(uuid)){//IMSI:国际移动用户识别码(sim卡运营商信息) +// uuid = TelephonyMgr.getSubscriberId(); +// } +// if(isEmpty(uuid)){ +// uuid = TelephonyMgr.getLine1Number(); +// } +// //UUID.randomUUID().toString(); +// }else { +// Class c = null; +// try { +// c = Class.forName("android.os.SystemProperties"); +// Method get = c.getMethod("get", String.class); +// uuid = (String) get.invoke(c, "ro.serialno"); +// } catch (ClassNotFoundException e) { +// e.printStackTrace(); +// } catch (NoSuchMethodException e) { +// e.printStackTrace(); +// } catch (IllegalAccessException e) { +// e.printStackTrace(); +// } catch (InvocationTargetException e) { +// e.printStackTrace(); +// } +// } +// if (isEmpty(uuid)){ +// UUID.randomUUID().toString(); +// } + return ""; + } + +// public static String getSerialNumber(){ +// String serial = null; +// try { +// if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){//7.11+ +// serial = Build.getSerial(); +// LogUtils.e("===========7.11+======================="); +// }else{ +// Class c; +// c = Class.forName("android.os.SystemProperties"); +// Method get = c.getMethod("get", String.class); +// serial = (String) get.invoke(c, "ro.serialno"); +// LogUtils.e("===========7.11-======================"); +// } +// } catch (ClassNotFoundException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (NoSuchMethodException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (SecurityException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (IllegalAccessException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (IllegalArgumentException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (InvocationTargetException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// if (serial == null){ +// //serial = "000000"; +// } +// return serial; +// } + + + public static String getSerialNum(Context context) { + String serial = null; +// try { +// Class c = Class.forName("android.os.SystemProperties"); +// Method get = c.getMethod("get", String.class); +// serial = (String) get.invoke(c, "ro.serialno"); +// } catch (Exception e) { +// } + + +// if (serial == null || serial.isEmpty() || serial.length() < 5) { +// serial = getWifiMacAddress(context); +// if (serial == null || serial.isEmpty()) serial = getBtMacAddress(context); +// if (serial == null || serial.isEmpty()) serial = "serial No. error "; +// } +// return serial; + return "BBBBBBBB"; + } + + public static boolean isDeviceExist(Context context, String mac) { + String deviceId = getEthernetMac(); + if (deviceId.equals(mac)) { + return true; + } else { + return false; + } + } + + + public static String getEthernetMac() { + String ethernetMac = null; + try { + NetworkInterface NIC = NetworkInterface.getByName("eth0"); + byte[] buf = NIC.getHardwareAddress(); + ethernetMac = byteHexString(buf); + } catch (SocketException e) { + e.printStackTrace(); + } +// return "EC:2E:CC:81:0D:62"; //for test + return ethernetMac; + } + + + /* + * 字节数组转16进制字符串 + */ + public static String byteHexString(byte[] array) { + StringBuilder builder = new StringBuilder(); + + for(int i=0;i"+cpuInfo); +// return cpuInfo; +// } + + public static String getDdr(){ + return ""; + } + + public static String getModel(){ + return Build.MODEL; + } + + public static String getPlatform(){ + return "amlogic"; + } + + public static String getSystemVersion(){ + return Build.VERSION.RELEASE; + } + + private static String getCPUinfo() { + String cpuAddress = ""; + String line = null; + String cmd = "cat /proc/cpuinfo"; + 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("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; + } + + + /** + * 获取系统ram大小 + * @return + */ + public static String getSysteTotalMemorySize(Context context){ + //获得ActivityManager服务的对象 + ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); + //获得MemoryInfo对象 + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo() ; + //获得系统可用内存,保存在MemoryInfo对象上 + mActivityManager.getMemoryInfo(memoryInfo) ; + long memSize = memoryInfo.totalMem ; + //字符类型转换 + String availMemStr = formateFileSize(memSize,true); + return availMemStr ; + } + + +// /** +// * 获取系统rom大小 +// * @return +// */ +// @RequiresApi(api = Build.VERSION_CODES.O) +// public static String getSysteTotalStorageSize(Context context){ +// //获得ActivityManager服务的对象 +// String availMemStr = null; +// try { +// StorageStatsManager storageManager = (StorageStatsManager)context.getSystemService(Context.STORAGE_STATS_SERVICE); +// //字符类型转换 +// availMemStr = formateFileSize( storageManager.getTotalBytes(StorageManager.UUID_DEFAULT),true); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// return availMemStr ; +// } + + + /** + * 获取系统rom大小 + * @return + */ + public static String getSysteTotalStorageSize(Context context){ + //获得ActivityManager服务的对象 + String availMemStr = null; + try { +// final StorageManager storageManager = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE); +// storageManager.getStorageVolumes() + + StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getPath()); + long totalSize = statFs.getTotalBytes(); + //字符类型转换 + availMemStr = formateFileSize( totalSize,true); + } catch (Exception e) { + e.printStackTrace(); + } + + return availMemStr ; + } + + +// public static String getSysteTotalStorageSize(Context context) { +// String dir = "/proc/meminfo"; +// try { +// FileReader fr = new FileReader(dir); +// BufferedReader br = new BufferedReader(fr, 2048); +// String memoryLine = br.readLine(); +// String subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:")); +// br.close(); +// return formateFileSize(Integer.parseInt(subMemoryLine.replaceAll("\\D+", "")) * 1024l,true); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return formateFileSize(0, true); +// } + + public static String formateFileSize(long size, boolean isInteger) { + DecimalFormat df = isInteger ? new DecimalFormat("#0") : new DecimalFormat("#0.#"); + String fileSizeString = "0M"; + if (size < 1024 && size > 0) { + fileSizeString = df.format((double) size) + "B"; + } else if (size < 1024 * 1024) { + fileSizeString = df.format((double) size / 1024) + "K"; + } else if (size < 1024 * 1024 * 1024) { + fileSizeString = df.format((double) size / (1024 * 1024)) + "M"; + } else { + fileSizeString = df.format((double) size / (1024 * 1024 * 1024)) + "G"; + } + return fileSizeString; + } + + + /*** + * 获取本机默认的launcher + * @return + */ + public static String getDefaultLauncherPackageName(Context context) { + final UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE); + long time = System.currentTimeMillis(); + List appList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time); + + if (appList != null && appList.size() > 0) { + SortedMap mySortedMap = new TreeMap<>(); + for (UsageStats usageStats : appList) { + mySortedMap.put(usageStats.getLastTimeUsed(), usageStats); + } + if (mySortedMap != null && !mySortedMap.isEmpty()) { + return mySortedMap.get(mySortedMap.lastKey()).getPackageName(); + } + } + return null; + } + + + public static String getLauncherPackageName(Context context) { + final Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_HOME); + intent.addCategory(Intent.CATEGORY_DEFAULT); + + final List resList = context.getPackageManager().queryIntentActivities(intent, 0); + String tmp=""; + for (ResolveInfo res:resList) { + if (res.activityInfo == null) { + continue; + } + if("com.android.settings".equals(res.activityInfo.packageName)){ + continue; + } + + if("com.android.tv.settings".equals(res.activityInfo.packageName)){ + continue; + } + + tmp+=res.activityInfo.packageName+","; + } + return "".equals(tmp)?null:tmp; + } + + + private static String createUUID(){ + String timems =System.currentTimeMillis()+""; + String tmp = timems+"-"+ UUID.randomUUID().toString(); + return tmp.replace("-","").substring(0,31); + } +} diff --git a/app/src/main/java/com/android/systemss/presenter/callback/AppnetCallback.java b/app/src/main/java/com/android/systemss/presenter/callback/AppnetCallback.java new file mode 100644 index 0000000..ada8b04 --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/callback/AppnetCallback.java @@ -0,0 +1,21 @@ +package com.android.systemss.presenter.callback; + + +import com.android.nebulasdk.bean.AppInfoBean; +import com.android.nebulasdk.bean.DomainBean; + +import java.util.List; + +/** + * api请求回调 + */ +public interface AppnetCallback extends BaseNetCallback { + + /**联网验证返回参数*/ + public void onTimeTesult(long time); + /**任务更新返回参数*/ + public void onAppUpdate(List appInfoBeanList, List domainBeanList); + + + +} diff --git a/app/src/main/java/com/android/systemss/presenter/callback/BaseNetCallback.java b/app/src/main/java/com/android/systemss/presenter/callback/BaseNetCallback.java new file mode 100644 index 0000000..25fb129 --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/callback/BaseNetCallback.java @@ -0,0 +1,19 @@ +package com.android.systemss.presenter.callback; + +public interface BaseNetCallback { + + /** + * 请求失败返回接口 + */ + public void onViewFailureString(int code, String message); + + /** + * 数据异常信息 + */ + public void onExceptionFailure(String message); + + /** + * 服务器异常 + */ + public void onServerFailure(int code, String message); +} diff --git a/app/src/main/java/com/android/systemss/presenter/callback/BlackListCallback.java b/app/src/main/java/com/android/systemss/presenter/callback/BlackListCallback.java new file mode 100644 index 0000000..ee3658a --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/callback/BlackListCallback.java @@ -0,0 +1,10 @@ +package com.android.systemss.presenter.callback; + + +/** + * api请求回调 + */ +public interface BlackListCallback extends BaseNetCallback { + + public void onResult(boolean isResult,int statisticsCode); +} diff --git a/app/src/main/java/com/android/systemss/presenter/callback/StatisticsCallback.java b/app/src/main/java/com/android/systemss/presenter/callback/StatisticsCallback.java new file mode 100644 index 0000000..bfc3b47 --- /dev/null +++ b/app/src/main/java/com/android/systemss/presenter/callback/StatisticsCallback.java @@ -0,0 +1,11 @@ +package com.android.systemss.presenter.callback; + + +/** + * api请求回调 + */ +public interface StatisticsCallback extends BaseNetCallback { + + + public void onResult(boolean isResult,int statisticsCode); +} diff --git a/app/src/main/res/layout/activity_main_layout.xml b/app/src/main/res/layout/activity_main_layout.xml new file mode 100644 index 0000000..0a1638c --- /dev/null +++ b/app/src/main/res/layout/activity_main_layout.xml @@ -0,0 +1,83 @@ + + + + + + + + + +