Android 多语言应用(步骤+源码)

简介: Android 多语言应用(步骤+源码)

运行效果图


image.gif


多语言应用



前言


  什么样的应用需要多语言呢?应用国际化,比如你的应用同时要在国内和国外使用,因此你需要对你的应用增加不同的语言。


正文


  按照国际惯例,首先创建一个项目,命名为LanguageDemo,这也是一篇实操型博客,最好按照步骤一步一步的来写,这样你了解的更多,当然如果你时间宝贵,也可以直接运行源码,或者拆分源码中的一些功能到自己的项目中。



一、修改样式


打开styles.xml。


20201207150926999.png


然后修改colors.xml,修改为colorPrimary和colorPrimaryDark为白色


2020120715143124.png


那么现在你运行项目就会是一片白。然后在新建一个基类的BaseActivity,时项目中所有的Activity都继承自这个BaseActivity。


BaseActivity代码如下:


package com.llw.language;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
 * 基类Activity
 *
 * @author llw
 */
public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        super.onCreate(savedInstanceState);
    }
    /**
     * 设置toolbar的左侧图标的点击事件
     *
     * @param toolbar
     */
    protected void Back(Toolbar toolbar) {
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
}

二、增加页面


这里思考一个问题,首先一个APP是由多个页面组成的,所以更改APP的语言也是要多个页面一起更改的。而且通常设置语言是在App的设置里面。


下面就来写这个两个页面。


先增加几个小图标吧。


在drawable下新建一个ic_check.xml,作为设置中选中语言的标识


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="#43A047"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M9,16.17L5.53,12.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41l4.18,4.18c0.39,0.39 1.02,0.39 1.41,0L20.29,7.71c0.39,-0.39 0.39,-1.02 0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0L9,16.17z" />
</vector>


再建一个ic_return.xml,作为页面左上角的返回图标。


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="#000000"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M14.71,15.88L10.83,12l3.88,-3.88c0.39,-0.39 0.39,-1.02 0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0L8.71,11.3c-0.39,0.39 -0.39,1.02 0,1.41l4.59,4.59c0.39,0.39 1.02,0.39 1.41,0 0.38,-0.39 0.39,-1.03 0,-1.42z" />
</vector>


再建一个ic_settings.xml,作为设置页面的进入图标。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="#000000"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98 0,0.33 0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM17.45,11.27c0.04,0.31 0.05,0.52 0.05,0.73 0,0.21 -0.02,0.43 -0.05,0.73l-0.14,1.13 0.89,0.7 1.08,0.84 -0.7,1.21 -1.27,-0.51 -1.04,-0.42 -0.9,0.68c-0.43,0.32 -0.84,0.56 -1.25,0.73l-1.06,0.43 -0.16,1.13 -0.2,1.35h-1.4l-0.19,-1.35 -0.16,-1.13 -1.06,-0.43c-0.43,-0.18 -0.83,-0.41 -1.23,-0.71l-0.91,-0.7 -1.06,0.43 -1.27,0.51 -0.7,-1.21 1.08,-0.84 0.89,-0.7 -0.14,-1.13c-0.03,-0.31 -0.05,-0.54 -0.05,-0.74s0.02,-0.43 0.05,-0.73l0.14,-1.13 -0.89,-0.7 -1.08,-0.84 0.7,-1.21 1.27,0.51 1.04,0.42 0.9,-0.68c0.43,-0.32 0.84,-0.56 1.25,-0.73l1.06,-0.43 0.16,-1.13 0.2,-1.35h1.39l0.19,1.35 0.16,1.13 1.06,0.43c0.43,0.18 0.83,0.41 1.23,0.71l0.91,0.7 1.06,-0.43 1.27,-0.51 0.7,1.21 -1.07,0.85 -0.89,0.7 0.14,1.13zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z" />
</vector>


图标有了,现在额外添加两个页面,OtherActivity和SettingActivity。然后先不要去管他们,后面再去改。


三、增加语言资源文件


图标有了,下面修改文字,打开strings.xml


<resources>
    <string name="app_name">LanguageDemo</string>
    <string name="multi_language">多语言</string>
    <string name="setting">设置</string>
    <string name="system_language">系统语言:</string>
    <string name="current_language">当前语言:</string>
    <string name="other_pages">其他页面</string>
    <string name="choose_lang">语言选择</string>
    <string name="system_lang">系统语言</string>
    <string name="chinese">中文</string>
    <string name="english">英文</string>
    <string name="traditional_chinese">中文繁体</string>
</resources>


一般情况下是只有这一个文字资源文件的。但是如果要做多语言的话,一个是不够的。因此就需要根据当前所需要的语言去创建相应的语言资源文件夹。


20201207153747410.png


从上面这个图可以得知,我增加了英文和繁体的语言文件夹,然后你可以把values下的strings.xml复制到values-en和values-zh-rTW下,看会发生什么变化。


20201207153952171.png


你会发现这两个文件夹下的strings.xml的图标不一样了,是以旗帜来标识的,先来看values-en下的strings.xml


<resources>
    <string name="app_name">LanguageDemo</string>
    <string name="multi_language">Multi language</string>
    <string name="setting">Setting</string>
    <string name="system_language">System language:</string>
    <string name="current_language">Current language:</string>
    <string name="other_pages">Other Pages</string>
    <string name="choose_lang">Language</string>
    <string name="system_lang">System language</string>
    <string name="chinese">Chinese</string>
    <string name="english">English</string>
    <string name="traditional_chinese">Traditional Chinese</string>
</resources>


再来看values-zh-rTW下的strings.xml


<resources>
    <string name="app_name">LanguageDemo</string>
    <string name="multi_language">多語言</string>
    <string name="setting">設置</string>
    <string name="system_language">系統語言:</string>
    <string name="current_language">當前語言:</string>
    <string name="other_pages">其他頁面</string>
    <string name="choose_lang">語言選擇</string>
    <string name="system_lang">系統語言</string>
    <string name="chinese">中文</string>
    <string name="english">英文</string>
    <string name="traditional_chinese">中文繁體</string>
</resources>


可能你会觉得这种方式比较的麻烦,那么还有一种简单的添加语言的方式。

右键点击res → New → Android Resource File


2020120715485592.png


然后会打开一个弹窗


20201207155409386.png


点击 >> 按钮之后


20201207155531420.png


现在Language下选择一个想要添加的语言。


20201207155730886.png


点击OK就可以了。


20201207155822125.png


这样就添加好了,这里再附一个values命名对应的国家目录,可供参考,我也是百度出来的。


Arabic, Egypt (ar_EG) -----------------------------阿拉伯语,埃及
Arabic, Israel (ar_IL) -------------------------------阿拉伯语,以色列
Bulgarian, Bulgaria (bg_BG) ---------------------保加利亚语,保加利亚
Catalan, Spain (ca_ES) ---------------------------加泰隆语,西班牙
Czech, Czech Republic (cs_CZ) -----------------捷克语,捷克共和国
Danish, Denmark(da_DK) ------------------------丹麦语,丹麦
German, Austria (de_AT) -------------------------德语,奥地利
German, Switzerland (de_CH) -------------------德语,瑞士
German, Germany (de_DE) ----------------------德语,德国
German, Liechtenstein (de_LI) ------------------德语,列支敦士登的
Greek, Greece (el_GR) ----------------------------希腊语,希腊
English, Australia (en_AU) -------------------------英语,澳大利亚
English, Canada (en_CA) --------------------------英语,加拿大
English, Britain (en_GB) ----------------------------英语,英国
English, Ireland (en_IE) -----------------------------英语,爱尔兰
English, India (en_IN) --------------------------------英语,印度
English, New Zealand (en_NZ) ---------------------英语,新西兰
English, Singapore(en_SG) --------------------------英语,新加坡
English, US (en_US) -----------------------------------英语,美国
English, Zimbabwe (en_ZA) --------------------------英语,津巴布韦
Spanish (es_ES) ----------------------------------------西班牙
Spanish, US (es_US) -----------------------------------西班牙语,美国
Finnish, Finland (fi_FI) ---------------------------------芬兰语,芬兰
French, Belgium (fr_BE) -------------------------------法语,比利时
French, Canada (fr_CA) -------------------------------法语,加拿大
French, Switzerland (fr_CH) --------------------------法语,瑞士
French, France (fr_FR) --------------------------------法语,法国
Hebrew, Israel (he_IL) ---------------------------------希伯来语,以色列
Hindi, India (hi_IN) -------------------------------------印地语,印度
Croatian, Croatia (hr_HR) ----------------------------克罗地亚语,克罗地亚
Hungarian, Hungary (hu_HU) ------------------------匈牙利语,匈牙利
Indonesian, Indonesia (id_ID) ------------------------印尼语,印尼
Italian, Switzerland (it_CH) ----------------------------意大利语,瑞士
Italian, Italy (it_IT) ---------------------------------------意大利语,意大利
Japanese (ja_JP) ----------------------------------------日语
Korean (ko_KR) ------------------------------------------朝鲜语
Lithuanian, Lithuania (lt_LT) --------------------------立陶宛语,立陶宛
Latvian, Latvia (lv_LV) ---------------------------------拉托维亚语,拉托维亚
Norwegian-Bokmol, Norway(nb_NO) ---------------挪威语,挪威
Dutch, Belgium (nl_BE) --------------------------------荷兰语,比利时
Dutch, Netherlands (nl_NL) ---------------------------荷兰语,荷兰
Polish (pl_PL) -------------------------------------------波兰
Portuguese, Brazil (pt_BR) ---------------------------葡萄牙语,巴西
Portuguese, Portugal (pt_PT) ------------------------葡萄牙语,葡萄牙
Romanian, Romania (ro_RO) ------------------------罗马尼亚语,罗马尼亚
Russian (ru_RU) ----------------------------------------俄语
Slovak, Slovakia (sk_SK) ------------------------------斯洛伐克语,斯洛伐克
Slovenian, Slovenia (sl_SI) ---------------------------斯洛文尼亚语,斯洛文尼亚
Serbian (sr_RS) ----------------------------------------塞尔维亚语
Swedish, Sweden (sv_SE) ----------------------------瑞典语,瑞典
Thai, Thailand (th_TH) --------------------------------泰语,泰国
Tagalog, Philippines (tl_PH) --------------------------菲律宾语,菲律宾
Turkish, Turkey (tr_TR) -------------------------------土耳其语,土耳其
Ukrainian, Ukraine (uk_UA) --------------------------联合王国
Vietnamese, Vietnam (vi_VN) -----------------------越南语,越南
Chinese, PRC (zh_CN)--------------------------------中文,中国
Chinese, Taiwan (zh_rTW)-----------------------------中文,台湾


values-加上后面括号里面的值就可以了。不保证一定正确,不正确的可以参考刚才AS手动添加语言文件夹步骤。


这里只是一个简单的教程而已,所以我会把刚才新建的values-zh删掉,因为已经有默认的values表示中文了。


多语言因为要注意一个点,当你添加了一个文字资源时,对应的语言文件夹里都要添加,比如我在values的strings.xml中添加了一个你好,那么就要在values-en的strings.xml中添加一个Hello,同样也要在values-zh-rTW下的strings.xml中添加你好。你好的简体和繁体都是一样的。

四、修改页面适配Android系统语言


下面修改一下activity_main.xml的布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <!--头部-->
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/multi_language"
            android:textColor="#000"
            android:textSize="18sp" />
        <ImageView
            android:id="@+id/iv_setting"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_gravity="end"
            android:layout_marginRight="12dp"
            android:src="@drawable/ic_settings" />
    </androidx.appcompat.widget.Toolbar>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_sys_language"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/system_language"
            android:textColor="#000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_cur_language"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:text="@string/current_language"
            android:textColor="#000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_other_pages"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:layout_marginTop="50dp"
            android:background="#FFF"
            android:gravity="center"
            android:text="@string/other_pages"
            android:textColor="#000"
            android:textSize="16sp" />
    </LinearLayout>
</LinearLayout>


然后修改activity_other.xml的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".OtherActivity">
    <!--头部-->
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        app:navigationIcon="@drawable/ic_return"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/other_pages"
            android:textColor="#000"
            android:textSize="18sp" />
    </androidx.appcompat.widget.Toolbar>
</LinearLayout>


最后修改activity_setting.xml的布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    tools:context=".SettingActivity">
    <!--头部-->
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        app:navigationIcon="@drawable/ic_return"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/setting"
            android:textColor="#000"
            android:textSize="18sp" />
    </androidx.appcompat.widget.Toolbar>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_choose_lang"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="24dp"
            android:text="@string/choose_lang"
            android:textColor="#7A7A7A"
            android:textSize="12sp" />
        <RelativeLayout
            android:id="@+id/lay_system"
            android:layout_width="match_parent"
            android:layout_height="44dp"
            android:background="#FFF"
            android:gravity="center_vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginStart="16dp"
                android:gravity="center"
                android:text="@string/system_lang"
                android:textColor="#4A4A4A"
                android:textSize="14sp" />
            <ImageView
                android:id="@+id/iv_system"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="24dp"
                android:padding="2dp"
                android:src="@drawable/ic_check" />
        </RelativeLayout>
        <RelativeLayout
            android:id="@+id/lay_chinese"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_marginTop="1dp"
            android:background="#FFF"
            android:gravity="center_vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginStart="16dp"
                android:gravity="center"
                android:text="@string/chinese"
                android:textColor="#4A4A4A"
                android:textSize="14sp" />
            <ImageView
                android:id="@+id/iv_chinese"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="24dp"
                android:padding="2dp"
                android:src="@drawable/ic_check"
                android:visibility="gone" />
        </RelativeLayout>
        <RelativeLayout
            android:id="@+id/lay_english"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_marginTop="1dp"
            android:background="#FFF"
            android:gravity="center_vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginStart="16dp"
                android:gravity="center"
                android:text="@string/english"
                android:textColor="#4A4A4A"
                android:textSize="14sp" />
            <ImageView
                android:id="@+id/iv_english"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="24dp"
                android:padding="2dp"
                android:src="@drawable/ic_check"
                android:visibility="gone" />
        </RelativeLayout>
        <RelativeLayout
            android:id="@+id/lay_traditional_chinese"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_marginTop="1dp"
            android:background="#FFF"
            android:gravity="center_vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginStart="16dp"
                android:gravity="center"
                android:text="@string/traditional_chinese"
                android:textColor="#4A4A4A"
                android:textSize="14sp" />
            <ImageView
                android:id="@+id/iv_traditional_chinese"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="24dp"
                android:padding="2dp"
                android:src="@drawable/ic_check"
                android:visibility="gone" />
        </RelativeLayout>
    </LinearLayout>
</LinearLayout>


三个Activity的页面都写好了,下面改动一下代码。

首先是MainActivity。在MainActivity中去继承BaseActivity,然后实现控件的点击事件监听。

package com.llw.language;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.LocaleList;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Locale;
/**
 * 主页面
 * @author llw
 */
public class MainActivity extends BaseActivity implements View.OnClickListener {
    private TextView tvSystemLanguage;//系统语言
    private TextView tvCurrentLanguage;//当前语言
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = findViewById(R.id.iv_setting);
        TextView tvOtherPage = findViewById(R.id.tv_other_pages);
        tvSystemLanguage = findViewById(R.id.tv_sys_language);
        tvCurrentLanguage = findViewById(R.id.tv_cur_language);
        imageView.setOnClickListener(this);
        tvOtherPage.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_setting://进入设置页面
                goToActivity(SettingActivity.class);
                break;
            case R.id.tv_other_pages://进入其他页面
                goToActivity(OtherActivity.class);
                break;
            default:
                break;
        }
    }
    /**
     * 跳转页面 
     * @param clazz 目标Activity
     */
    private void goToActivity(Class<?> clazz) {
        startActivity(new Intent(this,clazz));
    }
}


再来看。OtherActivity。

package com.llw.language;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
/**
 * 其他页面
 * @author llw
 */
public class OtherActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
        Toolbar toolbar = findViewById(R.id.toolbar);
        Back(toolbar);
    }
}


最后是SettingActivity。


package com.llw.language;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
/**
 * 设置页面
 * @author llw
 */
public class SettingActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        Toolbar toolbar = findViewById(R.id.toolbar);
        Back(toolbar);
    }
}


下面你就可以运行了,无论你是运行在虚拟器还是手机,都可以。AS中默认下载的模拟器打开之后是英文的,因此刚来可以测试一下这个APP是否会适配Android系统语言。


20201207162047736.png


OK,已经适配了,那么接下来用自己的手机来运行一下,看是不是会显示中文。(如果自己的手机默认是英文的语言,我只能说你是个人才)


2020120716231796.png


点击跳转其他页面或者设置页面也都是中文的,我这里就不一一截图了。


刚才不是还有一个繁体的吗?那么将自己手机的语言改成繁体,再打开这个APP,看看会怎么样。更改Android系统需要,通常在手机的设置里面,然后在设置里面找到有系统相关的选项。再找到语言相关的选项。之后选择语言和地区,然后切换一下语言看看。


20201207162702354.png


我现在已经切换到繁体了,然后再打开APP。


20201207162759488.png


呐,没骗你吧。骗倒是没骗我,不过,这难道就是多语言吗?只是配置了多个语言文件就可以了吗?


那当然不是,你要知道这种方式适合一般的用户使用,是没有问题的。而某些用户为了装个逼,明明系统语言是中文的,但是它要求你APP要有英文、日文、法文等一些语言。这个时候你再根据系统来设置就不合适了,因为不都不认识,多了改变资源文件只是在适配Android系统中改动的语言,而对于App中修改语言还要进一步改进才行。


五、工具类


刚才是通过改变系统语言进而改变APP页面,下面是不改变系统语言也要改变APP语言。


 做过Android应用开发的相信对Application是不陌生的,常规的是通过写一个自定义的Applictaion,比如BaseApplication,然后继承自Application。然后在BaseApplication中进行一些应用的初始化操作之类。而既然是改动APP的语言,那么肯定是和这个Applictaion是有关系的。


下面新建一个utils包,包下新建一个SPUtils类。代码如下:


package com.llw.language.utils;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Locale;
/**
 * 语言缓存工具类
 * @author llw
 */
public class SPUtils {
    private final String SP_NAME = "language_setting";//缓存名称
    private final String TAG_LANGUAGE = "language_select";
    private static volatile SPUtils instance;
    private final SharedPreferences mSharedPreferences;
    private Locale systemCurrentLocal = Locale.CHINESE;//系统当前本地语言为中文 初始值
    public SPUtils(Context context) {
        //通过上下文获取本地缓存
        mSharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    }
    /**
     * 设置语言
     *
     * @param select 选中的语言项
     */
    public void setLanguage(int select) {
        //缓存编辑者
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        //放入保存的语言项
        editor.putInt(TAG_LANGUAGE, select);
        //提交 之后 缓存语言项保存完毕
        editor.commit();
    }
    /**
     * 获取语言
     *
     * @return 从缓存中根据缓存名或者缓存值,如果没有,则返回默认值0
     */
    public int getLanguage() {
        return mSharedPreferences.getInt(TAG_LANGUAGE, 0);
    }
    /**
     * 设置系统当前本地
     *
     * @param local 本地对象
     */
    public void setSystemCurrentLocal(Locale local) {
        systemCurrentLocal = local;
    }
    /**
     * 获取系统当前本地
     *
     * @return 系统当前本地
     */
    public Locale getSystemCurrentLocal() {
        return systemCurrentLocal;
    }
    /**
     * 获取实例
     *
     * @param context 上下文参数
     * @return SPUtils实例对象
     */
    public static SPUtils getInstance(Context context) {
        if (instance == null) {//等于空则重新创建实例,不为空则直接返回
            synchronized (SPUtils.class) {//增加一个同步锁,如果已经有了实例则跳出
                if (instance == null) {
                    //创建新的对象
                    instance = new SPUtils(context);
                }
            }
        }
        return instance;
    }
}


下面是另一个工具类LocalManageUtils,代码如下:


package com.llw.language.utils;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;
import android.util.Log;
import com.llw.language.R;
import java.util.Locale;
/**
 * 本地管理工具类
 *
 * @author llw
 */
public class LocalManageUtils {
    private static final String TAG = "LocalManage";
    /**
     * 获取系统的 locale对象
     *
     * @param context 上下文参数
     * @return locale对象
     */
    public static Locale getSystemLocal(Context context) {
        return SPUtils.getInstance(context).getSystemCurrentLocal();
    }
    /**
     * 获取当前APP使用的语言
     *
     * @param context 上下文参数
     * @return 语言类型描述
     */
    public static String getSelectLanguage(Context context) {
        //根据缓存中的语言返回当前设置的语言类型文字
        switch (SPUtils.getInstance(context).getLanguage()) {
            case 0:
                return context.getString(R.string.system_lang);
            case 1:
                return context.getString(R.string.chinese);
            case 2:
                return context.getString(R.string.english);
            case 3:
                return context.getString(R.string.traditional_chinese);
            default:
                return context.getString(R.string.chinese);
        }
    }
    /**
     * 获取选择的语言设置
     *
     * @param context 上下文参数
     * @return locale
     */
    public static Locale getSelectLanguageLocal(Context context) {
        switch (SPUtils.getInstance(context).getLanguage()) {
            case 0:
                return getSystemLocal(context);//系统语言
            case 1:
                return Locale.CHINESE;//中文
            case 2:
                return Locale.ENGLISH;//英文
            case 3:
                return Locale.TRADITIONAL_CHINESE;//中文繁体
            default:
                return Locale.CHINESE;//中文
        }
    }
    /**
     * 设置选中的语言
     *
     * @param context 上下文参数
     * @param select  选中的语言项
     */
    public static void setSelectLanguage(Context context, int select) {
        //放入缓存中
        SPUtils.getInstance(context).setLanguage(select);
        //设置APP语言
        setAppLanguage(context);
    }
    /**
     * 设置App语言
     *
     * @param context
     */
    public static void setAppLanguage(Context context) {
        //通过应用全局上下文获取资源对象
        Resources resources = context.getApplicationContext().getResources();
        //获取资源配置对象
        Configuration config = resources.getConfiguration();
        //获取系统本地对象
        Locale locale = getSelectLanguageLocal(context);
        //配置本地资源
        config.setLocale(locale);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android7.0及以上
            //获取本地语言列表
            LocaleList localeList = new LocaleList(locale);
            //设置默认语言列表
            LocaleList.setDefault(localeList);
            //设置语言环境列表
            config.setLocales(localeList);
            //创建配置系统的上下文参数
            context.getApplicationContext().createConfigurationContext(config);
            //设置默认语言
            Locale.setDefault(locale);
        }
        //更新资源配置
        resources.updateConfiguration(config, resources.getDisplayMetrics());
    }
    /**
     * 设置本地语言
     *
     * @param context 上下文参数
     * @return 设置后的对象
     */
    public static Context setLocale(Context context) {
        return updateResource(context, getSelectLanguageLocal(context));
    }
    /**
     * 更新资源
     *
     * @param context 上下文参数
     * @param locale  本地语言
     * @return
     */
    private static Context updateResource(Context context, Locale locale) {
        //设置默认语言
        Locale.setDefault(locale);
        //通过上下文获取资源对象
        Resources resources = context.getResources();
        //资源配置对象
        Configuration config = new Configuration(resources.getConfiguration());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {//Android4.2及以上
            //设置语言
            config.setLocale(locale);
            //获取设置之后的上下文参数
            context = context.createConfigurationContext(config);
        } else {
            //配置语言
            config.setLocale(locale);
            //更新资源配置
            resources.updateConfiguration(config, resources.getDisplayMetrics());
        }
        return context;
    }
    /**
     * 设置系统当前语言
     *
     * @param context
     */
    public static void setSystemCurrentLanguage(Context context) {
        Locale locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android7.0及以上
            locale = LocaleList.getDefault().get(0);
        } else {
            locale = Locale.getDefault();
        }
        Log.d(TAG, locale.getLanguage());
        //设置应用当前本地语言
        SPUtils.getInstance(context).setSystemCurrentLocal(locale);
    }
    /**
     * 更改应用配置
     * @param context 上下文参数
     */
    public static void onConfigurationChanged(Context context) {
        setSystemCurrentLanguage(context);
        setLocale(context);
        setAppLanguage(context);
    }
}


里面的方法都是有注释的,也都是比较简单的方法,这里就不过多的解释了。


上面的LocalManageUtils中最多的参数是Context,上下文参数平时通常是在Activity、Service、Fragment等一些组件中使用,那你有没有想过这些组件中的Context是怎么来的,常规的都是这些组件的生命周期,你突然说Context是怎么来的?这就触及到我的知识盲区了。首先Activity的这个上下文参数是怎么来的,这里可以重写一个方法。


比如在BaseActivity中,通过重写attachBaseContext方法,对Actiivty附加基础上下文,里面使用父类的attachBaseContext方法。


  @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }


那么它的父类是谁呢?很显然之前我继承了AppCompatActivity。那么肯定就是这个里面,那么再进去里面看看。


20201208093211693.png


你会发现怎么这里面又调用了父类的attachBaseContext方法,那就还得再找下去,你会发现AppCompatActivity最终继承自Activity(中间省略若干个Activity),子类继承父类,一般来说都是为了拓展,那么为什么要拓展,而不是在原来的基础上改呢?因为要适配。都知道Android的版本有很多,很多古老的版本现在都见不到了,但是Google仍然要去适配,因为那些低版本的Android系统现在不一定还在手机上,但是Android系统又不是只有手机的产品,还有其他的,比如TV、智能穿戴,这些设备的Android版本通常不高,因为更多的是做定制的。所以Android版本级别越低得到的权限就越多,改起来越简单。


20201208093505767.png


然后你会发现Activity继承自ContextThemeWrapper,同样在调用了父类ContextThemeWrapper的attachBaseContext。


20201208094029567.png


而ContextThemeWrapper又继承了ContextWrapper,它里面也是调用父类ContextWrapper的attachBaseContext。


20201208094336709.png


在ContextWrapper这里终于不再调用父类了。累坏了吧,喝口水歇歇。

在这里可以看看有哪些类使用了attachBaseContext。哪些类就能拿到上下文参数。


2020120809452314.png


你有没有发现,这里并没有看到Fragment,因为Fragment是依附在Actiivty上的。而ContextWrapper 继承了底层的Context,Context本身是一个抽象类,所以ContextWrapper 就是它的实现类,在这个实现类中,获取上下文,然后通过层层的继承和封装就传到了Activity。


嗯!有理有据,不过你说了半天这个Context的意义在哪里呢?它的意义就在于它可以改变应用和页面的资源配置。而当页面的资源配置发生改变时,就会调用attachBaseContext方法重新配置上下文,以达到切换资源配置的目的,就像切换语言这样。这么说你是否有一些明白呢?

六、配置页面和应用的上下文


刚才说了这么多理论的东西,手痒难耐了吧,来动手实践一下吧。之前在BaseActivity中重写了attachBaseContext,然后里面调用父类的attachBaseContext,然后传了一个上下文参数进去,而我就是要对这个参数动手脚。


  @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(LocalManageUtils.setLocale(newBase));
    }


  这里调用了LocalManageUtils的setLocale方法。

  /**
     * 设置本地语言
     *
     * @param context 上下文参数
     * @return 设置后的对象
     */
    public static Context setLocale(Context context) {
        return updateResource(context, getSelectLanguageLocal(context));
    }


这个方法就是通过附加上下文时,改变上下文的一些配置,然后再返回上下文,这时这个上下文才会也页面生效。而我所有的Activity都继承自BaseActivity,那么它就对所有的Activity也生效。


而这还不够,因为现在你只是改变了页面而已,还没有改变这个App,那么怎么改变整个App呢?当然需要这个Application。

来看看这个自定义的BaseApplication。


package com.llw.language;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import androidx.annotation.NonNull;
import com.llw.language.utils.LocalManageUtils;
/**
 * 自定义基础Application
 * @author llw
 */
public class BaseApplication extends Application {
    public static final String TAG = "BaseApplication";
    @Override
    protected void attachBaseContext(Context base) {
        //设置系统当前语言
        LocalManageUtils.setSystemCurrentLanguage(base);
        super.attachBaseContext(LocalManageUtils.setLocale(base));
        Log.d(TAG,"attachBaseContext");
    }
    @Override
    public void onCreate() {
        super.onCreate();
        //设置App的语言
        LocalManageUtils.setAppLanguage(this);
        Log.d(TAG,"onCreate");
    }
    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        //通过全局的上下文参数更改相关资源配置
        LocalManageUtils.onConfigurationChanged(getApplicationContext());
        Log.d(TAG,"onConfigurationChanged");
    }
}


这里你要注意attachBaseContext是在onCreate之前执行的。既然写了BaseActivity,那么就需要到AndroidManifest.xml中去配置,否则你写了也是白写,不配置的话就会使用默认的Application,这个Application你是改变不了的。


20201208100814166.png

七、修改App语言


下面就要进入激动人心的,页面修改App语言的环节了。

SettingActivity页面代码如下:


package com.llw.language;
import androidx.appcompat.widget.Toolbar;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.llw.language.utils.LocalManageUtils;
import com.llw.language.utils.SPUtils;
/**
 * 设置页面
 *
 * @author llw
 */
public class SettingActivity extends BaseActivity implements View.OnClickListener {
    ImageView iv_system, iv_chinese, iv_english, iv_traditional_chinese;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        //初始化页面
        initView();
    }
    private void initView() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        Back(toolbar);
        RelativeLayout lay_system = findViewById(R.id.lay_system);
        RelativeLayout lay_chinese = findViewById(R.id.lay_chinese);
        RelativeLayout lay_english = findViewById(R.id.lay_english);
        RelativeLayout lay_traditional_chinese = findViewById(R.id.lay_traditional_chinese);
        iv_system = findViewById(R.id.iv_system);
        iv_chinese = findViewById(R.id.iv_chinese);
        iv_english = findViewById(R.id.iv_english);
        iv_traditional_chinese = findViewById(R.id.iv_traditional_chinese);
        lay_system.setOnClickListener(this);
        lay_chinese.setOnClickListener(this);
        lay_english.setOnClickListener(this);
        lay_traditional_chinese.setOnClickListener(this);
        //根据缓存中语言来表示设置中选中的语言
        controlView(SPUtils.getInstance(this).getLanguage());
    }
    /**
     * 控制选中视图
     * @param select 选项
     */
    private void controlView(int select) {
        switch (select) {
            case 0://系统
                iv_system.setVisibility(View.VISIBLE);
                iv_chinese.setVisibility(View.GONE);
                iv_english.setVisibility(View.GONE);
                iv_traditional_chinese.setVisibility(View.GONE);
                break;
            case 1://中文
                iv_system.setVisibility(View.GONE);
                iv_chinese.setVisibility(View.VISIBLE);
                iv_english.setVisibility(View.GONE);
                iv_traditional_chinese.setVisibility(View.GONE);
                break;
            case 2://英文
                iv_system.setVisibility(View.GONE);
                iv_chinese.setVisibility(View.GONE);
                iv_english.setVisibility(View.VISIBLE);
                iv_traditional_chinese.setVisibility(View.GONE);
                break;
            case 3://中文繁体
                iv_system.setVisibility(View.GONE);
                iv_chinese.setVisibility(View.GONE);
                iv_english.setVisibility(View.GONE);
                iv_traditional_chinese.setVisibility(View.VISIBLE);
                break;
            default:
                break;
        }
    }
    /**
     * 选择语言后,重新进入setting页面
     *
     * @param context
     * @param select
     */
    public void reStart(Context context, int select) {
        LocalManageUtils.setSelectLanguage(this, select);
        controlView(select);//控制选择的视图
        finish();
        Intent intent = new Intent(context, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.lay_system://系统
                reStart(this, 0);
                break;
            case R.id.lay_chinese://中文
                reStart(this, 1);
                break;
            case R.id.lay_english://英文
                reStart(this, 2);
                break;
            case R.id.lay_traditional_chinese://中文繁体
                reStart(this, 3);
                break;
            default:
                break;
        }
    }
}


首先对页面的控件进行初始化,添加点击事件,然后控制对应的语言类型显示勾选,其次就是点击之后通过改变语言的选项,然后设置语言类型,然后回到主页面看是否改变了应用语言。

下面来看看MainActivity的页面代码。

package com.llw.language;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.LocaleList;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.llw.language.utils.LocalManageUtils;
import java.util.Locale;
/**
 * 主页面
 *
 * @author llw
 */
public class MainActivity extends BaseActivity implements View.OnClickListener {
    private TextView tvSystemLanguage;//系统语言
    private TextView tvCurrentLanguage;//当前语言
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = findViewById(R.id.iv_setting);
        TextView tvOtherPage = findViewById(R.id.tv_other_pages);
        tvSystemLanguage = findViewById(R.id.tv_sys_language);
        tvCurrentLanguage = findViewById(R.id.tv_cur_language);
        imageView.setOnClickListener(this);
        tvOtherPage.setOnClickListener(this);
        //系统语言
        tvSystemLanguage.setText(getString(R.string.system_language) +
                LocalManageUtils.getSystemLocal(this).getDisplayLanguage());
        //当前应用语言
        tvCurrentLanguage.setText(getString(R.string.current_language) +
                LocalManageUtils.getSelectLanguage(this));
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_setting://进入设置页面
                goToActivity(SettingActivity.class);
                break;
            case R.id.tv_other_pages://进入其他页面
                goToActivity(OtherActivity.class);
                break;
            default:
                break;
        }
    }
    /**
     * 跳转页面
     *
     * @param clazz 目标Activity
     */
    private void goToActivity(Class<?> clazz) {
        startActivity(new Intent(this, clazz));
    }
}


其实新增的只有这两行代码而已,只不过是用来显示系统语言和当前语言而已。

    //系统语言
        tvSystemLanguage.setText(getString(R.string.system_language) +
                LocalManageUtils.getSystemLocal(this).getDisplayLanguage());
        //当前应用语言
        tvCurrentLanguage.setText(getString(R.string.current_language) +
                LocalManageUtils.getSelectLanguage(this));


到这里代码就写完了。


八、效果图和源码


下面来看运行的效果图。

20201208111225122.gif


就像这个效果图一样,语言就设置好了。


文末


  如果这篇文章对你有帮助的话,不妨点个赞再走。山高水长,后会有期。



相关文章
|
3天前
|
JSON 编译器 开发工具
VS Code阅读Android源码
VS Code阅读Android源码
9 1
|
2天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
2天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第24天】随着移动开发技术的不断演进,提升应用性能和用户体验已成为开发者的核心任务。在Android平台上,Kotlin语言凭借其简洁性和功能性成为主流选择之一。特别是Kotlin的协程功能,它为异步编程提供了一种轻量级的解决方案,使得处理并发任务更加高效和简洁。本文将深入探讨Kotlin协程在Android开发中的应用,通过实际案例分析协程如何优化应用性能,以及如何在项目中实现协程。
|
2天前
|
存储 缓存 安全
Android系统 应用存储路径与权限
Android系统 应用存储路径与权限
6 0
Android系统 应用存储路径与权限
|
2天前
|
存储 安全 Android开发
Android系统 自定义系统和应用权限
Android系统 自定义系统和应用权限
18 0
|
2天前
|
Linux 开发工具 Android开发
Docker系列(1)安装Linux系统编译Android源码
Docker系列(1)安装Linux系统编译Android源码
6 0
|
8天前
|
缓存 移动开发 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第18天】 在移动开发的世界中,打造一个既快速又流畅的Android应用并非易事。本文深入探讨了如何通过一系列创新的技术策略来提升应用性能和用户体验。我们将从用户界面(UI)设计的简约性原则出发,探索响应式布局和Material Design的实践,再深入剖析后台任务处理、内存管理和电池寿命优化的技巧。此外,文中还将讨论最新的Android Jetpack组件如何帮助开发者更高效地构建高质量的应用。此内容不仅适合经验丰富的开发者深化理解,也适合初学者构建起对Android高效开发的基础认识。
6 0
|
8天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
11 0
|
9天前
|
缓存 移动开发 Java
构建高效的Android应用:内存优化策略
【4月更文挑战第16天】 在移动开发领域,尤其是针对资源有限的Android设备,内存优化是提升应用性能和用户体验的关键因素。本文将深入探讨Android应用的内存管理机制,分析常见的内存泄漏问题,并提出一系列实用的内存优化技巧。通过这些策略的实施,开发者可以显著减少应用的内存占用,避免不必要的后台服务,以及提高垃圾回收效率,从而延长设备的电池寿命并确保应用的流畅运行。
|
11天前
|
搜索推荐 开发工具 Android开发
安卓即时应用(Instant Apps)开发指南
【4月更文挑战第14天】Android Instant Apps让用户体验部分应用功能而无需完整下载。开发者需将应用拆分成模块,基于已上线的基础应用构建。使用Android Studio的Instant Apps Feature Library定义模块特性,优化代码与资源以减小模块大小,同步管理即时应用和基础应用的版本。经过测试,可发布至Google Play Console,提升用户便利性,创造新获客机会。