version:1.3.5

fix:增加展锐平台签名
add:
This commit is contained in:
2021-06-03 10:29:05 +08:00
parent 299ada5a6f
commit 93b0e35af7
32 changed files with 1382 additions and 130 deletions

View File

@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.ACTION_SCREEN_ON" />
<uses-permission android:name="android.permission.ACTION_SCREEN_OFF" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
@@ -255,7 +256,7 @@
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<category android:name="com.info.sn" />
<category android:name="${JPUSH_PKGNAME}" />
</intent-filter>
</receiver>
<receiver

View File

@@ -78,6 +78,7 @@ import static com.info.sn.jpush.TagAliasOperatorHelper.ACTION_GET;
import static com.info.sn.jpush.TagAliasOperatorHelper.ACTION_SET;
import static com.info.sn.jpush.TagAliasOperatorHelper.TagAliasBean;
import static com.info.sn.jpush.TagAliasOperatorHelper.sequence;
import static java.lang.System.getProperty;
public class MainActivity extends CheckPermissionsActivity implements AMapLocationListener, CustomAdapt {
private static final String TAG = "MainActivity";
@@ -85,7 +86,7 @@ public class MainActivity extends CheckPermissionsActivity implements AMapLocati
public static final String REFRESHACTION = BuildConfig.APPLICATION_ID + ".REFRESH";
public static boolean isForeground = false;
private ImageView imageView, exit;
private TextView tv_note, tv_devsn, tv_username, tv_school, tv_grade, tv_version;
private TextView tv_note, tv_devsn, tv_username, tv_school, tv_grade, tv_version,tv_customversion;
private ConstraintLayout layout;
private int DeviceInfo;
@@ -166,8 +167,8 @@ public class MainActivity extends CheckPermissionsActivity implements AMapLocati
@Override
public void onNext(@NonNull Long aLong) {
HTTPInterface.getAllappPackage(MainActivity.this);
HTTPInterface.setBrowser(context);
HTTPInterface.getBrowserLabel(context);
HTTPInterface.setBrowser(context);
HTTPInterface.getSystemSettings(context);
HTTPInterface.getForceInstall(context);
HTTPInterface.getAppStart(context);
@@ -333,6 +334,9 @@ public class MainActivity extends CheckPermissionsActivity implements AMapLocati
tv_grade = findViewById(R.id.tv_grade);
tv_version = findViewById(R.id.version);
tv_version.setText(BuildConfig.VERSION_NAME);
tv_customversion = findViewById(R.id.tv_customversion);
String rom =Utils. getProperty("ro.custom.build.version", "获取失败");
tv_customversion.setText(rom);
}
final static int COUNTS = 4;// 点击次数

View File

@@ -5,6 +5,7 @@ import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -19,6 +20,7 @@ import com.info.sn.activity.MainActivity;
import com.info.sn.network.HTTPInterface;
import com.info.sn.receiver.APKinstallReceiver;
import com.info.sn.receiver.BootReceiver;
import com.info.sn.utils.JGYUtils;
import com.info.sn.utils.LogUtils;
import com.info.sn.utils.SPUtils;
import com.info.sn.utils.ToastUtil;
@@ -26,6 +28,10 @@ import com.info.sn.utils.ToastUtil;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//import com.blankj.utilcode.util.NetworkUtils;
//public class MyApplication extends Application implements NetworkUtils.OnNetworkStatusChangedListener {
@@ -33,6 +39,7 @@ public class MyApplication extends Application {
public static Context context;
private static MyApplication app;
private static AMapLocationClient locationClient = null;
private static String TAG = MyApplication.class.getSimpleName();
@Override
public void onCreate() {
@@ -50,6 +57,64 @@ public class MyApplication extends Application {
Aria.download(this).resumeAllTask();
registAppReceive();
registBootReceive();
hookWebView();
JGYUtils.init(this);
}
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);
}
}
@@ -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);

View File

@@ -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:

View File

@@ -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<BrowserBean> 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<BrowserBean> 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<BaseResponse<AppInfo>>() {

View File

@@ -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";
//上传屏幕截图
//获取时间管控
}

View File

@@ -14,6 +14,7 @@ public interface NewestAppUpdate {
@GET(UrlAddress.GET_NEWESTAPPUPDATE)
Observable<BaseResponse<AppInfo>> getAppUpdate(
@Query("packageName") String packageName,
@Query("versionCode") String versionCode
@Query("versionCode") String versionCode,
@Query("type") int type
);
}

View File

@@ -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<PackageInfo> list = pm.getInstalledPackages(0);
List<AppUploadInfo> 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<AppUploadInfo> appUploadInfos) {
String json = JSONArray.toJSONString(appUploadInfos);
Log.e(TAG, "onNext: " + json);
HTTPInterface.SendAppInstall(json);
}

View File

@@ -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

View File

@@ -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);
}
}
}
}

View File

@@ -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<String> idArrayList = new ArrayList<>(Arrays.asList(ids.split(",")));
ArrayList<String> packageArrayList = new ArrayList<>(Arrays.asList(packages.split(",")));
LinkedHashSet<String> idHashSet = new LinkedHashSet<>(idArrayList);
LinkedHashSet<String> packageHashSet = new LinkedHashSet<>(packageArrayList);
ArrayList<String> idList = new ArrayList<>(idHashSet);
ArrayList<String> 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<ActivityManager.RecentTaskInfo> 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<ActivityManager.RecentTaskInfo> list = getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), getCurrentUserId());
HashMap<String, Integer> 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<ActivityManager.RecentTaskInfo> 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();
}
}
}

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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<String> 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<String> URLList = new ArrayList<>(Arrays.asList(whiteList.split(",")));
if (!TextUtils.isEmpty(homePage)) {
if (URLList != null && !URLList.contains(homePage)) {
URLList.add(homePage);
}
}
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> 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<String>() {
@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();
}
}

View File

@@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -62,7 +62,7 @@
<ImageView
android:id="@+id/imageView3"
android:layout_width="120dp"
android:layout_width="180dp"
android:layout_height="120dp"
android:layout_marginTop="16dp"
android:adjustViewBounds="true"
@@ -312,14 +312,26 @@
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:text="连续点击版本号,自动下载新版本"
android:textColor="#E14B88"
android:textColor="@color/gray"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@+id/tv_customversion"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_customversion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginBottom="4dp"
android:textColor="@color/lightgrey"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@@ -46,7 +46,7 @@
<ImageView
android:id="@+id/imageView3"
android:layout_width="120dp"
android:layout_width="180dp"
android:layout_height="120dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
@@ -287,12 +287,22 @@
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="连续点击版本号,自动下载新版本"
android:textColor="#E14B88"
android:textColor="@color/gray"
android:textSize="11sp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/tv_customversion"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_customversion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginBottom="4dp"
android:textColor="@color/lightgrey"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -7,5 +7,6 @@
<color name="white">#ffffff</color>
<color name="black">#000000</color>
<color name="gray">#80808080</color>
<color name="lightgrey">#D3D3D3</color>
</resources>