diff --git a/myphoneinfo/src/main/AndroidManifest.xml b/myphoneinfo/src/main/AndroidManifest.xml index 0ffb645..0e19729 100644 --- a/myphoneinfo/src/main/AndroidManifest.xml +++ b/myphoneinfo/src/main/AndroidManifest.xml @@ -4,6 +4,14 @@ + + + + + + + + + val allGranted = permissions.all { it.value } + if (allGranted) { + // 权限已授予,刷新蓝牙信息 + refreshBluetoothInfo() + } else { + // 显示权限被拒绝的UI +// showPermissionDeniedUI() + Toast.makeText(requireContext(), "权限被拒绝", Toast.LENGTH_SHORT).show() + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } + override fun onResume() { + super.onResume() + checkAndDisplayBluetoothInfo() + } + + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentHardWareBinding.inflate(inflater, container, false) - dialogExtension=dialogExtension?: DialogExtension() + dialogExtension = dialogExtension ?: DialogExtension() initText() binding.cpuBtn.setOnClickListener { - var intent=Intent(requireContext(), AnalysisActivity::class.java) + var intent = Intent(requireContext(), AnalysisActivity::class.java) startActivity(intent) } - binding.bluetoothLayout.pair1.setOnClickListener { - dialogBlueTooth= dialogBlueTooth?: DialogBlueTooth() - println("showBluetoothDialog"+AndInfo.instance.bluetooth.bondedDevices.size) - dialogBlueTooth?.show(childFragmentManager, "BlueTooth1") - } // binding.pair2.setOnClickListener { // dialogBlueTooth= dialogBlueTooth?: DialogBlueTooth() // dialogBlueTooth?.show(childFragmentManager, "BlueTooth2") // } binding.othertext.setOnClickListener { - dialogInput=dialogInput?: DialogInput() + dialogInput = dialogInput ?: DialogInput() dialogInput?.show(childFragmentManager, "Input") } binding.extensionShow.setOnClickListener { dialogExtension?.show(childFragmentManager, "Extention") } binding.memoryLayout.disktext.setOnClickListener { - dialogDiskPart=dialogDiskPart?: DialogDiskPart() + dialogDiskPart = dialogDiskPart ?: DialogDiskPart() dialogDiskPart?.show(childFragmentManager, "DiskPart") } @@ -65,173 +89,376 @@ class HardWareFragment : Fragment() { } private fun initText() { - val cpu = AndInfo.instance.cpu//cpu信息 + val device = AndInfo.instance.device//设备信息 - val gpu=AndInfo.instance.gpu//gpu信息 + setProcessorInfo() + setGpuInfo() + setDisplayInfo() + setMemoryInfo() + setBlueToothInfo() + setAudioInfo() + } + /** + * Audio信息 + * */ + private fun setAudioInfo() { + binding.check1.content.text = getString(R.string.low_audio) + binding.check2.content.text = getString(R.string.pro_audio) + binding.check3.content.text = getString(R.string.midl) + } - //processor - //处理器 - binding.text0.textTitle.text = getString(R.string.processor) - binding.text0.textContent.text= cpu.getProcessorName() - //制造商 - binding.text1.textTitle.text = getString(R.string.vendor) - binding.text1.textContent.text=cpu.getVendor() - //硬件 - binding.text2.textTitle.text = getString(R.string.hardware) - binding.text2.textContent.text=cpu.getProcessorName() - //核心数 - binding.text3.textTitle.text = getString(R.string.cores) - binding.text3.textContent.text=cpu.cores.size.toString() - //cpu内核详情 - binding.text4.textTitle.text = getString(R.string.CPU) - binding.text4.textContent.text=cpu.getAllArchitectures().joinToString() - //制程工艺 - binding.text5.textTitle.text = getString(R.string.process) - binding.text5.textContent.text=cpu.getProcessInfo().process - //架构 - binding.text6.textTitle.text = getString(R.string.architecture) - binding.text6.textContent.text=cpu.getArchitecture() - //ABI - binding.text7.textTitle.text = getString(R.string.ABI) - binding.text7.textContent.text=cpu.getAbi() - //supported_ABls - binding.text8.textTitle.text = getString(R.string.supported_ABls) - binding.text8.textContent.text=cpu.getSupportedAbis().joinToString() - //频率 - binding.text9.textTitle.text = getString(R.string.frequencies) - binding.text9.textContent.text=cpu.getFrequencyText() + /** + * memory信息 + * */ + private fun setMemoryInfo() { + val storageInfo = AndInfo.instance.storage//存储信息 + val used = + Formatter.formatFileSize(AndInfo.instance.context, storageInfo.internalStorageUsedSpace) + val free = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.internalStorageAvailableSpace + ) + val total = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.internalStorageTotalSpace + ) + val outused = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.externalStorageUsedSpace ?: 0 + ) + val outfree = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.externalStorageAvailableSpace ?: 0 + ) + val outtotal = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.externalStorageTotalSpace ?: 0 + ) + binding.memoryLayout.memText1.textTitle.text = getString(R.string.ram_size) + binding.memoryLayout.memText1.textContent.text = total + binding.memoryLayout.ram1.text = used + " used" + binding.memoryLayout.ram2.text = free + " free" + binding.memoryLayout.seekbar.progress = + (used.substringBefore(" ").toDouble() / total.substringBefore(" ").toDouble() * 100).toInt() - //gpu + //storage + binding.memoryLayout.memText3.textTitle.text = getString(R.string.zram) + binding.memoryLayout.memText3.textContent.text = Formatter.formatFileSize( + AndInfo.instance.context, + storageInfo.internalStorageTotalSpace + ) + binding.memoryLayout.ram3.text = outused + " used" + binding.memoryLayout.ram4.text = outfree + " free" + binding.memoryLayout.seekbar2.progress = + (outused.substringBefore(" ").toDouble() / outtotal.substringBefore(" ").toDouble() * 100).toInt() + + //fileSystem + binding.memoryLayout.storText1.textTitle.text = getString(R.string.filesystem) + binding.memoryLayout.storText1.textContent.text = total + binding.memoryLayout.stor1.text = used + " used" + binding.memoryLayout.stor2.text = free + " free" + binding.memoryLayout.radius1.text = used + binding.memoryLayout.radius2.text = used + binding.memoryLayout.radius3.text = free + binding.memoryLayout.seekbar3.progress = + (used.substringBefore(" ").toDouble() / total.substringBefore(" ").toDouble() * 100).toInt() + + //internalStorage + binding.memoryLayout.interText1.textTitle.text = getString(R.string.filesystem) + binding.memoryLayout.interText1.textContent.text = + storageInfo.internalStorageEncryptionType.toString() + binding.memoryLayout.interText2.textTitle.text = getString(R.string.block_size) + binding.memoryLayout.interText2.textContent.text = total + binding.memoryLayout.interText3.textTitle.text = "/data" + binding.memoryLayout.interText3.textContent.text = total + binding.memoryLayout.stor3.text = used + " used" + binding.memoryLayout.stor4.text = free + " free" + binding.memoryLayout.seekbar2.progress = + (used.substringBefore(" ").toDouble() / total.substringBefore(" ").toDouble() * 100).toInt() + } + + /** + * display信息 + * */ + private fun setDisplayInfo() { + val display = AndInfo.instance.display//显示信息 + val defaultDisplayInfo = display.getDefaultDisplayInfo() + val width = defaultDisplayInfo?.widthPixels.toString() + val height = defaultDisplayInfo?.heightPixels.toString() + + if (defaultDisplayInfo != null) { + + binding.disText1.textContent.text = width + "x" + height + } + binding.disText1.textTitle.text = getString(R.string.resolution) + binding.disText2.textTitle.text = getString(R.string.screen_density)//这个是px + binding.disText2.textContent.text = defaultDisplayInfo?.ppi.toString() + binding.disText3.textTitle.text = getString(R.string.screen_density_d) + val dpiStr = + defaultDisplayInfo?.densityDpi.toString() + "(xxhdpi)\n" + defaultDisplayInfo?.xdpi?.roundToInt() + "dpx" + defaultDisplayInfo?.ydpi?.roundToInt() + "dp" + binding.disText3.textContent.text = dpiStr + binding.disText4.textTitle.text = getString(R.string.screen_size_e) + + binding.disText5.textTitle.text = getString(R.string.aspect_ratio) + binding.disText5.textContent.text = convertToApproximateAspectRatio( + width = width.toInt(), + height = height.toInt() + ).toString() + binding.disText6.textTitle.text = getString(R.string.refresh_rate) + binding.disText6.textContent.text = defaultDisplayInfo?.refreshRate.toString() + "HZ" + binding.disText7.textTitle.text = getString(R.string.wide_color_gamut) + binding.disText7.textContent.text = defaultDisplayInfo?.isWideColorGamut.toString() + binding.disText8.textTitle.text = getString(R.string.hdr_support) + if (defaultDisplayInfo?.isHdr == true) { + defaultDisplayInfo.hdrTypes.joinToString() + binding.disText8.textContent.text = defaultDisplayInfo.hdrTypes.joinToString() + } else { + binding.disText8.textContent.text = "No" + } + } + + /** + * gpu信息*/ + private fun setGpuInfo() { + val gpu = AndInfo.instance.gpu//gpu信息 binding.gpuText1.textTitle.text = getString(R.string.vendor) - binding.gpuText1.textContent.text=gpu.getVendorName() + binding.gpuText1.textContent.text = gpu.getVendorName() binding.gpuText2.textTitle.text = getString(R.string.gpu) gpu.getGpuInformation().vkPhysicalDevices?.let { devices -> if (devices.isNotEmpty()) { devices.forEachIndexed { index, vkPhysicalDevice -> - binding.gpuText2.textContent.text=vkPhysicalDevice.deviceName + binding.gpuText2.textContent.text = vkPhysicalDevice.deviceName } } } - binding.gpuText3.textTitle.text=getString(R.string.max_frequency) - binding.gpuText4.textTitle.text=getString(R.string.architecture) - binding.gpuText5.textTitle.text=getString(R.string.cores) - binding.gpuText5.textContent.text=gpu.getOpenGLExtensionCount().toString() - binding.gpuText6.textTitle.text=getString(R.string.total_l2) - binding.gpuText7.textTitle.text=getString(R.string.bus_width) - binding.gpuText8.textTitle.text=getString(R.string.vulkan_support) - binding.gpuText8.textContent.text=gpu.isVulkanSupported().toString() - binding.gpuText9.textTitle.text=getString(R.string.vulkan_API) - binding.gpuText9.textContent.text=gpu.getVulkanApiVersion() - binding.open1.text=getString(R.string.opengl) + binding.gpuText3.textTitle.text = getString(R.string.max_frequency) + binding.gpuText4.textTitle.text = getString(R.string.architecture) + binding.gpuText5.textTitle.text = getString(R.string.cores) + binding.gpuText5.textContent.text = gpu.getOpenGLExtensionCount().toString() + binding.gpuText6.textTitle.text = getString(R.string.total_l2) + binding.gpuText7.textTitle.text = getString(R.string.bus_width) + binding.gpuText8.textTitle.text = getString(R.string.vulkan_support) + binding.gpuText8.textContent.text = gpu.isVulkanSupported().toString() + binding.gpuText9.textTitle.text = getString(R.string.vulkan_API) + binding.gpuText9.textContent.text = gpu.getVulkanApiVersion() + binding.open1.text = getString(R.string.opengl) gpu.getGpuInformation().eglInformation?.let { eglInfo -> eglInfo.eglExtensions?.let { dialogExtension?.setContent(it.joinToString()) } } - binding.openItem1.text=gpu.getVendorName() - binding.openItem2.text=gpu.getRendererName() - binding.openItem3.text=gpu.getOpenGLVersion() - - - - //display - val display=AndInfo.instance.display//显示信息 - val defaultDisplayInfo = display.getDefaultDisplayInfo() - val width = defaultDisplayInfo?.widthPixels.toString() - val height = defaultDisplayInfo?.heightPixels.toString() - - if(defaultDisplayInfo!=null){ - - binding.disText1.textContent.text=width+"x"+height - } - binding.disText1.textTitle.text=getString(R.string.resolution) - binding.disText2.textTitle.text=getString(R.string.screen_density)//这个是px - binding.disText2.textContent.text=defaultDisplayInfo?.ppi.toString() - binding.disText3.textTitle.text=getString(R.string.screen_density_d) - val dpiStr=defaultDisplayInfo?.densityDpi.toString()+"(xxhdpi)\n"+defaultDisplayInfo?.xdpi?.roundToInt()+"dpx"+defaultDisplayInfo?.ydpi?.roundToInt()+"dp" - binding.disText3.textContent.text=dpiStr - binding.disText4.textTitle.text=getString(R.string.screen_size_e) - - binding.disText5.textTitle.text=getString(R.string.aspect_ratio) - binding.disText5.textContent.text=convertToApproximateAspectRatio(width = width.toInt(), height = height.toInt()).toString() - binding.disText6.textTitle.text=getString(R.string.refresh_rate) - binding.disText6.textContent.text=defaultDisplayInfo?.refreshRate.toString()+"HZ" - binding.disText7.textTitle.text=getString(R.string.wide_color_gamut) - binding.disText7.textContent.text=defaultDisplayInfo?.isWideColorGamut.toString() - binding.disText8.textTitle.text=getString(R.string.hdr_support) - if(defaultDisplayInfo?.isHdr == true){ - defaultDisplayInfo.hdrTypes.joinToString() - binding.disText8.textContent.text= defaultDisplayInfo.hdrTypes.joinToString() - }else{ - binding.disText8.textContent.text= "No" - } - - - - //memory - val storageInfo = AndInfo.instance.storage//存储信息 - val used=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.internalStorageUsedSpace) - val free=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.internalStorageAvailableSpace) - val total=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.internalStorageTotalSpace) - - val outused=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.externalStorageUsedSpace?: 0) - val outfree=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.externalStorageAvailableSpace?: 0) - val outtotal=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.externalStorageTotalSpace?: 0) - - binding.memoryLayout.memText1.textTitle.text=getString(R.string.ram_size) - binding.memoryLayout.memText1.textContent.text=total - binding.memoryLayout.ram1.text=used+" used" - binding.memoryLayout.ram2.text=free+" free" - binding.memoryLayout.seekbar.progress=(used.substring(0,used.indexOf(" ")).toDouble() / total.substring(0,total.indexOf(" ")).toDouble() *100).toInt() - - //storage - binding.memoryLayout.memText3.textTitle.text=getString(R.string.zram) - binding.memoryLayout.memText3.textContent.text=Formatter.formatFileSize(AndInfo.instance.context, storageInfo.internalStorageTotalSpace) - binding.memoryLayout.ram3.text=outused+" used" - binding.memoryLayout.ram4.text=outfree+" free" - binding.memoryLayout.seekbar2.progress=(outused.substring(0,outused.indexOf(" ")).toDouble() / outtotal.substring(0,outtotal.indexOf(" ")).toDouble() *100).toInt() - - //fileSystem - binding.memoryLayout.storText1.textTitle.text=getString(R.string.filesystem) - binding.memoryLayout.storText1.textContent.text=total - binding.memoryLayout.stor1.text=used+" used" - binding.memoryLayout.stor2.text=free+" free" - binding.memoryLayout.radius1.text=used - binding.memoryLayout.radius2.text=used - binding.memoryLayout.radius3.text=free - binding.memoryLayout.seekbar3.progress=(used.substring(0,used.indexOf(" ")).toDouble() / total.substring(0,total.indexOf(" ")).toDouble() *100).toInt() - - //internalStorage - binding.memoryLayout.interText1.textTitle.text=getString(R.string.filesystem) - binding.memoryLayout.interText1.textContent.text=storageInfo.internalStorageEncryptionType.toString() - binding.memoryLayout.interText2.textTitle.text=getString(R.string.block_size) - binding.memoryLayout.interText2.textContent.text=total - binding.memoryLayout.interText3.textTitle.text="/data" - binding.memoryLayout.interText3.textContent.text=total - binding.memoryLayout.stor3.text=used+" used" - binding.memoryLayout.stor4.text=free+" free" - binding.memoryLayout.seekbar2.progress=(used.substring(0,used.indexOf(" ")).toDouble() / total.substring(0,total.indexOf(" ")).toDouble() *100).toInt() - - - - - - //Audio - binding.check1.content.text=getString(R.string.low_audio) - binding.check2.content.text=getString(R.string.pro_audio) - binding.check3.content.text=getString(R.string.midl) + binding.openItem1.text = gpu.getVendorName() + binding.openItem2.text = gpu.getRendererName() + binding.openItem3.text = gpu.getOpenGLVersion() + } + /** + * processor信息*/ + private fun setProcessorInfo() { + val cpu = AndInfo.instance.cpu//cpu信息 + //处理器 + binding.text0.textTitle.text = getString(R.string.processor) + binding.text0.textContent.text = cpu.getProcessorName() + //制造商 + binding.text1.textTitle.text = getString(R.string.vendor) + binding.text1.textContent.text = cpu.getVendor() + //硬件 + binding.text2.textTitle.text = getString(R.string.hardware) + binding.text2.textContent.text = cpu.getProcessorName() + //核心数 + binding.text3.textTitle.text = getString(R.string.cores) + binding.text3.textContent.text = cpu.cores.size.toString() + //cpu内核详情 + binding.text4.textTitle.text = getString(R.string.CPU) + binding.text4.textContent.text = cpu.getAllArchitectures().joinToString() + //制程工艺 + binding.text5.textTitle.text = getString(R.string.process) + binding.text5.textContent.text = cpu.getProcessInfo().process + //架构 + binding.text6.textTitle.text = getString(R.string.architecture) + binding.text6.textContent.text = cpu.getArchitecture() + //ABI + binding.text7.textTitle.text = getString(R.string.ABI) + binding.text7.textContent.text = cpu.getAbi() + //supported_ABls + binding.text8.textTitle.text = getString(R.string.supported_ABls) + binding.text8.textContent.text = cpu.getSupportedAbis().joinToString() + //频率 + binding.text9.textTitle.text = getString(R.string.frequencies) + binding.text9.textContent.text = cpu.getFrequencyText() } + /** + * bluetooth相关信息*/ + private fun setBlueToothInfo() { + val bluetoothInfo = AndInfo.instance.bluetooth//蓝牙信息 + if (!bluetoothInfo.isEnabled) return + binding.bluetoothLayout.showLayout.setOnClickListener { + requestBluetoothPermissions() + } + binding.bluetoothLayout.pair1.setOnClickListener { + showPairedDevicesDialog() + } + // 打开弹窗开始扫描,超过15s扫描超时结束,显示扫描到的列表 + binding.bluetoothLayout.pair2.setOnClickListener { + showNearByDevicesDialog() + } + } + // 请求蓝牙权限的方法 + private fun requestBluetoothPermissions() { + val permissions = AndInfo.instance.bluetooth.requiredPermissions + requestPermissionLauncher.launch(permissions) + } + // 检查权限的方法 + private fun checkBluetoothPermissions(): Boolean { + val bluetoothInfo = AndInfo.instance.bluetooth + return bluetoothInfo.requiredPermissions.all { permission -> + ActivityCompat.checkSelfPermission(requireContext(), permission) == + PackageManager.PERMISSION_GRANTED + } + } + /** + * 检查并显示蓝牙信息 + */ + private fun checkAndDisplayBluetoothInfo() { + val bluetoothInfo = AndInfo.instance.bluetooth + + // 1. 检查权限 + val hasPermissions = checkBluetoothPermissions() + + if (!hasPermissions) { + // 没有权限,显示权限请求UI + binding.bluetoothLayout.showLayout.visibility = View.VISIBLE + binding.bluetoothLayout.blueList.visibility = View.GONE + return + } + + // 2. 检查蓝牙是否可用 + if (!bluetoothInfo.isEnabled) { + // 蓝牙未启用,显示提示 + showBluetoothDisabledUI() + return + } + + // 3. 有权限且蓝牙已启用,显示蓝牙信息 + binding.bluetoothLayout.showLayout.visibility = View.GONE + binding.bluetoothLayout.blueList.visibility = View.VISIBLE + + // 刷新蓝牙信息 + refreshBluetoothInfo() + } + + /** + * 显示蓝牙未启用的UI + */ + private fun showBluetoothDisabledUI() { + binding.bluetoothLayout.showLayout.visibility = View.VISIBLE + binding.bluetoothLayout.blueList.visibility = View.GONE + + // 更新UI文本 + binding.bluetoothLayout.showText.text = "Bluetooth is not enabled." + + // 设置打开蓝牙按钮 + binding.bluetoothLayout.show1.setOnClickListener { + openBluetoothSettings() + } + } + /** + * 显示已配对设备弹窗 + */ + private fun showPairedDevicesDialog() { + dialogBlueTooth = dialogBlueTooth ?: DialogBlueTooth() + println("showBluetoothDialog" + AndInfo.instance.bluetooth.bondedDevices.size) + dialogBlueTooth?.show(childFragmentManager, "BlueTooth1") + } + /** + * 显示扫描到附近设备弹窗 + */ + private fun showNearByDevicesDialog() { + // 检查权限 + if (!checkBluetoothPermissions()) { + Toast.makeText(requireContext(), "需要蓝牙权限", Toast.LENGTH_SHORT).show() + return + } + + // 检查蓝牙是否启用 + if (!AndInfo.instance.bluetooth.isEnabled) { + Toast.makeText(requireContext(), "请先开启蓝牙", Toast.LENGTH_SHORT).show() + return + } + dialogNearBlueTooth = dialogNearBlueTooth ?: DialogBlueTooth() + println("showBluetoothDialog" + AndInfo.instance.bluetooth.bondedDevices.size) + dialogNearBlueTooth?.show(childFragmentManager, "BlueTooth2") + } + + + + + /** + * 刷新蓝牙信息 + */ + private fun refreshBluetoothInfo() { + val bluetoothInfo = AndInfo.instance.bluetooth + + // 更新基本信息 +// binding.blueList.tvBluetoothStatus.text = bluetoothInfo.stateText +// binding.blueList.tvBluetoothStatus.setTextColor( +// when (bluetoothInfo.state) { +// BluetoothAdapter.STATE_ON -> ContextCompat.getColor(requireContext(), R.color.success_green) +// else -> ContextCompat.getColor(requireContext(), R.color.error_red) +// } +// ) +// +// binding.blueList.tvBluetoothAdapter.text = bluetoothInfo.adapterName ?: "未知" +// binding.blueList.tvBluetoothVersion.text = bluetoothInfo.getBluetoothVersionDetails() +// binding.blueList.tvBleSupport.text = if (bluetoothInfo.isBluetoothLeSupported) "支持" else "不支持" + + // 更新已配对设备数量 +// val pairedCount = bluetoothInfo.bondedDevices.size +// binding.blueList.tvPairedCount.text = "已配对: ${pairedCount}个设备" + } + + /** + * 打开蓝牙设置 + */ + private fun openBluetoothSettings() { + try { + val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) + startActivityForResult(intent, REQUEST_ENABLE_BT) + } catch (e: ActivityNotFoundException) { + // 尝试其他方式打开设置 + val intent = Intent(Settings.ACTION_BLUETOOTH_SETTINGS) + if (intent.resolveActivity(requireActivity().packageManager) != null) { + startActivity(intent) + } + } + } + /** + * 权限检查结果回调 + */ + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { + // 权限已授予,刷新UI + checkAndDisplayBluetoothInfo() + } else { + Toast.makeText(requireContext(), "Bluetooth permission is required.", Toast.LENGTH_SHORT).show() + } + } companion object { + private const val REQUEST_ENABLE_BT = 1001 @JvmStatic fun newInstance() = HardWareFragment().apply { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBlueTooth.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBlueTooth.kt index 29f7faf..a35e2ec 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBlueTooth.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBlueTooth.kt @@ -1,18 +1,21 @@ package com.xyzshell.myphoneinfo.dialog import android.os.Bundle +import android.os.CountDownTimer import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import android.widget.Toast import androidx.compose.material3.Text import com.xyzshell.andinfo.AndInfo import com.xyzshell.myphoneinfo.R import com.xyzshell.myphoneinfo.base.BaseDialogFragment import com.xyzshell.myphoneinfo.databinding.DialogBlueToothBinding -class DialogBlueTooth :BaseDialogFragment(DialogBlueToothBinding::inflate){ - +class DialogBlueTooth(val type:Int) :BaseDialogFragment(DialogBlueToothBinding::inflate){ + private var isScanning = false + private var scanTimer: CountDownTimer? = null override fun getTitle(): String = resources.getString(R.string.bluetooth) override fun getIconRes(): Int=5 @@ -20,50 +23,152 @@ class DialogBlueTooth :BaseDialogFragment(DialogBlueToot override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val bluetoothInfo = AndInfo.instance.bluetooth - val list=ArrayList>() - bluetoothInfo.bondedDevices.forEach { (name, address) -> - val deviceMap = mapOf( - "name" to (name ?: "Unknown device"), - "address" to (address ?: "") - ) - list.add(deviceMap) - } - val container = binding.view as? ViewGroup + val list= bluetoothInfo.getBondedDevicesInfo() - container?.let { - // 遍历 list,为每个设备创建 item view - if(list.isEmpty()){ - it.addView(TextView(requireContext()).apply { - text = "No devices" - }) - }else{ - list.forEach { deviceMap -> - // 加载 item 布局 - val itemView = LayoutInflater.from(requireContext()) - .inflate(R.layout.item_blue_tooth, it, false) +// ArrayList>() +// bluetoothInfo.bondedDevices.forEach { (name, address) -> +// val deviceMap = mapOf( +// "name" to (name ?: "Unknown device"), +// "address" to (address ?: "") +// ) +// list.add(deviceMap) +// } + if(type==0){// 显示已配对设备列表 + val container = binding.view as? ViewGroup + container?.let { + // 遍历 list,为每个设备创建 item view + if(list.isEmpty()){ + it.addView(TextView(requireContext()).apply { + text = "No devices" + }) + }else{ + list.forEach { deviceMap -> + // 加载 item 布局 + val itemView = LayoutInflater.from(requireContext()) + .inflate(R.layout.item_blue_tooth, it, false) - // 设置设备信息 - val tvName = itemView.findViewById(R.id.textTitle) - val tvAddress = itemView.findViewById(R.id.textContent) + // 设置设备信息 + val tvName = itemView.findViewById(R.id.textTitle) + val tvAddress = itemView.findViewById(R.id.textContent) - tvName.text = deviceMap["name"] - tvAddress.text = deviceMap["address"] - // 添加到容器 - it.addView(itemView) + tvName.text = deviceMap.name + tvAddress.text = deviceMap.address + // 添加到容器 + it.addView(itemView) + } } - } + } + }else{// 显示扫描设备列表 +// startScanning() } + } +// /** +// * 开始扫描设备 +// */ +// private fun startScanning() { +// if (isScanning) return +// +// val bluetoothInfo = AndInfo.instance.bluetooth +// +// // 显示扫描UI +// isScanning = true +// binding.view.visibility=View.GONE +// binding.progressbar.visibility=View.VISIBLE +// +// // 启动15秒倒计时 +// startScanTimer(scanDialog) +// +// // 开始扫描 +// try { +// // 同时扫描经典蓝牙和BLE设备 +// bluetoothInfo.scanNearbyDevices( +// onDeviceFound = { device -> +// requireActivity().runOnUiThread { +// scanDialog.addDevice(device) +// } +// }, +// onScanFinished = { +// requireActivity().runOnUiThread { +// stopScanning() +// scanDialog.scanFinished() +// } +// } +// ) +// +// // 扫描BLE设备 +// if (bluetoothInfo.isBluetoothLeSupported) { +// bluetoothInfo.scanLeDevices( +// onDeviceFound = { device -> +// requireActivity().runOnUiThread { +// scanDialog.addDevice(device) +// } +// }, +// durationMillis = SCAN_DURATION +// ) +// } +// +// } catch (e: SecurityException) { +// Toast.makeText(requireContext(), "蓝牙权限被拒绝", Toast.LENGTH_SHORT).show() +// stopScanning() +// } +// } +// +// /** +// * 启动扫描计时器 +// */ +// private fun startScanTimer(scanDialog: DialogScanDevices) { +// scanTimer = object : CountDownTimer(SCAN_DURATION, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// val secondsLeft = millisUntilFinished / 1000 +// binding.blueList.tvScanStatus.text = +// "正在扫描附近设备... ${secondsLeft}秒后结束" +// +// // 更新弹窗中的倒计时 +// scanDialog.updateTimer(secondsLeft.toInt()) +// } +// +// override fun onFinish() { +// stopScanning() +// scanDialog.scanFinished() +// } +// }.start() +// } +// +// /** +// * 停止扫描 +// */ +// private fun stopScanning() { +// if (!isScanning) return +// +// isScanning = false +// +// // 停止计时器 +// scanTimer?.cancel() +// scanTimer = null +// +// // 隐藏扫描UI +// binding.blueList.scanLayout.visibility = View.GONE +// +// // 停止蓝牙扫描 +// AndInfo.instance.bluetooth.stopScan() +// } override fun onNegativeClick() { super.onNegativeClick() +// stopScanning() } override fun onPositiveClick() { super.onPositiveClick() +// stopScanning() + } + override fun onPause() { + super.onPause() + // 停止扫描 +// stopScanning() } - } \ No newline at end of file diff --git a/myphoneinfo/src/main/res/layout/dialog_base.xml b/myphoneinfo/src/main/res/layout/dialog_base.xml index 58df52f..fee860c 100644 --- a/myphoneinfo/src/main/res/layout/dialog_base.xml +++ b/myphoneinfo/src/main/res/layout/dialog_base.xml @@ -88,7 +88,7 @@ android:padding="10dp" android:textColor="@color/white" android:text="@string/settings" - android:background="@drawable/hard_bg" + android:background="@drawable/dialog_ok_bg" android:visibility="gone" /> - - - + > + + + + + + \ No newline at end of file diff --git a/myphoneinfo/src/main/res/layout/hard_bluetooth.xml b/myphoneinfo/src/main/res/layout/hard_bluetooth.xml index 33e97a7..a389a9c 100644 --- a/myphoneinfo/src/main/res/layout/hard_bluetooth.xml +++ b/myphoneinfo/src/main/res/layout/hard_bluetooth.xml @@ -1,8 +1,9 @@ + android:layout_height="match_parent"> + + - + android:text="@string/bluetooth_support" /> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:visibility="gone" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/myphoneinfo/src/main/res/layout/hard_memory.xml b/myphoneinfo/src/main/res/layout/hard_memory.xml index f3437d3..0bd54ca 100644 --- a/myphoneinfo/src/main/res/layout/hard_memory.xml +++ b/myphoneinfo/src/main/res/layout/hard_memory.xml @@ -442,7 +442,7 @@ android:text="@string/disk_partitions" /> Exposure modes Autofocus modes Scene modes + Scanning... \ No newline at end of file