完成appinfo相关接口
This commit is contained in:
parent
bca6640cc3
commit
d3de7d8907
@ -1,5 +1,10 @@
|
||||
package com.xyzshell.myphoneinfo.custom
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import kotlin.math.abs
|
||||
|
||||
object SetNumberOrWordUtils {
|
||||
@ -98,5 +103,36 @@ object SetNumberOrWordUtils {
|
||||
fun setYesOrNo(boolean: Boolean): String {
|
||||
return if (boolean) "Yes" else "No"
|
||||
}
|
||||
// Long 扩展函数:获取格式化日期字符串
|
||||
fun Long.toFormattedDate(
|
||||
pattern: String = "MMMM dd, yyyy h:mm a",
|
||||
timeZone: TimeZone = TimeZone.getDefault()
|
||||
): String {
|
||||
val sdf = SimpleDateFormat(pattern, Locale.getDefault())
|
||||
sdf.timeZone = timeZone
|
||||
return sdf.format(Date(this))
|
||||
}
|
||||
|
||||
// 获取各个时间字段的扩展函数
|
||||
fun Long.toCalendar(): Calendar {
|
||||
return Calendar.getInstance().apply {
|
||||
time = Date(this@toCalendar)
|
||||
}
|
||||
}
|
||||
|
||||
fun Long.getYear(): Int = this.toCalendar().get(Calendar.YEAR)
|
||||
fun Long.getMonth(): Int = this.toCalendar().get(Calendar.MONTH) + 1
|
||||
fun Long.getDay(): Int = this.toCalendar().get(Calendar.DAY_OF_MONTH)
|
||||
fun Long.getHour(): Int = this.toCalendar().get(Calendar.HOUR_OF_DAY)
|
||||
fun Long.getMinute(): Int = this.toCalendar().get(Calendar.MINUTE)
|
||||
fun Long.getSecond(): Int = this.toCalendar().get(Calendar.SECOND)
|
||||
fun Long.getMillisecond(): Int = this.toCalendar().get(Calendar.MILLISECOND)
|
||||
|
||||
// Long 扩展函数:获取格式化大小字符串
|
||||
fun Long.toSizeString(): String = when {
|
||||
this < 1000 -> "$this B"
|
||||
this < 1000*1000 -> "%.1f KB".format(this/1000.0)
|
||||
this < 1000*1000*1000 -> "%.1f MB".format(this/(1000.0*1000))
|
||||
else -> "%.1f GB".format(this/(1000.0*1000*1000))
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.xyzshell.andinfo.AndInfo
|
||||
import com.xyzshell.andinfo.libs.AppDetails
|
||||
@ -15,6 +16,10 @@ import com.xyzshell.myphoneinfo.databinding.FragmentAppsBinding
|
||||
import com.xyzshell.myphoneinfo.dialog.AppDialogFragment
|
||||
import com.xyzshell.myphoneinfo.dialog.BottomDialogFragment
|
||||
import com.xyzshell.myphoneinfo.main.MainScrollActivity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class AppsFragment : Fragment(),AppListAdapter.OnShowDialogListener {
|
||||
private lateinit var binding: FragmentAppsBinding
|
||||
@ -34,15 +39,25 @@ class AppsFragment : Fragment(),AppListAdapter.OnShowDialogListener {
|
||||
val adapter= AppListAdapter()
|
||||
val installedApps = AndInfo.instance.app.getInstalledApps()
|
||||
val userSize=installedApps.size
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
delay(50) // 短暂延迟确保UI完成布局
|
||||
withContext(Dispatchers.Main) {
|
||||
adapter.setList(installedApps)
|
||||
adapter.setOnclickListener(this)
|
||||
adapter.setOnclickListener(this@AppsFragment)
|
||||
}}
|
||||
binding.recyclerView.adapter = adapter
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.tvTitle.text=when(0){//todo replace with user/system/all/none
|
||||
0 -> "User($userSize)"
|
||||
1 -> "System(23)"
|
||||
2 -> "All(23)"
|
||||
else -> "None"
|
||||
}
|
||||
binding.llTitle.setOnClickListener {
|
||||
bottomDialog= BottomDialogFragment(type = "apps", sel = sel, invoke = {item->
|
||||
sel = item
|
||||
binding.tvTitle.text=when(item){
|
||||
0 -> "User$userSize"
|
||||
0 -> "User($userSize)"
|
||||
1 -> "System(23)"
|
||||
2 -> "All(23)"
|
||||
else -> "None"
|
||||
@ -66,7 +81,7 @@ class AppsFragment : Fragment(),AppListAdapter.OnShowDialogListener {
|
||||
}
|
||||
|
||||
override fun onShowAppSelectDialog(item: AppDetails) {
|
||||
dialogFragment = AppDialogFragment()
|
||||
dialogFragment = AppDialogFragment(item)
|
||||
|
||||
dialogFragment.show(requireActivity().supportFragmentManager, "AppDialogFragment")
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresPermission
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.xyzshell.andinfo.AndInfo
|
||||
import com.xyzshell.andinfo.libs.NetworkInfo
|
||||
import com.xyzshell.myphoneinfo.R
|
||||
@ -17,6 +18,10 @@ import com.xyzshell.myphoneinfo.custom.SetNumberOrWordUtils.getHoursString
|
||||
import com.xyzshell.myphoneinfo.custom.SetNumberOrWordUtils.setYesOrNo
|
||||
import com.xyzshell.myphoneinfo.databinding.FragmentNetworkBinding
|
||||
import com.xyzshell.myphoneinfo.dialog.ShowLoadFragment
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.toString
|
||||
|
||||
class NetworkFragment : Fragment() {
|
||||
@ -42,6 +47,9 @@ private lateinit var binding:FragmentNetworkBinding
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
networkInfo= AndInfo.instance.network
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
delay(50) // 短暂延迟确保UI完成布局
|
||||
withContext(Dispatchers.Main) {
|
||||
refreshStatus()
|
||||
if(PermissionChecker.getMissingPermissions(context = requireContext()).isNotEmpty()){
|
||||
PermissionChecker.requestSimple(
|
||||
@ -105,6 +113,8 @@ private lateinit var binding:FragmentNetworkBinding
|
||||
showLoadFragment.show(requireActivity().supportFragmentManager, tag)
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
private fun refreshStatus() {
|
||||
|
||||
@ -1,23 +1,39 @@
|
||||
package com.xyzshell.myphoneinfo.dialog
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.xyzshell.andinfo.libs.AppDetails
|
||||
import com.xyzshell.myphoneinfo.R
|
||||
import com.xyzshell.myphoneinfo.custom.SetNumberOrWordUtils.toFormattedDate
|
||||
import com.xyzshell.myphoneinfo.custom.SetNumberOrWordUtils.toSizeString
|
||||
import com.xyzshell.myphoneinfo.databinding.CommonCheckStyle2Binding
|
||||
import com.xyzshell.myphoneinfo.databinding.DialogAppClickBinding
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class AppDialogFragment : DialogFragment() {
|
||||
class AppDialogFragment(var appInfo:AppDetails) : DialogFragment() {
|
||||
|
||||
private var _binding: DialogAppClickBinding? = null
|
||||
private val baseBinding get() = _binding!!
|
||||
private lateinit var appDetails:AppDetails
|
||||
|
||||
|
||||
open fun onPositiveClick() {}
|
||||
open fun onPositiveClick() {
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@ -25,18 +41,74 @@ class AppDialogFragment : DialogFragment() {
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = DialogAppClickBinding.inflate(inflater, container, false)
|
||||
appDetails = appInfo
|
||||
return baseBinding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setBasicAppInfo()
|
||||
loadPermissionsAsync()
|
||||
baseBinding.textCancel.setOnClickListener {
|
||||
onPositiveClick()
|
||||
dismiss()
|
||||
}
|
||||
baseBinding.textManage.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadPermissionsAsync() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
delay(50) // 短暂延迟确保UI完成布局
|
||||
withContext(Dispatchers.Main) {
|
||||
appDetails.permissions.forEach {
|
||||
//允许
|
||||
val allowedView= LayoutInflater.from(context).inflate(R.layout.common_check_style2,baseBinding.allowedLL,false)
|
||||
val allowedBinding = CommonCheckStyle2Binding.bind(allowedView)
|
||||
//不允许
|
||||
val notAllowedView= LayoutInflater.from(context).inflate(R.layout.common_check_style1,baseBinding.notAllowedLL,false)
|
||||
val notAllowedBinding = CommonCheckStyle2Binding.bind(notAllowedView)
|
||||
//特殊
|
||||
val specialView= LayoutInflater.from(context).inflate(R.layout.common_check_style3,baseBinding.specialLL,false)
|
||||
val specialBinding = CommonCheckStyle2Binding.bind(specialView)
|
||||
when(it.status){
|
||||
"Allowed"->{
|
||||
baseBinding.allowedTv.visibility = View.VISIBLE
|
||||
allowedBinding.content.text = it.name
|
||||
baseBinding.allowedLL.addView(allowedView)
|
||||
}
|
||||
"Denied"->{
|
||||
baseBinding.notAllowedTv.visibility = View.VISIBLE
|
||||
notAllowedBinding.content.text = it.name
|
||||
baseBinding.notAllowedLL.addView(notAllowedView)
|
||||
}
|
||||
"Special Access"->{
|
||||
baseBinding.specialTv.visibility = View.VISIBLE
|
||||
specialBinding.content.text = it.name
|
||||
baseBinding.specialLL.addView(specialView)
|
||||
}
|
||||
}
|
||||
Log.d("AppDialogFragment", it.status)
|
||||
}
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
private fun setBasicAppInfo() {
|
||||
baseBinding.imageIcon.setImageDrawable(appDetails.icon as? Drawable)
|
||||
baseBinding.dialogTitle.text = appDetails.appName
|
||||
baseBinding.tv1.setValue(appDetails.packageName)
|
||||
baseBinding.tv2.setValue(appDetails.versionName.toString())
|
||||
baseBinding.tv3.setValue(appDetails.targetSdkVersion.toString())
|
||||
baseBinding.tv4.setValue(appDetails.minSdkVersion.toString())
|
||||
// todo baseBinding.tv5.setValue(appDetails.packageName)
|
||||
baseBinding.tv6.setValue(appDetails.installer.toString())
|
||||
baseBinding.tv7.setValue(appDetails.size.toSizeString())
|
||||
baseBinding.tv8.setValue(appDetails.uid.toString())
|
||||
baseBinding.tv9.setValue("${appDetails.lastUpdateTime.toFormattedDate(pattern = "MMM dd, yyyy h:mm a")}")
|
||||
|
||||
}
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.let { window ->
|
||||
@ -56,4 +128,6 @@ class AppDialogFragment : DialogFragment() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -34,7 +34,6 @@
|
||||
android:layout_alignTop="@id/tv_label"
|
||||
android:layout_marginStart="35dp"
|
||||
android:layout_toEndOf="@id/tv_label"
|
||||
android:gravity="center"
|
||||
android:textSize="15sp"
|
||||
android:textColor="#C1C5C2"
|
||||
android:text="sppppppppppppppppppppp" />
|
||||
|
||||
@ -1,18 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/dashboard_model_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 子类内容容器 -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="20dp"
|
||||
android:fillViewport="true"
|
||||
>
|
||||
<LinearLayout
|
||||
android:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="35dp"
|
||||
>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/image_icon"
|
||||
android:layout_width="66dp"
|
||||
android:layout_height="66dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginTop="20dp"
|
||||
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:round="10dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -28,17 +47,7 @@
|
||||
app:layout_constraintLeft_toRightOf="@id/image_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/image_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/image_icon"/>
|
||||
<!-- 子类内容容器 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="16dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_icon"
|
||||
|
||||
android:orientation="vertical"
|
||||
>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.xyzshell.myphoneinfo.custom.LabelValueCustomView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -70,6 +79,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/tv6"
|
||||
app:labelText="@string/installed"/>
|
||||
<com.xyzshell.myphoneinfo.custom.LabelValueCustomView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/tv9"
|
||||
app:labelText="@string/last_updated_time"/>
|
||||
<com.xyzshell.myphoneinfo.custom.LabelValueCustomView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -94,10 +108,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/permissions" />
|
||||
<LinearLayout
|
||||
android:id="@+id/allowedTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="17dp"
|
||||
@ -118,13 +134,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/common_check_style2" android:id="@+id/check2"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/notAllowedTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="17dp"
|
||||
@ -145,14 +162,15 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/common_check_style1" android:id="@+id/check1"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/specialTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="17dp"
|
||||
@ -173,19 +191,18 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/common_check_style3" android:id="@+id/check3"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llbottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/contentContainer"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
@ -219,4 +236,4 @@
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="User apps (23)"
|
||||
android:text=""
|
||||
style="@style/TextHeavy20"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
@ -10,10 +11,11 @@
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:id="@+id/view">
|
||||
<ImageView
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
app:round="10dp"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
/>
|
||||
<LinearLayout
|
||||
|
||||
@ -232,6 +232,7 @@
|
||||
<string name="minimum_sdk">Minimum SDK</string>
|
||||
<string name="installer_type">Installer type</string>
|
||||
<string name="installed">Installed</string>
|
||||
<string name="last_updated_time">Last updated time</string>
|
||||
<string name="uid">UID</string>
|
||||
<string name="permissions">Permissions</string>
|
||||
<string name="allowed"> Allowed</string>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user