diff --git a/appmain/utils/system/AppContextUtils.java b/appmain/utils/system/AppContextUtils.java new file mode 100644 index 0000000..72a081a --- /dev/null +++ b/appmain/utils/system/AppContextUtils.java @@ -0,0 +1,29 @@ +package com.proxgrind.chameleon.utils.system; + +import android.app.Activity; +import android.app.Application; + +public class AppContextUtils { + private static AppContextUtils thiz = null; + public static Application app; + + private AppContextUtils() { + } + + public static AppContextUtils getInstance() { + if (thiz == null) { + thiz = new AppContextUtils(); + } + return thiz; + } + + public static void register(Application app) { + AppContextUtils.app = app; + } + + public void finishAll() { + for (Activity activity : CrashUtils.activities) { + activity.finish(); + } + } +} diff --git a/appmain/utils/system/AppListUtils.java b/appmain/utils/system/AppListUtils.java new file mode 100644 index 0000000..a15bc3d --- /dev/null +++ b/appmain/utils/system/AppListUtils.java @@ -0,0 +1,43 @@ +package com.proxgrind.chameleon.utils.system; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import java.util.ArrayList; +import java.util.List; + +public class AppListUtils { + + //获取用户安装的APP + public static List getInstalledApplication(Context context, boolean needSysAPP) { + PackageManager packageManager = context.getPackageManager(); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + List resolveInfos = packageManager.queryIntentActivities(intent, 0); + if (!needSysAPP) { + List resolveInfosWithoutSystem = new ArrayList<>(); + for (int i = 0; i < resolveInfos.size(); i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + try { + if (!isSysApp(context, resolveInfo.activityInfo.packageName)) { + resolveInfosWithoutSystem.add(resolveInfo); + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + return resolveInfosWithoutSystem; + } + return resolveInfos; + } + + //判断是否系统应用 + public static boolean isSysApp(Context context, String packageName) throws PackageManager.NameNotFoundException { + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1; + } +} diff --git a/appmain/utils/system/AppResourceUtils.java b/appmain/utils/system/AppResourceUtils.java new file mode 100644 index 0000000..3ccf2c3 --- /dev/null +++ b/appmain/utils/system/AppResourceUtils.java @@ -0,0 +1,48 @@ +package com.proxgrind.chameleon.utils.system; + +import android.app.Application; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; + +import com.proxgrind.chameleon.utils.system.AppContextUtils; + +public class AppResourceUtils { + + private static Application context = AppContextUtils.app; + + //根据colorId得到颜色 + public static int getColor(int colorId) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return context.getColor(colorId); + } + return context.getResources().getColor(colorId); + } + + //根据drawableId得到drawable对象 + public static Drawable getDrawable(int drawableId) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return context.getDrawable(drawableId); + } + return context.getResources().getDrawable(drawableId); + } + + //复制文本到剪贴板 + public static void copyStr2Clipborad(String label, String content) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboardManager == null) return; + //创建ClipData对象 + ClipData clipData = ClipData.newPlainText(label, content); + //添加ClipData对象到剪切板中 + clipboardManager.setPrimaryClip(clipData); + } + }); + } +} diff --git a/appmain/utils/system/AppRestartUtils.java b/appmain/utils/system/AppRestartUtils.java new file mode 100644 index 0000000..b7cd3d7 --- /dev/null +++ b/appmain/utils/system/AppRestartUtils.java @@ -0,0 +1,64 @@ +package com.proxgrind.chameleon.utils.system; + +import android.content.Context; +import android.content.Intent; + +import com.proxgrind.chameleon.services.RestartService; + +public class AppRestartUtils { + + public interface OnExitAction { + /* + * 如果返回true,则使用System.exit终结,否则使用他自几实现自带的。 + * */ + boolean usingSystemExit(); + } + + /** + * 此工具类用来重启APP,只是单纯的重启,不做任何处理。 + * Created by 13itch on 2016/8/5. + */ + + /** + * 重启整个APP + * + * @param context 上下文 + * @param Delayed 延迟多少毫秒 + * @param action 在退出时的回调,如果回调返回true,则杀死当前的进程! + */ + public static void restartAPP(Context context, long Delayed, OnExitAction action) { + /**开启一个新的服务,用来重启本APP*/ + Intent intent1 = new Intent(context, RestartService.class); + intent1.putExtra("PackageName", context.getApplicationContext().getPackageName()); + intent1.putExtra("Delayed", Delayed); + context.startService(intent1); + if (action != null && action.usingSystemExit()) { + /**杀死整个进程**/ + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); + } + } + + /** + * 重启整个APP + * + * @param context 上下文 + * @param Delayed 延迟多少毫秒 + */ + public static void restartAPP(Context context, long Delayed) { + Intent intent1 = new Intent(context, RestartService.class); + intent1.putExtra("PackageName", context.getApplicationContext().getPackageName()); + intent1.putExtra("Delayed", Delayed); + context.startService(intent1); + } + + /***重启整个APP*/ + public static void restartAPP(Context context) { + restartAPP(context, 2000, new OnExitAction() { + @Override + public boolean usingSystemExit() { + return true; + } + }); + } +} diff --git a/appmain/utils/system/CrashUtils.java b/appmain/utils/system/CrashUtils.java new file mode 100644 index 0000000..7ea0a25 --- /dev/null +++ b/appmain/utils/system/CrashUtils.java @@ -0,0 +1,85 @@ +package com.proxgrind.chameleon.utils.system; + +import android.app.Activity; +import android.app.Application; +import android.content.Intent; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.proxgrind.chameleon.activities.CrashActivity; + +import java.util.ArrayList; +import java.util.List; + +public class CrashUtils { + private static final Thread.UncaughtExceptionHandler DEFAULT_UNCAUGHT = Thread.getDefaultUncaughtExceptionHandler(); + public static final List activities = new ArrayList<>(); + + /* + * callback for activity! + * */ + private static final + Application.ActivityLifecycleCallbacks callbacks4Act = new Application.ActivityLifecycleCallbacks() { + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) { + //must add activity to list! + activities.add(activity); + } + + @Override + public void onActivityStarted(@NonNull Activity activity) { + + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + + } + + @Override + public void onActivityPaused(@NonNull Activity activity) { + + } + + @Override + public void onActivityStopped(@NonNull Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) { + + } + + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + //must remove activity from list! + activities.remove(activity); + } + }; + + public static void register(final Application application) { + //register callback! + application.registerActivityLifecycleCallbacks(callbacks4Act); + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) { + //跳转到奔溃信息处理界面 + Intent intent = new Intent(application, CrashActivity.class); + intent.putExtra("crash", e); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + //destroy all activity + for (Activity act : activities) { + act.finish(); + } + application.startActivity(intent); + //调用默认的异常处理 + if (DEFAULT_UNCAUGHT != null) { + DEFAULT_UNCAUGHT.uncaughtException(t, e); + } + } + }); + } +} diff --git a/appmain/utils/system/LanguageUtils.java b/appmain/utils/system/LanguageUtils.java new file mode 100644 index 0000000..d282d23 --- /dev/null +++ b/appmain/utils/system/LanguageUtils.java @@ -0,0 +1,44 @@ +package com.proxgrind.chameleon.utils.system; + +import android.content.Context; +import android.content.res.Configuration; +import android.os.Build; +import android.os.LocaleList; + +import java.util.Locale; + +public class LanguageUtils { + + /* + * 获得语言列表! + * */ + public static LocaleList getLocaleList(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return context.getResources().getConfiguration().getLocales(); + } else { + return new LocaleList(context.getResources().getConfiguration().locale); + } + } + + /* + * 获得当前系统默认的语言! + * */ + public static Locale getDefaultLocale(Context context) { + return Locale.getDefault(); + } + + /* + * 设置当前的语言! + * */ + public static Context setAppLanguage(Context context, String language) { + Configuration configuration = context.getResources().getConfiguration(); + configuration.setLocale(new Locale(language)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + return context.createConfigurationContext(configuration); + } else { + context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); + return context; + } + } + +} diff --git a/appmain/utils/system/LogUtils.java b/appmain/utils/system/LogUtils.java new file mode 100644 index 0000000..c135ddc --- /dev/null +++ b/appmain/utils/system/LogUtils.java @@ -0,0 +1,77 @@ +package com.proxgrind.chameleon.utils.system; + +import android.util.Log; + +import com.proxgrind.chameleon.BuildConfig; + +public class LogUtils { + private static String TAG = "LogUtils"; + private static boolean log_open; + + static { + // 是否需要打开DEBUG模式! + log_open = BuildConfig.DEBUG; + } + + public static void setEnable(boolean enable) { + log_open = enable; + } + + public static void setTAG(String tag) { + TAG = tag; + } + + public static String getTag() { + return TAG; + } + + public static void v(String msg) { + if (log_open) + Log.v(TAG, msg); + } + + public static void v(String msg, Throwable throwable) { + if (log_open) + Log.v(TAG, msg, throwable); + } + + public static void d(String msg) { + if (log_open) + Log.d(TAG, msg); + } + + public static void d(String msg, Throwable throwable) { + if (log_open) + Log.d(TAG, msg, throwable); + } + + public static void i(String msg) { + if (log_open) + Log.i(TAG, msg); + } + + public static void i(String msg, Throwable throwable) { + if (log_open) + Log.i(TAG, msg, throwable); + } + + public static void w(String msg) { + if (log_open) + Log.w(TAG, msg); + } + + public static void w(String msg, Throwable throwable) { + if (log_open) + Log.w(TAG, msg, throwable); + } + + public static void e(String msg) { + if (log_open) + Log.e(TAG, msg); + } + + public static void e(String msg, Throwable throwable) { + if (log_open) + Log.e(TAG, msg, throwable); + } +} diff --git a/appmain/utils/system/PermissionUtils.java b/appmain/utils/system/PermissionUtils.java new file mode 100644 index 0000000..6bb52d7 --- /dev/null +++ b/appmain/utils/system/PermissionUtils.java @@ -0,0 +1,250 @@ +package com.proxgrind.chameleon.utils.system; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.util.Log; + +import com.proxgrind.chameleon.utils.tools.ArrayUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; + +/** + * 权限操作工具! + * + * @author DXL + */ +public class PermissionUtils { + private static final String LOG_TAG = PermissionUtils.class.getSimpleName(); + //需要检查的权限! + private String[] permissions; + //丢失的权限! + private String[] permissionLose; + + //上下文! + private Context context; + //回调! + private Callback callback; + // 是否自动请求! + private boolean isAutoRequest = false; + + //权限请求的时候的返回值! + private int requestCode = 0x665; + // 使用队列进行顺序请求! + private Queue perQueue = new LinkedList<>(); + + public PermissionUtils(Context context) { + this.context = context; + } + + /** + * 检查权限,进行判断! + */ + public void checks() { + //在开始检查权限之前的操作! + if (callback != null) + callback.onStartChecks(this); + //在检查的时候的回调! + boolean isAllVaild = true; + if (permissions == null) { + Log.d(LOG_TAG, "传入的初始权限为空!"); + if (callback != null) + callback.onEndChecks(); + return; + } + for (String per : permissions) { + //迭代检查权限! + if (!check(per)) { + isAllVaild = false; + } + } + ArrayList list = new ArrayList<>(); + //所有的权限都正常时的回调!! + if (isAllVaild) { + if (callback != null) + callback.onPermissionNormal(this); + } else { + //先迭代进行权限丢失的处理! + for (String per : permissions) { + //迭代请求权限! + if (!check(per)) { + if (isAutoRequest) { + request(per); + } else { + //如果检查到的权限无法通过处理,则进行其他操作! + if (callback != null) + callback.whatPermissionLose(per, this); + list.add(per); + } + } + } + //缓存丢失的权限! + permissionLose = ArrayUtils.list2Arr(list); + //如果检查到的权限无法通过处理,则进行其他操作! + if (callback != null) + callback.onPermissionLose(this); + } + //在检查完毕之后的回调! + if (callback != null) + callback.onEndChecks(); + } + + public boolean check(String per) { + boolean ret; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + ret = context.checkSelfPermission(per) == PackageManager.PERMISSION_GRANTED; + } else { + ret = context.checkCallingOrSelfPermission(per) == PackageManager.PERMISSION_GRANTED; + } + updateQueue(); + return ret; + } + + public void request(String per) { + // 尝试使用开发者实现的申请实现! + if (callback.onRequest(per)) return; + if (callback != null) { + if (context instanceof Activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + ((Activity) context).requestPermissions(new String[]{per}, requestCode); + } + } + } + } + + private void updateQueue() { + // 添加到队列中! + perQueue.clear(); + if (permissionLose != null) + perQueue.addAll(Arrays.asList(permissionLose)); + } + + public void request() { + final boolean isAutoCheckTmp = isAutoRequest; + setAutoRequest(false); + checks(); + updateQueue(); + String per = perQueue.poll(); + if (per != null && ! + check(per)) { + // LogUtils.d("申请了权限: " + per); + request(per); + } + setAutoRequest(isAutoCheckTmp); + } + + public void requests() { + final boolean isAutoCheckTmp = isAutoRequest; + setAutoRequest(true); + checks(); + setAutoRequest(isAutoCheckTmp); + } + + public boolean isAutoRequest() { + return isAutoRequest; + } + + public void setAutoRequest(boolean autoRequest) { + isAutoRequest = autoRequest; + } + + public String[] getPermissions() { + return permissions; + } + + public void setPermissions(String[] permissions) { + this.permissions = permissions; + } + + public void removePermissions(String[] permissions) { + if (permissions == null || permissions.length == 0) return; + String[] pers = getPermissions(); + ArrayList newPersList = new ArrayList<>(); + for (String per : pers) { + for (String per1 : permissions) { + if (!per1.equalsIgnoreCase(per)) { + newPersList.add(per); + } + } + } + setPermissions(newPersList.toArray(new String[0])); + } + + public void removePermission(String permission) { + if (permission == null) return; + removePermissions(new String[]{permission}); + } + + public int getRequestCode() { + return requestCode; + } + + public void setRequestCode(int requestCode) { + this.requestCode = requestCode; + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public Callback getCallback() { + return callback; + } + + public void setCallback(Callback callback) { + this.callback = callback; + } + + public String[] getPermissionLose() { + return permissionLose; + } + + public interface Callback { + /** + * 在权限开始检查的时候的的回调! + * + * @param util 工具类对象! + */ + void onStartChecks(PermissionUtils util); + + /** + * 在权限丢失时的回调! + * + * @param util 工具类对象! + */ + void onPermissionLose(PermissionUtils util); + + /** + * 在权限正常的时候的回调! + * + * @param util 工具类对象! + */ + void onPermissionNormal(PermissionUtils util); + + /** + * 在权限丢失时的请求回调! + * + * @param per 丢失的权限! + * @param util 工具类对象! + */ + void whatPermissionLose(String per, PermissionUtils util); + + /** + * 在权限开始检查的时候的的回调! + */ + void onEndChecks(); + + /** + * 在需要自定义申请过程的时候的的回调! + */ + boolean onRequest(String per); + } +} diff --git a/appmain/utils/system/RomUtils.java b/appmain/utils/system/RomUtils.java new file mode 100644 index 0000000..f59074b --- /dev/null +++ b/appmain/utils/system/RomUtils.java @@ -0,0 +1,134 @@ +package com.proxgrind.chameleon.utils.system; + +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Created by HaiyuKing + * Used 判断手机ROM,检测ROM是MIUI、EMUI还是Flyme + * 参考资料:https://www.jianshu.com/p/ba9347a5a05a + */ +public class RomUtils { + private static final String TAG = "Rom"; + + public static final String ROM_MIUI = "MIUI"; + public static final String ROM_EMUI = "EMUI"; + public static final String ROM_FLYME = "FLYME"; + public static final String ROM_OPPO = "OPPO"; + public static final String ROM_SMARTISAN = "SMARTISAN"; + public static final String ROM_VIVO = "VIVO"; + public static final String ROM_QIKU = "QIKU"; + + private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name"; + private static final String KEY_VERSION_EMUI = "ro.build.version.emui"; + private static final String KEY_VERSION_OPPO = "ro.build.version.opporom"; + private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version"; + private static final String KEY_VERSION_VIVO = "ro.vivo.os.version"; + + private static String sName; + private static String sVersion; + + //华为 + public static boolean isEmui() { + return check(ROM_EMUI); + } + + //小米 + public static boolean isMiui() { + return check(ROM_MIUI); + } + + //vivo + public static boolean isVivo() { + return check(ROM_VIVO); + } + + //oppo + public static boolean isOppo() { + return check(ROM_OPPO); + } + + //魅族 + public static boolean isFlyme() { + return check(ROM_FLYME); + } + + //360手机 + public static boolean is360() { + return check(ROM_QIKU) || check("360"); + } + + //坚果手机 + public static boolean isSmartisan() { + return check(ROM_SMARTISAN); + } + + public static String getName() { + if (sName == null) { + check(""); + } + return sName; + } + + public static String getVersion() { + if (sVersion == null) { + check(""); + } + return sVersion; + } + + public static boolean check(String rom) { + if (sName != null) { + return sName.equals(rom); + } + + if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) { + sName = ROM_MIUI; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) { + sName = ROM_EMUI; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) { + sName = ROM_OPPO; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) { + sName = ROM_VIVO; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) { + sName = ROM_SMARTISAN; + } else { + sVersion = Build.DISPLAY; + if (sVersion.toUpperCase().contains(ROM_FLYME)) { + sName = ROM_FLYME; + } else { + sVersion = Build.UNKNOWN; + sName = Build.MANUFACTURER.toUpperCase(); + } + } + return sName.equals(rom); + } + + public static String getProp(String name) { + String line; + BufferedReader input = null; + try { + Process p = java.lang.Runtime.getRuntime().exec("getprop " + name); + input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); + line = input.readLine(); + input.close(); + } catch (IOException ex) { + Log.e(TAG, "Unable to read prop " + name, ex); + return null; + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return line; + } +} \ No newline at end of file diff --git a/appmain/utils/system/SystemUtils.java b/appmain/utils/system/SystemUtils.java new file mode 100644 index 0000000..bdd4b19 --- /dev/null +++ b/appmain/utils/system/SystemUtils.java @@ -0,0 +1,70 @@ +package com.proxgrind.chameleon.utils.system; + +/** + * @author DXL + */ +public class SystemUtils { + + /** + * 判断当前是否超时 + * + * @param startTimeStamp 开始时间(时间戳形式) + * @param timeoutms 超时值,当最新的时间超过了这个值时将会被判断为超时! + * @return true 超时, + */ + public static boolean isTimeout(long startTimeStamp, long timeoutms) { + return System.currentTimeMillis() - startTimeStamp >= timeoutms; + } + + // 简化休眠 + public static void sleep(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Calculates the checksum of the passed byte buffer. + * + * @param buffer + * @return byte checksum value + */ + public static byte calcChecksum(byte[] buffer, boolean sub) { + if (buffer == null) return 0; + byte checksum = 0; + int bufPos = 0; + int byteCount = buffer.length; + while (byteCount-- != 0) { + byte b = buffer[bufPos++]; + if (!sub) + checksum += b; + else + checksum -= b; + } + return checksum; + } + + /** + * Calculates the checksum of the passed byte buffer. + * + * @param buffer + * @return byte checksum value + */ + public static byte calcChecksub(byte checkSum, byte[] buffer, boolean sub) { + if (buffer == null) return 0; + byte checksum = checkSum; + int bufPos = 0; + int byteCount = buffer.length; + while (byteCount-- != 0) { + byte b = buffer[bufPos++]; + if (!sub) + checksum += b; + else + checksum -= b; + //System.out.println("value: " + HexUtil.toHexString(tmp) + "," + HexUtil.toHexString(b) + " checksum: " + HexUtil.toHexString(checksum)); + } + return checksum; + } +} diff --git a/appmain/utils/system/VibratorUtils.java b/appmain/utils/system/VibratorUtils.java new file mode 100644 index 0000000..02f1cf0 --- /dev/null +++ b/appmain/utils/system/VibratorUtils.java @@ -0,0 +1,27 @@ +package com.proxgrind.chameleon.utils.system; + +import android.content.Context; +import android.os.VibrationEffect; +import android.os.Vibrator; + +/** + * 震动工具! + * + * @author DXL + */ +public class VibratorUtils { + + //进行抖动! + public static void runOneAsDelay(Context context, int delay) { + Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrator != null) + if (vibrator.hasVibrator()) { //有振动器 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + VibrationEffect vibrationEffect = VibrationEffect.createOneShot(delay, VibrationEffect.DEFAULT_AMPLITUDE); + vibrator.vibrate(vibrationEffect); + } else { + vibrator.vibrate(delay); + } + } + } +}