整理下在工作中常用到的各种ADB命令和一些工具方法
隐藏/恢复系统的菜单栏和任务栏
隐藏:
shellwm overscan 0,-70,0,-70
恢复:
shellwm overscan 0,0,0,0
禁用/启用Launcher
shellpm disable-user com.android.launcher3 // 禁用 pm enable com.android.launcher3 // 启用
ADB 安装/卸载应用
shelladb install -r xxx.apk adb uninstall com.xxxx.xxxxx(应用包名)
ADB 启动/停止应用
am force-stop com.xxxxx; (应用包名) am start -n com.xxxxxx/.MainActivity (应用包名+应用入口Activity)
截图
screencap -p /sdcard/screenshot.png
导出某个时间段日志
shelladb 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
adb pull /sdcard/xxxx/ .
adb shell am start -a android.intent.action.VIEW -d https://baidu.com
shellsetprop service.adb.tcp.port 5555;stop adbd;start adbd
shellcmd package set-home-activity com.xxx/.MainActivity
shellpm grant com.xxxx
shellmedia volume --show --stream 2 --set 1
eboot;
kotlinclass 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))
}
}
}
kotlinobject 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
}
}
javapublic 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;
}
}
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()
}
}
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
}
}
kotlinimport 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
}
}
kotlinimport 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
}
}
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)
}
}
kotlinimport 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 许可协议。转载请注明出处!