diff --git a/app/build.gradle b/app/build.gradle
index f4ea6f4..7bebe5e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,13 +10,13 @@ def releaseTime() {
android {
compileSdkVersion 28
- buildToolsVersion "29.0.2"
+ buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.info.sn"
minSdkVersion 23
targetSdkVersion 28
- versionCode 31
- versionName "1.3.1"
+ versionCode 35
+ versionName "1.3.5"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
@@ -31,6 +31,12 @@ android {
]
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
buildTypes {
release {
minifyEnabled false
@@ -42,6 +48,14 @@ android {
}
//签名
signingConfigs {
+ zhanRui {
+ storeFile file("src/keys/zhanxun.keystore")
+ storePassword "123456"
+ keyAlias "zhanxun"
+ keyPassword "123456"
+ v1SigningEnabled true
+ v2SigningEnabled true
+ }
debug {
storeFile file("src/keys/xueshibaoos.jks")
storePassword "123456"
@@ -59,9 +73,22 @@ android {
}
buildTypes {
+ zhanRuiRelease.initWith(release)
+ zhanRuiRelease {
+ buildConfigField "String", "platform", '"ZhanRui"'
+ signingConfig signingConfigs.zhanRui
+ }
+
+ zhanRuiDebug.initWith(debug)
+ zhanRuiDebug {
+ versionNameSuffix "-debug"
+ buildConfigField "String", "platform", '"ZhanRui"'
+ debuggable true
+ signingConfig signingConfigs.zhanRui
+ }
+
debug {
- // 显示Log
- buildConfigField "boolean", "LOG_DEBUG", "true"
+ buildConfigField "String", "platform", '"MTK"'
versionNameSuffix "-debug"
minifyEnabled false
//Zipalign优化
@@ -70,15 +97,15 @@ android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (outputFile != null) {
- def fileName = "${appName()}-V${defaultConfig.versionName}-${releaseTime()}.apk"
+ def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk"
output.outputFileName = fileName
}
}
}
}
+
release {
- // 不显示Log
- buildConfigField "boolean", "LOG_DEBUG", "false"
+ buildConfigField "String", "platform", '"MTK"'
//混淆
minifyEnabled false
//Zipalign优化
@@ -92,9 +119,8 @@ android {
variant.outputs.each { output ->
def outputFile = ""
if (outputFile != null) {
- def fileName = "${appName()}-${defaultConfig.versionCode}-V${defaultConfig.versionName}-${releaseTime()}.apk"
+ def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk"
output.outputFileName = new File(outputFile, fileName)
-
}
}
}
@@ -127,25 +153,19 @@ dependencies {
implementation 'com.hjq:xxpermissions:6.0'
//okhttp
implementation 'com.squareup.okhttp3:okhttp:4.6.0'
- //RxJava和Retrofit
- implementation 'io.reactivex.rxjava2:rxjava:2.2.5'
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
- implementation 'com.squareup.retrofit2:retrofit:2.3.0'
- implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
- implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
-
- //http框架
- //implementation 'com.lzy.net:okgo:3.0.4'
- //implementation 'com.lzy.net:okrx:0.1.2'
- //implementation 'com.lzy.net:okserver:2.0.5'
-
+ //Retrofit
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+ implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
+ //RxJava
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.zxing:core:3.3.0'
implementation 'com.alibaba:fastjson:1.2.70'
-
//implementation 'com.blankj:utilcode:1.26.0'
implementation 'com.arialyy.aria:core:3.8.15'
annotationProcessor 'com.arialyy.aria:compiler:3.8.15'
@@ -158,3 +178,24 @@ dependencies {
//https://github.com/JessYanCoding/AndroidAutoSize
implementation 'me.jessyan:autosize:1.2.1'
}
+
+preBuild {
+ doLast {
+ def imlFile = file(project.name + ".iml")
+ println 'Change ' + project.name + '.iml order'
+ try {
+ def parsedXml = (new XmlParser()).parse(imlFile)
+ def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
+ parsedXml.component[1].remove(jdkNode)
+ def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
+ println 'what' + sdkString
+ new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
+ groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
+ } catch (FileNotFoundException e) {
+ // nop, iml not found
+ println "no iml found"
+ }
+ }
+ //https://www.pianshen.com/article/93481144911/
+ //使用系统编译后的framework.jar
+}
diff --git a/app/src/androidTest/java/com/info/sn/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/info/sn/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..f64e2ec
--- /dev/null
+++ b/app/src/androidTest/java/com/info/sn/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.info.sn;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.info.sn", appContext.getPackageName());
+ }
+}
diff --git a/app/src/keys/zhanxun.keystore b/app/src/keys/zhanxun.keystore
new file mode 100644
index 0000000..7c46fbc
Binary files /dev/null and b/app/src/keys/zhanxun.keystore differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ea08459..0f8ed25 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
+
@@ -255,7 +256,7 @@
-
+
factoryClass = Class.forName("android.webkit.WebViewFactory");
+ Field field = factoryClass.getDeclaredField("sProviderInstance");
+ field.setAccessible(true);
+ Object sProviderInstance = field.get(null);
+ if (sProviderInstance != null) {
+ Log.i(TAG, "sProviderInstance isn't null");
+ return;
+ }
+
+ Method getProviderClassMethod;
+ if (sdkInt > 22) {
+ getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
+ } else if (sdkInt == 22) {
+ getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
+ } else {
+ Log.i(TAG, "Don't need to Hook WebView");
+ return;
+ }
+ getProviderClassMethod.setAccessible(true);
+ Class> factoryProviderClass = (Class>) getProviderClassMethod.invoke(factoryClass);
+ Class> delegateClass = Class.forName("android.webkit.WebViewDelegate");
+ Constructor> delegateConstructor = delegateClass.getDeclaredConstructor();
+ delegateConstructor.setAccessible(true);
+ if (sdkInt < 26) {//低于Android O版本
+ Constructor> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
+ if (providerConstructor != null) {
+ providerConstructor.setAccessible(true);
+ sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
+ }
+ } else {
+ Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
+ chromiumMethodName.setAccessible(true);
+ String chromiumMethodNameStr = (String) chromiumMethodName.get(null);
+ if (chromiumMethodNameStr == null) {
+ chromiumMethodNameStr = "create";
+ }
+ Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
+ if (staticFactory != null) {
+ sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
+ }
+ }
+
+ if (sProviderInstance != null) {
+ field.set("sProviderInstance", sProviderInstance);
+ Log.i(TAG, "Hook success!");
+ } else {
+ Log.i(TAG, "Hook failed!");
+ }
+ } catch (Throwable e) {
+ Log.w(TAG, e);
+ }
}
@@ -184,10 +249,11 @@ public class MyApplication extends Application {
filter.addDataScheme("package");
registerReceiver(apKinstallReceiver, filter);
}
+
private BootReceiver bootReceiver;
private void registBootReceive() {
- if (null == bootReceiver){
+ if (null == bootReceiver) {
bootReceiver = new BootReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
diff --git a/app/src/main/java/com/info/sn/jpush/MyReceiver.java b/app/src/main/java/com/info/sn/jpush/MyReceiver.java
index 41d8c21..8b233ff 100644
--- a/app/src/main/java/com/info/sn/jpush/MyReceiver.java
+++ b/app/src/main/java/com/info/sn/jpush/MyReceiver.java
@@ -228,6 +228,7 @@ public class MyReceiver extends BroadcastReceiver {
String type = bundle.getString(JPushInterface.EXTRA_CONTENT_TYPE);
String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
// HTTPInterface.checkDevicesInfo(context);
+ ToastUtil.show(extras);
switch (message) {
case JIGUANG_GET_DRIVELINE:
@@ -256,6 +257,7 @@ public class MyReceiver extends BroadcastReceiver {
setAppLockedstate(context, extras);
break;
case JIGUANG_FORCE_INSTALLAPK:
+ HTTPInterface.getAllappPackage(context);
intallApk(context, extras);
break;
case JIGUANG_FORCE_UNINSTALLAPK:
diff --git a/app/src/main/java/com/info/sn/network/HTTPInterface.java b/app/src/main/java/com/info/sn/network/HTTPInterface.java
index cdb311f..c93a6cc 100644
--- a/app/src/main/java/com/info/sn/network/HTTPInterface.java
+++ b/app/src/main/java/com/info/sn/network/HTTPInterface.java
@@ -32,8 +32,10 @@ import com.info.sn.network.api.UpdateAdminSn;
import com.info.sn.service.InitJpushServer;
import com.info.sn.utils.ApkUtils;
import com.info.sn.utils.FileUtils;
+import com.info.sn.utils.JGYUtils;
import com.info.sn.utils.SPUtils;
import com.info.sn.utils.TimeUtils;
+import com.info.sn.utils.URLUtils;
import com.info.sn.utils.Utils;
import java.util.List;
@@ -100,6 +102,7 @@ public class HTTPInterface {
int code = baseResponse.code;
if (code == 200) {
JSONObject jsonObject = (JSONObject) JSON.toJSON(baseResponse.data);
+ //白名单
List white = JSON.parseArray(jsonObject.getString("browser"), BrowserBean.class);
if (null != white && white.size() != 0) {
String s = "";
@@ -111,6 +114,7 @@ public class HTTPInterface {
} else {
Settings.System.putString(context.getContentResolver(), "DeselectBrowserArray", " ");
}
+ //黑名单
List black = JSON.parseArray(jsonObject.getString("browser_black"), BrowserBean.class);
if (null != black && black.size() != 0) {
String s = "";
@@ -133,7 +137,8 @@ public class HTTPInterface {
@Override
public void onComplete() {
-
+ Log.e("setBrowser", "onComplete: ");
+ new URLUtils(context).setBrowserList();
}
});
}
@@ -161,6 +166,7 @@ public class HTTPInterface {
}
JsonObject label = jsonObject.getAsJsonArray("label").get(0).getAsJsonObject();
String home_page = label.get("home_page").getAsString();
+ Settings.System.putString(context.getContentResolver(), "homepagURL", home_page);
String label_page = label.get("label_page").getAsString();
// Log.e("getBrowserLabel", "onNext: " + home_page);
//主页
@@ -503,9 +509,10 @@ public class HTTPInterface {
jsonObject.put("address", address);
jsonObject.put("longitude", longitude);
jsonObject.put("latitude", latitude);
-// String a = jsonObject.toString();
-// String b = Utils.getMachine(context);
-// String c = Utils.getHardware(context);
+ String a = jsonObject.toString();
+ String b = Utils.getMachine(context);
+ String c = Utils.getHardware(context);
+ String d = Utils.getSerial();
UpdateAdminSn updateAdminSn = NetWorkManager.getUpdateAdminSnControl();
updateAdminSn.sendAdminSn(Utils.getSerial(),
jsonObject.toJSONString(),
@@ -665,7 +672,7 @@ public class HTTPInterface {
public static void checkUpdate(final Context context, String packageName, String versionCode) {
NewestAppUpdate newestAppUpdate = NetWorkManager.getNewestAppUpdateControl();
- newestAppUpdate.getAppUpdate(packageName, versionCode)
+ newestAppUpdate.getAppUpdate(packageName, versionCode, JGYUtils.getInstance().checkAppPlatform())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer>() {
diff --git a/app/src/main/java/com/info/sn/network/UrlAddress.java b/app/src/main/java/com/info/sn/network/UrlAddress.java
index 223f1ec..f1a2f8f 100644
--- a/app/src/main/java/com/info/sn/network/UrlAddress.java
+++ b/app/src/main/java/com/info/sn/network/UrlAddress.java
@@ -38,7 +38,7 @@ public class UrlAddress {
public final static String UPLOAD_SCREEN_SNAPSHOT = ROOT_URL + "sn/uploadScreenshot";
//上传屏幕截图
public final static String GET_SCREEN_LOCK = ROOT_URL + "sn/getScreenshot";
- //上传屏幕截图
+ //获取屏幕管控
public final static String GET_TIME_CONTROL = ROOT_URL + "sn/getTimeControl";
- //上传屏幕截图
+ //获取时间管控
}
diff --git a/app/src/main/java/com/info/sn/network/api/NewestAppUpdate.java b/app/src/main/java/com/info/sn/network/api/NewestAppUpdate.java
index b5b691a..f770c32 100644
--- a/app/src/main/java/com/info/sn/network/api/NewestAppUpdate.java
+++ b/app/src/main/java/com/info/sn/network/api/NewestAppUpdate.java
@@ -14,6 +14,7 @@ public interface NewestAppUpdate {
@GET(UrlAddress.GET_NEWESTAPPUPDATE)
Observable> getAppUpdate(
@Query("packageName") String packageName,
- @Query("versionCode") String versionCode
+ @Query("versionCode") String versionCode,
+ @Query("type") int type
);
}
diff --git a/app/src/main/java/com/info/sn/receiver/APKinstallReceiver.java b/app/src/main/java/com/info/sn/receiver/APKinstallReceiver.java
index 02bb851..827dabc 100644
--- a/app/src/main/java/com/info/sn/receiver/APKinstallReceiver.java
+++ b/app/src/main/java/com/info/sn/receiver/APKinstallReceiver.java
@@ -7,6 +7,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
@@ -27,6 +28,8 @@ import io.reactivex.schedulers.Schedulers;
public class APKinstallReceiver extends BroadcastReceiver {
+ private String TAG = APKinstallReceiver.class.getSimpleName();
+
@Override
public void onReceive(final Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
@@ -43,7 +46,7 @@ public class APKinstallReceiver extends BroadcastReceiver {
List list = pm.getInstalledPackages(0);
List uploadInfos = new ArrayList<>();
for (PackageInfo info : list) {
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1){
+ if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
continue;
}
AppUploadInfo uploadInfo = new AppUploadInfo();
@@ -69,6 +72,7 @@ public class APKinstallReceiver extends BroadcastReceiver {
@Override
public void onNext(List appUploadInfos) {
String json = JSONArray.toJSONString(appUploadInfos);
+ Log.e(TAG, "onNext: " + json);
HTTPInterface.SendAppInstall(json);
}
diff --git a/app/src/main/java/com/info/sn/service/InitJpushServer.java b/app/src/main/java/com/info/sn/service/InitJpushServer.java
index dd4da52..3e8dceb 100644
--- a/app/src/main/java/com/info/sn/service/InitJpushServer.java
+++ b/app/src/main/java/com/info/sn/service/InitJpushServer.java
@@ -32,6 +32,7 @@ import com.info.sn.utils.SPUtils;
import com.info.sn.utils.TimeUtils;
import com.info.sn.utils.Utils;
+import cn.jpush.android.api.JPushInterface;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@@ -71,6 +72,7 @@ public class InitJpushServer extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ JPushInterface.init(this);
// HTTPInterface.checkDevicesInfo(InitJpushServer.this);
HTTPInterface.getAllappPackage(InitJpushServer.this);
HTTPInterface.getForceInstall(InitJpushServer.this);
@@ -203,7 +205,6 @@ public class InitJpushServer extends Service {
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
//systemUiVisibility 关闭通知栏和导航栏
-
layoutParams.systemUiVisibility =
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
diff --git a/app/src/main/java/com/info/sn/service/ScreenLockService.java b/app/src/main/java/com/info/sn/service/ScreenLockService.java
new file mode 100644
index 0000000..14b3e53
--- /dev/null
+++ b/app/src/main/java/com/info/sn/service/ScreenLockService.java
@@ -0,0 +1,70 @@
+package com.info.sn.service;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.info.sn.activity.ScreenLockActivity;
+
+public class ScreenLockService extends Service {
+
+
+ public ScreenLockService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // TODO: Return the communication channel to the service.
+// throw new UnsupportedOperationException("Not yet implemented");
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ registerScreenLockReceiver();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (null != screenLockReceiver) {
+ unregisterReceiver(screenLockReceiver);
+ }
+ }
+
+ private ScreenLockReceiver screenLockReceiver;
+
+ public void registerScreenLockReceiver() {
+ if (null == screenLockReceiver) {
+ screenLockReceiver = new ScreenLockReceiver();
+ }
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ registerReceiver(screenLockReceiver, filter);
+ }
+
+ public static class ScreenLockReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.e("ScreenLockReceiver", "onReceive: "+action);
+ if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ Intent screenLock = new Intent(context, ScreenLockActivity.class);
+ screenLock.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+// context.startActivity(screenLock);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/info/sn/utils/JGYUtils.java b/app/src/main/java/com/info/sn/utils/JGYUtils.java
new file mode 100644
index 0000000..e57f044
--- /dev/null
+++ b/app/src/main/java/com/info/sn/utils/JGYUtils.java
@@ -0,0 +1,455 @@
+package com.info.sn.utils;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.ActivityTaskManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Build;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.JsonObject;
+import com.info.sn.BuildConfig;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
+
+
+public class JGYUtils {
+ private static final String TAG = JGYUtils.class.getSimpleName();
+
+ private static JGYUtils sInstance;
+ private Context mContext;
+ public static int MTKPlatform = 1;
+ public static int ZhanruiPlatform = 2;
+ public static int UnknowPlatform = 0;
+ public static String MTKTag = "MTK";
+ public static String ZhanruiTag = "展锐";
+
+
+ private JGYUtils(Context context) {
+ this.mContext = context;
+ }
+
+ public static void init(Context context) {
+ if (sInstance == null) {
+ sInstance = new JGYUtils(context);
+ }
+ }
+
+ public static JGYUtils getInstance() {
+ if (sInstance == null) {
+ throw new IllegalStateException("You must be init JGYUtils first");
+ }
+ return sInstance;
+ }
+
+ public static boolean isOfficialVersion() {
+ String channelValue = JGYUtils.getInstance().getStringMetaData();
+ return "official".equals(channelValue);
+ }
+
+ public static boolean isNewlyVersion() {
+ String channelValue = JGYUtils.getInstance().getStringMetaData();
+ return "beta".equals(channelValue);
+ }
+
+ public static boolean isBetaVersion() {
+ String channelValue = JGYUtils.getInstance().getStringMetaData();
+ return "beta".equals(channelValue);
+ }
+
+
+
+ private int getBatteryLevel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ BatteryManager batteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE);
+ return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
+ } else {
+ Intent intent = new ContextWrapper(mContext).registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
+ intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+ }
+ }
+
+
+ private PowerManager.WakeLock wakeLock = null;
+ private static final String mWakeLockName = "BackupService";
+
+ /**
+ * 获取电源锁,保持该服务在屏幕熄灭时仍然获取CPU时,保持运行
+ */
+ @SuppressLint("InvalidWakeLockTag")
+ private synchronized void acquireWakeLock() {
+ if (null == wakeLock) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
+ | PowerManager.ON_AFTER_RELEASE, mWakeLockName);
+ if (null != wakeLock) {
+ Log.e("fht", "acquireWakeLock!");
+ wakeLock.acquire();
+ }
+ }
+ }
+
+ /**
+ * 释放设备电源锁
+ */
+ private synchronized void releaseWakeLock() {
+ if (null != wakeLock) {
+ Log.e("fht", "releaseWakeLock!");
+ wakeLock.release();
+ wakeLock = null;
+ }
+ }
+
+
+ /**
+ * @param ids 需要管控的ID
+ * @param packages 应用程序包名
+ */
+ public void writeDeselectIDtoSystem(String ids, String packages) {
+ if (!TextUtils.isEmpty(ids) && !TextUtils.isEmpty(packages)) {
+ ArrayList idArrayList = new ArrayList<>(Arrays.asList(ids.split(",")));
+ ArrayList packageArrayList = new ArrayList<>(Arrays.asList(packages.split(",")));
+ LinkedHashSet idHashSet = new LinkedHashSet<>(idArrayList);
+ LinkedHashSet packageHashSet = new LinkedHashSet<>(packageArrayList);
+ ArrayList idList = new ArrayList<>(idHashSet);
+ ArrayList packageList = new ArrayList<>(packageHashSet);
+ StringBuilder idStringBuilder = new StringBuilder();
+ for (String id : idList) {
+ if (idStringBuilder.length() > 0) {
+ idStringBuilder.append(",");
+ }
+ idStringBuilder.append(id);
+ }
+ StringBuilder packageStringBuilder = new StringBuilder();
+ for (String pkg : packageList) {
+ if (packageStringBuilder.length() > 0) {
+ packageStringBuilder.append(",");
+ }
+ packageStringBuilder.append(pkg);
+ }
+
+
+ String olddeselectViewArray = Settings.System.getString(mContext.getContentResolver(), "qch_app_forbid_id");
+ Log.e("writeDeselectIDtoSystem", "olddeselectViewArray: " + olddeselectViewArray);
+
+ Settings.System.putString(mContext.getContentResolver(), "qch_app_forbid_id", packageStringBuilder.toString());
+ Settings.System.putString(mContext.getContentResolver(), "DeselectViewArray", idStringBuilder.toString());
+ Log.e("writeDeselectIDtoSystem", "qch_app_forbid_id: " + packageStringBuilder.toString());
+ Log.e("writeDeselectIDtoSystem", "deselectViewArray: " + idStringBuilder.toString());
+ } else {
+ Log.e("writeDeselectIDtoSystem", "writeDeselectIDtoSystem is null:");
+ Settings.System.putString(mContext.getContentResolver(), "qch_app_forbid_id", "");
+ Settings.System.putString(mContext.getContentResolver(), "DeselectViewArray", "");
+ }
+ }
+
+
+
+
+ private static void sendAllweb(Context context) {
+ Intent intent = new Intent("qch_app_website")
+ .setPackage("com.android.settings");
+ intent.putExtra("package_name", "Invalid");
+ context.sendBroadcast(intent);
+ }
+
+ private static void sendwebUrl(Context context) {
+ Intent intent = new Intent("qch_app_inside_website")
+ .setPackage("com.android.settings");
+ intent.putExtra("websitelist", "Invalid");
+ context.sendBroadcast(intent);
+ }
+
+
+ /**
+ * 从Manifest中获取meta-data值
+ * https://blog.csdn.net/yue_233/article/details/91453451
+ *
+ * @return
+ */
+ public String getStringMetaData() {
+ ApplicationInfo appInfo = null;
+ try {
+ appInfo = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ String value = appInfo.metaData.getString("CHANNEL_VALUE");
+ return value;
+ }
+
+ public void hookWebView() {
+ int sdkInt = Build.VERSION.SDK_INT;
+ try {
+ Class> factoryClass = Class.forName("android.webkit.WebViewFactory");
+ Field field = factoryClass.getDeclaredField("sProviderInstance");
+ field.setAccessible(true);
+ Object sProviderInstance = field.get(null);
+ if (sProviderInstance != null) {
+ Log.i(TAG, "sProviderInstance isn't null");
+ return;
+ }
+
+ Method getProviderClassMethod;
+ if (sdkInt > 22) {
+ getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
+ } else if (sdkInt == 22) {
+ getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
+ } else {
+ Log.i(TAG, "Don't need to Hook WebView");
+ return;
+ }
+ getProviderClassMethod.setAccessible(true);
+ Class> factoryProviderClass = (Class>) getProviderClassMethod.invoke(factoryClass);
+ Class> delegateClass = Class.forName("android.webkit.WebViewDelegate");
+ Constructor> delegateConstructor = delegateClass.getDeclaredConstructor();
+ delegateConstructor.setAccessible(true);
+ if (sdkInt < 26) {//低于Android O版本
+ Constructor> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
+ if (providerConstructor != null) {
+ providerConstructor.setAccessible(true);
+ sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
+ }
+ } else {
+ Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
+ chromiumMethodName.setAccessible(true);
+ String chromiumMethodNameStr = (String) chromiumMethodName.get(null);
+ if (chromiumMethodNameStr == null) {
+ chromiumMethodNameStr = "create";
+ }
+ Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
+ if (staticFactory != null) {
+ sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
+ }
+ }
+
+ if (sProviderInstance != null) {
+ field.set("sProviderInstance", sProviderInstance);
+ Log.i(TAG, "Hook success!");
+ } else {
+ Log.i(TAG, "Hook failed!");
+ }
+ } catch (Throwable e) {
+ Log.w(TAG, e);
+ }
+ }
+
+
+ /**
+ * 忽略电池优化
+ */
+ private void ignoreBatteryOptimization(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+
+ PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+ boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
+ // 判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。
+ if (!hasIgnored) {
+ Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(Uri.parse("package:" + context.getPackageName()));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ }
+ }
+ }
+
+ public void KillOTA() {
+ ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ manager.killBackgroundProcesses("com.adups.fota");
+ CmdUtil.execute("am force-stop " + "com.adups.fota");
+ }
+
+ public void openOTA() {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ /**知道要跳转应用的包命与目标Activity*/
+ ComponentName componentName = new ComponentName("com.adups.fota", "com.adups.fota.GoogleOtaClient");
+ intent.setComponent(componentName);
+ mContext.startActivity(intent);
+ }
+
+ public int checkSNPlatform(String sn) {
+ String secondChars = sn.substring(1, 2);
+ if ("N".equalsIgnoreCase(secondChars)) {//MTK平台
+ return MTKPlatform;
+ } else if ("R".equalsIgnoreCase(secondChars)) {//展锐平台
+ return ZhanruiPlatform;
+ } else {
+ Log.e(TAG, "checkSNPlatform: " + "sn: " + sn + "没有对应平台");
+ return UnknowPlatform;
+ }
+ }
+
+ public int checkAppPlatform() {
+ String platform = BuildConfig.platform;
+ if ("MTK".equalsIgnoreCase(platform)) {
+ Log.i(TAG, "checkAppPlatform: " + "MTK平台");
+ return MTKPlatform;
+ } else if ("ZhanRui".equalsIgnoreCase(platform)) {
+ Log.i(TAG, "checkAppPlatform: " + "展锐平台");
+ return ZhanruiPlatform;
+ } else {
+ Log.i(TAG, "checkAppPlatform: " + "没有数据");
+ return UnknowPlatform;
+ }
+ }
+
+ public boolean isSamePlatform(String platform) {
+ String AppPlatform = BuildConfig.platform;
+ if ("ZhanRui".equals(AppPlatform)) {
+ return ZhanruiTag.equals(platform);
+ } else {
+ return AppPlatform.equals(platform);
+ }
+ }
+
+ public interface GetAppPlatformCallback {
+ void AppPlatform(int platform);
+ }
+
+ public void getAppPlatform(GetAppPlatformCallback getAppPlatformCallback) {
+ String platform = BuildConfig.platform;
+ if ("MTK".equalsIgnoreCase(platform)) {
+ getAppPlatformCallback.AppPlatform(MTKPlatform);
+ } else if ("ZhanRui".equalsIgnoreCase(platform)) {
+ getAppPlatformCallback.AppPlatform(ZhanruiPlatform);
+ } else {
+ getAppPlatformCallback.AppPlatform(UnknowPlatform);
+ }
+ }
+
+ public void killBackgroundProcesses(Context context, String processName) {
+ gotoLauncher();
+ // mIsScanning = true;
+ removeTask(processName);
+ ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ String packageName = null;
+ try {
+ if (processName.indexOf(":") == -1) {
+ packageName = processName;
+ } else {
+ packageName = processName.split(":")[0];
+ }
+ activityManager.killBackgroundProcesses(packageName);
+ //
+ Method forceStopPackage = activityManager.getClass()
+ .getDeclaredMethod("forceStopPackage", String.class);
+ forceStopPackage.setAccessible(true);
+ forceStopPackage.invoke(activityManager, packageName);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 清除所有最近记录
+ */
+ public void removeAllTask(Context context) {
+ List list = getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), getCurrentUserId());
+
+ for (ActivityManager.RecentTaskInfo info : list) {
+ if (info.realActivity != null) {
+ Log.e(TAG, "removeAllTask: " + info.realActivity.getPackageName());
+ //排除自身
+ if (BuildConfig.APPLICATION_ID.equals(info.realActivity.getPackageName())) {
+ continue;
+ }
+ }
+ try {
+ ActivityManagerNative.getDefault().removeTask(info.id);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ Log.e(TAG, "removeAllTask: " + e.getMessage());
+ }
+ }
+ }
+
+ public void removeTask(String packageName) {
+ List list = getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), getCurrentUserId());
+ HashMap taskMap = new HashMap<>();
+ for (ActivityManager.RecentTaskInfo info : list) {
+ taskMap.put(info.realActivity.getPackageName(), info.id);
+ }
+ try {
+ ActivityManagerNative.getDefault().removeTask(taskMap.get(packageName));
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ Log.e(TAG, "removeTask: " + e.getMessage());
+ } catch (NullPointerException e) {
+ Log.e(TAG, "removeTask: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 如果界面正在最近任务列表,有些app可能不会被清理
+ */
+ private void gotoLauncher() {
+ Intent i = new Intent(Intent.ACTION_MAIN);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //android123提示如果是服务里调用,必须加入new task标识
+ i.addCategory(Intent.CATEGORY_HOME);
+ mContext.startActivity(i);
+ }
+
+
+ /**
+ * @return a list of the recents tasks.
+ * 获取近期任务列表
+ */
+ public List getRecentTasks(int numTasks, int userId) {
+ try {
+ return ActivityTaskManager.getService().getRecentTasks(numTasks,
+ RECENT_IGNORE_UNAVAILABLE, userId).getList();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get recent tasks", e);
+ return new ArrayList<>();
+ }
+ }
+
+ /**
+ * @return the current user's id.
+ * 获取userId
+ */
+ public int getCurrentUserId() {
+ UserInfo ui;
+ try {
+ ui = ActivityManager.getService().getCurrentUser();
+ return ui != null ? ui.id : 0;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/info/sn/utils/LogUtils.java b/app/src/main/java/com/info/sn/utils/LogUtils.java
index fd7e391..096241a 100644
--- a/app/src/main/java/com/info/sn/utils/LogUtils.java
+++ b/app/src/main/java/com/info/sn/utils/LogUtils.java
@@ -8,7 +8,7 @@ import com.info.sn.BuildConfig;
* @author Administrator
*/
public class LogUtils {
- static boolean isDebug = BuildConfig.LOG_DEBUG;
+ static boolean isDebug = BuildConfig.DEBUG;
public static void v(String tag, String msg) {
if (isDebug) {
diff --git a/app/src/main/java/com/info/sn/utils/ToastUtil.java b/app/src/main/java/com/info/sn/utils/ToastUtil.java
index 3702e8c..487a787 100644
--- a/app/src/main/java/com/info/sn/utils/ToastUtil.java
+++ b/app/src/main/java/com/info/sn/utils/ToastUtil.java
@@ -52,7 +52,7 @@ public class ToastUtil {
debugHandler.post(new Runnable() {
@Override
public void run() {
- if (BuildConfig.LOG_DEBUG) {
+ if (BuildConfig.DEBUG) {
if (debugToast != null) {
debugToast.setText(msg);
debugToast.show();
diff --git a/app/src/main/java/com/info/sn/utils/URLUtils.java b/app/src/main/java/com/info/sn/utils/URLUtils.java
new file mode 100644
index 0000000..f940db2
--- /dev/null
+++ b/app/src/main/java/com/info/sn/utils/URLUtils.java
@@ -0,0 +1,242 @@
+package com.info.sn.utils;
+
+import android.content.Context;
+import android.os.Build;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.webkit.WebSettings;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class URLUtils {
+ private static String TAG = URLUtils.class.getSimpleName();
+ private Context mContext;
+ private List baseURLList = new ArrayList<>();
+
+ public URLUtils(Context context) {
+ this.mContext = context;
+ }
+
+ public void setBrowserList() {
+ String whiteList = Settings.System.getString(mContext.getContentResolver(), "DeselectBrowserArray");
+ String homePage = Settings.System.getString(mContext.getContentResolver(), "homepagURL");
+
+ if (TextUtils.isEmpty(whiteList)) {
+ Log.e(TAG, "getBrowserWhiteList: " + "whiteList is empty");
+ } else {
+ List URLList = new ArrayList<>(Arrays.asList(whiteList.split(",")));
+ if (!TextUtils.isEmpty(homePage)) {
+ if (URLList != null && !URLList.contains(homePage)) {
+ URLList.add(homePage);
+ }
+ }
+ Observable.create(new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter emitter) throws Exception {
+ baseURLList.clear();
+ baseURLList.addAll(URLList);
+ for (String url : URLList) {
+ if (url.startsWith("http://")) {
+ String noHttp = url.substring(7);
+ if (!baseURLList.contains(noHttp)) {
+ baseURLList.add(noHttp);
+ }
+ emitter.onNext(getOkHttpURL(url));
+ } else if (url.startsWith("https://")) {
+ String noHttps = url.substring(8);
+ if (!baseURLList.contains(noHttps)) {
+ baseURLList.add(noHttps);
+ }
+ emitter.onNext(getOkHttpURL(url));
+ } else {
+ baseURLList.add("http://" + url);
+ emitter.onNext(getOkHttpURL("http://" + url));
+ baseURLList.add("https://" + url);
+ emitter.onNext(getOkHttpURL("https://" + url));
+ }
+ Log.e(TAG, "subscribe: " + url);
+ }
+ emitter.onComplete();
+ }
+ }).subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+
+ }
+
+ @Override
+ public void onNext(String s) {
+ Log.e(TAG, "onNext: " + s);
+ if (!baseURLList.contains(s)) {
+ baseURLList.add(s);
+ }
+ if (s.startsWith("http://")) {
+ String noHttp = s.substring(7);
+ Log.e(TAG, "onNext: noHttp: " + noHttp);
+ if (!baseURLList.contains(noHttp)) {
+ baseURLList.add(noHttp);
+ }
+ }
+ if (s.startsWith("https://")) {
+ String noHttps = s.substring(8);
+ Log.e(TAG, "onNext: noHttps: " + noHttps);
+ if (!baseURLList.contains(noHttps)) {
+ baseURLList.add(noHttps);
+ }
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Log.e(TAG, "onError: " + e.getMessage());
+ }
+
+ @Override
+ public void onComplete() {
+ Log.e(TAG, "onComplete: ");
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String s : baseURLList) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(",");
+ }
+ stringBuilder.append(s);
+ }
+ String DeselectBrowserArray = stringBuilder.toString();
+ boolean write = Settings.System.putString(mContext.getContentResolver(), "DeselectBrowserArray", DeselectBrowserArray);
+ Log.e(TAG, "onComplete: " + "white list: " + DeselectBrowserArray);
+ Log.e(TAG, "onComplete: " + "write :" + write);
+ }
+ });
+ }
+
+ }
+
+ private String getOkHttpURL(String URL) {
+ OkHttpClient okHttpClient = new OkHttpClient();
+ final Request request = new Request.Builder()
+ .url(URL)
+ .removeHeader("User-Agent")
+ .addHeader("User-Agent", getUserAgent())
+ .get()//默认就是GET请求,可以不写
+ .build();
+ Call call = okHttpClient.newCall(request);
+// call.enqueue(new Callback() {
+// @Override
+// public void onFailure(Call call, IOException e) {
+// Log.e(TAG, "onFailure: ");
+// }
+//
+// @Override
+// public void onResponse(Call call, Response response) throws IOException {
+// Log.e(TAG, "onResponse: " + getIP(response.request().url().uri()));
+// }
+// });
+ try {
+ Response response = call.execute();
+ if (response.isSuccessful()) {
+ Log.e(TAG, "getOkHttpURL: " + response.request().url().toString());
+ return getIP(response.request().url().uri()).toString();
+ } else {
+ return "";
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.e(TAG, "getOkHttpURL: " + e.getMessage());
+ return "";
+ }
+ }
+
+ /**
+ * Gets ip.
+ * 通过url获取到域名
+ *
+ * @param url the url
+ * @return the ip
+ */
+ public String getIP(String url) {
+ //使用正则表达式过滤,
+ String re = "((http|ftp|https)://)(([a-zA-Z0-9._-]+)|([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))(([a-zA-Z]{2,6})|(:[0-9]{1,4})?)";
+ String str = "";
+ // 编译正则表达式
+ Pattern pattern = Pattern.compile(re);
+ // 忽略大小写的写法
+ // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(url);
+ //若url==http://127.0.0.1:9040或www.baidu.com的,正则表达式表示匹配
+ if (matcher.matches()) {
+ str = url;
+ } else {
+ String[] split2 = url.split(re);
+ if (split2.length > 1) {
+ String substring = url.substring(0, url.length() - split2[1].length());
+ str = substring;
+ } else {
+ str = split2[0];
+ }
+ }
+ return str;
+ }
+
+ private URI getIP(URI uri) {
+ URI effectiveURI = null;
+ try {
+ // URI(String scheme, String userInfo, String host, int port, String
+ // path, String query,String fragment)
+ effectiveURI = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
+ } catch (Throwable var4) {
+ effectiveURI = null;
+ }
+ return effectiveURI;
+ }
+
+ /**
+ * @return 获取浏览器的UA
+ */
+ private String getUserAgent() {
+ String userAgent = "";
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ try {
+ userAgent = WebSettings.getDefaultUserAgent(mContext);
+ //需要hook webview
+ } catch (Exception e) {
+ Log.e(TAG, "getUserAgent: " + e.getMessage());
+ userAgent = System.getProperty("http.agent");
+ }
+ } else {
+ userAgent = System.getProperty("http.agent");
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, length = userAgent.length(); i < length; i++) {
+ char c = userAgent.charAt(i);
+ if (c <= '\u001f' || c >= '\u007f') {
+ sb.append(String.format("\\u%04x", (int) c));
+ } else {
+ sb.append(c);
+ }
+ }
+ Log.e(TAG, "getUserAgent: " + sb.toString());
+ return sb.toString();
+ }
+}
diff --git a/app/src/main/java/com/info/sn/utils/Utils.java b/app/src/main/java/com/info/sn/utils/Utils.java
index 24d1f55..775e970 100644
--- a/app/src/main/java/com/info/sn/utils/Utils.java
+++ b/app/src/main/java/com/info/sn/utils/Utils.java
@@ -1,86 +1,86 @@
package com.info.sn.utils;
- import android.annotation.SuppressLint;
- import android.app.ActivityManager;
- import android.app.admin.DevicePolicyManager;
- import android.bluetooth.BluetoothAdapter;
- import android.content.ActivityNotFoundException;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.ContextWrapper;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.SharedPreferences;
- import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.PackageManager.NameNotFoundException;
- import android.content.pm.ResolveInfo;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.PorterDuff;
- import android.graphics.PorterDuffXfermode;
- import android.net.ConnectivityManager;
- import android.net.NetworkInfo;
- import android.net.Uri;
- import android.net.wifi.WifiInfo;
- import android.net.wifi.WifiManager;
- import android.os.BatteryManager;
- import android.os.Build;
- import android.os.StatFs;
- import android.provider.Settings;
- import android.telephony.TelephonyManager;
- import android.text.TextUtils;
- import android.text.format.Formatter;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.WindowManager;
- import android.view.inputmethod.InputMethodManager;
- import android.widget.EditText;
- import android.widget.Toast;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.BatteryManager;
+import android.os.Build;
+import android.os.StatFs;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.Toast;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.google.zxing.BarcodeFormat;
- import com.google.zxing.EncodeHintType;
- import com.google.zxing.WriterException;
- import com.google.zxing.common.BitMatrix;
- import com.google.zxing.qrcode.QRCodeWriter;
- import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
- import com.info.sn.BuildConfig;
- import com.info.sn.R;
- import com.info.sn.bean.SystemSettings;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.info.sn.BuildConfig;
+import com.info.sn.R;
+import com.info.sn.bean.SystemSettings;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileFilter;
- import java.io.FileReader;
- import java.io.InputStreamReader;
- import java.io.LineNumberReader;
- import java.io.Reader;
- import java.lang.reflect.Method;
- import java.net.NetworkInterface;
- import java.net.SocketException;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Calendar;
- import java.util.Collections;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.regex.Pattern;
- import static java.lang.System.getProperty;
public class Utils {
@@ -1045,7 +1045,7 @@ public class Utils {
}
}
- private static void setIcon(Context mContext,SystemSettings settings) {
+ private static void setIcon(Context mContext, SystemSettings settings) {
try {
//added:2019.12.6
//设置5个app的开关
@@ -1090,7 +1090,7 @@ public class Utils {
/**
* @param context
- * @param notList 禁止列表
+ * @param notList 禁止列表
* @param allowList 允许列表
* @return
*/
@@ -1145,6 +1145,7 @@ public class Utils {
*在写入白名单之后和安装完成之后执行
*/
}
+
public static String getIMEI(Context context) {
String IMEI = "unknow";
String IMEI1, IMEI2, IMEI3;
@@ -1258,6 +1259,7 @@ public class Utils {
return 0;
}
}
+
/**
* 描述:获取可用内存.
*
@@ -1364,6 +1366,19 @@ public class Utils {
return jsonObject.toJSONString();
}
+ public static String getProperty(String key, String defaultValue) {
+ String value = defaultValue;
+ try {
+ Class> c = Class.forName("android.os.SystemProperties");
+ Method get = c.getMethod("get", String.class, String.class);
+ value = (String) (get.invoke(c, key, "unknown"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ return value;
+ }
+ }
+
public static String getHardware(Context context) {
int electric = getBattery(context);
int charging = getIsCharging(context);
diff --git a/app/src/main/res/drawable-hdpi/logo.png b/app/src/main/res/drawable-hdpi/logo.png
index 985e4d2..885554a 100644
Binary files a/app/src/main/res/drawable-hdpi/logo.png and b/app/src/main/res/drawable-hdpi/logo.png differ
diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml
index f32d045..2dae99e 100644
--- a/app/src/main/res/layout-land/activity_main.xml
+++ b/app/src/main/res/layout-land/activity_main.xml
@@ -62,7 +62,7 @@
+ app:layout_constraintStart_toStartOf="parent" />
+
+
+
diff --git a/app/src/main/res/layout-port/activity_main.xml b/app/src/main/res/layout-port/activity_main.xml
index 163e189..0296ffe 100644
--- a/app/src/main/res/layout-port/activity_main.xml
+++ b/app/src/main/res/layout-port/activity_main.xml
@@ -46,7 +46,7 @@
+ app:layout_constraintStart_toStartOf="parent" />
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
index 8daec7d..060c9e2 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 8daec7d..060c9e2 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 8daec7d..060c9e2 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 8daec7d..060c9e2 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index 8daec7d..060c9e2 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index e164500..787f057 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -7,5 +7,6 @@
#ffffff
#000000
#80808080
+ #D3D3D3
diff --git a/app/src/test/java/com/info/sn/ExampleUnitTest.java b/app/src/test/java/com/info/sn/ExampleUnitTest.java
new file mode 100644
index 0000000..36c20b8
--- /dev/null
+++ b/app/src/test/java/com/info/sn/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.info.sn;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..199d16e
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 56df4d5..edb85c2 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega