安卓 流量相关功能实现记录

news2024/12/17 9:40:45

1. 静态声明权限,在AndroidManifest.xml中申明

    <uses-permission xmlns:tools="http://schemas.android.com/tools"
        android:name="android.permission.PACKAGE_USAGE_STATS"
        tools:ignore="ProtectedPermissions" />

2.判断并动态申请 [使用情况] 权限

//是否拥有权限    
private fun hasPermission(): Boolean {
        return XXPermissions.isGranted(requireContext(), Manifest.permission.PACKAGE_USAGE_STATS)
    }

//申请权限的方法
private fun startSettings() {
        val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
        if (intent.resolveActivity(requireContext().packageManager) != null) {
            requireActivity().startActivity(intent)
        } else {
            //应用无权限打开这个设置界面,一般都有
        }
    }

3.相关的Bean对象

/*
* name : 应用名称
* packageName:包名
* icon:应用图标
* dataUsage:使用的流量字节数
* openCount:打开次数
* useTime:使用时间
* packageSize:包大小
* */

data class AppBean(
    val name: String,
    val packageName: String,
    val icon: Drawable?,
    var dataUsage: Long,
    val openCount : Int,
    val useTime : Long,
    val packageSize : Long = 0L
)

/**
* indexTime : 第i周、第i天、第i月
* timeRegion 时间的区间
* data : 显示的数据 ,如:1.2GB、1.2MB
 * progress : 这个Flow占所有的流量的百分比 
* */
data class Flow(var indexTime:String,var timeRegion : String ,val data:String, var progress:Int = 0)

4.统一的工具类

自己的包名

import android.app.DatePickerDialog
import android.app.usage.NetworkStats
import android.app.usage.NetworkStatsManager
import android.app.usage.StorageStats
import android.app.usage.StorageStatsManager
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.storage.StorageManager
import android.util.Log
import com.kodami.metoru.libui.bean.AppBean
import com.kodami.metoru.libui.bean.Flow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.net.InetSocketAddress
import java.net.Socket
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlin.random.Random


object FlowUtils {

    //获取所有应用的信息(包括icon,名称,流量使用量,打开次数,使用时间,包体大小)
    fun getAllInstalledAppsInfo(context: Context, startTime: Long, endTime: Long): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(0)
        val appBeans = mutableListOf<AppBean>()

        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage = getAppDataUsage(context, packageName, startTime, endTime)
                val pakageSize = getAppPackageSize(context, packageName)
                if (dataUsage > 1024) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            geAppTodayOpenCount(context, packageName),
                            getAppUseNetworkTime(context, packageName, startTime),
                            pakageSize
                        )
                    )
                }
            }
        }
        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.dataUsage }

        return appBeans
    }

    //获取今天所有应用的信息,通过使用流量排序

    fun getAllInstalledAppsInfo(context: Context): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(0)
        val appBeans = mutableListOf<AppBean>()
        val startTime = getTodayTimeInMillis()

        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage =
                    getAppDataUsage(context, packageName, startTime, getEndTimeInMillis(startTime))
                val pakageSize = getAppPackageSize(context, packageName)

                if (dataUsage > 1024) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            geAppTodayOpenCount(context, packageName),
                            getAppUseNetworkTime(context, packageName, startTime),
                            pakageSize
                        )
                    )
                }
            }
        }

        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.dataUsage }

        return appBeans
    }

    //重载方法,默认结束结束时间是今晚0点整
    fun getAllInstalledAppsInfo(context: Context, startTime: Long): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(0)
        val appBeans = mutableListOf<AppBean>()

        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage = getAppDataUsage(
                    context, packageName, startTime,
                    getEndTimeInMillis(getTodayTimeInMillis())
                )
                if (dataUsage > 1024) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            geAppTodayOpenCount(context, packageName),
                            getAppUseNetworkTime(context, packageName, startTime)
                        )
                    )
                }
            }
        }

        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.dataUsage }

        return appBeans
    }


    //获取今天所有应用的信息,按照使用时间排序(包括icon,名称,流量使用量,打开次数,使用时间)
    fun getAllInstalledAppsInfoSortByUseTime(context: Context, startTime: Long): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(0)
        val appBeans = mutableListOf<AppBean>()
        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage =
                    getAppDataUsage(
                        context, packageName, startTime, getEndTimeInMillis(
                            getTodayTimeInMillis()
                        )
                    )
                val useTime = getAppUseNetworkTime(context, packageName, startTime)
                val pakageSize = getAppPackageSize(context, packageName)
                if (useTime > 0) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            geAppTodayOpenCount(context, packageName),
                            useTime,
                            pakageSize
                        )
                    )
                }
            }
        }

        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.useTime }

        return appBeans
    }

    //获取今天所有应用的信息,按照包体大小排序(包括icon,名称,流量使用量,打开次数,使用时间)
    fun getAllInstalledAppsInfoSortByPackageSize(context: Context, startTime: Long): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(
            PackageManager.GET_ACTIVITIES or
                    PackageManager.GET_SERVICES
        )
        val appBeans = mutableListOf<AppBean>()

        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage = getAppDataUsage(
                    context, packageName, startTime,
                    getEndTimeInMillis(getTodayTimeInMillis())
                )
                val pakageSize = getAppPackageSize(context, packageName)
                if (pakageSize > 1024) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            geAppTodayOpenCount(context, packageName),
                            getAppUseNetworkTime(context, packageName, startTime),
                            pakageSize
                        )
                    )
                }
            }
        }

        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.packageSize }

        return appBeans
    }

    //获取今天所有应用的信息,按照打开次数排序(包括icon,名称,流量使用量,打开次数,使用时间)
    fun getAllInstalledAppsInfoSortByOpenCount(context: Context, startTime: Long): List<AppBean> {
        val packageManager = context.packageManager
        val packageInfoList = packageManager.getInstalledPackages(0)
        val appBeans = mutableListOf<AppBean>()

        for (packageInfo in packageInfoList) {
            if (!isSystemApp(packageInfo)) {  //排除掉系统级应用
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val icon = packageInfo.applicationInfo.loadIcon(packageManager)
                val dataUsage = getAppDataUsage(
                    context, packageName, startTime,
                    getEndTimeInMillis(getTodayTimeInMillis())
                )
                val openCount = geAppTodayOpenCount(context, packageName)
                if (openCount > 0) {
                    appBeans.add(
                        AppBean(
                            appName,
                            packageName,
                            icon,
                            dataUsage,
                            openCount,
                            getAppUseNetworkTime(context, packageName, startTime)
                        )
                    )
                }
            }
        }

        // 按数据使用情况降序对列表进行排序
        appBeans.sortByDescending { it.openCount }

        return appBeans
    }

    //获取安装包大小
    fun getAppPackageSize(context: Context, packageName: String): Long {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return 0L
        }
        val pm = context.packageManager
        val appInfo: ApplicationInfo?
        try {
            appInfo = pm.getApplicationInfo(packageName, 0)
        } catch (e: PackageManager.NameNotFoundException) {
            Log.e("AppSizeError", "Package not found", e)
            return 0L
        }

        val statsManager = context.getSystemService(StorageStatsManager::class.java)
        val uuid: UUID = StorageManager.UUID_DEFAULT
        val pkgStats: StorageStats?

        try {
            pkgStats = statsManager.queryStatsForUid(uuid, appInfo.uid)
        } catch (e: Exception) {
            Log.e("AppSizeError", "Error getting storage stats", e)
            return 0L
        }

        val cacheSize = pkgStats.cacheBytes  //缓存大小
        val dataSize = pkgStats.dataBytes //用户数据大小
        val codeSize = pkgStats.appBytes //包体大小

        return cacheSize + dataSize + codeSize
    }

    //获取App今日打开次数
    fun geAppTodayOpenCount(context: Context, packageName: String): Int {
        val usageStatsManager =
            context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager

        val startTime = System.currentTimeMillis() - 1000 * 60 * 60 * 24 // Start time: 24 hours ago
        val endTime = System.currentTimeMillis()

        val events = usageStatsManager.queryEvents(startTime, endTime)

        var openCount = 0

        while (events.hasNextEvent()) {
            val event = UsageEvents.Event()
            events.getNextEvent(event)
            if (event.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND && event.packageName != null && event.packageName == packageName) {
                openCount++
            }
        }

        return openCount
    }


    //获取app使用流量的时间
    fun getAppUseNetworkTime(context: Context, packageName: String, startTime: Long): Long {
        val usageStatsManager =
            context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

        var totalForegroundWithNetworkTime: Long = 0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            val networkCapabilities =
                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)

            if (networkCapabilities != null && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
                val usageStatsList = usageStatsManager.queryUsageStats(
                    UsageStatsManager.INTERVAL_BEST, startTime, getEndTimeInMillis(
                        getTodayTimeInMillis()
                    )
                )
                if (usageStatsList != null) {
                    for (usageStats in usageStatsList) {
                        if (usageStats.lastTimeUsed in startTime..getEndTimeInMillis(
                                getTodayTimeInMillis()
                            ) && usageStats.packageName == packageName
                        ) {
                            totalForegroundWithNetworkTime += usageStats.totalTimeInForeground
                        }
                    }
                }
            }

            return totalForegroundWithNetworkTime
        }
        return 0L
    }

    private fun getUidOfPackage(context: Context, packageName: String): Int {
        val packageManager = context.packageManager
        val applicationInfo = packageManager.getApplicationInfo(packageName, 0)
        return applicationInfo.uid
    }


    //查询指定应用程序在指定时间段内的移动网络使用情况
    fun getAppDataUsage(
        context: Context,
        packageName: String,
        startTime: Long,
        endTime: Long
    ): Long {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            try {

                val networkStatsManager =
                    context.getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager

                val packageInfo = context.packageManager.getPackageInfo(packageName, 0)
                val uid = packageInfo.applicationInfo.uid


                val networkStats = networkStatsManager.querySummary(
                    NetworkCapabilities.TRANSPORT_CELLULAR,
                    null,
                    startTime,
                    endTime
                )

                var rxBytes: Long = 0
                var txBytes: Long = 0

                // 遍历网络使用情况数据,计算接收和发送的字节数
                val bucket = NetworkStats.Bucket()
                while (networkStats.hasNextBucket()) {
                    networkStats.getNextBucket(bucket)
                    if (bucket.uid == uid) {
                        rxBytes += bucket.rxBytes
                        txBytes += bucket.txBytes
                    }
                }


                return txBytes + rxBytes
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        return 0
    }

    //获取指定时间段内所有应用使用的流量字节数,默认结束时间时今晚0点整
    fun getAllAppDataUsage(context: Context, startTime: Long): Long {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val networkStatsManager =
                context.getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager
            val bucketMobile: NetworkStats.Bucket
            try {
                bucketMobile = networkStatsManager.querySummaryForDevice(
                    NetworkCapabilities.TRANSPORT_CELLULAR,
                    null,
                    startTime,
                    getEndTimeInMillis(System.currentTimeMillis())
                )
                return bucketMobile.txBytes + bucketMobile.rxBytes
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return -1L
    }

    //获取指定时间段内所有应用使用的流量字节数
    fun getAllAppDataUsage(context: Context, startTime: Long, endTime: Long): Long {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val networkStatsManager =
                context.getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager
            val bucketMobile: NetworkStats.Bucket
            try {
                bucketMobile = networkStatsManager.querySummaryForDevice(
                    NetworkCapabilities.TRANSPORT_CELLULAR,
                    null,
                    startTime,
                    endTime
                )
                return bucketMobile.txBytes + bucketMobile.rxBytes
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return -1L
    }

    fun getThisWeekEveryDayFlowList(context: Context): List<Flow> {
        var startTimeMillis = getThisWeekMondayTimeInMillis()
        val thisWeekEveryDayFlowList = ArrayList<Flow>()
        for (i in 0 until 7) {
            val endTimeMillis = getEndTimeInMillis(startTimeMillis, 1)
            val data = getByteFromMb(getAllAppDataUsage(context, startTimeMillis, endTimeMillis))

            val indexTime = when (i) {
                0 -> "周日"
                1 -> "周一"
                2 -> "周二"
                3 -> "周三"
                4 -> "周四"
                5 -> "周五"
                6 -> "周六"
                else -> "无效周数"
            }
            thisWeekEveryDayFlowList.add(
                Flow(
                    indexTime,
                    "${getTimeStringFromTimestamp2(startTimeMillis)}",
                    "$data MB"
                )
            )
            startTimeMillis = endTimeMillis
        }
        return thisWeekEveryDayFlowList
    }

    //获取空值的流量列表 一般用于未授权时展示
    fun getNullThisWeekUseFlowList() : List<Flow> {
        var startTimeMillis = FlowUtils.getThisWeekMondayTimeInMillis()
        val thisWeekEveryDayFlowList = ArrayList<Flow>()
        for (i in 0 until 7) {
            val endTimeMillis = FlowUtils.getEndTimeInMillis(startTimeMillis, 1)

            val indexTime = when (i) {
                0 -> "星期日"
                1 -> "星期一"
                2 -> "星期二"
                3 -> "星期三"
                4 -> "星期四"
                5 -> "星期五"
                6 -> "星期六"
                else -> "无效周数"
            }
            thisWeekEveryDayFlowList.add(Flow(indexTime, "${FlowUtils.getTimeStringFromTimestamp2(startTimeMillis)}", "- MB"))
            startTimeMillis = endTimeMillis
        }
        return thisWeekEveryDayFlowList
    }


    //获取本月每日的流量列表
    fun getThisMonthEveryDayFlowList(context: Context): List<Flow> {
        var timeInMills = getThisMonthTimeInMillis()
        val thisMonthEveryDayFlowList = ArrayList<Flow>()

        for (i in 0 until getDayOfMonth()) {
            val data = getByteFromMb(
                getAllAppDataUsage(
                    context,
                    timeInMills,
                    getEndTimeInMillis(timeInMills)
                )
            )
            thisMonthEveryDayFlowList.add(
                Flow(
                    "${i + 1}日",
                    "${getTimeStringFromTimestamp2(timeInMills)}",
                    "$data MB"
                )
            )
            timeInMills = getEndTimeInMillis(timeInMills)
        }
        return thisMonthEveryDayFlowList
    }

    //获取本月每周的流量列表
    fun getThisMonthToWeekFlowList(context: Context): ArrayList<Flow> {
        val thisMonthStertTimeInMillis = getThisMonthTimeInMillis()

        val todayEndTimeInMillis = getEndTimeInMillis(getTodayTimeInMillis())
        var thisTimeInMillis = thisMonthStertTimeInMillis

        val thisMonthEveryWeekFlowList = ArrayList<Flow>()
        var i = 1
        while (thisTimeInMillis < todayEndTimeInMillis) {
            val endTimeInMillis = getEndTimeInMillis(
                thisTimeInMillis,
                getDaysUntilNextSunday(thisTimeInMillis)
            )
            val flowNum = getByteFromGb(
                getAllAppDataUsage(
                    context,
                    thisTimeInMillis,
                    endTimeInMillis
                )
            )
            val dateTime = "${getTimeStringFromTimestamp2(thisTimeInMillis)} - ${
                getTimeStringFromTimestamp2(endTimeInMillis)
            } "
            thisMonthEveryWeekFlowList.add(Flow("第${i}周", dateTime, "$flowNum GB"))

            thisTimeInMillis = endTimeInMillis
            i++
        }
        return thisMonthEveryWeekFlowList
    }

    //获取本年每月的流量列表
    fun getThisYearEveryMonthFlowList(context: Context): List<Flow> {
        val everyMonthTimeInMillisList = getJanuaryToNextMonthStartTimeMillisList()
        val thisYearEveryMonthFlowList = ArrayList<Flow>()
        for (i in 0 until everyMonthTimeInMillisList.size - 1) {
            val data = getByteFromGb(
                getAllAppDataUsage(
                    context,
                    everyMonthTimeInMillisList[i],
                    everyMonthTimeInMillisList[i + 1]
                )
            )
            val dateTime =
                "${getTimeStringFromTimestamp2(everyMonthTimeInMillisList[i])} - ${everyMonthTimeInMillisList[i + 1]} "
            thisYearEveryMonthFlowList.add(Flow("${i + 1}月", dateTime, "$data GB"))
        }
        return thisYearEveryMonthFlowList

    }

    //设置流量列表的中每项的进度
    fun setFlowListProgress(flowList: List<Flow>): List<Flow> {
        val max = flowList.maxByOrNull { it.data.split(" ")[0].toFloat() }?.data?.toFloat() ?: 0f
        if (max > 0f) {
            flowList.forEach {
                it.progress = (it.data.split(" ")[0].toFloat() / max * 1.25 * 100).toInt()
            }
        }
        return flowList
    }

    // 获取移动数据网络的带宽
    fun getMobileDataSpeed(context: Context): Int {
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val network = connectivityManager.activeNetwork
            val capabilities = connectivityManager.getNetworkCapabilities(network)
            return capabilities?.let { capabilities.linkUpstreamBandwidthKbps + capabilities.linkDownstreamBandwidthKbps } ?: 0
        } else {
            return Random.nextInt(8192, 8192*100)
        }
    }

    //获取下载速度
    fun getUploadSpeed(context: Context): String {
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val network =connectivityManager.activeNetwork
            val capabilities = connectivityManager.getNetworkCapabilities(network)

            if (capabilities != null ){
                val speed = (capabilities.linkUpstreamBandwidthKbps / 8 / 1024).toDouble()
                if (speed > 0.0) {
                     return String.format("%.1f", Random.nextDouble(0.0, speed))
                }
            }
        }
        return String.format("%.1f", Random.nextDouble(  0.0,10.0))
    }

    //字节转MB
    fun getByteFromMb(bytes: Long): Float {
        return String.format("%.1f", bytes / (1024 * 1024f)).toFloat()
    }

    //字节转GB
    fun getByteFromGb(bytes: Long): Float {
        return String.format("%.1f", bytes / (1024 * 1024 * 1024f)).toFloat()
    }

    //判断是否为系统应用
    fun isSystemApp(packageInfo: PackageInfo): Boolean {
        return packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
    }

    //获取网络延迟
    suspend fun getNetworkLatency(): String {
        return withContext(Dispatchers.IO) {
            var latency = "--"
            try {
                val socket = Socket()
                val startTime = System.currentTimeMillis()
                socket.connect(InetSocketAddress("www.baidu.com", 80), 3000)  // 连接百度服务器
                val endTime = System.currentTimeMillis()
                latency = (endTime - startTime).toString()
                Log.d("WifiInfo", "网络延迟: $latency ms")
                socket.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            latency
        }
    }

    //获取今年从1月到本月下一个月的每月开始日凌晨0:00的时间戳链表
    fun getJanuaryToNextMonthStartTimeMillisList(): List<Long> {
        val currentMonth = Calendar.getInstance().get(Calendar.MONTH)
        val currentYear = Calendar.getInstance().get(Calendar.YEAR)
        val timestamps = mutableListOf<Long>()

        val calendar = Calendar.getInstance()
        for (month in 0..currentMonth + 1) {
            calendar.clear()
            calendar.set(currentYear, month, 1, 0, 0, 0)
            timestamps.add(calendar.timeInMillis)
        }

        return timestamps

    }


    //当前年月
    fun getCurrentYearAndMonth(): String {
        val currentTime = Calendar.getInstance()
        val year = currentTime.get(Calendar.YEAR)
        val month = currentTime.get(Calendar.MONTH) + 1 // Calendar.MONTH 从 0 开始计数,所以需要加 1
        return "$year 年 $month 月"
    }

    //获取当前年月日
    fun getCurrentYearAndMonthAndDay(): String {
        val dateFormat = SimpleDateFormat("yyyy-MM-dd")
        val currentDate = Date()
        val formattedDate = dateFormat.format(currentDate)
        return formattedDate
    }

    //获取今天的在月份的天数
    fun getDayOfMonth(): Int {
        // 创建一个 Calendar 实例
        val calendar = Calendar.getInstance()
        // 将当前时间设置到 Calendar 实例中
        calendar.time = java.util.Date()
        return calendar.get(Calendar.DAY_OF_MONTH)
    }


    //流量单位转化
    fun getProgressFormatted(bytes: Long): String {
        return if (bytes < 1024) {
            "${bytes}B"
        } else if (bytes < 1024 * 1024) {
            String.format("%.1f", bytes / 1024f) + " KB"
        } else if (bytes < 1024 * 1024 * 1024) {
            String.format("%.1f", bytes / (1024 * 1024f)) + " MB"
        } else {
            String.format("%.1f", bytes / (1024 * 1024 * 1024f)) + " GB"
        }
    }

    //毫秒转化为中文时间字符串
    fun getMillisProgressFormattedChinese(millis: Long): String {
        val seconds = millis / 1000
        return when {
            seconds < 1 -> "${millis}毫秒"
            seconds < 60 -> "${seconds}秒"
            seconds < 3600 -> {
                val minutes = seconds / 60
                val remainingSeconds = seconds % 60
                "${minutes}分${remainingSeconds}秒"
            }

            else -> {
                val hours = seconds / 3600
                val remainingMinutes = (seconds % 3600) / 60
                "${hours}小时${remainingMinutes}分钟"
            }
        }
    }

    //毫秒单位转化
    fun getMillisProgressFormatted(millis: Long): String {
        val seconds = millis / 1000
        return when {
            seconds < 1 -> "${millis}ms"
            seconds < 60 -> "${seconds}s"
            seconds < 3600 -> {
                val minutes = seconds / 60
                val remainingSeconds = seconds % 60
                "${minutes}min${remainingSeconds}s"
            }

            else -> {
                val hours = seconds / 3600
                val remainingMinutes = (seconds % 3600) / 60
                val remainingSeconds = seconds % 60
                "${hours}h${remainingMinutes}min${remainingSeconds}s"
            }
        }
    }

    //获取本月总天数
    fun getThisMonthAllDayNum(): Int {
        val calendar = Calendar.getInstance()
        val year = calendar[Calendar.YEAR]
        val month = calendar[Calendar.MONTH]
        calendar[year, month] = 1 // 设置为本月的第一天
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
    }

    //获取今天的星期数
    fun getDayOfWeek(): Int {
        // 创建一个 Calendar 实例
        val calendar = Calendar.getInstance()

        // 将当前时间设置到 Calendar 实例中
        calendar.time = java.util.Date()

        // 获取今天的星期数,星期日为 1,星期一为 2,以此类推
        return calendar.get(Calendar.DAY_OF_WEEK)
    }

    //获取传入时间戳的星期数
    fun getDayOfWeek(timestamp: Long): String {
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = timestamp
        val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
        val days =
            arrayOf("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
        return days[dayOfWeek - 1]
    }


    //获取本周开始日(周日)凌晨的时间戳
    fun getThisWeekMondayTimeInMillis(): Long {

        val calendar = Calendar.getInstance()

        calendar.firstDayOfWeek = Calendar.SUNDAY
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY)
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)

        // 返回时间戳
        return calendar.timeInMillis
    }

    //获取传入时间戳距离下周开始日(周末)的天数
    fun getDaysUntilNextSunday(timestamp: Long): Int {
        val calendar = Calendar.getInstance().apply {
            timeInMillis = timestamp
        }
        val currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
        val daysUntilNextSunday = 8 - currentDayOfWeek // 计算距离下一周开始日(星期日)的天数
        return daysUntilNextSunday
    }

    //获取本月开始日凌晨的时间戳
    fun getThisMonthTimeInMillis(): Long {
        val cal = Calendar.getInstance()
        cal[cal[Calendar.YEAR], cal[Calendar.MONTH], cal[Calendar.DAY_OF_MONTH], 0, 0] =
            0
        cal[Calendar.DAY_OF_MONTH] = cal.getActualMinimum(Calendar.DAY_OF_MONTH)
        return cal.timeInMillis
    }


    //获取今天凌晨的时间戳
    fun getTodayTimeInMillis(): Long {
        val calendar = Calendar.getInstance()
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        return calendar.timeInMillis
    }

    //获取传入时间下一天凌晨的时间戳
    fun getEndTimeInMillis(startTime: Long): Long {
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = startTime
        calendar.add(Calendar.DAY_OF_MONTH, 1) // 加一天
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        return calendar.timeInMillis
    }

    //获取传入时间几天前/后凌晨的时间戳
    fun getEndTimeInMillis(startTime: Long, i: Int): Long {
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = startTime
        calendar.add(Calendar.DAY_OF_MONTH, i) // 增加/减少i天
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        return calendar.timeInMillis
    }

    //获取几天前凌晨的时间戳
    fun getStartTimeInMillis(i: Int): Long {
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = System.currentTimeMillis()
        calendar.add(Calendar.DAY_OF_YEAR, i) // 增加/减少i天
        calendar.set(Calendar.HOUR_OF_DAY, 0) // 设置小时为零
        calendar.set(Calendar.MINUTE, 0) // 设置分钟为零
        calendar.set(Calendar.SECOND, 0) // 设置秒数为零
        calendar.set(Calendar.MILLISECOND, 0) // 设置毫秒为零
        return calendar.timeInMillis
    }

    //获取现在的时间
    fun getCurrentTime(): String {
        val currentTime = Calendar.getInstance().time
        val dateFormat = SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault())
        return dateFormat.format(currentTime)
    }

    //获取日期的时间戳
    fun getTimestampAtMidnight(year: Int, month: Int, dayOfMonth: Int): Long {
        val calendar = Calendar.getInstance(TimeZone.getDefault())
        calendar.set(Calendar.YEAR, year)
        calendar.set(Calendar.MONTH, month - 1) // 注意:Java Calendar月份是从0开始的
        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)

        return calendar.timeInMillis
    }

    //通过时间戳获取时间
    fun getTimeStringFromTimestamp(timestamp: Long): String {
        val sdf = SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }

    fun getTimeStringFromTimestamYMD(timestamp: Long): String {
        val sdf = SimpleDateFormat("yyyy/MM/dd", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }

    fun getTimeStringFromTimestampD(timestamp: Long): String {
        val sdf = SimpleDateFormat("d", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }

    fun getTimeStringFromTimestamp2(timestamp: Long): String {
        val sdf = SimpleDateFormat("MM.dd", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }
    fun getTimeStringFromTimestampMDD(timestamp: Long): String {
        val sdf = SimpleDateFormat("M.dd", Locale.getDefault())
        return sdf.format(Date(timestamp))
    }

    //计算两个时间戳相差的天数
    fun daysBetweenTimestamps(startTimestamp: Long, endTimestamp: Long): Long {
        // 创建 Calendar 实例
        val calendarStart = Calendar.getInstance()
        val calendarEnd = Calendar.getInstance()

        // 设置 Calendar 对象的时间为指定的时间戳
        calendarStart.timeInMillis = startTimestamp
        calendarEnd.timeInMillis = endTimestamp

        // 计算两个时间戳之间的差值(毫秒)
        val diffInMillis = calendarEnd.timeInMillis - calendarStart.timeInMillis

        return Math.abs(TimeUnit.MILLISECONDS.toDays(diffInMillis))
    }

    //显示选择日期的日历dialog
    fun showDatePickerDialog(context: Context, calendar: Calendar = Calendar.getInstance(), onDateSet: (year: Int, month: Int, day: Int) -> Unit ) {
        DatePickerDialog(
            context,
            { _, year, monthOfYear, dayOfMonth ->
                onDateSet(year, monthOfYear + 1, dayOfMonth)
            },
            calendar.get(Calendar.YEAR),
            calendar.get(Calendar.MONTH),
            calendar.get(Calendar.DAY_OF_MONTH)
        ).show()
    }

}

5. 其他

5.1导入后面需要的包

   //协程
   api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
   api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
   api "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
   api "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
   api "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"

   //retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'

5.2获取IP相关信息和下载速度的接口

5.2.1  接口服务类

interface RetrofitService {

    @Streaming
    @GET
    fun downloadFile(@Url fileUrl: String): Call<ResponseBody>
    @GET("jsonp")
    fun getGeoLocation( @Query("ip")  ip : String?): Call<ResponseBody>
    @GET("jsonp")
    fun getGeoLocation(): Call<ResponseBody>
}

 5.2.3 ip的Bean

data class IpInfo(
    val country: String?,
    val shortName: String?,
    val province: String?,
    val city: String?,
    val area: String?,
    val isp: String?,
    val net: String?,
    val ip: String?,
    val code: Int?,
    val desc: String?
){
    constructor() : this("--","--","--","--","--","--","--","--",0,"--")

}

 5.2.3 实现类

package 你的包名

import android.content.Context
import android.os.Environment
import android.util.Log
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.io.FileOutputStream

class RetrofitImpl {
    //获取下载速度
    suspend fun getDownloadSpeed(context: Context): String {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://dldir1.qq.com/")
            .build()

        val service = retrofit.create(RetrofitService::class.java)

        return withContext(Dispatchers.IO) {
            val call =
                service.downloadFile("qqfile/qq/QQNT/Windows/QQ_9.9.7_240305_x86_01.exe").execute()
            if (call.isSuccessful) {
                val body = call.body()
                if (body != null) {
                    val startTime = System.currentTimeMillis()

                    val inputStream = body.byteStream()
                    val file =
                        File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "qq.apk")
                    val fileOutputStream = FileOutputStream(file)
                    val buffer = ByteArray(4096)
                    var bytesRead: Int
                    var totalBytesRead = 0

                    while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                        fileOutputStream.write(buffer, 0, bytesRead)
                        totalBytesRead += bytesRead

                        val currentTime = System.currentTimeMillis()
                        if (currentTime - startTime >= 1000) {
                            val totalTime = currentTime - startTime
                            val speedBytesPerSecond = totalBytesRead.toFloat() / totalTime * 1000
                            val speedMegaBytesPerSecond =
                                String.format("%.1f", speedBytesPerSecond / (1024 * 1024))

                            Log.d("RetrofitImpl", "Download speed: ${speedMegaBytesPerSecond} MB/s")

                            fileOutputStream.close()
                            inputStream.close()

                            return@withContext speedMegaBytesPerSecond
                        }
                    }

                    // 如果在一秒内下载未完成,则直接关闭流
                    fileOutputStream.close()
                    inputStream.close()
                }
            }
            return@withContext "-- Mb/s"
        }
    }

    //查询公网Ip对于的信息 包括所属省份、城市、运营商、网络类型等
    suspend fun getGeoLocation(ipAddress: String?): IpInfo {

        val BASE_URL = "https://ip.useragentinfo.com/"
        val httpClient = OkHttpClient.Builder().build()

        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(httpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val service = retrofit.create(RetrofitService::class.java)

        return withContext(Dispatchers.IO) {

            val response = if (ipAddress == null) {
                service.getGeoLocation().execute()  //查询本客户端
            }else{
                service.getGeoLocation(ipAddress).execute()
            }

            if (response.isSuccessful) {
                val responsedata = response.body()?.string()
                val data = Gson().fromJson(responsedata.toString().substring(9, responsedata!!.length - 2), IpInfo::class.java)

                Log.d("RetrofitImpl","获取公网Ip信息"+data.toString())

                return@withContext data
            }
            return@withContext IpInfo()
        }
    }
}

6.示例

fun getAndUpdateData() {
        
        CoroutineScope(Dispatchers.IO).launch {

            //下载速度
            val  downloadSpeed = RetrofitImpl().getDownloadSpeed(context)
            //网络延迟
            val networLatency = FlowUtils.getNetworkLatency()
            //网络带宽
            val mobileData = FlowUtils.getMobileDataSpeed(context)
            

            //今日使用的总流量数
            todayUseFlow = FlowUtils.getByteFromMb(
                FlowUtils.getAllAppDataUsage(
                    requireContext(),
                    FlowUtils.getTodayTimeInMillis()
                )
            )
            //本月使用的总流量数
            thisMonthUseFlow = FlowUtils.getByteFromGb(
                FlowUtils.getAllAppDataUsage(
                    requireContext(),
                    FlowUtils.getThisMonthTimeInMillis()
                )
            )
            //本周使用的总流量数
            thisWeekUseFlow = FlowUtils.getByteFromGb(
                FlowUtils.getAllAppDataUsage(
                    requireContext(),
                    FlowUtils.getThisWeekMondayTimeInMillis()
                )
            )
            //今日流量使用情况的appBean列表
            val todayApps = FlowUtils.getAllInstalledAppsInfo(
                requireContext(),
                FlowUtils.getTodayTimeInMillis()
            )
            //本周流量使用情况的appBean列表
            val thisWeekApps = FlowUtils.getAllInstalledAppsInfo(
                requireContext(),
                FlowUtils.getThisWeekMondayTimeInMillis()
            )
            //本月流量使用情况的appBean列表
            val thisMonthApps = FlowUtils.getAllInstalledAppsInfo(
                requireContext(),
                FlowUtils.getThisMonthTimeInMillis()
            )

            withContext(Dispatchers.Main) {

                //展示和处理相关数据

            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2260984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KeyFormer:使用注意力分数压缩KV缓存

Keyformer: KV Cache Reduction through Key Tokens Selection for Efficient Generative Inference 202403&#xff0c;发表在Mlsys Introduction 优化KV cache的策略&#xff0c;主要是集中在系统级别的优化上&#xff0c;比如FlashAttention、PagedAttention&#xff0c;它…

3.9 网际控制报文协议ICMP

欢迎大家订阅【计算机网络】学习专栏&#xff0c;开启你的计算机网络学习之旅&#xff01; 文章目录 前言1 ICMP报文的封装2 ICMP差错报告报文的类型3 不应发送ICMP差错报告报文的情况4 常用的ICMP询问报文类型5 ICMP的应用 前言 网际控制报文协议&#xff08;ICMP&#xff09…

东北大学《2024年839自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《东北大学839自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题

百度智能云千帆AppBuilder升级,百度AI搜索组件上线,RAG支持无限容量向量存储!

百度智能云千帆 AppBuilder 发版升级&#xff01; 进一步降低开发门槛&#xff0c;落地大模型到应用的最后一公里。在千帆 AppBuilder 最新升级的 V1.1版本中&#xff0c;企业级 RAG 和 Agent 能力再度提升&#xff0c;同时组件生态与应用集成分发更加优化。 • 企业级 RAG&am…

就业相关(硕士)

一、嵌入式 1.机器人行业 1.1 大致情况 要做机器人行业&#xff0c;主要技术栈是运动控制、深度学习、强化学习、具身智能等&#xff0c;主要求职方向有运动控制算法工程师和机器人算法工程师等等。大致薪资在30w到50w不等&#xff0c;主要看方向&#xff08;双211&#xff…

Selenium操作指南

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 大家好&#xff0c;今天带大家一起系统的学习下模拟浏览器运行库Selenium&#xff0c;它是一个用于Web自动化测试及爬虫应用的重要工具。 Selenium测试直接运行在…

OpenCV相机标定与3D重建(11)用于在图像上绘制世界坐标系的三条轴函数drawFrameAxes()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从姿态估计绘制世界/物体坐标系的轴。 cv::drawFrameAxes 是 OpenCV 库中的一个函数&#xff0c;用于在图像上绘制世界坐标系的三条轴&#xff0…

spring学习(XML中定义与配置bean(超详细)。IoC与DI入门spring案例)

目录 一、配置文件(XML)中定义与配置bean。 &#xff08;1&#xff09;bean的基础配置。&#xff08;id、class&#xff09; &#xff08;2&#xff09;bean的别名配置。 1、基本介绍。 2、demo测试。 3、NoSuchBeanDefinitionException&#xff01; &#xff08;3&#xff09;…

Docker容器编排与Docker Compose

1. Docker Compose介绍与基础概念 Docker Compose是一个用于定义和运行多容器Docker应用的工具。通过Compose&#xff0c;用户可以用YAML文件来定义多个容器的服务、网络、存储等配置&#xff0c;并通过一个命令来启动、停止和管理这些容器。它简化了多容器应用的管理&#xf…

鸿蒙项目云捐助第七讲鸿蒙App应用的首页推荐模块布局的实现

鸿蒙项目云捐助第七讲鸿蒙App应用的首页推荐模块布局的实现 最后设置首页的推荐模块&#xff0c;参考模板如下图所示。 一、首页热门推荐模块的实现 对于热门推荐模块&#xff0c;先有上面的小标题栏&#xff0c;这里的标题栏也有一个小图标&#xff0c;首先从“百度图库”中…

MySQL八股-MVCC入门

文章目录 当前读&#xff08;加锁&#xff09;快照读&#xff08;不加锁&#xff09;MVCC隐藏字段undo-log版本链A. 第一步B.第二步C. 第三步 readview MVCC原理分析RCA. 先来看第一次快照读具体的读取过程&#xff1a;B. 再来看第二次快照读具体的读取过程: RR隔离级别 当前读…

基于单片机的无绳跳绳设计

基于单片机设计了一款无绳跳绳&#xff0c;采用传感器代替了绳子的摆动&#xff0c;从而实现了模拟跳绳的功能。其研究的方法是&#xff1a;以单片机作为这次设计的核心&#xff0c;它的外围包含有传感器模块、按键模块、显示模块、语音播报模块及电源模块等。本设计采用STM32芯…

【图像处理】利用numpy实现直方图均衡、自适应直方图均衡、对比度受限自适应直方图均衡

直方图均衡化是一种在图像处理技术&#xff0c;通过调整图像的直方图来增强图像的对比度。 本博客不利用opencv库&#xff0c;仅利用numpy、matplotlib来实现直方图均衡、自适应直方图均衡、对比度受限自适应直方图均衡 直方图均衡 包括四个流程 计算图像RGB三通道的归一化直…

Azure Function流式返回

最近用azure function做了一个api和llm交互&#xff0c;需要流式返回。但是默认不支持流返回&#xff0c;搜索了一下。记录。 官方文档&#xff1a;https://techcommunity.microsoft.com/blog/azurecompute/azure-functions-support-for-http-streams-in-python-is-now-in-prev…

【软件工程】简答题系列(一)(山东大学·软院考试专属)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

WebGIS城市停水及影响范围可视化实践

目录 前言 一、相关信息介绍 1、停水信息的来源 2、停水包含的相关信息 二、功能简介 1、基础小区的整理 2、停水计划的管理 三、WebGIS空间可视化 1、使用到的组件 2、停水计划的展示 3、影响小区的展示 4、实际效果 四、总结 前言 城市停水&#xff0c;一个看似…

数据结构,链表的简单使用

任意位置删除&#xff1a; void Any_Del(LinkListPtr h,int a)//任意删 {if(NULLh||a>h->len){printf("删除失败");}LinkListPtr ph;for(int i0;i<a-1;i){pp->next;}LinkListPtr p2p;p2p2->next;p->nextp->next->next;free(p2);p2NULL;h-&g…

组织空转数据(人类+小鼠)

空间转录组&#xff08;Spatial Transcriptomics&#xff09;是一种新兴的高通量基因组学技术&#xff0c;它允许我们在组织切片中同时获取基因表达信息和细胞的空间位置信息。其可以帮助我们更好地理解细胞在组织中的空间分布和相互作用&#xff0c;揭示组织发育、器官功能和疾…

人工智能增强的音频和聊天协作服务

论文标题&#xff1a;AI-enabled Audio and Chat Collaboration Services 中文标题&#xff1a;人工智能增强的音频和聊天协作服务 作者信息&#xff1a; Emil P. Andersen, Norwegian Defence Research Establishment (FFI), Kjeller, NorwayJesper R. Goksr, Sindre E. Ha…

【操作系统1】一篇文章便可入门操作系统

操作系统 (Operating System,OS)是一种系统软件&#xff0c;它负责管理计算机的硬件和软件资源。它的主要任务是组织和调度计算机的工作&#xff0c;并分配资源给用户和其他软件。操作系统为用户和软件提供了方便的接口和环境。它是计算机系统中最基本的软件之一。 一、操作系…