编辑
2025-01-23
技术
00

目录

ADB指令(常见)
工具类&方法

整理下在工作中常用到的各种ADB命令和一些工具方法

ADB指令(常见)

  1. 隐藏/恢复系统的菜单栏和任务栏

    隐藏:

    shell
    wm overscan 0,-70,0,-70

    恢复:

    shell
    wm overscan 0,0,0,0
  2. 禁用/启用Launcher

    shell
    pm disable-user com.android.launcher3 // 禁用 pm enable com.android.launcher3 // 启用
  3. ADB 安装/卸载应用

    shell
    adb install -r xxx.apk adb uninstall com.xxxx.xxxxx(应用包名)
  4. ADB 启动/停止应用

    am force-stop com.xxxxx; (应用包名) am start -n com.xxxxxx/.MainActivity (应用包名+应用入口Activity)
  5. 截图

    screencap -p /sdcard/screenshot.png
  6. 导出某个时间段日志

shell
adb devices adb logcat -v time -t "2022-01-01 00:00:00" -T "2022-01-02 00:00:00" > log.txt adb pull log.txt /path/to/local/directory
  1. adb 导出文件到PC
adb pull /sdcard/xxxx/ .
  1. 打开设备浏览器并访问对应网址
adb shell am start -a android.intent.action.VIEW -d https://baidu.com
  1. 启动/停用设备自身adb端口
shell
setprop service.adb.tcp.port 5555;stop adbd;start adbd
  1. 设置应用为主屏幕应用
shell
cmd package set-home-activity com.xxx/.MainActivity
  1. 应用授权启动
shell
pm grant com.xxxx
  1. 设置音量
shell
media volume --show --stream 2 --set 1
  1. 重启应用
eboot;

工具类&方法

  1. 静默安装
kotlin
class InstallAPK { companion object { const val timeOut = 5 * 1000L private const val MD5_APPEND0 = "0" private const val MD5_STRING = "MD5" private const val SHA1_NAME = "SHA1" private const val TAG = "InstallAPK" /** * install slient * * @param context * @param filePath * @return 0 means normal, 1 means file not exist, 2 means other exception * error */ fun installSlient(filePath: String, packName: String): Int { val file = File(filePath) if (!file.exists()) { return 1 } var args: Array<String> if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { args = arrayOf("pm", "install", "-r", "-i", packName, "--user", "0", filePath) } else { args = arrayOf("pm", "install", "-r", filePath) } val processBuilder = ProcessBuilder(*args) var process: Process? = null var successResult: BufferedReader? = null var errorResult: BufferedReader? = null val successMsg = StringBuilder() val errorMsg = StringBuilder() var result: Int process = processBuilder.start() successResult = BufferedReader(InputStreamReader(process!!.inputStream)) errorResult = BufferedReader(InputStreamReader(process.errorStream)) var s: String? do { s = successResult.readLine() if (s != null) { successMsg.append(s) } else break } while (true) do { s = errorResult.readLine() if (s != null) { errorMsg.append(s) } else break } while (true) successResult?.close() errorResult?.close() process?.destroy() if (successMsg.toString().contains("Success") || successMsg.toString().contains("success") ) { result = 0 } else { result = 2 } return result } /** * 获取apk的包名 */ fun getApkPackageName( context: Context, apkPath: String?, ): String? { apkPath ?: return null val pm = context.packageManager val info = pm.getPackageArchiveInfo(apkPath, 0) return info?.packageName } /** * MD5加密 * @param byteStr 需要加密的内容 * @return 返回 byteStr的md5值 */ private fun encryptionMD5(byteStr: ByteArray?): String { var messageDigest: MessageDigest? = null val md5StrBuff = StringBuffer() try { messageDigest = MessageDigest.getInstance(MD5_STRING) messageDigest.reset() messageDigest.update(byteStr) val byteArray = messageDigest.digest() // return Base64.encodeToString(byteArray,Base64.NO_WRAP); for (i in byteArray.indices) { if (Integer.toHexString(0xFF and byteArray[i].toInt()).length == 1) { md5StrBuff.append(MD5_APPEND0).append( Integer.toHexString( 0xFF and byteArray[i] .toInt() ) ) } else { md5StrBuff.append(Integer.toHexString(0xFF and byteArray[i].toInt())) } } } catch (e: NoSuchAlgorithmException) { e.printStackTrace() } return md5StrBuff.toString() } /** * 获取app签名md5值,与“keytool -list -keystore D:\Desktop\app_key”‘keytool -printcert *file D:\Desktop\CERT.RSA’获取的md5值一样 */ fun getSignMd5Str(context: Context, packageName: String): String { try { val packageInfo: PackageInfo = context.packageManager.getPackageInfo( packageName, PackageManager.GET_SIGNATURES ) val signs: Array<Signature> = packageInfo.signatures val sign: Signature = signs[0] return encryptionMD5(sign.toByteArray()) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } return "" } private fun hexDigest(bytes: ByteArray?): String? { val md5: MessageDigest = try { MessageDigest.getInstance(MD5_STRING) } catch (e: java.lang.Exception) { e.printStackTrace() return "" } val md5Bytes = md5.digest(bytes) val hexValue = StringBuffer() for (i in md5Bytes.indices) { val `val` = md5Bytes[i].toInt() and 0xff if (`val` < 16) hexValue.append(MD5_APPEND0) hexValue.append(Integer.toHexString(`val`)) } return hexValue.toString() } /** * 从APK中读取签名 * * @param file * @return * @throws IOException */ @Throws(IOException::class) private fun getSignaturesFromApk(strFile: String): ByteArray? { val file = File(strFile) val jarFile = JarFile(file) try { val je: JarEntry = jarFile.getJarEntry("AndroidManifest.xml") val readBuffer = ByteArray(8192) val certs: Array<Certificate>? = loadCertificates(jarFile, je, readBuffer) if (certs != null) { for (c in certs) { return c.encoded } } } catch (ex: java.lang.Exception) { ex.printStackTrace() } return null } /** * 加载签名 * * @param jarFile * @param je * @param readBuffer * @return */ private fun loadCertificates( jarFile: JarFile, je: JarEntry?, readBuffer: ByteArray, ): Array<Certificate>? { try { val inputStream: InputStream = jarFile.getInputStream(je) while (inputStream.read(readBuffer, 0, readBuffer.size) !== -1) { } inputStream.close() return je?.certificates } catch (e: IOException) { e.printStackTrace() } return null } /** * 校验已经安装的软件签名是否和插件市场下发的软件签名一致 * @param localPkgName 已经安装的包名 * @param path 插件市场下发的软件路径 */ fun checkSign(context: Context, localPkgName: String, path: String): Boolean { try { val pathMD5 = hexDigest(getSignaturesFromApk(path)) val localPkgNameMD5 = getSignMd5Str(context, localPkgName) LogUtils.i("$TAG pathMD5: $pathMD5") LogUtils.i("$TAG localPkgNameMD5: $localPkgNameMD5") if (TextUtils.isEmpty(localPkgNameMD5)) { LogUtils.i("$TAG isEmpty") return true } LogUtils.i("$TAG isSame: ${pathMD5 == localPkgNameMD5}") return pathMD5 == localPkgNameMD5 } catch (e: java.lang.Exception) { e.printStackTrace() } return false } private fun allowDowngrade(sessionParams: PackageInstaller.SessionParams) { try { //允许低版本安装的原因:在新版本出问题但是来不及修复需要进行版本回退 val allowDowngrade: Method = PackageInstaller.SessionParams::class.java.getMethod( "setAllowDowngrade", Boolean::class.javaPrimitiveType ) allowDowngrade.isAccessible = true allowDowngrade.invoke(sessionParams, true) } catch (e: java.lang.Exception) { e.printStackTrace() } } @JvmStatic fun installApk21(context: Context, apkFilePath: String): Boolean { val apkFile = File(apkFilePath) if(apkFile.exists()) { LogHelper.saveRequestLog("$apkFilePath, 文件存在") }else{ LogHelper.saveRequestLog("$apkFilePath, 文件不存在") } val packageInstaller = context.packageManager.packageInstaller val pkgName = getApkPackageName(context, apkFilePath) LogHelper.saveRequestLog("InstallAPK apk path:$apkFilePath, package name:$pkgName") pkgName?.let { //如果签名不一致则先卸载 if (!checkSign(context, pkgName, apkFilePath)) { LogHelper.saveRequestLog("InstallAPK apk package uninstall") uninstallSignError21(context, pkgName, apkFilePath) } val sessionParams = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL) .apply { setAppPackageName(pkgName) setSize(apkFile.length()) } allowDowngrade(sessionParams) val sessionId = createSession(packageInstaller, sessionParams) if (sessionId != -1 && copyApkFile(packageInstaller, sessionId, apkFilePath, it)) { return install( context, packageInstaller, sessionId, InstallReceiver::class.java ) } } LogHelper.saveRequestLog("Install falied") return false } /** * 最后提交 session,并且设置回调 **/ @JvmStatic fun install( context: Context, packageInstaller: PackageInstaller, sessionId: Int, cls: Class<*> ): Boolean { var session: PackageInstaller.Session? = null try { LogHelper.saveRequestLog("start install") session = packageInstaller.openSession(sessionId).apply { val intent = Intent(context, cls) val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.getBroadcast( context, 1, intent, PendingIntent.FLAG_MUTABLE ) } else { PendingIntent.getBroadcast( context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT ) } commit(pendingIntent.intentSender) } return true } catch (ex: Exception) { LogHelper.saveRequestLog("Install falied exception:${ex.message}") } finally { session?.close() } return false } /** * 根据 sessionParams 创建 Session **/ @JvmStatic fun createSession( packageInstaller: PackageInstaller, sessionParams: PackageInstaller.SessionParams, ): Int { val sessionId: Int = try { packageInstaller.createSession(sessionParams) } catch (e: IOException) { e.printStackTrace() -1 } return sessionId } /** * 将 apk 文件输入 session **/ @JvmStatic fun copyApkFile( packageInstaller: PackageInstaller, sessionId: Int, apkFilePath: String, pkgName: String, ): Boolean { var success: Boolean val apkFile = File(apkFilePath) try { packageInstaller.openSession(sessionId).use { session -> session.openWrite(pkgName, 0, apkFile.length()).use { out -> FileInputStream(apkFile).use { input -> LogUtils.d("$TAG copyApkFile openWrite start writing ${apkFile.absolutePath}") var read: Int val buffer = ByteArray(1024) while (input.read(buffer).also { read = it } != -1) { out.write(buffer, 0, read) } session.fsync(out) syncFile2Disk() success = true } } } } catch (e: IOException) { LogUtils.e(e.stackTraceToString()) success = false } LogUtils.d("$TAG copyApkFile openWrite writ done! success = $success") return success } private fun syncFile2Disk() { try { CmdUtil.execCmdSilent("sync") // Shell.SH.run("sync") } catch (e: Exception) { e.printStackTrace() } } @JvmStatic private fun uninstallSignError21(context: Context, pkgName: String, apkFilePath: String) { try { runBlocking(Dispatchers.IO) { LogUtils.d(">>> InstallAPK apk package name:$pkgName sign diff $apkFilePath") uninstall21(context, pkgName) //给卸载一些时间 5秒 delay(timeOut) } } catch (e: java.lang.Exception) { e.printStackTrace() } } @SuppressLint("MissingPermission") @JvmStatic fun uninstall21(context: Context, pkgName: String) { LogUtils.d(">>> InstallAPK uninstall21 pkgName = $pkgName") val packageInstaller = context.packageManager.packageInstaller val intent = Intent(context, InstallReceiver::class.java) val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.getBroadcast( context, 2, intent, PendingIntent.FLAG_MUTABLE ) } else { PendingIntent.getBroadcast( context, 2, intent, PendingIntent.FLAG_UPDATE_CURRENT ) } try { packageInstaller.uninstall(pkgName, pendingIntent.intentSender) } catch (e: IllegalArgumentException) { e.printStackTrace() } } fun installSilence() { } fun installSilentWithReflection(context: Context, filePath: String?,packName: String) { val packageManager = context.packageManager val method: Method = packageManager.javaClass.getDeclaredMethod( "installPackage", *arrayOf<Class<*>?>( Uri::class.java, IPackageInstallObserver::class.java, Int::class.javaPrimitiveType, String::class.java ) ) method.setAccessible(true) val apkFile = File(filePath) val apkUri: Uri = Uri.fromFile(apkFile) method.invoke(packageManager, arrayOf(apkUri, object : IPackageInstallObserver.Stub() { @Throws(RemoteException::class) override fun packageInstalled(pkgName: String, resultCode: Int) { } }, 2, packName)) } } }
  1. 获取设备各种基本信息(部分需要root)
kotlin
object DeviceInfoUtil { private const val maximumPassengerPref = "maximum" @SuppressLint("HardwareIds") fun getSN(): String { //return "e0d8c45adef0" return Build.SERIAL } fun isNetworkAvailable(context: Context): Boolean { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager if (connectivityManager != null) { val activeNetworkInfo: NetworkInfo? = connectivityManager.activeNetworkInfo return activeNetworkInfo != null && activeNetworkInfo.isConnected() } return false } fun getSN(context:Context):String{ var androidId: String = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID) if(androidId.isNullOrBlank()) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { androidId = Build.getSerial() } else { androidId = Build.SERIAL } }catch (e:Exception){ } } if(androidId.isNullOrBlank()) { try { val telephonyManager = context.getSystemService(TELEPHONY_SERVICE) as TelephonyManager androidId = telephonyManager.imei }catch (e:Exception){ } } return androidId } fun getMacAddress(): String { var macAddress="" try { val all: List<NetworkInterface> = Collections.list(NetworkInterface.getNetworkInterfaces()) for (nif in all) { if (!nif.name.equals("eth0", ignoreCase = true)) continue val macBytes = nif.getHardwareAddress() ?: return "" val res1 = StringBuilder() for (b in macBytes) { res1.append(String.format("%02X:", b)) } if (res1.length > 0) { res1.deleteCharAt(res1.length - 1) } macAddress = res1.toString() } } catch (ex: Exception) { // Handle exception } return macAddress // Default MAC address if not found } fun saveRequestLog(data:String) { try { var formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") var formatter2: DateFormat = SimpleDateFormat("yyyy-MM-dd") val time: String = formatter.format(Date()) val fileName = "request-${formatter2.format(Date())}.log" if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { val sdCardPath = Environment.getExternalStorageDirectory(); val path = sdCardPath.getAbsolutePath() + "/TVAgent/logs" val dir = File(path) if (!dir.exists()) { dir.mkdirs() } var content = "Time:[${time}]---${data}\n" val file = File("${path}/${fileName}") val raf = RandomAccessFile(file, "rw") val originalContent = ByteArray(raf.length().toInt()) raf.readFully(originalContent) raf.seek(0) raf.write(content.toByteArray()) raf.write(originalContent) raf.close() } }catch (ex: IOException) { } } fun getStorageInfo():String { val statFs = StatFs(Environment.getRootDirectory().getPath()) val blockSize = statFs.blockSizeLong val totalBlocks = statFs.blockCountLong val availableBlocks = statFs.availableBlocksLong val totalSpace = totalBlocks * blockSize val availableSpace = availableBlocks * blockSize return (availableSpace.toDouble()/totalSpace.toDouble()).toString() } fun readCPUStat(): LongArray { try { BufferedReader(FileReader("/proc/stat")).use { br -> val line = br.readLine() if (line != null && line.startsWith("cpu")) { val tokens = line.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() } .toTypedArray() val user = tokens[1].toLong() val nice = tokens[2].toLong() val system = tokens[3].toLong() val idle = tokens[4].toLong() val iowait = tokens[5].toLong() val irq = tokens[6].toLong() val softirq = tokens[7].toLong() saveRequestLog("读取cpu信息:user:${user} nice:${nice} system:${system} idle:${idle} iowait:${iowait} irq:${irq} softirq:${softirq}") // 包含所有CPU时间的数组 return longArrayOf(user, nice, system, idle, iowait, irq, softirq) } } } catch (e: IOException) { saveRequestLog("读取cpu信息异常:${e.message}") } return LongArray(0) } fun getSystemMemoryInfo(context: Context):String { val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val memoryInfo = ActivityManager.MemoryInfo() activityManager.getMemoryInfo(memoryInfo) var totalMemory=0L if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { totalMemory = memoryInfo.totalMem } val availableMemory = memoryInfo.availMem val lowMemory = memoryInfo.lowMemory // 设备当前是否处于低内存状态 return (availableMemory.toDouble()/totalMemory.toDouble()).toString() } fun getIP(): String { val interfaces = NetworkInterface.getNetworkInterfaces() while (interfaces.hasMoreElements()) { val networkInterface = interfaces.nextElement() val addresses = networkInterface.inetAddresses while (addresses.hasMoreElements()) { val address = addresses.nextElement() if (!address.isLoopbackAddress && address.hostAddress.indexOf(':') < 0) { return address.hostAddress } } } return "" } fun getVersionType(context: Context): Int { val sharedPreferences = context.getSharedPreferences("version", Context.MODE_PRIVATE) return sharedPreferences.getInt("version_type", 0) } fun setVersionType(context: Context, versionType: Int) { val sharedPreferences = context.getSharedPreferences("version", Context.MODE_PRIVATE) val editor = sharedPreferences.edit() editor.putInt("version_type", versionType) editor.apply() } fun getVersionName(context: Context): String? { val packageManager = context.packageManager val packageInfo: PackageInfo var versionName: String? = "" try { packageInfo = packageManager.getPackageInfo(context.packageName, 0) versionName = packageInfo.versionName } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } return versionName } }
  1. 应用执行ADB Shell指令
java
public class CmdUtil { // 执行adb shell并获取返回字符串 public static String execCmd(String cmd) { String result = ""; String line = ""; try { Process proc = Runtime.getRuntime().exec(cmd); InputStreamReader is = new InputStreamReader(proc.getInputStream()); BufferedReader br = new BufferedReader(is); while ((line = br.readLine()) != null) { result += line; } } catch (Exception e) { e.printStackTrace(); } return result; } // cmd="chmod 777 /dev/ttyACM" public static int execRootCmdSilent(String cmd) { int result = -1; DataOutputStream dos = null; try { Process p = Runtime.getRuntime().exec("su"); dos = new DataOutputStream(p.getOutputStream()); dos.writeBytes(cmd + "\n"); dos.flush(); dos.writeBytes("exit\n"); dos.flush(); p.waitFor(); result = p.exitValue(); } catch (Exception e) { e.printStackTrace(); } finally { if (dos != null) { try { dos.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } public static int execCmdSilent(String cmd) { int result = -1; DataOutputStream dos = null; try { Process p = Runtime.getRuntime().exec(cmd); dos = new DataOutputStream(p.getOutputStream()); dos.writeBytes("exit\n"); dos.flush(); p.waitFor(); result = p.exitValue(); } catch (Exception e) { e.printStackTrace(); } finally { if (dos != null) { try { dos.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } public static void rebootSystem(Context context) { LogUtils.v("Reboot", "Reboot-->broadcast_reboot"); try { Intent intent = new Intent(Intent.ACTION_REBOOT); intent.putExtra("nowait", 1); intent.putExtra("interval", 1); intent.putExtra("window", 0); context.sendBroadcast(intent); }catch (Exception e) { LogUtils.e(e); } } @SuppressLint("HardwareIds") public static String getDeviceSN(Context context) { String serialNumber = System.getProperty("persist.sys.boardsn.value", null); if(serialNumber == null) { serialNumber= Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); } return serialNumber; } public static String callCmd(String cmd, String filter) { String result = ""; String line = ""; try { Process proc = Runtime.getRuntime().exec(cmd); InputStreamReader is = new InputStreamReader(proc.getInputStream()); BufferedReader br = new BufferedReader(is); while ((line = br.readLine()) != null && line.contains(filter) == false) { result += line; } result = line; } catch (Exception e) { e.printStackTrace(); } return result; } }
  1. 网络信息相关获取
kotlin
class NetworkInfoUtil(val context: ReactContext) { var ipv4: String = "" get() { return field.apply { refreshIp() } } var ipv6: String = "" val TAG = "network" var bssid = "" private val request: NetworkRequest = NetworkRequest .Builder() .addTransportType( NetworkCapabilities.TRANSPORT_WIFI ).build() var mac: String = "" private var connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager /** * 用于Android12 以下获取IP */ private fun refreshIp() { try { val en: Enumeration<NetworkInterface> = NetworkInterface.getNetworkInterfaces() while (en.hasMoreElements()) { val intf: NetworkInterface = en.nextElement() val enumIpAddr: Enumeration<InetAddress> = intf.inetAddresses while (enumIpAddr.hasMoreElements()) { val inetAddress: InetAddress = enumIpAddr.nextElement() if (inetAddress.isLoopbackAddress) { continue } LogUtils.d("WifiPreference", inetAddress.hostAddress) if (inetAddress is Inet6Address) { LogUtils.d("ipv6", inetAddress.hostAddress) ipv6 = inetAddress.hostAddress as String continue } if (inetAddress is Inet4Address) { LogUtils.d("ipv4", inetAddress.hostAddress) ipv4 = inetAddress.hostAddress as String continue } } } } catch (ex: SocketException) { LogUtils.e("WifiPreference IpAddress", ex.toString()) } } fun getMacAddress(): String { val wm = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? if (wm != null) { val winfo = wm.connectionInfo if (winfo != null) { val s = winfo.bssid?: "" LogUtils.d("mac", s) return s } } return "" } fun isLocationEnabled(): Boolean { var locationMode = 0 val locationProviders: String return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { locationMode = try { Settings.Secure.getInt(context.contentResolver, Settings.Secure.LOCATION_MODE) } catch (e: Settings.SettingNotFoundException) { e.printStackTrace() return false } locationMode != Settings.Secure.LOCATION_MODE_OFF } else { locationProviders = Settings.Secure.getString( context.contentResolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED ) !TextUtils.isEmpty(locationProviders) } } fun getSSID(context: Context, callback: Callback) { val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? if (!wifiManager!!.isWifiEnabled) { callback.invoke("") return } if (wifiManager != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val mRequest: NetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build() val mConnectivityManager: ConnectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val mNetworkCallback = object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) { override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { super.onCapabilitiesChanged(network, networkCapabilities) val wifiInfo = networkCapabilities.transportInfo as WifiInfo? var ssid = "" wifiInfo?.let { ssid = wifiInfo.ssid.replace("\"", "").replace("<", "").replace(">", "") LogUtils.d("ssid", ssid) mConnectivityManager.unregisterNetworkCallback(this) } try { callback.invoke(ssid) }catch (e: Exception){ } } } mConnectivityManager.registerNetworkCallback(mRequest, mNetworkCallback) } else { val connectionInfo = wifiManager.connectionInfo if (connectionInfo?.networkId != -1) { var ssid = connectionInfo?.ssid?.replace("\"", "") callback.invoke(ssid) } } } // return ssid } // 获取系统LocationMode的值 fun getLocationMode(): Int { // 返回值是0 的时候, 就是 LOCATION_MODE_OFF 这个宏 // 返回值为1的时候 就是 LOCATION_MODE_SENSORS_ONLY 就是上面的仅限设备GPS // 返回值是2, 就是 LOCATION_MODE_BATTERY_SAVING 低耗电量 // 返回值为3, 就是 LOCATION_MODE_HIGH_ACCURACY 仅限设备 var locationMode = 0 return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { locationMode = try { Settings.Secure.getInt(context.contentResolver, Settings.Secure.LOCATION_MODE) } catch (e: Settings.SettingNotFoundException) { LogUtils.e("getLocationMode", e.message) e.printStackTrace() return 0 } locationMode } else { 0 } } fun getScanWifiEnable(context: Context): Boolean { val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager? return locationManager!!.isProviderEnabled(LocationManager.NETWORK_PROVIDER) } fun getSSID(context: Context, callback: (ssid: String?)-> Unit) { val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? if (!wifiManager!!.isWifiEnabled) { callback.invoke("") return } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val mRequest: NetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build() val mConnectivityManager: ConnectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val mNetworkCallback = object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) { override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { super.onCapabilitiesChanged(network, networkCapabilities) val wifiInfo = networkCapabilities.transportInfo as WifiInfo? var ssid = "" wifiInfo?.let { ssid = wifiInfo.ssid.replace("\"", "").replace("<", "").replace(">", "") LogUtils.d("ssid", ssid) mConnectivityManager.unregisterNetworkCallback(this) } try { callback.invoke(ssid) }catch (e: Exception){ } } } mConnectivityManager.registerNetworkCallback(mRequest, mNetworkCallback) } else { val connectionInfo = wifiManager.connectionInfo if (connectionInfo?.networkId != -1) { var ssid = connectionInfo?.ssid?.replace("\"", "") connectionInfo.bssid?.let { bssid = it } callback.invoke(ssid) } } // return ssid } private fun initNetwork() { when (Build.VERSION.SDK_INT) { Build.VERSION_CODES.S -> { val obj = object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) { override fun onLinkPropertiesChanged( network: Network, linkProperties: LinkProperties ) { super.onLinkPropertiesChanged(network, linkProperties) for (addr in linkProperties.linkAddresses) { LogUtils.d("ip", addr.address.hostAddress) if (addr.address is Inet6Address) { LogUtils.d("ipv6", addr.address.hostAddress) ipv6 = addr.address.hostAddress as String continue } if (addr.address is Inet4Address) { LogUtils.d("ipv4", addr.address.hostAddress) ipv4 = addr.address.hostAddress as String continue } } } override fun onCapabilitiesChanged( network: Network, networkCapabilities: NetworkCapabilities ) { super.onCapabilitiesChanged(network, networkCapabilities) try { val wifiInfo = networkCapabilities.transportInfo as WifiInfo if (wifiInfo.bssid != "02:00:00:00:00:00"){ mac = wifiInfo.bssid } if (wifiInfo.ssid != "<unknown ssid>") { // ssid = wifiInfo.ssid } } catch (e: Exception) { LogUtils.e(e) } } override fun onLost(network: Network) { // ssid = "" mac = "" super.onLost(network) } override fun onUnavailable() { // ssid = "" mac = "" super.onUnavailable() } } connMgr.registerNetworkCallback(request, obj) } else -> { val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager val net = wifiManager.connectionInfo // ssid = net.ssid?: "" mac = net.bssid?: "" refreshIp() } } } init { initNetwork() } }
  1. 签名、加密与keystore相关
  • 获取签名:
kotlin
import android.content.Context import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.pm.Signature import android.util.Log import java.security.MessageDigest import java.util.Locale /** * 获取签名工具类 */ object AppSigning { val MD5 = "MD5" val SHA1 = "SHA1" val SHA256 = "SHA256" private val mSignMap = HashMap<String, ArrayList<String>?>() /** * 返回一个签名的对应类型的字符串 * * @param context * @param type * @return 因为一个安装包可以被多个签名文件签名,所以返回一个签名信息的list */ fun getSignInfo(context: Context?, type: String?): ArrayList<String>? { if (context == null || type == null) { return null } val packageName = context.packageName ?: return null if (mSignMap[type] != null) { return mSignMap[type] } val mList = ArrayList<String>() try { val signs = getSignatures(context, packageName) for (sig: Signature in signs!!) { var tmp = "error!" if (MD5 == type) { tmp = getSignatureByteString(sig, MD5) } else if (SHA1 == type) { tmp = getSignatureByteString(sig, SHA1) } else if (SHA256 == type) { tmp = getSignatureByteString(sig, SHA256) } mList.add(tmp) } } catch (e: Exception) { Log.e("e", e.message!!) } mSignMap[type] = mList return mList } /** * 获取签名sha1值 * * @param context * @return */ fun getSha1(context: Context?): String { var res = "" val mlist = getSignInfo(context, SHA1) if (mlist != null && mlist.size != 0) { res = mlist[0] } return res } /** * 获取签名MD5值 * * @param context * @return */ fun getMD5(context: Context?): String { var res = "" val mlist = getSignInfo(context, MD5) if (mlist != null && mlist.size != 0) { res = mlist[0] } return res } /** * 获取签名SHA256值 * * @param context * @return */ fun getSHA256(context: Context?): String { var res = "" val mlist = getSignInfo(context, SHA256) if (mlist != null && mlist.size != 0) { res = mlist[0] } return res } /** * 返回对应包的签名信息 * * @param context * @param packageName * @return */ private fun getSignatures(context: Context, packageName: String): Array<Signature>? { var packageInfo: PackageInfo? = null try { packageInfo = context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) return packageInfo.signatures } catch (e: Exception) { Log.e("e", e.toString()) } return null } /** * 获取相应的类型的字符串(把签名的byte[]信息转换成16进制) * * @param sig * @param type * @return */ private fun getSignatureString(sig: Signature, type: String): String { val hexBytes = sig.toByteArray() var fingerprint = "error!" try { val digest = MessageDigest.getInstance(type) if (digest != null) { val digestBytes = digest.digest(hexBytes) val sb = StringBuilder() for (digestByte: Byte in digestBytes) { sb.append( Integer.toHexString(digestByte.toInt() and 0xFF or 0x100) .substring(1, 3) ) } fingerprint = sb.toString() } } catch (e: Exception) { Log.e("e", e.toString()) } return fingerprint } /** * 获取相应的类型的字符串(把签名的byte[]信息转换成 95:F4:D4:FG 这样的字符串形式) * * @param sig * @param type * @return */ private fun getSignatureByteString(sig: Signature, type: String): String { val hexBytes = sig.toByteArray() var fingerprint = "error!" try { val digest = MessageDigest.getInstance(type) if (digest != null) { val digestBytes = digest.digest(hexBytes) val sb = StringBuilder() for (digestByte: Byte in digestBytes) { sb.append( Integer.toHexString(digestByte.toInt() and 0xFF or 0x100) .substring(1, 3).uppercase(Locale.getDefault()) ) sb.append(":") } fingerprint = sb.substring(0, sb.length - 1).toString() } } catch (e: Exception) { Log.e("e", e.toString()) } return fingerprint } }
  • 加解密:
kotlin
import java.io.IOException import java.nio.charset.Charset import java.security.* import java.security.cert.CertificateException import javax.crypto.* import javax.crypto.spec.GCMParameterSpec /** * 解密 */ class Decrypt { private val TRANSFORMATION = "AES/GCM/NoPadding" private val ANDROID_KEY_STORE = "AndroidKeyStore" private var keyStore: KeyStore? = null init { initKeyStore() } @Throws( KeyStoreException::class, CertificateException::class, NoSuchAlgorithmException::class, IOException::class ) private fun initKeyStore() { keyStore = KeyStore.getInstance(ANDROID_KEY_STORE).apply { load(null) } } @Throws( UnrecoverableEntryException::class, NoSuchAlgorithmException::class, KeyStoreException::class, NoSuchProviderException::class, NoSuchPaddingException::class, InvalidKeyException::class, IOException::class, BadPaddingException::class, IllegalBlockSizeException::class, InvalidAlgorithmParameterException::class ) fun decryptData(alias: String, encryptedData: ByteArray?, encryptionIv: ByteArray?): String { val cipher: Cipher = Cipher.getInstance(TRANSFORMATION) val spec = GCMParameterSpec(128, encryptionIv) cipher.init(Cipher.DECRYPT_MODE, getSecretKey(alias), spec) return String(cipher.doFinal(encryptedData), Charset.forName("UTF-8")) } @Throws( NoSuchAlgorithmException::class, UnrecoverableEntryException::class, KeyStoreException::class ) private fun getSecretKey(alias: String): SecretKey? { return (keyStore!!.getEntry(alias, null) as KeyStore.SecretKeyEntry).secretKey } }
kotlin
import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyProperties import androidx.annotation.NonNull import java.io.IOException import java.security.* import javax.crypto.* data class EncryptIndex( val encryption: ByteArray, val vi: ByteArray ) /** * 加密 */ class Encrypt { private val TRANSFORMATION = "AES/GCM/NoPadding" private val ANDROID_KEY_STORE = "AndroidKeyStore" private lateinit var iv: ByteArray @Throws( UnrecoverableEntryException::class, NoSuchAlgorithmException::class, KeyStoreException::class, NoSuchProviderException::class, NoSuchPaddingException::class, InvalidKeyException::class, IOException::class, InvalidAlgorithmParameterException::class, SignatureException::class, BadPaddingException::class, IllegalBlockSizeException::class ) fun encryptText(alias: String, textToEncrypt: String): EncryptIndex { val cipher: Cipher = Cipher.getInstance(TRANSFORMATION) cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(alias)) return EncryptIndex(cipher.doFinal(textToEncrypt.toByteArray(charset("UTF-8"))), cipher.iv) } @NonNull @Throws( NoSuchAlgorithmException::class, NoSuchProviderException::class, InvalidAlgorithmParameterException::class ) private fun getSecretKey(alias: String): SecretKey? { val keyGenerator: KeyGenerator = KeyGenerator .getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE) keyGenerator.init( KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build() ) return keyGenerator.generateKey() } fun getIv(): ByteArray { return iv } }
  • keystore数据存储
kotlin
class KeyStoreUtil(val context: ReactContext) { private val encrypt = Encrypt() private val decrypt = Decrypt() val kDfpSharedPreference = SharePreferencesBuilder().build(context, "security") val cerfPfxSharedPreferences = SharePreferencesBuilder().build(context, "pfx") private var pfxKeyStore: KeyStore? = null fun getPfxKeyStore(pfx: ByteArrayInputStream, pwd: String): KeyStore? { if (pfxKeyStore != null) return pfxKeyStore pfxKeyStore = KeyStore.getInstance("PKCS12") pfxKeyStore!!.load(pfx, pwd.toCharArray()) return pfxKeyStore } fun decodeData(user: String, data: String, iv: String): String { val decodeData: ByteArray = Base64.decode(data, Base64.DEFAULT) val decodeIv: ByteArray = Base64.decode(iv, Base64.DEFAULT) return decryptData(user, decodeData, decodeIv) } fun getAssertIndex(user: String): NativeAsset? { val data = cerfPfxSharedPreferences.getString(user) val iv = cerfPfxSharedPreferences.getString(user + "iv") val index = decodeData(user, data, iv) return Gson().fromJson(index, NativeAsset::class.java) } fun getPfxCertWithHttp(user: String): OkHttpClient { val assetModel = getAssertIndex(user) val pfxByte = Base64.decode(assetModel?.pfx, Base64.DEFAULT) val pfx = pfxByte.inputStream() val pwd = assetModel?.password val sslParams = TrustManagerUtil.getSslSocketFactory(pfx, pwd, context, user) return OkHttpClient.Builder() .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) .hostnameVerifier{ _, _ -> true} .build() } fun getPfxSn(user: String): String? { return try { val data = cerfPfxSharedPreferences.getString(user) val iv = cerfPfxSharedPreferences.getString(user + "iv") val index = decodeData(user, data, iv) val assetModel = Gson().fromJson(index, NativeAsset::class.java) val pfx = Base64.decode(assetModel.pfx, Base64.DEFAULT).inputStream() val sn = getPfxSn(pfx, assetModel.password).apply { LogUtils.d("pfx sn:", this) } sn }catch (e: Exception) { e.printStackTrace() e.message } } fun getCert(user: String): X509Certificate? { return try { val data = cerfPfxSharedPreferences.getString(user) val iv = cerfPfxSharedPreferences.getString(user + "iv") val index = decodeData(user, data, iv) val assetModel = Gson().fromJson(index, NativeAsset::class.java) val pfx = Base64.decode(assetModel.pfx, Base64.DEFAULT).inputStream() getX509Certificate(pfx, assetModel.password)!!.cert }catch (e: Exception) { e.printStackTrace() e.message null } } data class CertData( val cert: X509Certificate, val privateKey: PrivateKey, var caList: ArrayList<X509Certificate> = ArrayList() ) // pfx证书 fun getX509Certificate(pfx: ByteArrayInputStream, pwd: String): CertData? { val pfxKeyStore = getPfxKeyStore(pfx, pwd) val aliases: Enumeration<String> = pfxKeyStore!!.aliases() var x509Certificate: X509Certificate? = null var privateKey: PrivateKey? = null aliases.iterator().forEach { if (pfxKeyStore.isKeyEntry(it)) { try { privateKey = pfxKeyStore.getKey(it, pwd.toCharArray()) as PrivateKey x509Certificate = pfxKeyStore.getCertificate(it) as X509Certificate }catch (e: Exception){ LogUtils.e("load x509 fail", e) } } } return x509Certificate?.let { privateKey?.let { it1 -> CertData(it, it1) } } } // 获取证书序列号 fun getPfxSn(pfx: ByteArrayInputStream, pwd: String): String? { return try { val cert = getX509Certificate(pfx, pwd)!!.cert val serialNumber = cert.serialNumber serialNumber.toString() }catch (e: Exception) { e.printStackTrace() null } } fun deleteCert(alias: String) { try { val aliases = pfxKeyStore!!.aliases(); aliases.iterator().forEach { if (pfxKeyStore!!.isKeyEntry(it)) { pfxKeyStore?.deleteEntry(alias) } } }catch (e: Exception) { e.printStackTrace() } } // 加密 fun encryptData(alias: String, data: String): EncryptIndex? { return try { encrypt.encryptText(alias, data) } catch (e: Exception) { e.printStackTrace() LogUtils.e(e.message) null } } // 解密 private fun decryptData(alias: String, data: ByteArray, iv: ByteArray): String { return decrypt.decryptData(alias, data, iv) } }
  • http自定义信任管理
kotlin
import android.annotation.SuppressLint import com.facebook.react.bridge.ReactContext import java.io.IOException import java.io.InputStream import java.security.KeyStore import java.security.KeyStoreException import java.security.NoSuchAlgorithmException import java.security.cert.CertificateException import java.security.cert.X509Certificate import javax.net.ssl.* class TrustManagerUtil { class SSLParams { lateinit var sSLSocketFactory: SSLSocketFactory lateinit var trustManager: X509TrustManager } private class UnSafeTrustManager : X509TrustManager { @SuppressLint("TrustAllX509TrustManager") @Throws(CertificateException::class) override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) { } @SuppressLint("TrustAllX509TrustManager") @Throws(CertificateException::class) override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) { } override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() } } private class MyTrustManager @Throws(NoSuchAlgorithmException::class, KeyStoreException::class) constructor(private val localTrustManager: X509TrustManager) : X509TrustManager { private val defaultTrustManager: X509TrustManager? init { val var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) var4.init(null as KeyStore?) defaultTrustManager = chooseTrustManager(var4.trustManagers) } @SuppressLint("TrustAllX509TrustManager") @Throws(CertificateException::class) override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) { } @Throws(CertificateException::class) override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) { try { defaultTrustManager!!.checkServerTrusted(chain, authType) } catch (ce: CertificateException) { localTrustManager.checkServerTrusted(chain, authType) } } override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() } } companion object { fun getSslSocketFactory(certificates: InputStream, password: String?, context: ReactContext, alias: String): SSLParams { val sslParams = SSLParams() try { val trustManagers = prepareTrustManager(certificates, context, alias) val keyManagers = prepareKeyManager(certificates, password) val sslContext = SSLContext.getInstance("TLS") var trustManager: X509TrustManager = UnSafeTrustManager() trustManagers?.let { arrayOfTrustManagers -> val x509TrustManager = chooseTrustManager(arrayOfTrustManagers) x509TrustManager?.let { trustManager = MyTrustManager(it) } } sslContext.init(keyManagers, arrayOf<TrustManager>(trustManager), null) sslParams.sSLSocketFactory = sslContext.socketFactory sslParams.trustManager = trustManager return sslParams } catch (e: Exception) { throw AssertionError(e) } } private fun prepareTrustManager(certificate: InputStream, context: ReactContext, alias: String): Array<TrustManager>? { if (certificate == null) return null try { val keyStore = KeyStore.getInstance("PKCS12") keyStore.load(null) val cert = KeyStoreUtil(context).getCert(alias) keyStore.setCertificateEntry(alias, cert) try { certificate.close() } catch (e: IOException) { } val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) trustManagerFactory.init(keyStore) return trustManagerFactory.trustManagers } catch (e: Exception) { e.printStackTrace() } return null } private fun prepareKeyManager(bksFile: InputStream?, password: String?): Array<KeyManager>? { try { if (bksFile == null || password == null) return null val clientKeyStore = KeyStore.getInstance("PKCS12") clientKeyStore.load(bksFile, password.toCharArray()) val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()) keyManagerFactory.init(clientKeyStore, password.toCharArray()) return keyManagerFactory.keyManagers } catch (e: java.lang.Exception) { e.printStackTrace() } return null } private fun chooseTrustManager(trustManagers: Array<TrustManager>): X509TrustManager? { for (trustManager in trustManagers) { if (trustManager is X509TrustManager) { return trustManager } } return null } } }

本文作者:伞菌

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!