Android App 设置系统时间,语言和时区、系统重启_android断电重启后设置系统时间的类在哪-程序员宅基地

技术标签: 语言切换  android  系统设置  Android utils  

说明

以下功能的实现是在有系统签名和设置了 android:sharedUserId=“android.uid.system” 的情况下实现的。如果你的应用没有系统签名,可能无法实现以下功能。

1. 修改系统时间

设置系统时间,首先需要保证app的uid为system,关于如何设置uid,可以看看这篇 App设置系统签名

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.xxx.xxx"
  android:sharedUserId="android.uid.system">

并给予相应的权限:

    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
    <uses-permission android:name="android.permission.SET_TIME_ZONE" />

设置系统时间,主要是通过 Calendar 进行日期的设定,通过 Calendar.getTimeInMillis() 获取毫秒数,再通过 SystemClock.setCurrentTimeMillis() 来进行设置。

1. 设置系统时间(仅设置xx:xx)

 /** 设置系统时间*/
    @Throws(IOException::class)
    fun setTime(hour: Int, minute: Int) {
    
        val calendar = Calendar.getInstance()
        calendar.set(Calendar.HOUR_OF_DAY, hour)
        calendar.set(Calendar.MINUTE, minute)
        val timeMills: Long = calendar.timeInMillis
        SystemClock.setCurrentTimeMillis(timeMills)
    }

2. 设置系统日期(仅设置到xxxx年xx月xx日)

/** 设置系统日期*/
    @Throws(IOException::class)
    fun setDate(year: Int, month: Int, day: Int) {
    
        val calendar = Calendar.getInstance()
        calendar.set(Calendar.YEAR, year)
        calendar.set(Calendar.MONTH, month)
        calendar.set(Calendar.DAY_OF_MONTH, day)
        val timeMills: Long = calendar.timeInMillis
        SystemClock.setCurrentTimeMillis(timeMills)
    }

3.设置系统是否自动获取时间


    /**
     * 设置系统是否自动获取时间
     * @param context Activity's context.
     * @param checked If checked > 0, it will auto set date.
     */
    fun setAutoDateTime(context: Context, checked: Int) {
    
        Settings.Global.putInt(
            context.contentResolver,
            Settings.Global.AUTO_TIME, checked
        )
    }
4.判断系统是否自动获取时间

    /**
     * 判断系统是否自动获取时间
     * @param context Activity's context.
     * @return If date is auto setting.
     */
    fun checkDateAutoSet(context: Context): Boolean {
    
        return try {
    
            Settings.Global.getInt(
                context.contentResolver,
                Settings.Global.AUTO_TIME
            ) > 0
        } catch (exception: SettingNotFoundException) {
    
            exception.printStackTrace()
            false
        }
    }

2. 修改系统时区

系统是通过 AlarmManager 来修改 TimeZone 的。也需要权限:

  <uses-permission android:name="android.permission.SET_TIME_ZONE" />

1. 设置系统时区

/** 设置系统时区*/
    fun setTimeZone(context: Context, timeZone: String?) {
    
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.setTimeZone(timeZone)
    }

2. 设置系统是否自动获取时区

/**
     * 设置系统是否自动获取时区
     * @param context Activity's context.
     * @param checked If checked > 0, it will auto set timezone.
     */
    fun setAutoTimeZone(context: Context, checked: Int) {
    
        Settings.Global.putInt(
            context.contentResolver,
            Settings.Global.AUTO_TIME_ZONE, checked
        )
    }

3. 判断系统是否自动获取时区

 /**
     * 判断系统是否自动获取时区
     * @param context Activity's context.
     * @return If timezone is auto setting.
     */
    fun checkTimeZoneAutoSet(context: Context): Boolean {
    
        return try {
    
            Settings.Global.getInt(
                context.contentResolver,
                Settings.Global.AUTO_TIME_ZONE
            ) > 0
        } catch (exception: SettingNotFoundException) {
    
            exception.printStackTrace()
            false
        }
    }

3. 修改系统语言

我们要实现在 APP 内修改系统语言,并且系统语言更改后,APP 的语言会随之改变,且无需重启 APP。OK,要实现这个功能,我用的是 Java 反射。通过查资料,发现 6.0 以前和 6.0 以后的反射代码会略有不同,下面的代码对切换系统语言做了一个简单的封装,可以实现在 APP 内修改系统语言,即使系统重启也会生效。

package com.xzy.syssettings.utils

import android.app.Activity
import android.app.backup.BackupManager
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import android.os.LocaleList
import android.widget.Toast
import com.xzy.syssettings.MainActivity2
import com.xzy.syssettings.language.LanguageUtil
import com.xzy.syssettings.language.Sp
import java.lang.Exception
import java.lang.reflect.Method
import java.util.Locale

/**
 *
 * @author :created by xzy.
 * @date :2021/10/28
 */
object LanguageUtil {
    
    /**
     * 这个方法不需要系统签名
     * 经过测试:android 8.0 以下的版本需要更新 configuration 和 resources,
     * android 8.0 以上只需要将当前的语言环境写入 Sp 文件即可。
     * 测试机型 android4.4、android6.0、android7.0、android7.1、android8.1
     * 然后,重新创建当前页面。
     * @param language
     */
    fun changeAppLanguage(language: String?, activity: Activity) {
    
        // 版本低于 android 8.0 不执行该方法
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    
            // 注意,这里的 context 不能传 Application 的 context
            LanguageUtil.changeAppLanguage(activity, language!!)
        }
        Sp.put("language", language!!)
        // 不同的版本,使用不同的重启方式,达到最好的效果
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
    
            // 6.0 以及以下版本,使用这种方式,并给 activity 添加启动动画效果,可以规避黑屏和闪烁问题
            val intent = Intent(activity, MainActivity2::class.java)
            // intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
            activity.startActivity(intent)
            activity.finish()
        } else {
    
            // 6.0 以上系统直接调用重新创建函数,可以达到无缝切换的效果
            activity.recreate()
        }
    }

    /**
     * 这个方法需要系统签名
     * */
    fun changeSystemLanguage(locale: Locale?, context: Context) {
    
        if (locale != null) {
    
            try {
    
                val classActivityManagerNative = Class.forName("android.app.ActivityManagerNative")
                val getDefault: Method = classActivityManagerNative.getDeclaredMethod("getDefault")
                val objIActivityManager: Any = getDefault.invoke(classActivityManagerNative)

                val classIActivityManager = Class.forName("android.app.IActivityManager")
                val getConfiguration: Method =
                    classIActivityManager.getDeclaredMethod("getConfiguration")
                val config: Configuration =
                    getConfiguration.invoke(objIActivityManager) as Configuration
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    
                    config.locales = LocaleList(locale)
                } else {
    
                    config.setLocale(locale)
                }
                val clzConfig = Class
                    .forName("android.content.res.Configuration")
                val userSetLocale = clzConfig
                    .getField("userSetLocale")
                userSetLocale[config] = true
                val clzParams = arrayOf<Class<*>>(
                    Configuration::class.java
                )
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
                    // 该代码决定是否修改系统语言设置(需要有系统签名和sharedUserId)
                    val updatePersistentConfiguration: Method =
                        classIActivityManager.getDeclaredMethod(
                            "updatePersistentConfiguration",
                            *clzParams
                        )
                    updatePersistentConfiguration.invoke(objIActivityManager, config)
                    BackupManager.dataChanged("com.android.providers.settings")
                } else {
    
                    // updateConfiguration
                    val configuration = context.resources.configuration
                    // 获取想要切换的语言类型
                    configuration.setLocale(locale)
                    // updateConfiguration
                    val dm = context.resources.displayMetrics
                    context.resources.updateConfiguration(configuration, dm)
                    // 下面的代码决定是否修改系统语言设置(需要有系统签名和sharedUserId)
                    val updateConfiguration: Method =
                        classIActivityManager.getDeclaredMethod(
                            "updateConfiguration",
                            *clzParams
                        )
                    updateConfiguration.invoke(objIActivityManager, config)
                    BackupManager.dataChanged("com.android.providers.settings")
                }

                Toast.makeText(
                    context,
                    "language:" + locale.language + "--country:" + locale.country,
                    Toast.LENGTH_SHORT
                ).show()
            } catch (exception: Exception) {
    
                exception.printStackTrace()
            }
        }
    }
}

如果只需要修改 APP 语言,则只需要调用 changeAppLanguage(LanguageType.ENGLISH.language, this) 即可。
如果同时需要修改系统语言,调用方式为:

 changeSystemLanguage(Locale.ENGLISH, this)
 changeAppLanguage(LanguageType.ENGLISH.language, this)

4. 系统重启

由于 App 有系统签名,所以实现系统重启功能比较简单。其中的一种方式是使用 PowerManager 实现。代码如下:

  // 重新启动到 fastboot模式
  val pManager = getSystemService(Context.POWER_SERVICE) as PowerManager
  pManager.reboot("")

5. 源码

以上功能的实现源码点击这里:源码

6. 参考

  1. Android App设置系统时间,语言和时区
  2. Android 切换系统语言功能实现(下)
  3. android获取地区,Android获取语言及地区总结
  4. android多国语言的国家代码
  5. Android6.0和7.0应用层更改系统语言(反射)
  6. 常用时区
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jdfkldjlkjdl/article/details/121020649

智能推荐

React学习记录-程序员宅基地

文章浏览阅读936次,点赞22次,收藏26次。React核心基础

Linux查磁盘大小命令,linux系统查看磁盘空间的命令是什么-程序员宅基地

文章浏览阅读2k次。linux系统查看磁盘空间的命令是【df -hl】,该命令可以查看磁盘剩余空间大小。如果要查看每个根路径的分区大小,可以使用【df -h】命令。df命令以磁盘分区为单位查看文件系统。本文操作环境:red hat enterprise linux 6.1系统、thinkpad t480电脑。(学习视频分享:linux视频教程)Linux 查看磁盘空间可以使用 df 和 du 命令。df命令df 以磁..._df -hl

Office & delphi_range[char(96 + acolumn) + inttostr(65536)].end[xl-程序员宅基地

文章浏览阅读923次。uses ComObj;var ExcelApp: OleVariant;implementationprocedure TForm1.Button1Click(Sender: TObject);const // SheetType xlChart = -4109; xlWorksheet = -4167; // WBATemplate xlWBATWorksheet = -4167_range[char(96 + acolumn) + inttostr(65536)].end[xlup]

若依 quartz 定时任务中 service mapper无法注入解决办法_ruoyi-quartz无法引入ruoyi-admin的service-程序员宅基地

文章浏览阅读2.3k次。上图为任务代码,在任务具体执行的方法中使用,一定要写在方法内使用SpringContextUtil.getBean()方法实例化Spring service类下边是ruoyi-quartz模块中util/SpringContextUtil.java(已改写)import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.s..._ruoyi-quartz无法引入ruoyi-admin的service

CentOS7配置yum源-程序员宅基地

文章浏览阅读2w次,点赞10次,收藏77次。yum,全称“Yellow dog Updater, Modified”,是一个专门为了解决包的依赖关系而存在的软件包管理器。可以这么说,yum 是改进型的 RPM 软件管理器,它很好的解决了 RPM 所面临的软件包依赖问题。yum 在服务器端存有所有的 RPM 包,并将各个包之间的依赖关系记录在文件中,当管理员使用 yum 安装 RPM 包时,yum 会先从服务器端下载包的依赖性文件,通过分析此文件从服务器端一次性下载所有相关的 RPM 包并进行安装。_centos7配置yum源

智能科学毕设分享(算法) 基于深度学习的抽烟行为检测算法实现(源码分享)-程序员宅基地

文章浏览阅读828次,点赞21次,收藏8次。今天学长向大家分享一个毕业设计项目毕业设计 基于深度学习的抽烟行为检测算法实现(源码分享)毕业设计 深度学习的抽烟行为检测算法实现通过目前应用比较广泛的 Web 开发平台,将模型训练完成的算法模型部署,部署于 Web 平台。并且利用目前流行的前后端技术在该平台进行整合实现运营车辆驾驶员吸烟行为检测系统,方便用户使用。本系统是一种运营车辆驾驶员吸烟行为检测系统,为了降低误检率,对驾驶员视频中的吸烟烟雾和香烟目标分别进行检测,若同时检测到则判定该驾驶员存在吸烟行为。进行流程化处理,以满足用户的需要。

随便推点

STM32单片机示例:多个定时器同步触发启动_stm32 定时器同步-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏14次。多个定时器同步触发启动是一种比较实用的功能,这里将对此做个示例说明。_stm32 定时器同步

android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...-程序员宅基地

文章浏览阅读348次。出处 : http://www.cnblogs.com/mythou/p/3187881.html本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务。客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题。没办法,只能看看是怎么回事。今天分析一下Launcher启动APP的过程。从用户点击到程序启动的流程,下面针对WorkSpa..._回调bubbletextview

Ubuntu 12 最快的两个源 个人感觉 163与cn99最快 ubuntu安装源下包过慢_un.12.cc-程序员宅基地

文章浏览阅读6.2k次。Ubuntu 12 最快的两个源 个人感觉 163与cn99最快 ubuntu下包过慢 1、首先备份Ubuntu 12.04源列表 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup (备份下当前的源列表,有备无患嘛) 2、修改更新源 sudo gedit /etc/apt/sources.list (打开Ubuntu 12_un.12.cc

vue动态路由(权限设置)_vue动态路由权限-程序员宅基地

文章浏览阅读5.8k次,点赞6次,收藏86次。1.思路(1)动态添加路由肯定用的是addRouter,在哪用?(2)vuex当中获取到菜单,怎样展示到界面2.不管其他先试一下addRouter找到router/index.js文件,内容如下,这是我自己先配置的登录路由现在先不管请求到的菜单是什么样,先写一个固定的菜单通过addRouter添加添加以前注意:addRoutes()添加的是数组在export defult router的上一行图中17行写下以下代码var addRoute=[ { path:"/", name:"_vue动态路由权限

JSTL 之变量赋值标签-程序员宅基地

文章浏览阅读8.9k次。 关键词: JSTL 之变量赋值标签 /* * Author Yachun Miao * Created 11-Dec-06 */关于JSP核心库的set标签赋值变量,有两种方式: 1.日期" />2. 有种需求要把ApplicationResources_zh_CN.prope

VGA带音频转HDMI转换芯片|VGA转HDMI 转换器方案|VGA转HDMI1.4转换器芯片介绍_vga转hdmi带音频转换器,转接头拆解-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏2次。1.1ZY5621概述ZY5621是VGA音频到HDMI转换器芯片,它符合HDMI1.4 DV1.0规范。ZY5621也是一款先进的高速转换器,集成了MCU和VGA EDID芯片。它还包含VGA输入指示和仅音频到HDMI功能。进一步降低系统制造成本,简化系统板上的布线。ZY5621方案设计简单,且可以完美还原输入端口的信号,此方案设计广泛应用于投影仪、教育多媒体、视频会议、视频展台、工业级主板显示、手持便携设备、转换盒、转换线材等产品设计上面。1.2 ZY5621 特性内置MCU嵌入式VGA_vga转hdmi带音频转换器,转接头拆解

推荐文章

热门文章

相关标签