blob: b725d56d127cac989bb98389b2b64ee6c82121f3 [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/**
2 * Copyright (C) 2007 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package com.android.settings;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.ApplicationInfo;
22import android.content.pm.PackageManager;
Daisuke Miyakawaa2633d02010-09-15 20:09:12 -070023import android.content.pm.ResolveInfo;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070024import android.content.pm.PackageManager.NameNotFoundException;
Anders Hammar1b2dd9032010-04-08 10:03:50 +020025import android.content.res.Resources;
26import android.content.res.Resources.NotFoundException;
27import android.graphics.drawable.Drawable;
Amith Yamasanic06d4c42011-02-25 14:35:20 -080028import android.net.ConnectivityManager;
29import android.net.LinkProperties;
Amith Yamasania4379d62011-07-22 10:34:58 -070030import android.os.BatteryManager;
Anders Hammar1b2dd9032010-04-08 10:03:50 +020031import android.os.Bundle;
Amith Yamasani60133dd2010-09-11 14:17:31 -070032import android.os.SystemProperties;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080033import android.preference.Preference;
34import android.preference.PreferenceGroup;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070035import android.preference.PreferenceActivity.Header;
Amith Yamasani60133dd2010-09-11 14:17:31 -070036import android.telephony.TelephonyManager;
Anders Hammar1b2dd9032010-04-08 10:03:50 +020037import android.text.TextUtils;
Daisuke Miyakawaa2633d02010-09-15 20:09:12 -070038
Amith Yamasanic06d4c42011-02-25 14:35:20 -080039import java.net.InetAddress;
Jean Chalard71ad1f42011-05-12 15:06:16 +090040import java.util.Arrays;
Amith Yamasanic06d4c42011-02-25 14:35:20 -080041import java.util.Iterator;
Daisuke Miyakawaa2633d02010-09-15 20:09:12 -070042import java.util.List;
Jean Chalard71ad1f42011-05-12 15:06:16 +090043import java.util.Locale;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080044
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080045public class Utils {
46
47 /**
48 * Set the preference's title to the matching activity's label.
49 */
50 public static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1;
51
52 /**
Anders Hammar1b2dd9032010-04-08 10:03:50 +020053 * Name of the meta-data item that should be set in the AndroidManifest.xml
54 * to specify the icon that should be displayed for the preference.
55 */
56 private static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";
57
58 /**
59 * Name of the meta-data item that should be set in the AndroidManifest.xml
60 * to specify the title that should be displayed for the preference.
61 */
62 private static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
63
64 /**
65 * Name of the meta-data item that should be set in the AndroidManifest.xml
66 * to specify the summary text that should be displayed for the preference.
67 */
68 private static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
69
70 /**
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080071 * Finds a matching activity for a preference's intent. If a matching
72 * activity is not found, it will remove the preference.
Ying Wanga7188322010-01-04 18:45:10 -080073 *
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080074 * @param context The context.
75 * @param parentPreferenceGroup The preference group that contains the
76 * preference whose intent is being resolved.
77 * @param preferenceKey The key of the preference whose intent is being
78 * resolved.
79 * @param flags 0 or one or more of
80 * {@link #UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY}
81 * .
82 * @return Whether an activity was found. If false, the preference was
83 * removed.
84 */
85 public static boolean updatePreferenceToSpecificActivityOrRemove(Context context,
86 PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags) {
Ying Wanga7188322010-01-04 18:45:10 -080087
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080088 Preference preference = parentPreferenceGroup.findPreference(preferenceKey);
89 if (preference == null) {
90 return false;
91 }
Ying Wanga7188322010-01-04 18:45:10 -080092
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080093 Intent intent = preference.getIntent();
94 if (intent != null) {
95 // Find the activity that is in the system image
96 PackageManager pm = context.getPackageManager();
97 List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
98 int listSize = list.size();
99 for (int i = 0; i < listSize; i++) {
100 ResolveInfo resolveInfo = list.get(i);
101 if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
102 != 0) {
Ying Wanga7188322010-01-04 18:45:10 -0800103
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800104 // Replace the intent with this specific activity
105 preference.setIntent(new Intent().setClassName(
106 resolveInfo.activityInfo.packageName,
107 resolveInfo.activityInfo.name));
108
109 if ((flags & UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY) != 0) {
110 // Set the preference title to the activity's label
111 preference.setTitle(resolveInfo.loadLabel(pm));
112 }
Ying Wanga7188322010-01-04 18:45:10 -0800113
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800114 return true;
115 }
116 }
117 }
118
119 // Did not find a matching activity, so remove the preference
120 parentPreferenceGroup.removePreference(preference);
Ying Wanga7188322010-01-04 18:45:10 -0800121
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800122 return true;
123 }
Ying Wanga7188322010-01-04 18:45:10 -0800124
125 /**
Anders Hammar1b2dd9032010-04-08 10:03:50 +0200126 * Finds a matching activity for a preference's intent. If a matching
127 * activity is not found, it will remove the preference. The icon, title and
128 * summary of the preference will also be updated with the values retrieved
129 * from the activity's meta-data elements. If no meta-data elements are
130 * specified then the preference title will be set to match the label of the
131 * activity, an icon and summary text will not be displayed.
132 *
133 * @param context The context.
134 * @param parentPreferenceGroup The preference group that contains the
135 * preference whose intent is being resolved.
136 * @param preferenceKey The key of the preference whose intent is being
137 * resolved.
138 *
139 * @return Whether an activity was found. If false, the preference was
140 * removed.
141 *
142 * @see {@link #META_DATA_PREFERENCE_ICON}
143 * {@link #META_DATA_PREFERENCE_TITLE}
144 * {@link #META_DATA_PREFERENCE_SUMMARY}
145 */
146 public static boolean updatePreferenceToSpecificActivityFromMetaDataOrRemove(Context context,
147 PreferenceGroup parentPreferenceGroup, String preferenceKey) {
148
149 IconPreferenceScreen preference = (IconPreferenceScreen)parentPreferenceGroup
150 .findPreference(preferenceKey);
151 if (preference == null) {
152 return false;
153 }
154
155 Intent intent = preference.getIntent();
156 if (intent != null) {
157 // Find the activity that is in the system image
158 PackageManager pm = context.getPackageManager();
159 List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
160 int listSize = list.size();
161 for (int i = 0; i < listSize; i++) {
162 ResolveInfo resolveInfo = list.get(i);
163 if ((resolveInfo.activityInfo.applicationInfo.flags
164 & ApplicationInfo.FLAG_SYSTEM) != 0) {
165 Drawable icon = null;
166 String title = null;
167 String summary = null;
168
169 // Get the activity's meta-data
170 try {
171 Resources res = pm
172 .getResourcesForApplication(resolveInfo.activityInfo.packageName);
173 Bundle metaData = resolveInfo.activityInfo.metaData;
174
175 if (res != null && metaData != null) {
176 icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
177 title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
178 summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
179 }
180 } catch (NameNotFoundException e) {
181 // Ignore
182 } catch (NotFoundException e) {
183 // Ignore
184 }
185
186 // Set the preference title to the activity's label if no
187 // meta-data is found
188 if (TextUtils.isEmpty(title)) {
189 title = resolveInfo.loadLabel(pm).toString();
190 }
191
192 // Set icon, title and summary for the preference
193 preference.setIcon(icon);
194 preference.setTitle(title);
195 preference.setSummary(summary);
196
197 // Replace the intent with this specific activity
198 preference.setIntent(new Intent().setClassName(
199 resolveInfo.activityInfo.packageName,
200 resolveInfo.activityInfo.name));
201
202 return true;
203 }
204 }
205 }
206
207 // Did not find a matching activity, so remove the preference
208 parentPreferenceGroup.removePreference(preference);
209
210 return false;
211 }
212
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700213 public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
214 List<Header> target, Header header) {
215
216 Intent intent = header.intent;
217 if (intent != null) {
218 // Find the activity that is in the system image
219 PackageManager pm = context.getPackageManager();
220 List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
221 int listSize = list.size();
222 for (int i = 0; i < listSize; i++) {
223 ResolveInfo resolveInfo = list.get(i);
224 if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
225 != 0) {
226 Drawable icon = null;
227 String title = null;
228 String summary = null;
229
230 // Get the activity's meta-data
231 try {
232 Resources res = pm.getResourcesForApplication(
233 resolveInfo.activityInfo.packageName);
234 Bundle metaData = resolveInfo.activityInfo.metaData;
235
236 if (res != null && metaData != null) {
237 icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
238 title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
239 summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
240 }
241 } catch (NameNotFoundException e) {
242 // Ignore
243 } catch (NotFoundException e) {
244 // Ignore
245 }
246
247 // Set the preference title to the activity's label if no
248 // meta-data is found
249 if (TextUtils.isEmpty(title)) {
250 title = resolveInfo.loadLabel(pm).toString();
251 }
252
253 // Set icon, title and summary for the preference
254 // TODO:
255 //header.icon = icon;
256 header.title = title;
257 header.summary = summary;
258 // Replace the intent with this specific activity
259 header.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
260 resolveInfo.activityInfo.name);
261
262 return true;
263 }
264 }
265 }
266
267 // Did not find a matching activity, so remove the preference
268 if (target.remove(header)) System.err.println("Removed " + header.id);
269
270 return false;
271 }
272
Anders Hammar1b2dd9032010-04-08 10:03:50 +0200273 /**
Ying Wanga7188322010-01-04 18:45:10 -0800274 * Returns true if Monkey is running.
275 */
276 public static boolean isMonkeyRunning() {
277 return SystemProperties.getBoolean("ro.monkey", false);
278 }
Amith Yamasani60133dd2010-09-11 14:17:31 -0700279
280 /**
281 * Returns whether the device is voice-capable (meaning, it is also a phone).
282 */
283 public static boolean isVoiceCapable(Context context) {
284 TelephonyManager telephony =
285 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
286 return telephony != null && telephony.isVoiceCapable();
287 }
Amith Yamasani0f85c482011-02-23 17:19:11 -0800288
289 public static boolean isWifiOnly() {
290 return "wifi-only".equals(SystemProperties.get("ro.carrier"));
291 }
Amith Yamasanic06d4c42011-02-25 14:35:20 -0800292
293 /**
294 * Returns the WIFI IP Addresses, if any, taking into account IPv4 and IPv6 style addresses.
295 * @param context the application context
296 * @return the formatted and comma-separated IP addresses, or null if none.
297 */
298 public static String getWifiIpAddresses(Context context) {
299 ConnectivityManager cm = (ConnectivityManager)
300 context.getSystemService(Context.CONNECTIVITY_SERVICE);
301 LinkProperties prop = cm.getLinkProperties(ConnectivityManager.TYPE_WIFI);
302 if (prop == null) return null;
303 Iterator<InetAddress> iter = prop.getAddresses().iterator();
304 // If there are no entries, return null
305 if (!iter.hasNext()) return null;
306 // Concatenate all available addresses, comma separated
307 String addresses = "";
308 while (iter.hasNext()) {
309 addresses += iter.next().getHostAddress();
310 if (iter.hasNext()) addresses += ", ";
311 }
312 return addresses;
313 }
Jean Chalard71ad1f42011-05-12 15:06:16 +0900314
315 public static Locale createLocaleFromString(String localeStr) {
316 // TODO: is there a better way to actually construct a locale that will match?
317 // The main problem is, on top of Java specs, locale.toString() and
318 // new Locale(locale.toString()).toString() do not return equal() strings in
319 // many cases, because the constructor takes the only string as the language
320 // code. So : new Locale("en", "US").toString() => "en_US"
321 // And : new Locale("en_US").toString() => "en_us"
322 if (null == localeStr)
323 return Locale.getDefault();
324 String[] brokenDownLocale = localeStr.split("_", 3);
325 // split may not return a 0-length array.
326 if (1 == brokenDownLocale.length) {
327 return new Locale(brokenDownLocale[0]);
328 } else if (2 == brokenDownLocale.length) {
329 return new Locale(brokenDownLocale[0], brokenDownLocale[1]);
330 } else {
331 return new Locale(brokenDownLocale[0], brokenDownLocale[1], brokenDownLocale[2]);
332 }
333 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700334
335 public static String getBatteryPercentage(Intent batteryChangedIntent) {
336 int level = batteryChangedIntent.getIntExtra("level", 0);
337 int scale = batteryChangedIntent.getIntExtra("scale", 100);
338 return String.valueOf(level * 100 / scale) + "%";
339 }
340
341 public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
342 final Intent intent = batteryChangedIntent;
343
344 int plugType = intent.getIntExtra("plugged", 0);
345 int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
346 String statusString;
347 if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
348 statusString = res.getString(R.string.battery_info_status_charging);
349 if (plugType > 0) {
350 statusString = statusString
351 + " "
352 + res.getString((plugType == BatteryManager.BATTERY_PLUGGED_AC)
353 ? R.string.battery_info_status_charging_ac
354 : R.string.battery_info_status_charging_usb);
355 }
356 } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
357 statusString = res.getString(R.string.battery_info_status_discharging);
358 } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
359 statusString = res.getString(R.string.battery_info_status_not_charging);
360 } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
361 statusString = res.getString(R.string.battery_info_status_full);
362 } else {
363 statusString = res.getString(R.string.battery_info_status_unknown);
364 }
365
366 return statusString;
367 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800368}