diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/base/BaseActivity.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/base/BaseActivity.kt index d40d89f..ba1d8fd 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/base/BaseActivity.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/base/BaseActivity.kt @@ -39,4 +39,13 @@ abstract class BaseActivity : AppCompatActivity() { } protected open fun initData() {} + override fun onResume() { + super.onResume() + mainViewModel.startRealTimeRefresh(this) + } + + override fun onPause() { + super.onPause() + mainViewModel.stopRealTimeRefresh() + } } \ No newline at end of file diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/BatteryFragment.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/BatteryFragment.kt index 66300d4..d3f2af5 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/BatteryFragment.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/BatteryFragment.kt @@ -5,11 +5,18 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.activityViewModels +import com.xyzshell.andinfo.AndInfo import com.xyzshell.myphoneinfo.R +import com.xyzshell.myphoneinfo.custom.RefreshManager.load +import com.xyzshell.myphoneinfo.custom.RefreshManager.stop +import com.xyzshell.myphoneinfo.custom.SetNumberOrWordUtils.setDecimal1 import com.xyzshell.myphoneinfo.databinding.FragmentBatteryBinding +import com.xyzshell.myphoneinfo.main.MainViewModel class BatteryFragment : Fragment() { private lateinit var binding: FragmentBatteryBinding + private val mainViewModel: MainViewModel by activityViewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } @@ -21,11 +28,67 @@ class BatteryFragment : Fragment() { // Inflate the layout for this fragment binding = FragmentBatteryBinding.inflate(inflater, container, false) initView() + binding.swipeRefresh.setOnRefreshListener { + load(binding.swipeRefresh) + mainViewModel.refreshBatteryInfo() + } return binding.root } - private fun initView() { + override fun onResume() { + super.onResume() + mainViewModel.refreshBatteryInfo() + } + private fun initView() { + binding.info1.textTitle.text=getString(R.string.temperature) + binding.info2.textTitle.text=getString(R.string.technology) + binding.info3.textTitle.text=getString(R.string.health) + binding.info4.textTitle.text=getString(R.string.capacity_by) + binding.info5.textTitle.text=getString(R.string.charge_count) + binding.info6.textTitle.text=getString(R.string.charging_cycle) + + mainViewModel.batteryInfo.observe(viewLifecycleOwner){batteryInfo -> + batteryInfo?.let { + stop(binding.swipeRefresh) + it.getBatteryDetails().let {item-> + val percentage = item.percentage + binding.signalStrength.text = "$percentage%" + binding.textCurrent.visibility= View.VISIBLE + binding.textPower.visibility= View.VISIBLE + binding.textRemain.visibility= View.VISIBLE + + if(item.isCharging){ + if(percentage == 100){ + binding.conText1.text = getString(R.string.full_usb)+" ${item.plugType}" + }else{ + binding.conText1.text= getString(R.string.charging_usb)+" ${item.plugType}" + } + binding.conTExt3.text=" ${item.currentNow} mA" + binding.conTExt4.text=" ${setDecimal1(item.powerUsage ?: 0.00)} W" + binding.conTExt5.text=" ${item.voltage} mV" + + }else{ + binding.conText1.text= getString(R.string.discharging) + binding.textCurrent.visibility= View.GONE + binding.textPower.visibility= View.GONE + binding.textRemain.visibility= View.GONE + } + binding.info1.textContent.text=item.temperature.toString()+"°C" + //电池类型 +// binding.info2.textTitle.text=item. + binding.info3.textContent.text=item.health + binding.info4.textContent.text="${item.capacity} mAh" + binding.info5.textContent.text="${item.chargeCounter} mAh" + binding.info6.textContent.text="${item.chargeCycles}" + + } + + + + + } + } } companion object { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/DashboardFragment.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/DashboardFragment.kt index e288b60..7460ee0 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/DashboardFragment.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/DashboardFragment.kt @@ -1,16 +1,15 @@ package com.xyzshell.myphoneinfo.dashboard -import android.Manifest import android.content.Intent import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.annotation.RequiresPermission -import androidx.core.app.ActivityCompat +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.GridLayoutManager -import com.xyzshell.andinfo.AndInfo +import com.xyzshell.andinfo.libs.BatteryDetails +import com.xyzshell.andinfo.libs.BuildInfo +import com.xyzshell.myphoneinfo.R import com.xyzshell.myphoneinfo.base.BaseFragment import com.xyzshell.myphoneinfo.databinding.FragmentDashboardBinding import com.xyzshell.myphoneinfo.dialog.DialogAppInstall @@ -20,6 +19,7 @@ import com.xyzshell.myphoneinfo.dialog.DialogMemory import com.xyzshell.myphoneinfo.dialog.DialogNetwork import com.xyzshell.myphoneinfo.dialog.DialogOperating import com.xyzshell.myphoneinfo.dialog.DialogStorage +import com.xyzshell.myphoneinfo.main.MainViewModel private const val ARG_PARAM1 = "param1" @@ -37,6 +37,9 @@ class DashboardFragment : BaseFragment() { private var dialogAppInstall: DialogAppInstall? = null private var dialogMemory: DialogMemory? = null private var dialogStorage: DialogStorage? = null + private val mainViewModel: MainViewModel by activityViewModels() + private lateinit var buildDialogInfo: BuildInfo + private lateinit var batteryDialogInfo: BatteryDetails companion object { @@ -68,11 +71,48 @@ class DashboardFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + setObserve() initCpu() initClick() + } + private fun setObserve(){ + //top + mainViewModel.deviceInfo.observe(viewLifecycleOwner) {deviceInfo -> + binding.layoutTop.phoneLogo.text=deviceInfo?.brand + binding.layoutTop.tvPhoneBrand.text=deviceInfo?.brand + } + mainViewModel.cpuInfo.observe(viewLifecycleOwner) {cpuInfo -> + binding.layoutTop.tvPhoneApiVersion.text=cpuInfo?.getProcessorName() + } + mainViewModel.buildInfo.observe(viewLifecycleOwner) {buildInfo -> + if (buildInfo != null) { + buildDialogInfo=buildInfo + } + binding.layoutTop.tvAndroidVersion.text="Android ${buildInfo?.versionRelease} (${buildInfo?.versionCodename})" + } + + //center + + mainViewModel.batteryInfo.observe(viewLifecycleOwner) {batteryInfo -> + batteryInfo?.getBatteryDetails().let{ + if (it != null) { + batteryDialogInfo=it + } + when(it?.percentage){ + in 0..25->binding.layoutCenter.iconBattery.setImageResource(R.mipmap.property_125) + in 25..50->binding.layoutCenter.iconBattery.setImageResource(R.mipmap.property_150) + in 50..75->binding.layoutCenter.iconBattery.setImageResource(R.mipmap.property_175) + in 75..100->binding.layoutCenter.iconBattery.setImageResource(R.mipmap.property_1full) + else->binding.layoutCenter.iconBattery.setImageResource(R.mipmap.property_1full) + } + binding.layoutCenter.seekbar.progress=it!!.percentage + binding.layoutCenter.percent.text=it.percentage.toString()+"%" + binding.layoutCenter.batteryContent.text="${it.temperature}°C" + } + } + } private fun initCpu() { binding.layoutCpu.run { @@ -107,7 +147,7 @@ class DashboardFragment : BaseFragment() { } binding.layoutCenter.run { relayoutBattery.setOnClickListener { - dialogBattery = dialogBattery ?: DialogBattery() + dialogBattery = dialogBattery ?: DialogBattery(batteryDialogInfo) dialogBattery?.show(parentFragmentManager, "") } relayoutNetwork.setOnClickListener { @@ -132,7 +172,7 @@ class DashboardFragment : BaseFragment() { } } binding.layoutTop.root.setOnClickListener { - dialogOperating = dialogOperating ?: DialogOperating() + dialogOperating = dialogOperating ?: DialogOperating(buildDialogInfo) dialogOperating?.show(parentFragmentManager, "") } binding.layoutBottom.run { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/HardWareFragment.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/HardWareFragment.kt index 5fa0a81..05daa07 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/HardWareFragment.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/HardWareFragment.kt @@ -36,8 +36,8 @@ import kotlin.math.roundToInt class HardWareFragment : Fragment() { private lateinit var binding: FragmentHardWareBinding - private var dialogBlueTooth: DialogBlueTooth? = null - private var dialogNearBlueTooth: DialogBlueTooth? = null +// private var dialogBlueTooth: DialogBlueTooth? = null +// private var dialogNearBlueTooth: DialogBlueTooth? = null private var dialogInput: DialogInput? = null private var dialogExtension: DialogExtension? = null private var dialogDiskPart: DialogDiskPart? = null @@ -94,7 +94,6 @@ class HardWareFragment : Fragment() { load(binding.swipeRefresh) mainViewModel.refreshHardwareInfo(requireContext()) } - return binding.root } @@ -208,10 +207,14 @@ class HardWareFragment : Fragment() { binding.memoryLayout.radius1.text = appsAndData binding.memoryLayout.radius2.text = system binding.memoryLayout.radius3.text = other - binding.memoryLayout.seekbar3.progress = - (stoUsed.substringBefore(" ").toDouble() / stoTotal.substringBefore(" ") - .toDouble() * 100).toInt() - + //appsAndData + binding.memoryLayout.seekbarr2.progress = +// (breakdown.appsAndDataSize.toDouble() / breakdown.totalSpace.toDouble() * 100).toInt() + 50 + //system + binding.memoryLayout.seekbarr1.progress = +// ((50+storageInfo.systemSize).toDouble() / breakdown.totalSpace.toDouble() * 100).toInt() +70 //internalStorage val interUsed = storageInfo.getInternalStorageBreakdown().usedSpace @@ -509,7 +512,7 @@ class HardWareFragment : Fragment() { * 显示已配对设备弹窗 */ private fun showPairedDevicesDialog() { - dialogBlueTooth = dialogBlueTooth ?: DialogBlueTooth(type = 0) + val dialogBlueTooth = DialogBlueTooth(type = 0) println("showBluetoothDialog" + AndInfo.instance.bluetooth.bondedDevices.size) dialogBlueTooth?.show(childFragmentManager, "BlueTooth1") } @@ -529,7 +532,7 @@ class HardWareFragment : Fragment() { Toast.makeText(requireContext(), "请先开启蓝牙", Toast.LENGTH_SHORT).show() return } - dialogNearBlueTooth = dialogNearBlueTooth ?: DialogBlueTooth(type = 1) + val dialogNearBlueTooth = DialogBlueTooth(type = 1) println("showBluetoothDialog" + AndInfo.instance.bluetooth.bondedDevices.size) dialogNearBlueTooth?.show(childFragmentManager, "BlueTooth2") } diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/NetworkFragment.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/NetworkFragment.kt index 61e2154..55d45f0 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/NetworkFragment.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/NetworkFragment.kt @@ -58,14 +58,17 @@ class NetworkFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initView() + binding.swipeRefresh.setOnRefreshListener { + load(binding.swipeRefresh) + mainViewModel.refreshNetworkInfo(requireContext()) + } setObservers() - - } private fun setObservers() { mainViewModel.networkStatus.observe(viewLifecycleOwner) { type -> stop(binding.swipeRefresh) + Log.d("NetworkFragment", "setObservers: $type") when (type) { NetworkInfo.NetworkType.WIFI -> { status = 1 @@ -124,7 +127,7 @@ class NetworkFragment : Fragment() { onDenied = { Toast.makeText( context, - getString(R.string.permissions_required), + getString(R.string.net_permissions_required), Toast.LENGTH_SHORT ).show() setNoConnect() @@ -179,13 +182,6 @@ class NetworkFragment : Fragment() { showLoadFragment.show(requireActivity().supportFragmentManager, tag) } } - - binding.swipeRefresh.setOnRefreshListener { - load(binding.swipeRefresh){ - Log.d("TTTTTTTT","刷新超时") - } - mainViewModel.refreshNetworkInfo(requireContext()) - } } @@ -202,7 +198,6 @@ class NetworkFragment : Fragment() { * */ private fun setMobileInfo(mobileDetails: NetworkInfo.MobileDetails) { binding.noConnect.visibility = View.GONE - binding.conText1.text = getString(R.string.mobile) binding.connectData.visibility = View.VISIBLE Log.d("TTTTTTTT", "wifi not connected") binding.networkLayout.wifiList.visibility = View.GONE @@ -257,41 +252,40 @@ class NetworkFragment : Fragment() { * 设置wifi信息 * */ private fun setWifiDetail(wifiDetails: NetworkInfo.WifiDetails) { - binding.noConnect.visibility = View.GONE - binding.conText1.text = getString(R.string.wifi) - binding.connectData.visibility = View.VISIBLE - binding.networkLayout.wifiList.visibility = View.VISIBLE - binding.networkLayout.llPubShow.visibility = View.VISIBLE - Log.d("TTTTTTTT", wifiDetails.connected.toString()) - binding.networkLayout.wifiList.visibility = View.VISIBLE - binding.networkLayout.wfText1.textContent.text = getString(R.string.connected) - wifiDetails.signalLevelPercent?.let { percent -> - binding.strengthView.setStrength(calculateSignalLevel(percent = percent)) + binding.networkLayout.wfText1.textContent.text = if(wifiDetails.connected) getString(R.string.connected) else getString(R.string.not_connected) + if(status==1){ + binding.noConnect.visibility = View.GONE + binding.connectData.visibility = View.VISIBLE + binding.networkLayout.wifiList.visibility = View.VISIBLE + binding.networkLayout.llPubShow.visibility = View.VISIBLE + binding.networkLayout.wifiList.visibility = View.VISIBLE + wifiDetails.signalLevelPercent?.let { percent -> + binding.strengthView.setStrength(calculateSignalLevel(percent = percent)) + } + + binding.conText2.text = "${wifiDetails.ssid}·${wifiDetails.linkSpeedMbps} Mbps" + binding.conTExt3.text = "${wifiDetails.signalLevelPercent}% ${wifiDetails.rssi} dBm" + + binding.networkLayout.wfText3.textContent.text = wifiDetails.bssid + binding.networkLayout.wfText4.textContent.text = wifiDetails.capabilities + binding.networkLayout.wfText5.textContent.text = "${wifiDetails.linkSpeedMbps} Mbps" + binding.networkLayout.wfText6.textContent.text = "${wifiDetails.rssi} dBm" + binding.networkLayout.wfText7.textContent.text = "${wifiDetails.frequency} MHz" + binding.networkLayout.wfText8.textContent.text = wifiDetails.channel.toString() + binding.networkLayout.wfText10.textContent.text = wifiDetails.standard.toString() + + binding.networkLayout.dhText1.textContent.text = wifiDetails.dhcpServer + binding.networkLayout.dhText2.textContent.text = + getHoursString(wifiDetails.leaseDuration ?: 0) + binding.networkLayout.dhText3.textContent.text = wifiDetails.gateway + binding.networkLayout.dhText4.textContent.text = wifiDetails.subnetMask + binding.networkLayout.dhText5.textContent.text = wifiDetails.dns1 + binding.networkLayout.dhText6.textContent.text = wifiDetails.dns2 + binding.networkLayout.dhText7.textContent.text = wifiDetails.ip + val toString = wifiDetails.ipv6.toString() + val ipv6 = toString.replace("[", "").replace("]", "") + binding.networkLayout.dhText8.textContent.text = ipv6 } - - binding.conText2.text = "${wifiDetails.ssid}·${wifiDetails.linkSpeedMbps} Mbps" - binding.conTExt3.text = "${wifiDetails.signalLevelPercent}% ${wifiDetails.rssi} dBm" - - binding.networkLayout.wfText3.textContent.text = wifiDetails.bssid - binding.networkLayout.wfText4.textContent.text = wifiDetails.capabilities - binding.networkLayout.wfText5.textContent.text = "${wifiDetails.linkSpeedMbps} Mbps" - binding.networkLayout.wfText6.textContent.text = "${wifiDetails.rssi} dBm" - binding.networkLayout.wfText7.textContent.text = "${wifiDetails.frequency} MHz" - binding.networkLayout.wfText8.textContent.text = wifiDetails.channel.toString() - binding.networkLayout.wfText10.textContent.text = wifiDetails.standard.toString() - - binding.networkLayout.dhText1.textContent.text = wifiDetails.dhcpServer - binding.networkLayout.dhText2.textContent.text = - getHoursString(wifiDetails.leaseDuration ?: 0) - binding.networkLayout.dhText3.textContent.text = wifiDetails.gateway - binding.networkLayout.dhText4.textContent.text = wifiDetails.subnetMask - binding.networkLayout.dhText5.textContent.text = wifiDetails.dns1 - binding.networkLayout.dhText6.textContent.text = wifiDetails.dns2 - binding.networkLayout.dhText7.textContent.text = wifiDetails.ip - val toString = wifiDetails.ipv6.toString() - val ipv6 = toString.replace("[", "").replace("]", "") - binding.networkLayout.dhText8.textContent.text = ipv6 - binding.networkLayout.hardCheck1.image.isSelected = wifiDetails.supportedStandards?.size == 5 binding.networkLayout.hardCheck2.image.isSelected = wifiDetails.wifiDirect == true @@ -299,7 +293,6 @@ class NetworkFragment : Fragment() { binding.networkLayout.hardCheck4.image.isSelected = wifiDetails.wifiPasspoint == true binding.networkLayout.hardCheck5.image.isSelected = wifiDetails.support5G == true binding.networkLayout.hardCheck6.image.isSelected = wifiDetails.support6G == true - } private fun calculateSignalLevel(percent: Int): Int { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/SystemShowFragment.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/SystemShowFragment.kt index b53aa6b..f6a1d70 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/SystemShowFragment.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dashboard/SystemShowFragment.kt @@ -102,7 +102,6 @@ private val mainViewModel: MainViewModel by activityViewModels() binding.textOp9.textTitle.text=getString(R.string.initial_release) // todo binding.textOp11.textTitle.text=getString(R.string.instruction_sets) - // todo binding.textOp10.textTitle.text=getString(R.string.architecture) binding.textOp12.textTitle.text=getString(R.string.treble) binding.textOp13.textTitle.text=getString(R.string.root_access) @@ -115,6 +114,7 @@ private val mainViewModel: MainViewModel by activityViewModels() binding.textOp20.textTitle.text=getString(R.string.kernel) mainViewModel.buildInfo.observe(viewLifecycleOwner) { buildInfo -> buildInfo?.let { + binding.androidName.text="Android ${buildInfo.versionRelease} (${buildInfo.versionCodename})" binding.textOp1.textContent.text=buildInfo.versionRelease binding.textOp2.textContent.text=buildInfo.versionSdkInt.toString() binding.textOp4.textContent.text=buildInfo.securityPatch @@ -152,6 +152,7 @@ mainViewModel.buildInfo.observe(viewLifecycleOwner) { buildInfo -> deviceInfo -> stop(binding.swipeRefresh) deviceInfo?.let { + binding.logoDevice.text=deviceInfo.brand binding.phoneName.text=deviceInfo.brand binding.text0.textContent.text=deviceInfo.model binding.text1.textContent.text=deviceInfo.productName diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBattery.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBattery.kt index 7972f5f..d301c41 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBattery.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogBattery.kt @@ -2,18 +2,26 @@ package com.xyzshell.myphoneinfo.dialog import android.os.Bundle import android.view.View +import com.xyzshell.andinfo.libs.BatteryDetails import com.xyzshell.myphoneinfo.R import com.xyzshell.myphoneinfo.base.BaseDialogFragment import com.xyzshell.myphoneinfo.databinding.DialogBatteryBinding -class DialogBattery :BaseDialogFragment(DialogBatteryBinding::inflate){ +class DialogBattery(val batteryInfo: BatteryDetails) :BaseDialogFragment(DialogBatteryBinding::inflate){ override fun getTitle(): String = resources.getString(R.string.battery) - override fun getIconRes(): Int? =1 + override fun getIconRes(): Int =1 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + binding.tv1BatteryLevel.setValue("${batteryInfo.percentage}%") + binding.tv2Temperature.setValue("${batteryInfo.temperature}°C") + binding.tv3Status.setValue(batteryInfo.status) + //todo +// binding.tv4Technology.setValue(batteryInfo.capacity.toString()) + binding.tv5Health.setValue(batteryInfo.health) + binding.tv6Voltage.setValue("${batteryInfo.voltage}mV") + binding.tv7Capacity.setValue("${batteryInfo.capacity}mAh") } override fun onNegativeClick() { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogOperating.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogOperating.kt index 28aa57f..05db07a 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogOperating.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/dialog/DialogOperating.kt @@ -2,18 +2,26 @@ package com.xyzshell.myphoneinfo.dialog import android.os.Bundle import android.view.View +import com.xyzshell.andinfo.libs.BuildInfo import com.xyzshell.myphoneinfo.R import com.xyzshell.myphoneinfo.base.BaseDialogFragment import com.xyzshell.myphoneinfo.databinding.DialogOperatingBinding -class DialogOperating :BaseDialogFragment(DialogOperatingBinding::inflate){ +class DialogOperating(val build: BuildInfo) :BaseDialogFragment(DialogOperatingBinding::inflate){ + override fun getTitle(): String = resources.getString(R.string.operating_system) override fun getIconRes(): Int? =7 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + binding.tv1BatteryLevel.setValue(build.versionRelease) + binding.tv2Temperature.setValue(build.securityPatch) + binding.tv3Status.setValue(build.buildDate.toString()) + binding.tv5Health.setValue(build.kernelCompleteVersion.toString()) + binding.tv6Voltage.setValue(build.kernelArchitecture.toString()) + //todo 指令集 +// binding.tv7Capacity.setValue() } override fun onNegativeClick() { diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/main/MainViewModel.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/main/MainViewModel.kt index f53c3be..6537e5c 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/main/MainViewModel.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/main/MainViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.xyzshell.andinfo.AndInfo import com.xyzshell.andinfo.libs.AppDetails +import com.xyzshell.andinfo.libs.BatteryInfo import com.xyzshell.andinfo.libs.BluetoothInfo import com.xyzshell.andinfo.libs.BuildInfo import com.xyzshell.andinfo.libs.CameraInfo @@ -24,10 +25,16 @@ import com.xyzshell.andinfo.libs.NetworkInfo import com.xyzshell.andinfo.libs.StorageInfo import com.xyzshell.myphoneinfo.custom.PermissionChecker import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.async +import kotlinx.coroutines.delay import kotlinx.coroutines.launch -class MainViewModel: ViewModel() { +class MainViewModel : ViewModel() { + // 刷新状态 + private var refreshJob: Job? = null + private var isRefreshing = MutableLiveData(false) + // 硬件相关数据 private val _cpuInfo = MutableLiveData() val cpuInfo: LiveData = _cpuInfo @@ -46,7 +53,7 @@ class MainViewModel: ViewModel() { private val _bluetoothInfo = MutableLiveData() val bluetoothInfo: LiveData = _bluetoothInfo - private val _inputInfo= MutableLiveData() + private val _inputInfo = MutableLiveData() val input: LiveData = _inputInfo // 系统相关数据 @@ -60,9 +67,16 @@ class MainViewModel: ViewModel() { private val _widevineDrmDetail = MutableLiveData() val widevineDrmDetail: LiveData = _widevineDrmDetail - //网络相关 - private val networkInfo= AndInfo.instance.network - private val _networkStatus= MutableLiveData() + // 电池状态 + private val _batteryInfo = MutableLiveData() + val batteryInfo: LiveData = _batteryInfo + + // 电池实时刷新相关 + private var lastBatteryRefreshTime = 0L + private val batteryRefreshInterval = 10000L // 10秒刷新一次电池信息 + + // 网络相关 + private val _networkStatus = MutableLiveData() val networkStatus: LiveData = _networkStatus private val _wifiDetails = MutableLiveData() val wifiDetails: LiveData = _wifiDetails @@ -73,29 +87,104 @@ class MainViewModel: ViewModel() { private val _networkPermissionGranted = MutableLiveData() val networkPermissionGranted: LiveData = _networkPermissionGranted + // 网络实时刷新相关 + private var lastNetworkRefreshTime = 0L + private var lastNetworkType: NetworkInfo.NetworkType? = null + private val networkRefreshInterval = 5000L // 5秒刷新一次网络信息 - //应用列表 - private val _installedApps= MutableLiveData>() + // 应用列表 + private val _installedApps = MutableLiveData>() val installedApps: LiveData> = _installedApps - //相机相关 + // 相机相关 private val _cameraInfo = MutableLiveData() val cameraInfo: LiveData = _cameraInfo - init{ - loadApps() + init { + loadApps() refreshSystemInfo() refreshCameraInfo() + refreshHardwareInfo(null) // 首次加载硬件信息 + refreshBatteryInfo() } - fun refreshApps() { - loadApps() - } /** - * 刷新网络信息(带权限检查) + * 启动实时刷新(只刷新电池和网络) */ - fun refreshNetworkInfo(context: Context){ - viewModelScope.launch(Dispatchers.IO){ + fun startRealTimeRefresh(context: Context) { + stopRealTimeRefresh() // 确保之前的任务被取消 + + refreshJob = viewModelScope.launch { + while (true) { + isRefreshing.value = true + + // 并行刷新电池和网络 + launch { refreshBatteryIfNeeded() } + launch { refreshNetworkIfNeeded(context) } + + delay(1000) // 每秒检查一次是否需要刷新 + isRefreshing.value = false + } + } + } + + /** + * 停止实时刷新 + */ + fun stopRealTimeRefresh() { + refreshJob?.cancel() + refreshJob = null + isRefreshing.value = false + } + + /** + * 条件刷新电池信息(防止频繁刷新) + */ + private suspend fun refreshBatteryIfNeeded() { + val currentTime = System.currentTimeMillis() + val timeSinceLastRefresh = currentTime - lastBatteryRefreshTime + + // 如果距离上次刷新时间超过间隔,则刷新 + if (timeSinceLastRefresh >= batteryRefreshInterval) { + refreshBatteryInfo() + lastBatteryRefreshTime = currentTime + } + } + + /** + * 条件刷新网络信息(防止频繁刷新) + */ + private suspend fun refreshNetworkIfNeeded(context: Context) { + val currentTime = System.currentTimeMillis() + val timeSinceLastRefresh = currentTime - lastNetworkRefreshTime + + // 如果距离上次刷新时间超过间隔,则刷新 + if (timeSinceLastRefresh >= networkRefreshInterval) { + refreshNetworkInfoOptimized(context) + lastNetworkRefreshTime = currentTime + } + } + + /** + * 优化后的电池信息刷新 + */ + fun refreshBatteryInfo() { + viewModelScope.launch(Dispatchers.IO) { + try { + val battery = AndInfo.instance.battery + _batteryInfo.postValue(battery) + } catch (e: Exception) { + e.printStackTrace() + // 可以添加错误处理,比如重试机制 + } + } + } + + /** + * 优化后的网络信息刷新(带增量更新) + */ + private fun refreshNetworkInfoOptimized(context: Context) { + viewModelScope.launch(Dispatchers.IO) { // 检查权限 val hasPermissions = PermissionChecker.getMissingPermissions(context).isEmpty() _networkPermissionGranted.postValue(hasPermissions) @@ -106,8 +195,79 @@ class MainViewModel: ViewModel() { try { // 获取网络类型 + val networkInfo = AndInfo.instance.network + val newNetworkType = networkInfo.getCurrentNetworkType() + + // 只在网络类型变化时更新状态 + if (newNetworkType != lastNetworkType) { + _networkStatus.postValue(newNetworkType) + lastNetworkType = newNetworkType + + // 网络变化时刷新详细信息 + refreshNetworkDetails(networkInfo, newNetworkType) + } else { + // 如果网络类型没变,只检查是否有权限获取详细信息 + refreshNetworkDetailsIfNeeded(networkInfo, newNetworkType) + } + } catch (e: Exception) { + e.printStackTrace() + // 可以添加重试逻辑 + } + } + } + + /** + * 刷新网络详细信息 + */ + private fun refreshNetworkDetails( + networkInfo: NetworkInfo, + networkType: NetworkInfo.NetworkType + ) { + when (networkType) { + NetworkInfo.NetworkType.WIFI -> { + _wifiDetails.postValue(networkInfo.getWifiDetails()) + // WiFi下也尝试获取移动网络信息(可能为null) + _mobileDetails.postValue(networkInfo.getMobileDetails()) + } + NetworkInfo.NetworkType.MOBILE -> { + _mobileDetails.postValue(networkInfo.getMobileDetails()) + // 移动网络下也尝试获取WiFi信息(可能为null) + _wifiDetails.postValue(networkInfo.getWifiDetails()) + } + else -> { + _wifiDetails.postValue(null) + _mobileDetails.postValue(null) + } + } + } + + /** + * 只在需要时刷新网络详细信息(避免频繁调用) + */ + private fun refreshNetworkDetailsIfNeeded( + networkInfo: NetworkInfo, + networkType: NetworkInfo.NetworkType + ) { + // 这里可以根据需要添加更复杂的逻辑 + // 例如:WiFi信号强度变化超过一定阈值时才刷新 + refreshNetworkDetails(networkInfo, networkType) + } + + /** + * 外部调用的刷新网络信息方法(保持原有接口) + */ + fun refreshNetworkInfo(context: Context) { + viewModelScope.launch(Dispatchers.IO) { + // 检查权限 + val hasPermissions = PermissionChecker.getMissingPermissions(context).isEmpty() + _networkPermissionGranted.postValue(hasPermissions) + + try { + // 获取网络类型 + val networkInfo = AndInfo.instance.network val type = networkInfo.getCurrentNetworkType() _networkStatus.postValue(type) + lastNetworkType = type // 根据网络类型获取详细信息 when (type) { @@ -124,13 +284,35 @@ class MainViewModel: ViewModel() { _mobileDetails.postValue(null) } } + + lastNetworkRefreshTime = System.currentTimeMillis() } catch (e: Exception) { e.printStackTrace() - // 处理异常 } - } } + + /** + * 刷新所有信息(手动触发) + */ + fun refreshAll(context: Context) { + viewModelScope.launch { + isRefreshing.value = true + + // 并行刷新所有信息 + launch { refreshBatteryInfo() } + launch { refreshNetworkInfo(context) } + launch { refreshHardwareInfo(context) } + launch { refreshSystemInfo() } + launch { refreshCameraInfo() } + launch { refreshApps() } + + // 等待所有刷新完成 + delay(1000) // 给足够时间完成 + isRefreshing.value = false + } + } + /** * 仅检查网络权限 */ @@ -140,69 +322,88 @@ class MainViewModel: ViewModel() { _networkPermissionGranted.postValue(hasPermissions) } } + + fun refreshApps() { + loadApps() + } + fun loadApps() { - viewModelScope.launch(Dispatchers.IO){ - val apps= AndInfo.instance.app.getInstalledApps() + viewModelScope.launch(Dispatchers.IO) { + val apps = AndInfo.instance.app.getInstalledApps() _installedApps.postValue(apps) } } /** * 硬件刷新方法 - * */ - - fun refreshHardwareInfo(context: Context){ - viewModelScope.launch(Dispatchers.IO){ + */ + fun refreshHardwareInfo(context: Context?) { + viewModelScope.launch(Dispatchers.IO) { try { - val cpu= async{AndInfo.instance.cpu} + val cpu = async { AndInfo.instance.cpu } _cpuInfo.postValue(cpu.await()) - val gpu= async{AndInfo.instance.gpu} + + val gpu = async { AndInfo.instance.gpu } _gpuInfo.postValue(gpu.await()) - val display = async{AndInfo.instance.display} + + val display = async { AndInfo.instance.display } _displayInfo.postValue(display.await()) - val storage = async{AndInfo.instance.storage} + + val storage = async { AndInfo.instance.storage } _storageInfo.postValue(storage.await()) - val mem = async{AndInfo.instance.memory} + + val mem = async { AndInfo.instance.memory } _memInfo.postValue(mem.await()) - // 检查权限 - val bluetoothInfo = AndInfo.instance.bluetooth - val inputInfo= async{AndInfo.instance.input} + + val inputInfo = async { AndInfo.instance.input } _inputInfo.postValue(inputInfo.await()) - val hasPermissions= bluetoothInfo.requiredPermissions.all { permission -> - ActivityCompat.checkSelfPermission(context, permission) == - PackageManager.PERMISSION_GRANTED - } + // 蓝牙信息需要权限检查 + if (context != null) { + val bluetoothInfo = AndInfo.instance.bluetooth + val hasPermissions = bluetoothInfo.requiredPermissions.all { permission -> + ActivityCompat.checkSelfPermission(context, permission) == + PackageManager.PERMISSION_GRANTED + } - if (!hasPermissions) { - return@launch + if (hasPermissions) { + _bluetoothInfo.postValue(bluetoothInfo) + } } - _bluetoothInfo.postValue(bluetoothInfo) - //蓝牙信息 - }catch (e: Exception){ + } catch (e: Exception) { e.printStackTrace() } } } - fun refreshSystemInfo(){ - viewModelScope.launch(Dispatchers.IO){ - val device = AndInfo.instance.device - _deviceInfo.postValue(device) - val buildInfo = AndInfo.instance.build - _buildInfo.postValue(buildInfo) - val clearkeyDrmDetail = AndInfo.instance.drm.getDrmDetail(DRMInfo.CLEARKEY_UUID) - _clearkeyDrmDetail.postValue(clearkeyDrmDetail) - val widevineDrmDetail = AndInfo.instance.drm.getDrmDetail(DRMInfo.WIDEVINE_UUID) - _widevineDrmDetail.postValue(widevineDrmDetail) + fun refreshSystemInfo() { + viewModelScope.launch(Dispatchers.IO) { + val device = async { AndInfo.instance.device } + _deviceInfo.postValue(device.await()) + + val buildInfo = async { AndInfo.instance.build } + _buildInfo.postValue(buildInfo.await()) + + val clearkeyDrmDetail = async { AndInfo.instance.drm.getDrmDetail(DRMInfo.CLEARKEY_UUID) } + _clearkeyDrmDetail.postValue(clearkeyDrmDetail.await()) + + val widevineDrmDetail = async { AndInfo.instance.drm.getDrmDetail(DRMInfo.WIDEVINE_UUID) } + _widevineDrmDetail.postValue(widevineDrmDetail.await()) } } - fun refreshCameraInfo(){ - viewModelScope.launch(Dispatchers.IO){ + fun refreshCameraInfo() { + viewModelScope.launch(Dispatchers.IO) { val cameraInfo = AndInfo.instance.camera _cameraInfo.postValue(cameraInfo) } + } + /** + * 清理资源 + */ + override fun onCleared() { + super.onCleared() + stopRealTimeRefresh() } } \ No newline at end of file diff --git a/myphoneinfo/src/main/res/drawable/progress_first_segment.xml b/myphoneinfo/src/main/res/drawable/progress_first_segment.xml new file mode 100644 index 0000000..5a5b646 --- /dev/null +++ b/myphoneinfo/src/main/res/drawable/progress_first_segment.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/myphoneinfo/src/main/res/drawable/progress_second_segment.xml b/myphoneinfo/src/main/res/drawable/progress_second_segment.xml new file mode 100644 index 0000000..6d158dc --- /dev/null +++ b/myphoneinfo/src/main/res/drawable/progress_second_segment.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/myphoneinfo/src/main/res/layout/dashboard_module_center.xml b/myphoneinfo/src/main/res/layout/dashboard_module_center.xml index 65ba191..3914793 100644 --- a/myphoneinfo/src/main/res/layout/dashboard_module_center.xml +++ b/myphoneinfo/src/main/res/layout/dashboard_module_center.xml @@ -23,12 +23,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" - android:src="@mipmap/battery_ic" /> + android:src="@mipmap/property_1full" /> + + + + + android:textSize="10sp" + android:layout_marginStart="@dimen/each_item_padding_horizontal" + /> @@ -70,10 +99,10 @@ android:layout_centerVertical="true" android:src="@mipmap/stroke_bg" /> + + + + - - @@ -36,19 +33,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="20dp" - android:text="Xiaomi Mi" - android:textSize="28sp" + android:textSize="16sp" tools:ignore="RelativeOverlap" /> - + - diff --git a/myphoneinfo/src/main/res/layout/dialog_battery.xml b/myphoneinfo/src/main/res/layout/dialog_battery.xml index 6e03330..630a623 100644 --- a/myphoneinfo/src/main/res/layout/dialog_battery.xml +++ b/myphoneinfo/src/main/res/layout/dialog_battery.xml @@ -27,8 +27,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv4_technology" - app:labelText="@string/technology" - app:valueText="@string/capacity"/> + app:labelText="@string/technology" /> - + + + + + + - + + + + + + + + + @@ -18,8 +48,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="28.01 GB used" - android:textSize="17sp" - android:textStyle="bold" /> + android:textSize="14sp" /> + android:textSize="14sp" /> + android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginTop="15dp" + android:layout_marginHorizontal="25dp" + android:orientation="horizontal"> - + - + - - + + - - - - - - - - - - + android:textSize="14sp" /> + android:textSize="14sp" /> + android:layout_marginStart="15dp"> @@ -108,6 +108,7 @@ @@ -129,7 +130,31 @@ android:text=" 0.5 W" tools:ignore="RelativeOverlap" /> + + + + + + + @@ -165,6 +190,9 @@ + diff --git a/myphoneinfo/src/main/res/layout/hard_memory.xml b/myphoneinfo/src/main/res/layout/hard_memory.xml index cb6205f..0f5baca 100644 --- a/myphoneinfo/src/main/res/layout/hard_memory.xml +++ b/myphoneinfo/src/main/res/layout/hard_memory.xml @@ -222,17 +222,38 @@ - + android:layout_height="wrap_content"> + + + + + + + @@ -308,7 +329,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="11dp" - android:text="18.77 GB" + android:text="GB" android:textColor="@color/right_color" tools:ignore="RelativeOverlap" /> @@ -345,7 +366,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="11dp" - android:text="18.77 GB" + android:text="GB" android:textColor="@color/right_color" tools:ignore="RelativeOverlap" /> diff --git a/myphoneinfo/src/main/res/mipmap-xhdpi/property_125.png b/myphoneinfo/src/main/res/mipmap-xhdpi/property_125.png new file mode 100644 index 0000000..28a1715 Binary files /dev/null and b/myphoneinfo/src/main/res/mipmap-xhdpi/property_125.png differ diff --git a/myphoneinfo/src/main/res/mipmap-xhdpi/property_150.png b/myphoneinfo/src/main/res/mipmap-xhdpi/property_150.png new file mode 100644 index 0000000..7f52be8 Binary files /dev/null and b/myphoneinfo/src/main/res/mipmap-xhdpi/property_150.png differ diff --git a/myphoneinfo/src/main/res/mipmap-xhdpi/property_175.png b/myphoneinfo/src/main/res/mipmap-xhdpi/property_175.png new file mode 100644 index 0000000..2383f8f Binary files /dev/null and b/myphoneinfo/src/main/res/mipmap-xhdpi/property_175.png differ diff --git a/myphoneinfo/src/main/res/mipmap-xhdpi/property_1full.png b/myphoneinfo/src/main/res/mipmap-xhdpi/property_1full.png new file mode 100644 index 0000000..c8014bf Binary files /dev/null and b/myphoneinfo/src/main/res/mipmap-xhdpi/property_1full.png differ diff --git a/myphoneinfo/src/main/res/values/strings.xml b/myphoneinfo/src/main/res/values/strings.xml index a718ddc..7967e43 100644 --- a/myphoneinfo/src/main/res/values/strings.xml +++ b/myphoneinfo/src/main/res/values/strings.xml @@ -294,7 +294,7 @@ Google Play Services version Toybox Java VM - current + Current AE lock WB lock White balance modes @@ -305,6 +305,7 @@ Scanning... No devices Bluetooth permission denied. + permission denied. Bluetooth is not enabled. Bluetooth LE (Low Energy) Multiple advertisement @@ -335,4 +336,11 @@ Not ready Disabled Enabled + Full + Charging + Discharging + Voltage + Capacity(reported by system) + Charge counter + Charging cycle \ No newline at end of file