pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息
+ if (pinfo != null) {
+ for (int i = 0; i < pinfo.size(); i++) {
+ String pn = pinfo.get(i).packageName;
+ if (pn.equals("com.tencent.mm")) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 打电话
+ *
+ * Intent.ACTION_DIAL Intent.ACTION_CALL
+ *
+ * @param context
+ * @param mobile
+ */
+ public static void callUp(Context context, String mobile) {
+ Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"
+ + mobile));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+
+ /**
+ * 获取设备ID
+ *
+ * @param context
+ * @return
+ */
+ public static String getDevId(Context context) {
+ TelephonyManager TelephonyMgr = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ return TelephonyMgr.getDeviceId();
+ }
+
+ /**
+ * 姓名脱敏
+ *
+ * @param fullName
+ * @return
+ */
+ public static String desensitizedName(String fullName) {
+ if (fullName == null || fullName.length() <= 1) {
+ return fullName;
+ }
+ char[] nameArr = fullName.toCharArray();
+ if (nameArr.length > 2) {
+ for (int i = 1; i < nameArr.length - 1; i++) {
+ nameArr[i] = '*';
+ }
+ } else {
+ nameArr[1] = '*';
+ }
+
+ return new String(nameArr);
+ }
+
+
+ public static String formatDateGetFull(String date) {
+ if (isEmpty(date)) {
+ return "";
+ }
+ Date d = new Date(Long.parseLong(date));
+ SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+ return dateFormat1.format(d);
+ }
+
+ public static String formatDateGetCurrentTime() {
+ Date d = new Date(System.currentTimeMillis());
+ SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//.SSS
+ return dateFormat1.format(d);
+ }
+
+
+ public static String formatDateGetFull(long date) {
+ if (date == 0) {
+ return "";
+ }
+ Date d = new Date(date);
+ SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ return dateFormat1.format(d);
+ }
+
+ public static String formatDateGetDay(long date) {
+ if (date == 0) {
+ return "";
+ }
+ Date d = new Date(date);
+ SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
+ return dateFormat1.format(d);
+ }
+
+ public static boolean isEmpty(String s) {
+ if (TextUtils.isEmpty(s) || s.trim().equals("null")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * 格式化浮点型
+ *
+ * @param data
+ * @return
+ */
+ public static String formatDouble(double data) {
+ return new DecimalFormat("0.00").format(data);
+ }
+
+
+ /**
+ * 格式化分钟
+ *
+ * @param minutes
+ * @return
+ */
+ public static String formatMinutes(int minutes) {
+ int hour = minutes / 60;
+ int minute = minutes % 60;
+ if (hour > 0 && minute > 0) {
+ return hour + "小时" + minute + "分钟";
+ } else if (hour > 0) {
+ return hour + "小时";
+ } else {
+ return minute + "分钟";
+ }
+ }
+
+
+ //com.fawan.news
+ public static void goToMarket(Context context, String packageName) {
+ Uri uri = Uri.parse("market://details?id=" + packageName);
+ Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
+ try {
+ context.startActivity(goToMarket);
+ } catch (ActivityNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * true为存在,false为不存在
+ *
+ * @param context
+ * @param packageName
+ * @return
+ */
+ public static boolean isInstallApp(Context context, String packageName) {
+ try {
+ context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * 格式化float 保留两位小数
+ *
+ * @param data
+ * @return
+ */
+ public static float formatFloat2(float data) {
+// DecimalFormat decimalFormat = new DecimalFormat("0.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
+// return decimalFormat.format(data);//返回字符串
+
+ int scale = 1;//设置位数
+ int roundingMode = 4;//表示四舍五入,可以选择其他舍值方式,例如去尾,等等.
+ BigDecimal bd = new BigDecimal((double) data);
+ bd = bd.setScale(scale, roundingMode);
+ data = bd.floatValue();
+ return data;
+ }
+
+ /**
+ * Android 6.0 之前(不包括6.0)获取mac地址
+ * 必须的权限
+ *
+ * @param context * @return
+ */
+ public static String getMacDefault(Context context) {
+ String mac = "";
+ if (context == null) {
+ return mac;
+ }
+ WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ WifiInfo info = null;
+ try {
+ info = wifi.getConnectionInfo();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (info == null) {
+ return null;
+ }
+ mac = info.getMacAddress();
+ if (!TextUtils.isEmpty(mac)) {
+ mac = mac.toUpperCase(Locale.ENGLISH);
+ }
+ return mac;
+ }
+
+ /**
+ * Android 6.0-Android 7.0 获取mac地址
+ */
+ public static String getMacAddress() {
+ String macSerial = null;
+ String str = "";
+
+ try {
+ Process pp = Runtime.getRuntime().exec("cat/sys/class/net/wlan0/address");
+ InputStreamReader ir = new InputStreamReader(pp.getInputStream());
+ LineNumberReader input = new LineNumberReader(ir);
+
+ while (null != str) {
+ str = input.readLine();
+ if (str != null) {
+ macSerial = str.trim();//去空格
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ // 赋予默认值
+ ex.printStackTrace();
+ }
+
+ return macSerial;
+ }
+
+ /**
+ * Android 7.0之后获取Mac地址
+ * 遍历循环所有的网络接口,找到接口是 wlan0
+ * 必须的权限
+ *
+ * @return
+ */
+ public static String getMacFromHardware() {
+ try {
+ ArrayList all = Collections.list(NetworkInterface.getNetworkInterfaces());
+ for (NetworkInterface nif : all) {
+ if (!nif.getName().equals("wlan0"))
+ continue;
+ byte[] macBytes = nif.getHardwareAddress();
+ if (macBytes == null) return "";
+ StringBuilder res1 = new StringBuilder();
+ for (Byte b : macBytes) {
+ res1.append(String.format("%02X:", b));
+ }
+ if (!TextUtils.isEmpty(res1)) {
+ res1.deleteCharAt(res1.length() - 1);
+ }
+ return res1.toString();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return "";
+ }
+
+ /**
+ * 获取mac地址(适配所有Android版本)
+ *
+ * @return
+ */
+ public static String getMac(Context context) {
+ String mac = "";
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ mac = getMacDefault(context);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ mac = getMacAddress();
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ mac = getMacFromHardware();
+ }
+ return mac;
+ }
+
+ //把String转化为float
+ public static double convertToFloat(String number, double defaultValue) {
+ if (TextUtils.isEmpty(number)) {
+ return defaultValue;
+ }
+ try {
+ return Double.parseDouble(number);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+
+ }
+
+ /**
+ * 获取AndroidId
+ *
+ * @param context
+ * @return
+ */
+ public static String getAndroidId(Context context) {
+ String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+ return androidId;
+ }
+
+ /**
+ * 获取设备唯一 UDID
+ *
+ * @param context
+ * @return
+ */
+ @SuppressLint("MissingPermission")
+ public static String getUDID(Context context) {
+// String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+// L.e("androidID===" + androidID);
+// return androidID;
+ String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+ if (!androidID.equals("")) {
+ try {
+ if (!"9774d56d682e549c".equals(androidID)) {
+ androidID = UUID.nameUUIDFromBytes(androidID.getBytes("utf8")).toString();
+ } else {
+ @SuppressLint("MissingPermission") final String deviceId = ((TelephonyManager) context.getSystemService(TELEPHONY_SERVICE)).getDeviceId();
+ androidID = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")).toString() : UUID.randomUUID().toString();
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ return androidID;
+ }
+
+ //需要权限 android.permission.READ_PHONE_STATE
+ TelephonyManager TelephonyMgr = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
+ String szImei = TelephonyMgr.getDeviceId();
+ if (!szImei.equals("")) {
+ return szImei;
+ }
+
+ //需要权限 android.permission.ACCESS_WIFI_STATE
+ WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
+ if (!m_szWLANMAC.equals("")) {
+ return m_szWLANMAC;
+ }
+
+ //需要权限 android.permission.BLUETOOTH
+ BluetoothAdapter m_BluetoothAdapter = null;
+ m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ String m_szBTMAC = m_BluetoothAdapter.getAddress();
+ if (!m_szBTMAC.equals("")) {
+ return m_szBTMAC;
+ }
+ return getUniquePsuedoID();
+ }
+
+ //获得 Psuedo ID
+ public static String getUniquePsuedoID() {
+ String serial = null;
+ String m_szDevIDShort = "35" +
+ Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
+ Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
+ Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
+ Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
+ Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
+ Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
+ Build.USER.length() % 10; //13 位
+ try {
+ serial = Build.class.getField("SERIAL").get(null).toString();
+ //API>=9 使用serial号
+ return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
+ } catch (Exception exception) {
+ //serial需要一个初始化,随意值
+ serial = "serial";
+ }
+
+ //使用硬件信息拼凑出来的15位号码
+ return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
+ }
+
+ public static String getCPUSerial() {
+ String line = "";
+ String TAG = "aaa";
+ Log.e(TAG, " get_quck_Sn() ");
+ Class> c = null;
+ try {
+ c = Class.forName("android.os.SystemProperties");
+
+ Method get = c.getMethod("get", String.class);
+ line = (String) get.invoke(c, "ro.serialno");
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Log.e(TAG, " get_quck_Sn() " + line);
+ System.out.println("设备串号" + line);
+ return line;
+ }
+
+ /**
+ * 判断网络连接状态
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isNetworkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isAvailable();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断WiFi连接状态
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isWifiConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ if (mWiFiNetworkInfo != null) {
+ return mWiFiNetworkInfo.isAvailable();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断移动网络状态
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isMobileConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mMobileNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+ if (mMobileNetworkInfo != null) {
+ return mMobileNetworkInfo.isAvailable();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 获取网络连接类型
+ *
+ * @param context
+ * @return
+ */
+ public static int getConnectedType(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
+ return mNetworkInfo.getType();
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 根据字符的起始和结束索引提取子串
+ *
+ * @param input 原始字符串
+ * @param startIndex 起始索引(包含,从0开始)
+ * @param endIndex 结束索引(不包含)
+ * @return 子串,若输入无效或索引越界则返回空字符串
+ */
+ public static String getSubstringByIndices(String input, int startIndex, int endIndex) {
+ if (input == null) {
+ return "";
+ }
+ // 处理索引越界问题
+ int safeStart = Math.max(startIndex, 0);
+ int safeEnd = Math.min(endIndex, input.length());
+ if (safeStart > safeEnd) {
+ return "";
+ }
+ return input.substring(safeStart, safeEnd);
+ }
+
+ public static String getSubstringByIndex(String input, int startIndex, int length) {
+ if (input == null) {
+ return "";
+ }
+ // 处理索引越界问题
+ int safeStart = Math.max(startIndex, 0);
+ int safeEnd = Math.min(startIndex + length, input.length());
+ if (safeStart > safeEnd) {
+ return "";
+ }
+ return input.substring(safeStart, safeEnd);
+ }
+
+ /**
+ * 十进制转十六进制
+ *
+ * @param decimal
+ * @return
+ */
+ public static String decimalToHexWithPadding(int decimal, int padding) {
+ // 将十进制转换为十六进制,并转换为字符串
+ String hex = Integer.toHexString(decimal);
+
+ // 确保字符串长度为至少4位,不足部分前面补0
+ while (hex.length() < padding) {
+ hex = "0" + hex;
+ }
+
+ return hex.toUpperCase(); // 返回大写形式的十六进制字符串
+ }
+
+ /**
+ * 十进制转二进制,且返回的二进制为至少7位数
+ *
+ * @param decimal
+ * @return
+ */
+ public static String decimalToBinary(int decimal) {
+ // 如果输入为0,直接返回"0"
+ if (decimal == 0) {
+ return "0";
+ }
+
+ StringBuilder binary = new StringBuilder();
+
+ // 除2取余法,将余数加入二进制字符串
+ while (decimal > 0) {
+ int remainder = decimal % 2;
+ binary.insert(0, remainder);
+ decimal = decimal / 2;
+ }
+ int length = binary.length();
+ if (length < 7) {
+ int padding = 7 - length;
+ for (int i = 0; i < padding; i++) {
+ binary.insert(0, '0');
+ }
+ }
+ return binary.toString();
+ }
+
+ /**
+ * 将二进制字符串转换为十六进制字符串,每8位转换为两位十六进制,不足两位前面补零
+ *
+ * @param binaryStr 输入的二进制字符串(仅包含0和1)
+ * @return 转换后的十六进制字符串
+ * @throws IllegalArgumentException 如果输入不是有效的二进制字符串
+ */
+ public static String binaryToHex(String binaryStr) {
+ // 校验输入合法性
+ if (binaryStr == null || !binaryStr.matches("[01]+")) {
+ throw new IllegalArgumentException("Invalid binary string");
+ }
+
+ // 补前导零使长度成为8的倍数
+ int length = binaryStr.length();
+ int padding = (8 - (length % 8)) % 8; // 计算需要补零的数量
+ StringBuilder paddedBinary = new StringBuilder();
+ for (int i = 0; i < padding; i++) {
+ paddedBinary.append('0');
+ }
+ paddedBinary.append(binaryStr);
+
+ // 每8位转换为两位十六进制
+ StringBuilder hexStr = new StringBuilder();
+ for (int i = 0; i < paddedBinary.length(); i += 8) {
+ String byteStr = paddedBinary.substring(i, i + 8);
+ int decimalValue = Integer.parseInt(byteStr, 2);
+ hexStr.append(String.format("%02X", decimalValue & 0xFF));
+ }
+
+ return hexStr.toString();
+ }
+
+ /**
+ * 数据校验 异或处理
+ */
+ public static String getXor(String content) {
+ int a = 0;
+ for (int i = 0; i < content.length() / 2; i++) {
+ a = a ^ Integer.parseInt(content.substring(i * 2, (i * 2) + 2), 16);
+ }
+ String result = Integer.toHexString(a).toUpperCase();
+ if (result.length() == 1) {
+ return "0" + result;
+ } else {
+ return result;
+ }
+ }
+
+ public static double formatPersonInfo(String input, int startIndex, int length) {
+ if (input == null) {
+ return 0;
+ }
+ // 处理索引越界问题
+ int safeStart = Math.max(startIndex, 0);
+ int safeEnd = Math.min(startIndex + length, input.length());
+ if (safeStart > safeEnd) {
+ return 0;
+ }
+ String result = input.substring(safeStart, safeEnd);
+ double num = Integer.parseInt(result, 16);
+ return num;
+ }
+
+ /**
+ * 安装apk
+ *
+ * @param activity
+ * @param apkFile
+ */
+ public static void installApk(Context activity, File apkFile) {
+ //文件有所有者概念,现在是属于当前进程的,需要把这个文件暴露给系统安装程序(其他进程)去安装
+ //因此,可能会存在权限问题,需要做下面的设置
+ //如果文件是sdcard上的,就不需要这个操作了
+ try {
+ apkFile.setExecutable(true, false);
+ apkFile.setReadable(true, false);
+ apkFile.setWritable(true, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Intent intent = new Intent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setAction(Intent.ACTION_VIEW);
+ Uri uri;
+
+ //TODO N FileProvider
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ uri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileProvider", apkFile);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+// intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ } else {
+ uri = Uri.fromFile(apkFile);
+ }
+
+ intent.setDataAndType(uri, "application/vnd.android.package-archive");
+ activity.startActivity(intent);
+
+ //TODO 0 INSTALL PERMISSION
+ //在AndroidManifest中加入权限即可
+ }
+
+}
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/utils/QRCodeUtil.kt b/app/src/main/java/com/shuwei/intelligent/shelves/utils/QRCodeUtil.kt
new file mode 100644
index 0000000..b05a2ca
--- /dev/null
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/utils/QRCodeUtil.kt
@@ -0,0 +1,101 @@
+package com.shuwei.intelligent.shelves.utils
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+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
+
+
+/**
+ * 二维码生成工具类
+ */
+object QRCodeUtil {
+
+ /**
+ * 生成二维码(默认大小)
+ * @param content 二维码内容
+ * @return 生成的二维码Bitmap
+ */
+ @JvmOverloads
+ fun generateQRCode(content: String, size: Int = 500): Bitmap? {
+ return generateQRCode(content, size, Color.BLACK, Color.WHITE)
+ }
+
+ /**
+ * 生成二维码(自定义颜色)
+ * @param content 二维码内容
+ * @param size 二维码边长(像素)
+ * @param colorCode 二维码颜色
+ * @param backgroundColor 背景颜色
+ * @return 生成的二维码Bitmap
+ */
+ fun generateQRCode(
+ content: String,
+ size: Int,
+ colorCode: Int,
+ backgroundColor: Int
+ ): Bitmap? {
+ if (content.isEmpty()) {
+ return null
+ }
+
+ return try {
+ val hints = mutableMapOf().apply {
+ put(EncodeHintType.CHARACTER_SET, "UTF-8")
+ put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H) // 纠错级别
+ put(EncodeHintType.MARGIN, 1) // 边距
+ }
+
+ val bitMatrix = QRCodeWriter().encode(
+ content,
+ BarcodeFormat.QR_CODE,
+ size,
+ size,
+ hints
+ )
+
+ val pixels = IntArray(size * size).apply {
+ for (y in 0 until size) {
+ for (x in 0 until size) {
+ this[y * size + x] = if (bitMatrix.get(x, y)) colorCode else backgroundColor
+ }
+ }
+ }
+
+ Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888).apply {
+ setPixels(pixels, 0, size, 0, 0, size, size)
+ }
+
+ } catch (e: WriterException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 生成带Logo的二维码
+ * @param content 二维码内容
+ * @param size 二维码边长(像素)
+ * @param logo Logo Bitmap
+ * @return 带Logo的二维码Bitmap
+ */
+ fun generateQRCodeWithLogo(content: String, size: Int, logo: Bitmap?): Bitmap? {
+ val qrCode = generateQRCode(content, size) ?: return null
+ logo ?: return qrCode
+
+ val logoSize = size / 5 // Logo大小约为二维码的1/5
+ val scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, false)
+
+ val offset = (size - logoSize) / 2
+ return Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888).apply {
+ val canvas = Canvas(this)
+ canvas.drawBitmap(qrCode, 0f, 0f, null)
+ canvas.drawBitmap(scaledLogo, offset.toFloat(), offset.toFloat(), null)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/utils/SpTool.kt b/app/src/main/java/com/shuwei/intelligent/shelves/utils/SpTool.kt
new file mode 100644
index 0000000..dbb0bc4
--- /dev/null
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/utils/SpTool.kt
@@ -0,0 +1,31 @@
+package com.shuwei.intelligent.shelves.utils
+
+import com.shuwei.intelligent.shelves.App
+import com.shuwei.intelligent.shelves.utils.ext.put
+import kotlin.to
+
+object SpTool {
+
+ const val DEVICE_CONFIG_CACHE = "deviceConfigCache"
+ const val TOKEN = "token"
+ const val LAUNCH_PAGE_TYPE = "launchPageType"
+ const val DEVICE_ID = "deviceId"
+
+ val pref = App.getSharedPref()!!
+
+ fun put(key: String, value: Any) {
+ pref.put(key to value)
+ }
+
+ fun getInt(key: String, defValue: Int = 0): Int {
+ return pref.getInt(key, defValue)
+ }
+
+ fun getString(key: String, defValue: String? = ""): String {
+ return pref.getString(key, defValue) ?: ""
+ }
+
+ fun getBoolean(key: String, defValue: Boolean = false): Boolean {
+ return pref.getBoolean(key, defValue)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_init_button.xml b/app/src/main/res/drawable/bg_init_button.xml
new file mode 100644
index 0000000..71ff7c1
--- /dev/null
+++ b/app/src/main/res/drawable/bg_init_button.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/img_init.png b/app/src/main/res/drawable/img_init.png
new file mode 100644
index 0000000..e8d0844
Binary files /dev/null and b/app/src/main/res/drawable/img_init.png differ
diff --git a/app/src/main/res/layout/activity_init.xml b/app/src/main/res/layout/activity_init.xml
new file mode 100644
index 0000000..6839fee
--- /dev/null
+++ b/app/src/main/res/layout/activity_init.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_logo512.png b/app/src/main/res/mipmap-xxxhdpi/ic_logo512.png
new file mode 100644
index 0000000..55e3eac
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_logo512.png differ
diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml
index 1564dab..7c1df30 100644
--- a/app/src/main/res/xml/network_security_config.xml
+++ b/app/src/main/res/xml/network_security_config.xml
@@ -1,7 +1,8 @@
-
- 192.168.1.3
- 192.168.1.7
-
+
+
+
+
+
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 248ed79..8c889e6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -8,8 +8,12 @@ junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.10.0"
+core = "3.4.1"
+androidCore = "3.3.0"
[libraries]
+android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
+core = { module = "com.google.zxing:core", version.ref = "core" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }