Android 系统设置中显示设置之休眠和屏保设置篇

来源:互联网 发布:seo 优化 标题怎么优化 编辑:程序博客网 时间:2024/04/30 11:04

1、休眠设置  

  首先我们来看一下休眠设置在界面中的定义:

复制代码
1     <ListPreference2        android:key="screen_timeout"3        android:title="@string/screen_timeout"4        android:summary="@string/screen_timeout_summary" 5        android:persistent="false"                     6        android:entries="@array/screen_timeout_entries"   //当点击的时候弹出的listView显示的内容7        android:entryValues="@array/screen_timeout_values"  //listView显示的内容对应的时间8         />
复制代码
复制代码
1   <string-array name="screen_timeout_entries">2     <item msgid="3342301044271143016">"15 秒"</item>3     <item msgid="8881760709354815449">"30 秒"</item>4     <item msgid="7589406073232279088">"1 分钟"</item>5     <item msgid="7001195990902244174">"2 分钟"</item>6     <item msgid="7489864775127957179">"5 分钟"</item>7     <item msgid="2314124409517439288">"10 分钟"</item>8     <item msgid="6864027152847611413">"30 分钟"</item>9   </string-array>
复制代码
复制代码
 1     <!-- Do not translate. --> 2     <string-array name="screen_timeout_values" translatable="false"> 3         <!-- Do not translate. --> 4         <item>15000</item> 5         <!-- Do not translate. --> 6         <item>30000</item> 7         <!-- Do not translate. --> 8         <item>60000</item> 9         <!-- Do not translate. -->10         <item>120000</item>11         <!-- Do not translate. -->12         <item>300000</item>13         <!-- Do not translate. -->14         <item>600000</item>15         <!-- Do not translate. -->16         <item>1800000</item>17     </string-array>
复制代码

  接下来我们看看DisplaySettings.java中休眠的相关代码:

复制代码
 1         mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT); 2         //说明我们的休眠时间是保存在Settings.System中,如果获取不到,则默认值为FALLBACK_SCREEN_TIMEOUT_VALUE = 30000,也就是30秒 3         final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT, 4                 FALLBACK_SCREEN_TIMEOUT_VALUE); 5         mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout)); 6         mScreenTimeoutPreference.setOnPreferenceChangeListener(this); 7         //更新休眠时间列表 8         disableUnusableTimeouts(mScreenTimeoutPreference); 9         //修改值之后,更新summary的信息10         updateTimeoutPreferenceDescription(currentTimeout);
复制代码

  至于disableUnusableTimeouts和updateTimeoutPreferenceDescription函数,是比较容易理解的,我这里就只是贴出代码。

复制代码
 1     private void updateTimeoutPreferenceDescription(long currentTimeout) { 2         ListPreference preference = mScreenTimeoutPreference; 3         String summary; 4         if (currentTimeout < 0) { 5             // Unsupported value 6             summary = ""; 7         } else { 8             final CharSequence[] entries = preference.getEntries(); 9             final CharSequence[] values = preference.getEntryValues();10             if (entries == null || entries.length == 0) {11                 summary = "";12             } else {13                 int best = 0;14                 for (int i = 0; i < values.length; i++) {15                     long timeout = Long.parseLong(values[i].toString());16                     if (currentTimeout >= timeout) {17                         best = i;18                     }19                 }20                 summary = preference.getContext().getString(R.string.screen_timeout_summary,21                         entries[best]);22             }23         }24         preference.setSummary(summary);25     }26 27     private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {28         final DevicePolicyManager dpm =29                 (DevicePolicyManager) getActivity().getSystemService(30                 Context.DEVICE_POLICY_SERVICE);31         final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;32         if (maxTimeout == 0) {33             return; // policy not enforced34         }35         final CharSequence[] entries = screenTimeoutPreference.getEntries();36         final CharSequence[] values = screenTimeoutPreference.getEntryValues();37         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();38         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();39         for (int i = 0; i < values.length; i++) {40             long timeout = Long.parseLong(values[i].toString());41             if (timeout <= maxTimeout) {42                 revisedEntries.add(entries[i]);43                 revisedValues.add(values[i]);44             }45         }46         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {47             final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());48             screenTimeoutPreference.setEntries(49                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));50             screenTimeoutPreference.setEntryValues(51                     revisedValues.toArray(new CharSequence[revisedValues.size()]));52             if (userPreference <= maxTimeout) {53                 screenTimeoutPreference.setValue(String.valueOf(userPreference));54             } else if (revisedValues.size() > 055                     && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString())56                     == maxTimeout) {57                 // If the last one happens to be the same as the max timeout, select that58                 screenTimeoutPreference.setValue(String.valueOf(maxTimeout));59             } else {60                 // There will be no highlighted selection since nothing in the list matches61                 // maxTimeout. The user can still select anything less than maxTimeout.62                 // TODO: maybe append maxTimeout to the list and mark selected.63             }64         }65         screenTimeoutPreference.setEnabled(revisedEntries.size() > 0);66     }
复制代码

  既然我们的休眠时间是从Settings.System中获取的,那我们又是怎么存的呢?

复制代码
 1     public boolean onPreferenceChange(Preference preference, Object objValue) { 2         final String key = preference.getKey(); 3         if (KEY_SCREEN_TIMEOUT.equals(key)) { 4             int value = Integer.parseInt((String) objValue); 5             try { 6                 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value); 7                 updateTimeoutPreferenceDescription(value); 8             } catch (NumberFormatException e) { 9                 Log.e(TAG, "could not persist screen timeout setting", e);10             }11         }12         if (KEY_FONT_SIZE.equals(key)) {13             //该函数对字体进行设置14             writeFontSizePreference(objValue);15         }16 17         return true;18     }
复制代码

  有时候需要设备不进入休眠,我们只需要将SCREEN_OFF_TIMEOUT属性设置为-1即可。

  Settings.System.putInt(getContentResolver(),android.provider.Settings.System.SCREEN_OFF_TIMEOUT, -1);

     权限:<uses-permission android:name="android.permission.WRITE_SETTINGS" />

  以上便是系统设置中休眠的相关内容。

2、屏幕保护

  说完了休眠设置,我们接下来了解一下屏幕保护吧!首先来看看对应的布局:

   1 <PreferenceScreen 2 android:key="screensaver" 3 android:title="@string/screensaver_settings_title" android:fragment="com.android.settings.DreamSettings" /> 

  我们可以看到其中定义了android:fragment,也就是说当点击该item的时候会跳转到DreamSettings这个fragment。我们还是先看看DisplaySettings中有关屏保的代码吧!

  

复制代码
1         mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);2         //此处读取com.android.internal.R.bool.config_dreamsSupported的值,true表示支持屏保,false表示不支持3         if (mScreenSaverPreference != null4                 && getResources().getBoolean(5                         com.android.internal.R.bool.config_dreamsSupported) == false) {6             getPreferenceScreen().removePreference(mScreenSaverPreference);7         }
复制代码

 

  那初始化的代码在哪里呢?

    private void updateScreenSaverSummary() {        if (mScreenSaverPreference != null) {            mScreenSaverPreference.setSummary(                    DreamSettings.getSummaryTextWithDreamName(getActivity()));//获取当前的屏保的名称        }    }

 

  我们知道在定义屏保的时候指定了android:fragment属性,该属性的意思是当点击该preference时跳转到DreamSettings的fragment中,这里想问的是为什么这里指定了android:fragment就能跳转到对应的fragment呢? 原来在preference.java的构造函数中,保存了fragment这个成员变量,在PreferenceFragment中定了onPreferenceTreeClick函数,当preference点击的时候就会调用该函数,由于在preference中保存了fragment,所以会跳转到该fragment中。

复制代码
 1     /** 2      * {@inheritDoc} 3      */ 4     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 5             Preference preference) { 6         if (preference.getFragment() != null && 7                 getActivity() instanceof OnPreferenceStartFragmentCallback) { 8             return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment( 9                     this, preference);10         }11         return false;12     }
复制代码

 

  好的,刚刚解释了点击该preference为何能跳转到指定的fragment的原理。现在就让我们进入DreamSettings中一探究竟,Let's go!

  首先找到onCreate函数,里面定义了一个控制打开关闭屏保的开关switch:

复制代码
 1     @Override 2     public void onCreate(Bundle icicle) { 3         logd("onCreate(%s)", icicle); 4         super.onCreate(icicle); 5         Activity activity = getActivity(); 6  7         mBackend = new DreamBackend(activity);//对屏保的一个管理的类 8         mSwitch = new Switch(activity); //控制屏保是否打开的开关 9         mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {10             @Override11             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {12                 if (!mRefreshing) { //默认或者屏保刷新完毕即可进行下来的修改,否则跳过13                     mBackend.setEnabled(isChecked);//设置开关的状态14                     refreshFromBackend();   //刷新屏保信息15                 }16             }17         });
复制代码

 

  当屏保打开的时候,我们的界面是用listView进行显示的,listView的初始化是放在onActivityCreate中的,如下:

  

复制代码
 1     @Override 2     public void onActivityCreated(Bundle savedInstanceState) { 3         logd("onActivityCreated(%s)", savedInstanceState); 4         super.onActivityCreated(savedInstanceState); 5  6         ListView listView = getListView(); 7  8         listView.setItemsCanFocus(true); 9 10         TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);11         emptyView.setText(R.string.screensaver_settings_disabled_prompt);12         listView.setEmptyView(emptyView);13 14         mAdapter = new DreamInfoAdapter(mContext);15         listView.setAdapter(mAdapter);16     }
复制代码

  屏保中还有两个菜单供用户进行选择,他们分别是开始播放和设置时间进行播放,这部分的代码:

复制代码
 1     @Override 2     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 3         logd("onCreateOptionsMenu()"); 4  5         boolean isEnabled = mBackend.isEnabled(); 6  7         // create "start" action 8         MenuItem start = createMenuItem(menu, R.string.screensaver_settings_dream_start, 9                 MenuItem.SHOW_AS_ACTION_ALWAYS,10                 isEnabled, new Runnable(){11                     @Override12                     public void run() {13                         mBackend.startDreaming();//调用錽tartDreaming进行屏保的播放14                     }});15 16         // create "when to dream" overflow menu item17         MenuItem whenToDream = createMenuItem(menu,18                 R.string.screensaver_settings_when_to_dream,19                 MenuItem.SHOW_AS_ACTION_IF_ROOM,20                 isEnabled,21                 new Runnable() {22                     @Override23                     public void run() {24                         showDialog(DIALOG_WHEN_TO_DREAM);//弹出对话框让用户设置时间进行播放25                     }});26 27         // create "help" overflow menu item (make sure it appears last)28         super.onCreateOptionsMenu(menu, inflater);29 30         mMenuItemsWhenEnabled = new MenuItem[] { start, whenToDream };31     }
复制代码

  接下来我们需要学习一下刷新的功能,refreshFromBackend函数:

复制代码
 1     private void refreshFromBackend() { 2         logd("refreshFromBackend()"); 3         mRefreshing = true; 4         boolean dreamsEnabled = mBackend.isEnabled(); 5         if (mSwitch.isChecked() != dreamsEnabled) 6             mSwitch.setChecked(dreamsEnabled); 7  8         mAdapter.clear();//清空列表 9         if (dreamsEnabled) {10             List<DreamInfo> dreamInfos = mBackend.getDreamInfos();//通过getDreamInfos获取所有屏保信息11             mAdapter.addAll(dreamInfos);//重新加载数据并调用notifyDataSetChanged进行刷新12         }13         if (mMenuItemsWhenEnabled != null)14             for (MenuItem menuItem : mMenuItemsWhenEnabled)15                 menuItem.setEnabled(dreamsEnabled);16         mRefreshing = false;17     }
复制代码

  当然我们这里需要注意的是有时候我们的屏保是个apk,所以我们需要对apk卸载和安装进行监听,这样能够保证屏保的及时更新。这个操作的代码为:

复制代码
 1     @Override 2     public void onResume() { 3         logd("onResume()"); 4         super.onResume(); 5         refreshFromBackend(); 6  7         // listen for package changes 8         IntentFilter filter = new IntentFilter(); 9         filter.addAction(Intent.ACTION_PACKAGE_ADDED);//安装10         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);//改变11         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);//卸载12         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);//替换13         filter.addDataScheme(PACKAGE_SCHEME);14         mContext.registerReceiver(mPackageReceiver , filter);15     }16     private class PackageReceiver extends BroadcastReceiver {17         @Override18         public void onReceive(Context context, Intent intent) {19             logd("PackageReceiver.onReceive");20             refreshFromBackend();21         }22     }
复制代码

 

  以上就是屏保的设置内容。您的支持是我不懈的动力,当然不喜勿喷,希望与之交流!有错误或者错字的地方请指正,谢谢!

  补充:这里有个重点没有介绍,那就是DreamBackend这个对屏保管理的类没有进行介绍,我这里只是将代码提供出来,感兴趣的朋友可以一起看看。

复制代码
  1 /*  2  * Copyright (C) 2012 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; 18  19 import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK; 20 import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP; 21 import static android.provider.Settings.Secure.SCREENSAVER_ENABLED; 22  23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.content.pm.ResolveInfo; 28 import android.content.pm.PackageManager.NameNotFoundException; 29 import android.content.pm.ServiceInfo; 30 import android.content.res.Resources; 31 import android.content.res.TypedArray; 32 import android.content.res.XmlResourceParser; 33 import android.graphics.drawable.Drawable; 34 import android.os.RemoteException; 35 import android.os.ServiceManager; 36 import android.provider.Settings; 37 import android.service.dreams.DreamService; 38 import android.service.dreams.IDreamManager; 39 import android.util.AttributeSet; 40 import android.util.Log; 41 import android.util.Xml; 42  43 import org.xmlpull.v1.XmlPullParser; 44 import org.xmlpull.v1.XmlPullParserException; 45  46 import java.io.IOException; 47 import java.util.ArrayList; 48 import java.util.Collections; 49 import java.util.Comparator; 50 import java.util.List; 51  52 public class DreamBackend { 53     private static final String TAG = DreamSettings.class.getSimpleName() + ".Backend"; 54  55     public static class DreamInfo { 56         CharSequence caption; 57         Drawable icon; 58         boolean isActive; 59         public ComponentName componentName; 60         public ComponentName settingsComponentName; 61  62         @Override 63         public String toString() { 64             StringBuilder sb = new StringBuilder(DreamInfo.class.getSimpleName()); 65             sb.append('[').append(caption); 66             if (isActive) 67                 sb.append(",active"); 68             sb.append(',').append(componentName); 69             if (settingsComponentName != null) 70                 sb.append("settings=").append(settingsComponentName); 71             return sb.append(']').toString(); 72         } 73     } 74  75     private final Context mContext; 76     private final IDreamManager mDreamManager; 77     private final DreamInfoComparator mComparator; 78     private final boolean mDreamsEnabledByDefault; 79     private final boolean mDreamsActivatedOnSleepByDefault; 80     private final boolean mDreamsActivatedOnDockByDefault; 81  82     public DreamBackend(Context context) { 83         mContext = context; 84         mDreamManager = IDreamManager.Stub.asInterface( 85                 ServiceManager.getService(DreamService.DREAM_SERVICE)); 86         mComparator = new DreamInfoComparator(getDefaultDream()); 87         mDreamsEnabledByDefault = context.getResources() 88                 .getBoolean(com.android.internal.R.bool.config_dreamsEnabledByDefault); 89         mDreamsActivatedOnSleepByDefault = context.getResources() 90                 .getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault); 91         mDreamsActivatedOnDockByDefault = context.getResources() 92                 .getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault); 93     } 94  95     public List<DreamInfo> getDreamInfos() { 96         logd("getDreamInfos()"); 97         ComponentName activeDream = getActiveDream(); 98         PackageManager pm = mContext.getPackageManager(); 99         Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);100         List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,101                 PackageManager.GET_META_DATA);102         List<DreamInfo> dreamInfos = new ArrayList<DreamInfo>(resolveInfos.size());103         for (ResolveInfo resolveInfo : resolveInfos) {104             if (resolveInfo.serviceInfo == null)105                 continue;106             DreamInfo dreamInfo = new DreamInfo();107             dreamInfo.caption = resolveInfo.loadLabel(pm);108             dreamInfo.icon = resolveInfo.loadIcon(pm);109             dreamInfo.componentName = getDreamComponentName(resolveInfo);110             dreamInfo.isActive = dreamInfo.componentName.equals(activeDream);111             dreamInfo.settingsComponentName = getSettingsComponentName(pm, resolveInfo);112             dreamInfos.add(dreamInfo);113         }114         Collections.sort(dreamInfos, mComparator);115         return dreamInfos;116     }117 118     public ComponentName getDefaultDream() {119         if (mDreamManager == null)120             return null;121         try {122             return mDreamManager.getDefaultDreamComponent();123         } catch (RemoteException e) {124             Log.w(TAG, "Failed to get default dream", e);125             return null;126         }127     }128 129     public CharSequence getActiveDreamName() {130         ComponentName cn = getActiveDream();131         if (cn != null) {132             PackageManager pm = mContext.getPackageManager();133             try {134                 ServiceInfo ri = pm.getServiceInfo(cn, 0);135                 if (ri != null) {136                     return ri.loadLabel(pm);137                 }138             } catch (PackageManager.NameNotFoundException exc) {139                 return null; // uninstalled?140             }141         }142         return null;143     }144 145     public boolean isEnabled() {146         return getBoolean(SCREENSAVER_ENABLED, mDreamsEnabledByDefault);147     }148 149     public void setEnabled(boolean value) {150         logd("setEnabled(%s)", value);151         setBoolean(SCREENSAVER_ENABLED, value);152     }153 154     public boolean isActivatedOnDock() {155         return getBoolean(SCREENSAVER_ACTIVATE_ON_DOCK, mDreamsActivatedOnDockByDefault);156     }157 158     public void setActivatedOnDock(boolean value) {159         logd("setActivatedOnDock(%s)", value);160         setBoolean(SCREENSAVER_ACTIVATE_ON_DOCK, value);161     }162 163     public boolean isActivatedOnSleep() {164         return getBoolean(SCREENSAVER_ACTIVATE_ON_SLEEP, mDreamsActivatedOnSleepByDefault);165     }166 167     public void setActivatedOnSleep(boolean value) {168         logd("setActivatedOnSleep(%s)", value);169         setBoolean(SCREENSAVER_ACTIVATE_ON_SLEEP, value);170     }171 172     private boolean getBoolean(String key, boolean def) {173         return Settings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1;174     }175 176     private void setBoolean(String key, boolean value) {177         Settings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0);178     }179 180     public void setActiveDream(ComponentName dream) {181         logd("setActiveDream(%s)", dream);182         if (mDreamManager == null)183             return;184         try {185             ComponentName[] dreams = { dream };186             mDreamManager.setDreamComponents(dream == null ? null : dreams);187         } catch (RemoteException e) {188             Log.w(TAG, "Failed to set active dream to " + dream, e);189         }190     }191 192     public ComponentName getActiveDream() {193         if (mDreamManager == null)194             return null;195         try {196             ComponentName[] dreams = mDreamManager.getDreamComponents();197             return dreams != null && dreams.length > 0 ? dreams[0] : null;198         } catch (RemoteException e) {199             Log.w(TAG, "Failed to get active dream", e);200             return null;201         }202     }203 204     public void launchSettings(DreamInfo dreamInfo) {205         logd("launchSettings(%s)", dreamInfo);206         if (dreamInfo == null || dreamInfo.settingsComponentName == null)207             return;208         mContext.startActivity(new Intent().setComponent(dreamInfo.settingsComponentName));209     }210 211     public void preview(DreamInfo dreamInfo) {212         logd("preview(%s)", dreamInfo);213         if (mDreamManager == null || dreamInfo == null || dreamInfo.componentName == null)214             return;215         try {216             mDreamManager.testDream(dreamInfo.componentName);217         } catch (RemoteException e) {218             Log.w(TAG, "Failed to preview " + dreamInfo, e);219         }220     }221 222     public void startDreaming() {223         logd("startDreaming()");224         if (mDreamManager == null)225             return;226         try {227             mDreamManager.dream();228         } catch (RemoteException e) {229             Log.w(TAG, "Failed to dream", e);230         }231     }232 233     private static ComponentName getDreamComponentName(ResolveInfo resolveInfo) {234         if (resolveInfo == null || resolveInfo.serviceInfo == null)235             return null;236         return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);237     }238 239     private static ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {240         if (resolveInfo == null241                 || resolveInfo.serviceInfo == null242                 || resolveInfo.serviceInfo.metaData == null)243             return null;244         String cn = null;245         XmlResourceParser parser = null;246         Exception caughtException = null;247         try {248             parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA);249             if (parser == null) {250                 Log.w(TAG, "No " + DreamService.DREAM_META_DATA + " meta-data");251                 return null;252             }253             Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);254             AttributeSet attrs = Xml.asAttributeSet(parser);255             int type;256             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT257                     && type != XmlPullParser.START_TAG) {258             }259             String nodeName = parser.getName();260             if (!"dream".equals(nodeName)) {261                 Log.w(TAG, "Meta-data does not start with dream tag");262                 return null;263             }264             TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.Dream);265             cn = sa.getString(com.android.internal.R.styleable.Dream_settingsActivity);266             sa.recycle();267         } catch (NameNotFoundException e) {268             caughtException = e;269         } catch (IOException e) {270             caughtException = e;271         } catch (XmlPullParserException e) {272             caughtException = e;273         } finally {274             if (parser != null) parser.close();275         }276         if (caughtException != null) {277             Log.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);278             return null;279         }280         if (cn != null && cn.indexOf('/') < 0) {281             cn = resolveInfo.serviceInfo.packageName + "/" + cn;282         }283         return cn == null ? null : ComponentName.unflattenFromString(cn);284     }285 286     private static void logd(String msg, Object... args) {287         if (DreamSettings.DEBUG)288             Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));289     }290 291     private static class DreamInfoComparator implements Comparator<DreamInfo> {292         private final ComponentName mDefaultDream;293 294         public DreamInfoComparator(ComponentName defaultDream) {295             mDefaultDream = defaultDream;296         }297 298         @Override299         public int compare(DreamInfo lhs, DreamInfo rhs) {300             return sortKey(lhs).compareTo(sortKey(rhs));301         }302 303         private String sortKey(DreamInfo di) {304             StringBuilder sb = new StringBuilder();305             sb.append(di.componentName.equals(mDefaultDream) ? '0' : '1');306             sb.append(di.caption);307             return sb.toString();308         }309     }310 }
0 0