1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.localepicker; 18 19 import android.app.FragmentTransaction; 20 import android.app.LocaleManager; 21 import android.content.pm.PackageManager; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.os.LocaleList; 25 import android.text.TextUtils; 26 import android.util.Log; 27 import android.view.MenuItem; 28 import android.view.View; 29 import android.widget.FrameLayout; 30 import android.widget.ListView; 31 32 import androidx.core.view.ViewCompat; 33 34 import com.android.internal.app.LocalePickerWithRegion; 35 import com.android.internal.app.LocaleStore; 36 import com.android.settings.R; 37 import com.android.settings.applications.AppLocaleUtil; 38 import com.android.settings.applications.appinfo.AppLocaleDetails; 39 import com.android.settings.core.SettingsBaseActivity; 40 41 public class AppLocalePickerActivity extends SettingsBaseActivity 42 implements LocalePickerWithRegion.LocaleSelectedListener, MenuItem.OnActionExpandListener { 43 private static final String TAG = AppLocalePickerActivity.class.getSimpleName(); 44 45 private String mPackageName; 46 private LocalePickerWithRegion mLocalePickerWithRegion; 47 private AppLocaleDetails mAppLocaleDetails; 48 private View mAppLocaleDetailContainer; 49 50 @Override onCreate(Bundle savedInstanceState)51 public void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 Uri data = getIntent().getData(); 54 if (data == null) { 55 Log.d(TAG, "There is no uri data."); 56 finish(); 57 return; 58 } 59 mPackageName = data.getSchemeSpecificPart(); 60 if (TextUtils.isEmpty(mPackageName)) { 61 Log.d(TAG, "There is no package name."); 62 finish(); 63 return; 64 } 65 66 if (!canDisplayLocaleUi()) { 67 Log.w(TAG, "Not allow to display Locale Settings UI."); 68 finish(); 69 return; 70 } 71 72 setTitle(R.string.app_locale_picker_title); 73 getActionBar().setDisplayHomeAsUpEnabled(true); 74 75 mLocalePickerWithRegion = LocalePickerWithRegion.createLanguagePicker( 76 this, 77 this, 78 false /* translate only */, 79 null, 80 mPackageName, 81 this); 82 mAppLocaleDetails = AppLocaleDetails.newInstance(mPackageName, getUserId()); 83 mAppLocaleDetailContainer = launchAppLocaleDetailsPage(); 84 // Launch Locale picker part. 85 launchLocalePickerPage(); 86 } 87 88 @Override onOptionsItemSelected(MenuItem item)89 public boolean onOptionsItemSelected(MenuItem item) { 90 if (item.getItemId() == android.R.id.home) { 91 super.onBackPressed(); 92 return true; 93 } 94 return super.onOptionsItemSelected(item); 95 } 96 97 @Override onLocaleSelected(LocaleStore.LocaleInfo localeInfo)98 public void onLocaleSelected(LocaleStore.LocaleInfo localeInfo) { 99 if (localeInfo == null || localeInfo.getLocale() == null || localeInfo.isSystemLocale()) { 100 setAppDefaultLocale(""); 101 } else { 102 setAppDefaultLocale(localeInfo.getLocale().toLanguageTag()); 103 } 104 finish(); 105 } 106 107 @Override onMenuItemActionCollapse(MenuItem item)108 public boolean onMenuItemActionCollapse(MenuItem item) { 109 mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/); 110 ViewCompat.setNestedScrollingEnabled(mAppLocaleDetails.getListView(), true); 111 ViewCompat.setNestedScrollingEnabled(mLocalePickerWithRegion.getListView(), true); 112 return true; 113 } 114 115 @Override onMenuItemActionExpand(MenuItem item)116 public boolean onMenuItemActionExpand(MenuItem item) { 117 mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/); 118 ViewCompat.setNestedScrollingEnabled(mAppLocaleDetails.getListView(), false); 119 ViewCompat.setNestedScrollingEnabled(mLocalePickerWithRegion.getListView(), false); 120 return true; 121 } 122 123 /** Sets the app's locale to the supplied language tag */ setAppDefaultLocale(String languageTag)124 private void setAppDefaultLocale(String languageTag) { 125 Log.d(TAG, "setAppDefaultLocale: " + languageTag); 126 LocaleManager localeManager = getSystemService(LocaleManager.class); 127 if (localeManager == null) { 128 Log.w(TAG, "LocaleManager is null, cannot set default app locale"); 129 return; 130 } 131 localeManager.setApplicationLocales(mPackageName, LocaleList.forLanguageTags(languageTag)); 132 } 133 launchAppLocaleDetailsPage()134 private View launchAppLocaleDetailsPage() { 135 FrameLayout appLocaleDetailsContainer = new FrameLayout(this); 136 appLocaleDetailsContainer.setId(R.id.layout_app_locale_details); 137 getSupportFragmentManager() 138 .beginTransaction() 139 .replace(R.id.layout_app_locale_details, mAppLocaleDetails) 140 .commit(); 141 return appLocaleDetailsContainer; 142 } 143 launchLocalePickerPage()144 private void launchLocalePickerPage() { 145 // LocalePickerWithRegion use android.app.ListFragment. Thus, it can not use 146 // getSupportFragmentManager() to add this into container. 147 android.app.FragmentManager fragmentManager = getFragmentManager(); 148 fragmentManager.registerFragmentLifecycleCallbacks( 149 new android.app.FragmentManager.FragmentLifecycleCallbacks() { 150 @Override 151 public void onFragmentViewCreated( 152 android.app.FragmentManager fm, 153 android.app.Fragment f, View v, Bundle s) { 154 super.onFragmentViewCreated(fm, f, v, s); 155 ListView listView = (ListView) v.findViewById(android.R.id.list); 156 if (listView != null) { 157 listView.addHeaderView(mAppLocaleDetailContainer); 158 } 159 } 160 }, true); 161 fragmentManager.beginTransaction() 162 .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 163 .replace(R.id.content_frame, mLocalePickerWithRegion) 164 .commit(); 165 } 166 canDisplayLocaleUi()167 private boolean canDisplayLocaleUi() { 168 try { 169 PackageManager packageManager = getPackageManager(); 170 return AppLocaleUtil.canDisplayLocaleUi(this, 171 packageManager.getApplicationInfo(mPackageName, 0), 172 packageManager.queryIntentActivities(AppLocaleUtil.LAUNCHER_ENTRY_INTENT, 173 PackageManager.GET_META_DATA)); 174 } catch (PackageManager.NameNotFoundException e) { 175 Log.e(TAG, "Unable to find info for package: " + mPackageName); 176 } 177 178 return false; 179 } 180 } 181