Saturday, December 24, 2016

Android Studio - Change Language (Locale) On Application Without Open Menu Setting

Today i going to show you how to change application's language without open menu setting on your device.

In this tutorial, even you force stop your application, the language won't change. For example if you choose Indonesian, after that do force stop, the language will still Indonesian on your Apps.

VIDEO DEMO



In this case i use to tow languages, but you can provide with much languages in your application.


PREPARATION

After you created the project, the next thing that you do is create the folder values for your language. For example :

In this case (this tutorial) :

There is a default folder values (for English), i need to translate this apps to Bahasa Indonesia. So i create new folder values, for Indonesia i have to create values-in. -in is Indonesian language's code. You can check your language code HERE

After your create the folder values-yourCountryCode, inside this folder create new strings.xml. The output look like the following Figure 1:

Figure 1
Explanation refer on the number of Figure 1 :

  1. In order to easy you create the new values folder, just change from Android to  project 
  2. Right  click on res folder, create new directory, and give it name values-yourLanguageCode (in my case : values-in)
  3. The default values folder
  4. The values folder that you created will display here.

IMPLEMENTATION

Now create your apps as usual, follow the steps below :

Create some layouts :
  1. activity_splash_screen.xml
  2. activity_before_main.xml
  3. activity_main.xml
  4. activity_second.xml
Create some java classes :
  1. SplashScreenActivity.java
  2. BeforeMainActivity.java
  3. MainActivity.java
  4. SecondActivity.java
Note :
In every give text/label in Button, TextView, EditText, etc, please save the string inside strings.xml

Now modify every layouts :

Open activity_splash_screen.xml, paste the following code :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_splash_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="@drawable/paper"
tools:context="com.putuguna.changelanguagewithoutopensetting.SplashScreenActivity">
<ProgressBar
android:id="@+id/progressbar"
android:layout_marginBottom="50dp"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
Open activity_before_main.xml, paste the following code :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_before_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.putuguna.changelanguagewithoutopensetting.BeforeMainActivity">
<Button
android:id="@+id/btn_goto_main_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_go_to_mainactivity"
android:textAllCaps="false"/>
</RelativeLayout>
Open activity_main.xml, paste the following code :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Spinner
android:layout_margin="20dp"
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/label_spinner_promt"
android:entries="@array/array_spinner"></Spinner>
<TextView
android:id="@+id/txt_change_language"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/label_change_language" />
<Button
android:id="@+id/btn_next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_next_activity"/>
</LinearLayout>
Open activity_second.xml, paste the following code :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_second"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.putuguna.changelanguagewithoutopensetting.SecondActivity">
<TextView
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent"
android:text="@string/label_jadilah_anak_yang_baik"/>
</RelativeLayout>
You have finished with the layouts, Remember you have to store the string inside strings.xml (@string/your_label), for example please take a look at the following Figure 2 :

Figure 2
Next modify all of java classes.

Open SplashScreenActivity.java, paste the following code :


package com.putuguna.changelanguagewithoutopensetting;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.util.Locale;
public class SplashScreenActivity extends AppCompatActivity {
/**
* you can change this timer
* 2000 = 2 second
*/
public static final int SPLASH_DELAY = 2000;
private ProgressBar progressBar;
private Locale mLocale;
private Configuration configuration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_splash_screen);
getSupportActionBar().hide();
progressBar = (ProgressBar) findViewById(R.id.progressbar);
progressBar.setVisibility(View.VISIBLE);
getCurrentLocale();
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
@Override
public void run(){
progressBar.setVisibility(View.GONE);
Intent intent = new Intent(SplashScreenActivity.this, BeforeMainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);;
finish();
}
}, SPLASH_DELAY);
}
/**
* this method used to get current locale
*/
private void getCurrentLocale(){
SharedPreferences sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
String locale = sharedPreferences.getString("myLanguage",null);
if(locale==null){
}else {
configuration = getBaseContext().getResources().getConfiguration();
mLocale = new Locale(locale);
Locale.setDefault(mLocale);
configuration.locale = mLocale;
getBaseContext().getResources().updateConfiguration(configuration, getBaseContext().getResources().getDisplayMetrics());
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Configuration config = getResources().getConfiguration();
Locale.setDefault(mLocale);
config.locale = mLocale;
super.onConfigurationChanged(newConfig);
super.onConfigurationChanged(newConfig);
}
}
The splash screen created by Thread, it will appears for 2 seconds (you can change the timer). After that please take a look of this method  getCurrentLocale() . That method used to detect the change of the locale.

If there is any change, the configuration will change the language of the apps. Please take a look of the method : onConfigurationChanged(Configuration newConfig) . That method will change the language if there is any change detected by method getCurrentLocale()

Open BeforeMainActivity.java, paste the following code :

package com.putuguna.changelanguagewithoutopensetting;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.Locale;
public class BeforeMainActivity extends AppCompatActivity {
private Button btnGotoMainActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_before_main);
btnGotoMainActivity = (Button) findViewById(R.id.btn_goto_main_activity);
btnGotoMainActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(BeforeMainActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}
}
Open MainActivity.java, paste the following code :

package com.putuguna.changelanguagewithoutopensetting;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button btnNext;
private TextView tvText;
private Spinner spinnerLanguage;
private Locale mLocale;
private Configuration config;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText = (TextView) findViewById(R.id.txt_change_language);
btnNext = (Button) findViewById(R.id.btn_next);
spinnerLanguage = (Spinner) findViewById(R.id.spinner);
btnNext.setOnClickListener(this);
//spinner onItemSelectedListener
spinnerLanguage.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int i, long id) {
if(i==0){
}else if(i==1){
config = getBaseContext().getResources().getConfiguration();
changeLanguage("id");
}else if(i==2){
config = getBaseContext().getResources().getConfiguration();
changeLanguage("en");
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
* this method used to change locale on apps
* @param lang
*/
private void changeLanguage(String lang){
mLocale = new Locale(lang);
Locale.setDefault(mLocale);
config.locale = mLocale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Intent intent = new Intent(MainActivity.this, MainActivity.class); //pasang class itu sendiri
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
overridePendingTransition(0,0);
SharedPreferences sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("myLanguage", lang);
editor.commit();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Configuration config = getBaseContext().getResources().getConfiguration();
Locale.setDefault(mLocale);
config.locale = mLocale;
super.onConfigurationChanged(newConfig);
}
@Override
public void onClick(View view) {
int id = view.getId();
if(id==R.id.btn_next){
Intent intents = new Intent(this, SecondActivity.class);
intents.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intents);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent a = new Intent(this,BeforeMainActivity.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);
return true;
}
return super.onKeyDown(keyCode, event);
}
}
In MainActivity.java, there is a spinner that contains the name of any languages. In every click on spinner's item, get the configuration and change the locale (Method changeLanguage(String lang)).

Inside the method changeLanguage(String lang)  beside we'll change the locale, also will save the locale on sharedPreference and then refresh the activity.

onConfigurationChanged(Configuration newConfig) will change the configuration so the language will translated.

onKeyDown(int keyCode, KeyEvent event), this method used to refresh the previous activity when user tap the back button.

Why use onKeyDown(int keyCode, KeyEvent event)?

Because if use onBackPressed() won't refresh the previous activity, so we use intent inside onKeyDown(int keyCode, KeyEvent event).

Open SecondActivity.java, paste the following code :

package com.putuguna.changelanguagewithoutopensetting;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==android.R.id.home){
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
}

You have finished with your java classes, now please take a look in last several steps below :

Give this android:configChanges="locale" in every activity in your AndroidManifest.xml

Copy the strings.xml's value from strings.xml inside folder values to strings.xml inside folder values-yourLanguageCode (in my case values-in).

Done!! even you force stop your application, it won't change the language to the default. Hope it helps. Thank you.

Related Posts


EmoticonEmoticon

:)
:(
hihi
:-)
:D
=D
:-d
;(
;-(
@-)
:o
:>)
(o)
:p
:-?
(p)
:-s
8-)
:-t
:-b
b-(
(y)
x-)
(h)