Loading src/com/android/settings/notificationlight/NotificationLightSettings.java +137 −136 Original line number Diff line number Diff line Loading @@ -16,24 +16,12 @@ package com.android.settings.notificationlight; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import android.app.AlertDialog; import android.app.Dialog; import android.app.Notification; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -50,6 +38,7 @@ import android.preference.PreferenceScreen; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; Loading @@ -62,11 +51,18 @@ import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeSet; public class NotificationLightSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener, AdapterView.OnItemLongClickListener { private static final String TAG = "NotificationLightSettings"; Loading @@ -74,7 +70,6 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem private static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON = "notification_light_pulse_default_led_on"; private static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF = "notification_light_pulse_default_led_off"; private static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE = "notification_light_pulse_custom_enable"; private static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES = "notification_light_pulse_custom_values"; private static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse"; private static final String NOTIFICATION_LIGHT_PULSE_CALL_COLOR = "notification_light_pulse_call_color"; private static final String NOTIFICATION_LIGHT_PULSE_CALL_LED_ON = "notification_light_pulse_call_led_on"; Loading @@ -94,20 +89,19 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem private int mDefaultColor; private int mDefaultLedOn; private int mDefaultLedOff; private List<ResolveInfo> mInstalledApps; private PackageManager mPackageManager; private boolean mCustomEnabled; private boolean mLightEnabled; private boolean mVoiceCapable; private PreferenceGroup mAppList; private PreferenceGroup mApplicationPrefList; private ApplicationLightPreference mDefaultPref; private ApplicationLightPreference mCallPref; private ApplicationLightPreference mVoicemailPref; private CheckBoxPreference mCustomEnabledPref; private Menu mMenu; AppAdapter mAppAdapter; private String mApplicationList; private Map<String, Application> mApplications; private PackageAdapter mPackageAdapter; private String mPackageList; private Map<String, Package> mPackages; @Override public void onCreate(Bundle savedInstanceState) { Loading @@ -124,13 +118,9 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem // Get launch-able applications mPackageManager = getPackageManager(); final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); mInstalledApps = mPackageManager.queryIntentActivities(mainIntent, 0); mAppAdapter = new AppAdapter(mInstalledApps); mAppAdapter.update(); mPackageAdapter = new PackageAdapter(); mApplications = new HashMap<String, Application>(); mPackages = new HashMap<String, Package>(); // Determine if the device has voice capabilities TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); Loading @@ -143,7 +133,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem public void onResume() { super.onResume(); refreshDefault(); refreshCustomApplications(); refreshCustomApplicationPrefs(); setCustomEnabled(); getListView().setOnItemLongClickListener(this); } Loading Loading @@ -206,48 +196,39 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem } } mAppList = (PreferenceGroup) prefSet.findPreference("applications_list"); mApplicationPrefList = (PreferenceGroup) prefSet.findPreference("applications_list"); mApplicationPrefList.setOrderingAsAdded(false); } private void refreshCustomApplications() { private void refreshCustomApplicationPrefs() { Context context = getActivity(); if (!parseApplicationList()) { if (!parsePackageList()) { return; } // Add the Application Preferences final PreferenceScreen prefSet = getPreferenceScreen(); final PackageManager pm = getPackageManager(); if (mAppList != null) { final Map<CharSequence, ApplicationLightPreference> prefs = new TreeMap<CharSequence, ApplicationLightPreference>(); mAppList.removeAll(); if (mApplicationPrefList != null) { mApplicationPrefList.removeAll(); for (Application i : mApplications.values()) { for (Package pkg : mPackages.values()) { try { PackageInfo info = pm.getPackageInfo(i.name, PackageManager.GET_META_DATA); PackageInfo info = mPackageManager.getPackageInfo(pkg.name, PackageManager.GET_META_DATA); ApplicationLightPreference pref = new ApplicationLightPreference(context, i.color, i.timeon, i.timeoff); final CharSequence label = info.applicationInfo.loadLabel(pm); new ApplicationLightPreference(context, pkg.color, pkg.timeon, pkg.timeoff); pref.setKey(i.name); pref.setTitle(label); pref.setIcon(info.applicationInfo.loadIcon(pm)); pref.setKey(pkg.name); pref.setTitle(info.applicationInfo.loadLabel(mPackageManager)); pref.setIcon(info.applicationInfo.loadIcon(mPackageManager)); pref.setPersistent(false); pref.setOnPreferenceChangeListener(this); prefs.put(label, pref); mApplicationPrefList.addPreference(pref); } catch (NameNotFoundException e) { // Do nothing } } for (ApplicationLightPreference pref : prefs.values()) { mAppList.addPreference(pref); } } } Loading @@ -261,39 +242,39 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem } // Custom applications if (mAppList != null) { mAppList.setEnabled(enabled); if (mApplicationPrefList != null) { mApplicationPrefList.setEnabled(enabled); setHasOptionsMenu(enabled); } } private void addCustomApplication(String packageName) { Application app = mApplications.get(packageName); if (app == null) { app = new Application(packageName, mDefaultColor, mDefaultLedOn, mDefaultLedOff); mApplications.put(packageName, app); saveApplicationList(false); refreshCustomApplications(); private void addCustomApplicationPref(String packageName) { Package pkg = mPackages.get(packageName); if (pkg == null) { pkg = new Package(packageName, mDefaultColor, mDefaultLedOn, mDefaultLedOff); mPackages.put(packageName, pkg); savePackageList(false); refreshCustomApplicationPrefs(); } } private void removeCustomApplication(String packageName) { if (mApplications.remove(packageName) != null) { saveApplicationList(false); refreshCustomApplications(); private void removeCustomApplicationPref(String packageName) { if (mPackages.remove(packageName) != null) { savePackageList(false); refreshCustomApplicationPrefs(); } } private boolean parseApplicationList() { private boolean parsePackageList() { final String baseString = Settings.System.getString(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES); if (TextUtils.equals(mApplicationList, baseString)) { if (TextUtils.equals(mPackageList, baseString)) { return false; } mApplicationList = baseString; mApplications.clear(); mPackageList = baseString; mPackages.clear(); if (baseString != null) { final String[] array = TextUtils.split(baseString, "\\|"); Loading @@ -301,9 +282,9 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem if (TextUtils.isEmpty(item)) { continue; } Application app = Application.fromString(item); if (app != null) { mApplications.put(app.name, app); Package pkg = Package.fromString(item); if (pkg != null) { mPackages.put(pkg.name, pkg); } } } Loading @@ -311,43 +292,43 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return true; } private void saveApplicationList(boolean preferencesUpdated) { private void savePackageList(boolean preferencesUpdated) { List<String> settings = new ArrayList<String>(); for (Application app : mApplications.values()) { for (Package app : mPackages.values()) { settings.add(app.toString()); } final String value = TextUtils.join("|", settings); if (preferencesUpdated) { mApplicationList = value; mPackageList = value; } Settings.System.putString(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, value); } /** * Updates the default or application specific notification settings. * Updates the default or package specific notification settings. * * @param application Package name of application specific settings to update * @param packageName Package name of application specific settings to update * @param color * @param timeon * @param timeoff */ protected void updateValues(String application, Integer color, Integer timeon, Integer timeoff) { protected void updateValues(String packageName, Integer color, Integer timeon, Integer timeoff) { ContentResolver resolver = getContentResolver(); if (application.equals(DEFAULT_PREF)) { if (packageName.equals(DEFAULT_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, timeoff); refreshDefault(); return; } else if (application.equals(MISSED_CALL_PREF)) { } else if (packageName.equals(MISSED_CALL_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_LED_OFF, timeoff); refreshDefault(); return; } else if (application.equals(VOICEMAIL_PREF)) { } else if (packageName.equals(VOICEMAIL_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_LED_OFF, timeoff); Loading @@ -355,20 +336,20 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return; } // Find the custom app and sets its new values Application app = mApplications.get(application); // Find the custom package and sets its new values Package app = mPackages.get(packageName); if (app != null) { app.color = color; app.timeon = timeon; app.timeoff = timeoff; saveApplicationList(true); savePackageList(true); } } public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { final Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position); if (mAppList.findPreference(pref.getKey()) != pref) { if (mApplicationPrefList.findPreference(pref.getKey()) != pref) { return false; } Loading @@ -379,7 +360,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { removeCustomApplication(pref.getKey()); removeCustomApplicationPref(pref.getKey()); } }) .setNegativeButton(android.R.string.cancel, null); Loading Loading @@ -439,7 +420,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem switch (id) { case DIALOG_APPS: final ListView list = new ListView(getActivity()); list.setAdapter(mAppAdapter); list.setAdapter(mPackageAdapter); builder.setTitle(R.string.profile_choose_app); builder.setView(list); Loading @@ -449,8 +430,8 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // Add empty application definition, the user will be able to edit it later AppItem info = (AppItem) parent.getItemAtPosition(position); addCustomApplication(info.packageName); PackageItem info = (PackageItem) parent.getItemAtPosition(position); addCustomApplicationPref(info.packageName); dialog.cancel(); } }); Loading @@ -464,7 +445,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem /** * Application class */ private static class Application { private static class Package { public String name; public Integer color; public Integer timeon; Loading @@ -477,16 +458,13 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem * @param timeon * @param timeoff */ public Application(String name, Integer color, Integer timeon, Integer timeoff) { public Package(String name, Integer color, Integer timeon, Integer timeoff) { this.name = name; this.color = color; this.timeon = timeon; this.timeoff = timeoff; } public Application() { } public String toString() { StringBuilder builder = new StringBuilder(); builder.append(name); Loading @@ -499,7 +477,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return builder.toString(); } public static Application fromString(String value) { public static Package fromString(String value) { if (TextUtils.isEmpty(value)) { return null; } Loading @@ -512,7 +490,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return null; try { Application item = new Application(app[0], Integer.parseInt(values[0]), Integer Package item = new Package(app[0], Integer.parseInt(values[0]), Integer .parseInt(values[1]), Integer.parseInt(values[2])); return item; } catch (NumberFormatException e) { Loading @@ -525,76 +503,92 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem /** * AppItem class */ class AppItem implements Comparable<AppItem> { private static class PackageItem implements Comparable<PackageItem> { CharSequence title; TreeSet<CharSequence> activityTitles = new TreeSet<CharSequence>(); String packageName; Drawable icon; @Override public int compareTo(AppItem another) { return this.title.toString().compareTo(another.title.toString()); public int compareTo(PackageItem another) { int result = title.toString().compareToIgnoreCase(another.title.toString()); return result != 0 ? result : packageName.compareTo(another.packageName); } } /** * AppAdapter class */ class AppAdapter extends BaseAdapter { protected List<ResolveInfo> mInstalledAppInfo; protected List<AppItem> mInstalledApps = new LinkedList<AppItem>(); private class PackageAdapter extends BaseAdapter { private List<PackageItem> mInstalledPackages = new LinkedList<PackageItem>(); private void reloadList() { final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { synchronized (mInstalledApps) { mInstalledApps.clear(); for (ResolveInfo info : mInstalledAppInfo) { final AppItem item = new AppItem(); item.title = info.loadLabel(mPackageManager); item.icon = info.loadIcon(mPackageManager); item.packageName = info.activityInfo.packageName; handler.post(new Runnable() { synchronized (mInstalledPackages) { mInstalledPackages.clear(); } final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> installedAppsInfo = mPackageManager.queryIntentActivities(mainIntent, 0); for (ResolveInfo info : installedAppsInfo) { ApplicationInfo appInfo = info.activityInfo.applicationInfo; final PackageItem item = new PackageItem(); item.title = appInfo.loadLabel(mPackageManager); item.activityTitles.add(info.loadLabel(mPackageManager)); item.icon = appInfo.loadIcon(mPackageManager); item.packageName = appInfo.packageName; handler.post(new Runnable() { @Override public void run() { int index = Collections.binarySearch(mInstalledApps, item); // NO synchronize here: We know that mInstalledApps.clear() // was called and will never be called again. // At this point the only thread modifying mInstalledApp is main int index = Collections.binarySearch(mInstalledPackages, item); if (index < 0) { index = -index - 1; mInstalledApps.add(index, item); mInstalledPackages.add(-index - 1, item); } else { mInstalledPackages.get(index).activityTitles.addAll(item.activityTitles); } notifyDataSetChanged(); } }); } } } }).start(); } public AppAdapter(List<ResolveInfo> installedAppsInfo) { mInstalledAppInfo = installedAppsInfo; } public void update() { public PackageAdapter() { reloadList(); } @Override public int getCount() { return mInstalledApps.size(); synchronized (mInstalledPackages) { return mInstalledPackages.size(); } } @Override public AppItem getItem(int position) { return mInstalledApps.get(position); public PackageItem getItem(int position) { synchronized (mInstalledPackages) { return mInstalledPackages.get(position); } } @Override public long getItemId(int position) { return mInstalledApps.get(position).packageName.hashCode(); synchronized (mInstalledPackages) { // packageName is guaranteed to be unique in mInstalledPackages return mInstalledPackages.get(position).packageName.hashCode(); } } @Override Loading @@ -611,18 +605,25 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem holder.summary = (TextView) convertView.findViewById(com.android.internal.R.id.summary); holder.icon = (ImageView) convertView.findViewById(R.id.icon); } AppItem applicationInfo = getItem(position); PackageItem applicationInfo = getItem(position); if (holder.title != null) { holder.title.setText(applicationInfo.title); holder.icon.setImageDrawable(applicationInfo.icon); boolean needSummary = applicationInfo.activityTitles.size() > 0; if (applicationInfo.activityTitles.size() == 1) { if (TextUtils.equals(applicationInfo.title, applicationInfo.activityTitles.first())) { needSummary = false; } if (holder.summary != null) { holder.summary.setVisibility(View.GONE); } if (holder.icon != null) { Drawable loadIcon = applicationInfo.icon; holder.icon.setImageDrawable(loadIcon); if (needSummary) { holder.summary.setText(TextUtils.join(", ", applicationInfo.activityTitles)); holder.summary.setVisibility(View.VISIBLE); } else { holder.summary.setVisibility(View.GONE); } return convertView; } } Loading Loading
src/com/android/settings/notificationlight/NotificationLightSettings.java +137 −136 Original line number Diff line number Diff line Loading @@ -16,24 +16,12 @@ package com.android.settings.notificationlight; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import android.app.AlertDialog; import android.app.Dialog; import android.app.Notification; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -50,6 +38,7 @@ import android.preference.PreferenceScreen; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; Loading @@ -62,11 +51,18 @@ import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeSet; public class NotificationLightSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener, AdapterView.OnItemLongClickListener { private static final String TAG = "NotificationLightSettings"; Loading @@ -74,7 +70,6 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem private static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON = "notification_light_pulse_default_led_on"; private static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF = "notification_light_pulse_default_led_off"; private static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE = "notification_light_pulse_custom_enable"; private static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES = "notification_light_pulse_custom_values"; private static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse"; private static final String NOTIFICATION_LIGHT_PULSE_CALL_COLOR = "notification_light_pulse_call_color"; private static final String NOTIFICATION_LIGHT_PULSE_CALL_LED_ON = "notification_light_pulse_call_led_on"; Loading @@ -94,20 +89,19 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem private int mDefaultColor; private int mDefaultLedOn; private int mDefaultLedOff; private List<ResolveInfo> mInstalledApps; private PackageManager mPackageManager; private boolean mCustomEnabled; private boolean mLightEnabled; private boolean mVoiceCapable; private PreferenceGroup mAppList; private PreferenceGroup mApplicationPrefList; private ApplicationLightPreference mDefaultPref; private ApplicationLightPreference mCallPref; private ApplicationLightPreference mVoicemailPref; private CheckBoxPreference mCustomEnabledPref; private Menu mMenu; AppAdapter mAppAdapter; private String mApplicationList; private Map<String, Application> mApplications; private PackageAdapter mPackageAdapter; private String mPackageList; private Map<String, Package> mPackages; @Override public void onCreate(Bundle savedInstanceState) { Loading @@ -124,13 +118,9 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem // Get launch-able applications mPackageManager = getPackageManager(); final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); mInstalledApps = mPackageManager.queryIntentActivities(mainIntent, 0); mAppAdapter = new AppAdapter(mInstalledApps); mAppAdapter.update(); mPackageAdapter = new PackageAdapter(); mApplications = new HashMap<String, Application>(); mPackages = new HashMap<String, Package>(); // Determine if the device has voice capabilities TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); Loading @@ -143,7 +133,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem public void onResume() { super.onResume(); refreshDefault(); refreshCustomApplications(); refreshCustomApplicationPrefs(); setCustomEnabled(); getListView().setOnItemLongClickListener(this); } Loading Loading @@ -206,48 +196,39 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem } } mAppList = (PreferenceGroup) prefSet.findPreference("applications_list"); mApplicationPrefList = (PreferenceGroup) prefSet.findPreference("applications_list"); mApplicationPrefList.setOrderingAsAdded(false); } private void refreshCustomApplications() { private void refreshCustomApplicationPrefs() { Context context = getActivity(); if (!parseApplicationList()) { if (!parsePackageList()) { return; } // Add the Application Preferences final PreferenceScreen prefSet = getPreferenceScreen(); final PackageManager pm = getPackageManager(); if (mAppList != null) { final Map<CharSequence, ApplicationLightPreference> prefs = new TreeMap<CharSequence, ApplicationLightPreference>(); mAppList.removeAll(); if (mApplicationPrefList != null) { mApplicationPrefList.removeAll(); for (Application i : mApplications.values()) { for (Package pkg : mPackages.values()) { try { PackageInfo info = pm.getPackageInfo(i.name, PackageManager.GET_META_DATA); PackageInfo info = mPackageManager.getPackageInfo(pkg.name, PackageManager.GET_META_DATA); ApplicationLightPreference pref = new ApplicationLightPreference(context, i.color, i.timeon, i.timeoff); final CharSequence label = info.applicationInfo.loadLabel(pm); new ApplicationLightPreference(context, pkg.color, pkg.timeon, pkg.timeoff); pref.setKey(i.name); pref.setTitle(label); pref.setIcon(info.applicationInfo.loadIcon(pm)); pref.setKey(pkg.name); pref.setTitle(info.applicationInfo.loadLabel(mPackageManager)); pref.setIcon(info.applicationInfo.loadIcon(mPackageManager)); pref.setPersistent(false); pref.setOnPreferenceChangeListener(this); prefs.put(label, pref); mApplicationPrefList.addPreference(pref); } catch (NameNotFoundException e) { // Do nothing } } for (ApplicationLightPreference pref : prefs.values()) { mAppList.addPreference(pref); } } } Loading @@ -261,39 +242,39 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem } // Custom applications if (mAppList != null) { mAppList.setEnabled(enabled); if (mApplicationPrefList != null) { mApplicationPrefList.setEnabled(enabled); setHasOptionsMenu(enabled); } } private void addCustomApplication(String packageName) { Application app = mApplications.get(packageName); if (app == null) { app = new Application(packageName, mDefaultColor, mDefaultLedOn, mDefaultLedOff); mApplications.put(packageName, app); saveApplicationList(false); refreshCustomApplications(); private void addCustomApplicationPref(String packageName) { Package pkg = mPackages.get(packageName); if (pkg == null) { pkg = new Package(packageName, mDefaultColor, mDefaultLedOn, mDefaultLedOff); mPackages.put(packageName, pkg); savePackageList(false); refreshCustomApplicationPrefs(); } } private void removeCustomApplication(String packageName) { if (mApplications.remove(packageName) != null) { saveApplicationList(false); refreshCustomApplications(); private void removeCustomApplicationPref(String packageName) { if (mPackages.remove(packageName) != null) { savePackageList(false); refreshCustomApplicationPrefs(); } } private boolean parseApplicationList() { private boolean parsePackageList() { final String baseString = Settings.System.getString(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES); if (TextUtils.equals(mApplicationList, baseString)) { if (TextUtils.equals(mPackageList, baseString)) { return false; } mApplicationList = baseString; mApplications.clear(); mPackageList = baseString; mPackages.clear(); if (baseString != null) { final String[] array = TextUtils.split(baseString, "\\|"); Loading @@ -301,9 +282,9 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem if (TextUtils.isEmpty(item)) { continue; } Application app = Application.fromString(item); if (app != null) { mApplications.put(app.name, app); Package pkg = Package.fromString(item); if (pkg != null) { mPackages.put(pkg.name, pkg); } } } Loading @@ -311,43 +292,43 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return true; } private void saveApplicationList(boolean preferencesUpdated) { private void savePackageList(boolean preferencesUpdated) { List<String> settings = new ArrayList<String>(); for (Application app : mApplications.values()) { for (Package app : mPackages.values()) { settings.add(app.toString()); } final String value = TextUtils.join("|", settings); if (preferencesUpdated) { mApplicationList = value; mPackageList = value; } Settings.System.putString(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, value); } /** * Updates the default or application specific notification settings. * Updates the default or package specific notification settings. * * @param application Package name of application specific settings to update * @param packageName Package name of application specific settings to update * @param color * @param timeon * @param timeoff */ protected void updateValues(String application, Integer color, Integer timeon, Integer timeoff) { protected void updateValues(String packageName, Integer color, Integer timeon, Integer timeoff) { ContentResolver resolver = getContentResolver(); if (application.equals(DEFAULT_PREF)) { if (packageName.equals(DEFAULT_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, timeoff); refreshDefault(); return; } else if (application.equals(MISSED_CALL_PREF)) { } else if (packageName.equals(MISSED_CALL_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_CALL_LED_OFF, timeoff); refreshDefault(); return; } else if (application.equals(VOICEMAIL_PREF)) { } else if (packageName.equals(VOICEMAIL_PREF)) { Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR, color); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_LED_ON, timeon); Settings.System.putInt(resolver, NOTIFICATION_LIGHT_PULSE_VMAIL_LED_OFF, timeoff); Loading @@ -355,20 +336,20 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return; } // Find the custom app and sets its new values Application app = mApplications.get(application); // Find the custom package and sets its new values Package app = mPackages.get(packageName); if (app != null) { app.color = color; app.timeon = timeon; app.timeoff = timeoff; saveApplicationList(true); savePackageList(true); } } public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { final Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position); if (mAppList.findPreference(pref.getKey()) != pref) { if (mApplicationPrefList.findPreference(pref.getKey()) != pref) { return false; } Loading @@ -379,7 +360,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { removeCustomApplication(pref.getKey()); removeCustomApplicationPref(pref.getKey()); } }) .setNegativeButton(android.R.string.cancel, null); Loading Loading @@ -439,7 +420,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem switch (id) { case DIALOG_APPS: final ListView list = new ListView(getActivity()); list.setAdapter(mAppAdapter); list.setAdapter(mPackageAdapter); builder.setTitle(R.string.profile_choose_app); builder.setView(list); Loading @@ -449,8 +430,8 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // Add empty application definition, the user will be able to edit it later AppItem info = (AppItem) parent.getItemAtPosition(position); addCustomApplication(info.packageName); PackageItem info = (PackageItem) parent.getItemAtPosition(position); addCustomApplicationPref(info.packageName); dialog.cancel(); } }); Loading @@ -464,7 +445,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem /** * Application class */ private static class Application { private static class Package { public String name; public Integer color; public Integer timeon; Loading @@ -477,16 +458,13 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem * @param timeon * @param timeoff */ public Application(String name, Integer color, Integer timeon, Integer timeoff) { public Package(String name, Integer color, Integer timeon, Integer timeoff) { this.name = name; this.color = color; this.timeon = timeon; this.timeoff = timeoff; } public Application() { } public String toString() { StringBuilder builder = new StringBuilder(); builder.append(name); Loading @@ -499,7 +477,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return builder.toString(); } public static Application fromString(String value) { public static Package fromString(String value) { if (TextUtils.isEmpty(value)) { return null; } Loading @@ -512,7 +490,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem return null; try { Application item = new Application(app[0], Integer.parseInt(values[0]), Integer Package item = new Package(app[0], Integer.parseInt(values[0]), Integer .parseInt(values[1]), Integer.parseInt(values[2])); return item; } catch (NumberFormatException e) { Loading @@ -525,76 +503,92 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem /** * AppItem class */ class AppItem implements Comparable<AppItem> { private static class PackageItem implements Comparable<PackageItem> { CharSequence title; TreeSet<CharSequence> activityTitles = new TreeSet<CharSequence>(); String packageName; Drawable icon; @Override public int compareTo(AppItem another) { return this.title.toString().compareTo(another.title.toString()); public int compareTo(PackageItem another) { int result = title.toString().compareToIgnoreCase(another.title.toString()); return result != 0 ? result : packageName.compareTo(another.packageName); } } /** * AppAdapter class */ class AppAdapter extends BaseAdapter { protected List<ResolveInfo> mInstalledAppInfo; protected List<AppItem> mInstalledApps = new LinkedList<AppItem>(); private class PackageAdapter extends BaseAdapter { private List<PackageItem> mInstalledPackages = new LinkedList<PackageItem>(); private void reloadList() { final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { synchronized (mInstalledApps) { mInstalledApps.clear(); for (ResolveInfo info : mInstalledAppInfo) { final AppItem item = new AppItem(); item.title = info.loadLabel(mPackageManager); item.icon = info.loadIcon(mPackageManager); item.packageName = info.activityInfo.packageName; handler.post(new Runnable() { synchronized (mInstalledPackages) { mInstalledPackages.clear(); } final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> installedAppsInfo = mPackageManager.queryIntentActivities(mainIntent, 0); for (ResolveInfo info : installedAppsInfo) { ApplicationInfo appInfo = info.activityInfo.applicationInfo; final PackageItem item = new PackageItem(); item.title = appInfo.loadLabel(mPackageManager); item.activityTitles.add(info.loadLabel(mPackageManager)); item.icon = appInfo.loadIcon(mPackageManager); item.packageName = appInfo.packageName; handler.post(new Runnable() { @Override public void run() { int index = Collections.binarySearch(mInstalledApps, item); // NO synchronize here: We know that mInstalledApps.clear() // was called and will never be called again. // At this point the only thread modifying mInstalledApp is main int index = Collections.binarySearch(mInstalledPackages, item); if (index < 0) { index = -index - 1; mInstalledApps.add(index, item); mInstalledPackages.add(-index - 1, item); } else { mInstalledPackages.get(index).activityTitles.addAll(item.activityTitles); } notifyDataSetChanged(); } }); } } } }).start(); } public AppAdapter(List<ResolveInfo> installedAppsInfo) { mInstalledAppInfo = installedAppsInfo; } public void update() { public PackageAdapter() { reloadList(); } @Override public int getCount() { return mInstalledApps.size(); synchronized (mInstalledPackages) { return mInstalledPackages.size(); } } @Override public AppItem getItem(int position) { return mInstalledApps.get(position); public PackageItem getItem(int position) { synchronized (mInstalledPackages) { return mInstalledPackages.get(position); } } @Override public long getItemId(int position) { return mInstalledApps.get(position).packageName.hashCode(); synchronized (mInstalledPackages) { // packageName is guaranteed to be unique in mInstalledPackages return mInstalledPackages.get(position).packageName.hashCode(); } } @Override Loading @@ -611,18 +605,25 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem holder.summary = (TextView) convertView.findViewById(com.android.internal.R.id.summary); holder.icon = (ImageView) convertView.findViewById(R.id.icon); } AppItem applicationInfo = getItem(position); PackageItem applicationInfo = getItem(position); if (holder.title != null) { holder.title.setText(applicationInfo.title); holder.icon.setImageDrawable(applicationInfo.icon); boolean needSummary = applicationInfo.activityTitles.size() > 0; if (applicationInfo.activityTitles.size() == 1) { if (TextUtils.equals(applicationInfo.title, applicationInfo.activityTitles.first())) { needSummary = false; } if (holder.summary != null) { holder.summary.setVisibility(View.GONE); } if (holder.icon != null) { Drawable loadIcon = applicationInfo.icon; holder.icon.setImageDrawable(loadIcon); if (needSummary) { holder.summary.setText(TextUtils.join(", ", applicationInfo.activityTitles)); holder.summary.setVisibility(View.VISIBLE); } else { holder.summary.setVisibility(View.GONE); } return convertView; } } Loading