Android7.0反射類找不到的問題

Java中使用反射的地方較多,尤其是各種框架中。最近在Android7.0的項目中遇到個問題很奇怪,反射使用的類找不到了,但是編譯的時候沒問題啊。然后在代碼中使用非反射的方式調用代碼也是沒有問題的,這時奇怪的現象出現了,加入手動調用代碼后反射代碼找不到類的問題也不出現了。其實這個是混淆代碼所做的工作,一個類沒有被使用的情況下會在編譯中直接刪除掉,顯然并沒有考慮反射調用的情況。關閉混淆或者修改混淆的配置文件即可解決這個問題。各種框架自動所做的工作大部分是節省了程序員的時間,但是一旦出問題查起來花費的時間也是不少

當處于應用層時,如果只是修改應用內多語言時,上層app可以輕松完成各種語言的切換,網上方法很多,就不在詳細敘述,app內部設置多語言可參考下面這篇文章

Android 實現應用內置語言切換(附有源碼下載地址7.0可用)。

但是,如何通過app,設置系統語言呢?這正是本文討論核心。

android6.0

android設置系統語言的核心方法在framework層,地址是\frameworks\base\core\java\com\android\internal\app\LocalePicker.java類里,方法如下:

? ?/**
? ? ?* Requests the system to update the system locale. Note that the system looks halted
? ? ?* for a while during the Locale migration, so the caller need to take care of it.
? ? ?*/
? ? public static void updateLocale(Locale locale) {
? ? ? ? try {
? ? ? ? ? ? IActivityManager am = ActivityManagerNative.getDefault();
? ? ? ? ? ? Configuration config = am.getConfiguration();
? ? ? ? ? ? config.setLocale(locale);
? ? ? ? ? ? config.userSetLocale = true;
? ? ? ? ? ? am.updateConfiguration(config);
? ? ? ? ? ? // Trigger the dirty bit for the Settings Provider.
? ? ? ? ? ? BackupManager.dataChanged("com.android.providers.settings");
? ? ? ? } catch (RemoteException e) {
? ? ? ? ? ? // Intentionally left blank
? ? ? ? }
? ? }

android6.0設置系統語言的關鍵邏輯就是上面那個方法。如果上層APP想要設置系統語言必須通過反射方法獲取,核心方法代碼如下(本方法可以持久化系統語言設置,也就是說重啟手機后不會恢復默認系統語言):

private void changeSystemLanguage(Locale locale) {if (locale != null) {try {Class classActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
            Method getDefault = classActivityManagerNative.getDeclaredMethod("getDefault");
            Object objIActivityManager = getDefault.invoke(classActivityManagerNative);
            Class classIActivityManager = Class.forName("android.app.IActivityManager");
            Method getConfiguration = classIActivityManager.getDeclaredMethod("getConfiguration");
            Configuration config = (Configuration) getConfiguration.invoke(objIActivityManager);
            config.setLocale(locale);
            //config.userSetLocale = true;
            Class clzConfig = Class.forName("android.content.res.Configuration");
            java.lang.reflect.Field userSetLocale = clzConfig.getField("userSetLocale");
            userSetLocale.set(config, true);
            Class[] clzParams = {Configuration.class};
            Method updateConfiguration = classIActivityManager.getDeclaredMethod("updateConfiguration", clzParams);
            updateConfiguration.invoke(objIActivityManager, config);
            BackupManager.dataChanged("com.android.providers.settings");
        } catch (Exception e) {Log.d(TAG, "changeSystemLanguage: " + e.getLocalizedMessage());
        }}
}
調用時如下:

Local locale = Locale.ENGLISH;
changeSystemLanguage(locale);
系統語言就變成了英文。(不再贅述)

android7.0

7.0與6.0的源碼有所不同,LocalePicker.Java定義系統語言的方式,不在是一種Local,而是一個LocaleList,具體方法如下:

? public static void updateLocale(Locale locale) {
? ? ? ? updateLocales(new LocaleList(locale));
? ? }

updateLocale調用了updateLocales方法,updateLocales方法如下:

?public static void updateLocales(LocaleList locales) {
? ? ? ? try {
? ? ? ? ? ? final IActivityManager am = ActivityManagerNative.getDefault();
? ? ? ? ? ? final Configuration config = am.getConfiguration();
? ? ? ? ? ? config.setLocales(locales);
? ? ? ? ? ? config.userSetLocale = true;
? ? ? ? ? ? am.updatePersistentConfiguration(config);
? ? ? ? ? ? // Trigger the dirty bit for the Settings Provider.
? ? ? ? ? ? BackupManager.dataChanged("com.android.providers.settings");
? ? ? ? } catch (RemoteException e) {
? ? ? ? ? ? // Intentionally left blank
? ? ? ? }
? ? }

可見,6.0上的反射直接照搬到7.0是不起作用的,需要重新運用反射方法,反射方法代碼如下

protected void changeSystemLanguage(LocaleList locale) {if (locale != null) {try {Class classActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
            Method getDefault = classActivityManagerNative.getDeclaredMethod("getDefault");
            Object objIActivityManager = getDefault.invoke(classActivityManagerNative);
            Class classIActivityManager = Class.forName("android.app.IActivityManager");
            Method getConfiguration = classIActivityManager.getDeclaredMethod("getConfiguration");
            Configuration config = (Configuration) getConfiguration.invoke(objIActivityManager);
            config.setLocales(locale);
            Class[] clzParams = {Configuration.class};
            Method updateConfiguration = classIActivityManager.getDeclaredMethod("updatePersistentConfiguration", clzParams);
            updateConfiguration.invoke(objIActivityManager, config);
        } catch (Exception e) {Log.d(TAG, "changeSystemLanguage: " + e.getLocalizedMessage());
        }}
}

6.0和7.0設置系統語言源碼不同之出,有兩點:

1.設置參數的方法不同,6.0是updateConfiguration,7.0是updatePersistentConfiguration,這點需要注意

2.6.0傳遞的local,而7.0是一個列表LocaleList

7.0反射方法調用如下:

Locale newLocale = new Locale("zh", "CN");
final LocaleList localeList = new LocaleList(newLocale);
changeSystemLanguage(localeList);

android7.0app切換系統語言Demo源碼下載:http://download.csdn.net/download/zhaokai621/9930068


生成的apk,需要系統簽名,可放在源碼vendor\customer\你的文件下通過mm編譯,需要注意的是,需要有.mk文件,生成的apk在out的目錄下(當然層級有很多),把out目錄下生成的apkpush到手機system/priv-app/你的文件夾,重啟手機即可。

操作如下:

1.把studio生成的apk放入如下目錄:


Android.mk文件如下(供參考):

--------------------------開始(下面才是)-------------------------------------------------------------

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_OVERRIDES_PACKAGES := Calendar
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
#LOCAL_PREBUILT_JNI_LIBS:= \
#@lib/armeabi/liblocSDK4d.so
#LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/operator/app
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PREBUILT)

--------------------------------結束(本行不是)-----------------------------------------------------------------------------

2.編譯源碼,單編模塊

命令如下(前提是你已經整編過一套android源碼)

source ./build/envsetup.sh(加載命令)

lunch 16(序號和你整編時選的一樣,本文以android7.0源碼為準)

mmm?vendor/customer/Test

3.生成的apk(已經打包了系統簽名):在如下目錄(可能有出入)


4.push到手機,不要install,重啟手機

adb push XXXX system/priv-app/Test

XXX是你out生成的apk,可拖拽到此。


現在就可以看到一個應用了,點擊就可以切換系統語言了。多多交流 ? *-*


android7.0app切換系統語言Demo源碼下載:http://download.csdn.net/download/zhaokai621/9930068

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387469.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387469.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387469.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2.6 multimap

#include<map> multimap的元素插入、刪除、查找與map不同 multimap元素的插入&#xff1a;&#xff08;未提供mm[key]value插入方式&#xff09; multimap<string, double> mm; mm.insert(pair<string, double>("haha", 11.1)); mm.insert(pai…

Mybatis學習筆記18 - 緩存

兩級緩存&#xff1a; 一級緩存&#xff1a;&#xff08;本地緩存&#xff09;&#xff1a;sqlSession級別的緩存。一級緩存是一直開啟的&#xff1b;SqlSession級別的一個Map 數據庫同一次會話期間查詢到的數據會放在本地緩存中。以后如果需要獲取相同的數據&#xff0c;直接從…

2.7 deque

#include<deque> 雙端隊列容器 注意&#xff1a;頭入隊時伴隨的是尾出隊&#xff1b;提供中間元素的更新和刪除操作。 與vector一樣&#xff0c;采用線性表順序存儲結構 deque采用分塊的線性存儲結構來存儲數據&#xff0c;每塊大小一般為512字節 所有deque塊由一個…

APK 加殼方法

下載工具http://download.csdn.net/download/sys025/8958363一款免費的為apk加固的工具。 特別說明&#xff1a;加固后需要重新簽名apk才能安裝。加固的apk包會比未加固的大一些。 jarsigner -verbose -keystore dms.keystore -storepass pactera -keypass pactera -sigfile CE…

Java DSL簡介(收集整理)

一、領域特定語言&#xff08;DSL&#xff09; 領域特定語言&#xff08;DSL&#xff09;通常被定義為一種特別針對某類特殊問題的計算機語言&#xff0c;它不打算解決其領域外的問題。對于DSL的正式研究已經持續很多年&#xff0c;直 到最近&#xff0c;在程序員試圖采用最易讀…

[轉]JSon數據解析的四種方式

轉至http://blog.csdn.net/enuola/article/details/7903632 作為一種輕量級的數據交換格式&#xff0c;json正在逐步取代xml&#xff0c;成為網絡數據的通用格式。 有的json代碼格式比較混亂&#xff0c;可以使用此“http://www.bejson.com/”網站來進行JSON格式化校驗&#xf…

2.8 list

#include<list> 雙向循環鏈表 list結點的三個域&#xff1a;數據域、前驅元素指針域、后繼元素指針域 對于list的迭代器&#xff0c;只有或--的操作&#xff0c;無n或-n的操作 創建list對象&#xff1a; list<int> l; list<int> l(10); 插入和遍歷&…

Spring AOP兩種實現機制是什么?

Spring AOP兩種實現機制是什么&#xff1f; 1.如果是有接口聲明的類進行AOP 時&#xff0c;spring調用的是java.lang.reflection.Proxy 類來做處理 2.如果是沒有接口聲明的類時&#xff0c; spring通過cglib包和內部類來實現 在AOP&#xff0c;權限控制&#xff0c;事務管理等…

iOS開發UI篇—Quartz2D使用(繪圖路徑)

1 //1.獲取圖形上下文 2 CGContextRef ctxUIGraphicsGetCurrentContext(); 3 //2.繪圖&#xff08;畫線&#xff09; 4 //設置起點 5 CGContextMoveToPoint(ctx, 20, 20); 6 //設置終點 7 CGContextAddLineToPoint(ctx, 200, 300); 8 //渲染 9…

2.9 bitset

#include<bitset> bitset容器是一個bit位元素的序列容器&#xff0c;每個元素只占一個bit位&#xff0c;取值為0或1&#xff0c;因而很節省內存空間。 bitset<n> b; b.any() 是否有1 b.none() 是否無1 b.count() 1的個數 b.size() 大小 b[pos] 訪問 b.…

C# 談談Interface和通過Interface傳遞web頁面數據

接口&#xff1a;描述可屬于任何類或結構的一組相關功能&#xff0c;通過interface關鍵字來聲明&#xff1b;接口只包含方法、委托或事件和屬性的簽名&#xff08;接口包含的成員&#xff09;、不能包含字段&#xff08;因為字段是包含數據的&#xff09;。方法的實現是“繼承”…

Spring支持如下5種作用域

當通過Spring容器創建一個Bean實例時&#xff0c;不僅可以完成Bean實例的實例化&#xff0c;還可以為Bean指定特定的作用域。Spring支持如下5種作用域&#xff1a; singleton&#xff1a;單例模式&#xff0c;在整個Spring IoC容器中&#xff0c;使用singleton定義的Bean將只有…

RBAC授權

給用戶授予RBAC權限沒有權限會報如下錯誤&#xff1a;執行查看資源報錯&#xff1a; unable to upgrade connection: Forbidden (userkubernetes, verbcreate, resourcenodes, subresourceproxy)[roottest4 ~]# kubectl exec -it http-test-dm2-6dbd76c7dd-cv9qf sh error: una…

出卷子

http://chujuanzi.com/ 出卷子 涵蓋初高中全部學科題庫&#xff0c;全國名校試卷最快更新。試卷新、試題全、解析準、完全免費&#xff0c;提供豐富試題輔助教師有效出試卷&#xff0c;組卷方便快捷。&#xff08;高中語文 高中數學 高中英語 高中物理 高中化學 高中生物 高中政…

2.10 stack

#include<stack> 后進先出 Last In First Out LIFO 插入和刪除元素只能在表的一端進行。 插入端 棧頂 Stack Top 入棧 Push 刪除端 棧底 Stack Bottom 出棧 Pop stack<int> s; s.push(1); //入棧 int i s.top(); //獲得棧頂元素 s.pop(); //出棧 s.size…

13結構型模式之橋接模式

概念 Bridge 模式又叫做橋接模式&#xff0c;是構造型的設計模式之一。Bridge模式基于類的最小設計原則&#xff0c;通過使用封裝&#xff0c;聚合以及繼承等行為來讓不同的類承擔不同的責任。它的主要特點是把抽象&#xff08;abstraction&#xff09;與行為實現&#xff08;i…

話說Svn與Git的區別

把第一條理解到位思想到位了做起來才會有的放矢&#xff0c;其他幾條都是用的時候才能體會到 1) 最核心的區別Git是分布式的&#xff0c;而Svn不是分布的。能理解這點&#xff0c;上手會很容易&#xff0c;聲明一點Git并不是目前唯一的分布式版本控制系統&#xff0c;還有比如M…

Ubuntu下Postgres安裝與配置

postgres8.4安裝配置&#xff1a;1.安裝postgres8.4~$ sudo apt-get install postgresql 2.修改超級管理員postgres密碼&#xff1a;以系統用戶運行psql~$ sudo -u postgres psql postgres修改postgres密碼(123456)postgres# /password postgres 3.備份修改的配置文件&#xff…

2.11 queue

#include<queue> 先進先出&#xff08;First In First Out, FIFO&#xff09; 隊尾插入&#xff0c;隊首刪除 queue<int> q; q.push(1); //入隊 int qf q.front(); //獲取隊首元素 int qe q.back(); //獲取隊尾元素 q.pop(); //出隊 q.size(); //大小 q.…

簡易中控紫貓插件版(3)壓縮包使用說明

1.環境配置腳本運行環境&#xff1a;沒什么說的 正常的最新版手機按鍵 當然還需要 最新的紫貓插件中控運行環境&#xff1a;首先要保證把壓縮包的所有php文件都扔到網站的根目錄下 必須保證網站的php版本是5.4 不然紫貓插件的php框架會出問題 然后你要知道網站數據庫的賬號和密…