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