Android language settings

Source: Internet
Author: User

 

[Android] three methods of application language switching

 

Android has done a good job in international and multi-language switching. An application only needs to name the values-[language] folder of the corresponding language family, you can switch between multiple languages by using "Settings"> "Language & keyboard"> "Select language.

But how to implement it in the application? The following methods have been found on the Internet after searching:

View plaincopy to clipboardprint?

 

Resources res = getResources ();

Configuration config = res. getConfiguration ();

Config. locale = locale;

DisplayMetrics dm = res. getDisplayMetrics ();

Res. updateConfiguration (config, dm );

The principle of the first two methods is to implement "Select language" in the application ". By viewing the source code, the core code is:

 

View plaincopy to clipboardprint? IActivityManager iActMag = ActivityManagerNative. getDefault ();

Try {

Configuration config = iActMag. getConfiguration ();

Config. locale = locale;

// Permission must be declared here: android. permission. CHANGE_CONFIGURATION

// OnCreate () will be called again ();

IActMag. updateConfiguration (config );

} Catch (RemoteException e ){

E. printStackTrace ();

}

PS: Thanks to Zeng Yang for his help.

IActivityManager iActMag = ActivityManagerNative. getDefault ();

Try {

Configuration config = iActMag. getConfiguration ();

Config. locale = locale;

// Permission must be declared here: android. permission. CHANGE_CONFIGURATION

// OnCreate () will be called again ();

IActMag. updateConfiguration (config );

} Catch (RemoteException e ){

E. printStackTrace ();

}

PS: Thanks to Zeng Yang for his help. It can be found that both IActivityManager and ActivityManagerNative are non-public classes. How to call it? The first is API spoofing, and the second is Java reflection.

1. API Spoofing

Android. jar, which is burned to a mobile phone, contains various types and methods required by Android. jar, which is only part of android. jar, is used by developers. API spoofing refers to simulating undisclosed classes and methods in an application so that the application can compile and generate an APK, however, what is called in the actual operation of the application is still the real android in the mobile phone. jar.

 

The core code shows that the two methods getConfiguration () and updateConfiguration (config) in ActivityManagerNative are simulated ). With reference to the source code, the engineering structure diagram and Code Simulation of the application are as follows:

 

 

Code:

 

View plaincopy to clipboardprint? ActivityManagerNative. java

Package android. app;

 

/**

* @ Author Sodino E-mail: sodinoopen@hotmail.com

* @ Version Time: 11:37:01

*/

Public abstract class ActivityManagerNative {

Public static IActivityManager getDefault (){

Return null;

}

}

 

IActivityManager. java

Package android. app;

 

Import android. content. res. Configuration;

Import android. OS. RemoteException;

 

/**

* @ Author Sodino E-mail: sodinoopen@hotmail.com

* @ Version Time: 11:37:46

*/

Public abstract interface IActivityManager {

Public abstract Configuration getConfiguration () throws RemoteException;

 

Public abstract void updateConfiguration (Configuration paramConfiguration)

Throws RemoteException;

}

ActivityManagerNative. java

Package android. app;

/**

* @ Author Sodino E-mail: sodinoopen@hotmail.com

* @ Version Time: 11:37:01

*/

Public abstract class ActivityManagerNative {

Public static IActivityManager getDefault (){

Return null;

}

}

IActivityManager. java

Package android. app;

Import android. content. res. Configuration;

Import android. OS. RemoteException;

/**

* @ Author Sodino E-mail: sodinoopen@hotmail.com

* @ Version Time: 11:37:46

*/

Public abstract interface IActivityManager {

Public abstract Configuration getConfiguration () throws RemoteException;

Public abstract void updateConfiguration (Configuration paramConfiguration)

Throws RemoteException;

} After simulating these two classes, you can use the core code of the conversion language mentioned above.

 

Directly run the Code:

View plaincopy to clipboardprint?

Private void updateLanguage (Locale locale ){

Log. d ("ANDROID_LAB", locale. toString ());

Try {

Object objIActMag, objActMagNative;

Class clzIActMag = Class. forName ("android. app. IActivityManager ");

Class clzActMagNative = Class. forName ("android. app. ActivityManagerNative ");

Method mtdActMagNative $ getDefault = clzActMagNative. getDeclaredMethod ("getDefault ");

// IActivityManager iActMag = ActivityManagerNative. getDefault ();

ObjIActMag = mtdActMagNative $ getDefault. invoke (clzActMagNative );

// Configuration config = iActMag. getConfiguration ();

Method mtdIActMag $ getConfiguration = clzIActMag. getDeclaredMethod ("getConfiguration ");

Configuration config = (Configuration) mtdIActMag $ getConfiguration. invoke (objIActMag );

Config. locale = locale;

// IActMag. updateConfiguration (config );

// Permission must be declared here: android. permission. CHANGE_CONFIGURATION

// OnCreate () will be called again ();

Class [] clzParams = {Configuration. class };

Method mtdIActMag $ updateConfiguration = clzIActMag. getDeclaredMethod (

"UpdateConfiguration", clzParams );

MtdIActMag $ updateConfiguration. invoke (objIActMag, config );

} Catch (Exception e ){

E. printStackTrace ();

}

}

Private void updateLanguage (Locale locale) {Log. d ("ANDROID_LAB", locale. toString (); try {Object objIActMag, objActMagNative; Class clzIActMag = Class. forName ("android. app. IActivityManager "); Class clzActMagNative = Class. forName ("android. app. activityManagerNative "); Method mtdActMagNative $ getDefault = clzActMagNative. getDeclaredMethod ("getDefault"); // IActivityManager iActMag = ActivityManagerN Ative. getDefault (); objIActMag = mtdActMagNative $ getDefault. invoke (clzActMagNative); // Configuration config = iActMag. getConfiguration (); Method mtdIActMag $ getConfiguration = clzIActMag. getDeclaredMethod ("getConfiguration"); Configuration config = (Configuration) mtdIActMag $ getConfiguration. invoke (objIActMag); config. locale = locale; // iActMag. updateConfiguration (config); // The permission must be declared here: android. per Mission. CHANGE_CONFIGURATION // The onCreate (); Class [] clzParams = {Configuration. class}; Method mtdIActMag $ updateConfiguration = clzIActMag. getDeclaredMethod ("updateConfiguration", clzParams); mtdIActMag $ updateConfiguration. invoke (objIActMag, config);} catch (Exception e) {e. after printStackTrace () ;}} was running, it was found that after setting a new Locale for the current system, not only did its application language change, but all application languages of the system changed. This must be unreasonable. One solution is to set Locale to the system before exiting the application interface. However, I do not like this method. In addition, after calling the updateConfiguration () method, the entire Activity will be re-onCreate (), which may be difficult to consider the life cycle of the Activity. So there is the third method below.

 

 

The content of values/strings. xml is the same as that of xml/english. xml; the content of values-zh-rCN/strings. xml is the same as that of xml/chinese. xml. The reason for this redundancy is that when the APK is generated, all the content in values hits rasc and cannot be read.

The following considerations must be taken into account to achieve the transformation of the language family:

3.1 R. xxxxx. id corresponds to the text string in the corresponding language family (Special consideration must be given to the R. array. string array ).

3.2 Parse xml.

3.3 After the language family is set, all interface elements are refreshed manually.

Declare a string in xml in this format:

View plaincopy to clipboardprint?

<String name = "app_name"> language application </string>

<String name = "app_name"> language application </string> the corresponding R file will generate an id to refer to this string

View plaincopy to clipboardprint?

Public static final class string {

Public static final int app_name = 0x7f050001;

}

Public static final class string {public static final int app_name = 0x7f050001 ;}

The 3.1 problem is how to match the id and string. The solution is as follows:

View plaincopy to clipboardprint?

Resources res = context. getResources ();

String pkg = context. getPackageName ();

String tag = "app_name ";

Int idTag = res. getIdentifier (tag, "string", pkg );

Resources res = context. getResources (); String pkg = context. getPackageName (); String tag = "app_name"; int idTag = res. getIdentifier (tag, "string", pkg); 3.2 Parse XML

A new tool is used here: XmlResourceParser. The parsing process is a bit winding, but it is simpler than SAX. For details, see the code in the LanguageApp_Sodino project.

3.3 manually refresh the interface.

To obtain all the indexes that involve the update components of the language family, you can perform manual work with some effort.

For detailed implementation process, see the following three projects:

LanguageApp_APICheat

LanguageApp_Reflection

LanguageApp_Sodino

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.