diff --git a/res/drawable-hdpi/ic_settings_home.png b/res/drawable-hdpi/ic_settings_home.png new file mode 100644 index 00000000000..42354cd7c2f Binary files /dev/null and b/res/drawable-hdpi/ic_settings_home.png differ diff --git a/res/drawable-mdpi/ic_settings_home.png b/res/drawable-mdpi/ic_settings_home.png new file mode 100644 index 00000000000..8064773265e Binary files /dev/null and b/res/drawable-mdpi/ic_settings_home.png differ diff --git a/res/drawable-xhdpi/ic_settings_home.png b/res/drawable-xhdpi/ic_settings_home.png new file mode 100644 index 00000000000..687025d5f90 Binary files /dev/null and b/res/drawable-xhdpi/ic_settings_home.png differ diff --git a/res/layout/preference_home_app.xml b/res/layout/preference_home_app.xml new file mode 100644 index 00000000000..841816171ef --- /dev/null +++ b/res/layout/preference_home_app.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 8ffa17f34e1..ad3e5be7d9e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1732,6 +1732,7 @@ + Home Display Sound @@ -4667,6 +4668,9 @@ Expand settings for application + + Uninstall this application + This setting affects all users on this tablet. diff --git a/res/xml/home_selection.xml b/res/xml/home_selection.xml new file mode 100644 index 00000000000..a348f9d3ffe --- /dev/null +++ b/res/xml/home_selection.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/res/xml/settings_headers.xml b/res/xml/settings_headers.xml index 6aa6691c022..55b3bca036a 100644 --- a/res/xml/settings_headers.xml +++ b/res/xml/settings_headers.xml @@ -62,6 +62,13 @@
+ +
+
mPrefs; + HomeAppPreference mCurrentHome = null; + final IntentFilter mHomeFilter; + + public HomeSettings() { + mHomeFilter = new IntentFilter(Intent.ACTION_MAIN); + mHomeFilter.addCategory(Intent.CATEGORY_HOME); + mHomeFilter.addCategory(Intent.CATEGORY_DEFAULT); + } + + OnClickListener mHomeClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + int index = (Integer)v.getTag(); + HomeAppPreference pref = mPrefs.get(index); + if (!pref.isChecked) { + makeCurrentHome(pref); + } + } + }; + + OnClickListener mDeleteClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + int index = (Integer)v.getTag(); + uninstallApp(mPrefs.get(index)); + } + }; + + void makeCurrentHome(HomeAppPreference newHome) { + if (mCurrentHome != null) { + mCurrentHome.setChecked(false); + } + newHome.setChecked(true); + mCurrentHome = newHome; + + mPm.replacePreferredActivity(mHomeFilter, IntentFilter.MATCH_CATEGORY_EMPTY, + mHomeComponentSet, newHome.activityName); + } + + void uninstallApp(HomeAppPreference pref) { + // Uninstallation is done by asking the OS to do it + Uri packageURI = Uri.parse("package:" + pref.activityName.getPackageName()); + Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI); + uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false); + int requestCode = REQUESTING_UNINSTALL + (pref.isChecked ? 1 : 0); + startActivityForResult(uninstallIntent, requestCode); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + // Rebuild the list now that we might have nuked something + buildHomeActivitiesList(); + + // if the previous home app is now gone, fall back to the system one + if (requestCode > REQUESTING_UNINSTALL) { + // if mCurrentHome has gone null, it means we didn't find the previously- + // default home app when rebuilding the list, i.e. it was the one we + // just uninstalled. When that happens we make the system-bundled + // home app the active default. + if (mCurrentHome == null) { + for (int i = 0; i < mPrefs.size(); i++) { + HomeAppPreference pref = mPrefs.get(i); + if (pref.isSystem) { + makeCurrentHome(pref); + break; + } + } + } + } + } + + void buildHomeActivitiesList() { + ArrayList homeActivities = new ArrayList(); + ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities); + + Context context = getActivity(); + mCurrentHome = null; + mPrefGroup.removeAll(); + mPrefs = new ArrayList(); + mHomeComponentSet = new ComponentName[homeActivities.size()]; + int prefIndex = 0; + for (int i = 0; i < homeActivities.size(); i++) { + final ResolveInfo candidate = homeActivities.get(i); + final ActivityInfo info = candidate.activityInfo; + ComponentName activityName = new ComponentName(info.packageName, info.name); + mHomeComponentSet[i] = activityName; + try { + Drawable icon = info.loadIcon(mPm); + CharSequence name = info.loadLabel(mPm); + boolean isSystem = (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + HomeAppPreference pref = new HomeAppPreference(context, activityName, prefIndex, + icon, name, this, isSystem); + mPrefs.add(pref); + mPrefGroup.addPreference(pref); + pref.setEnabled(true); + if (activityName.equals(currentDefaultHome)) { + mCurrentHome = pref; + } + prefIndex++; + } catch (Exception e) { + Log.v(TAG, "Problem dealing with activity " + activityName, e); + } + } + + if (mCurrentHome != null) { + new Handler().post(new Runnable() { + public void run() { + mCurrentHome.setChecked(true); + } + }); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.home_selection); + + mPm = getPackageManager(); + mPrefGroup = (PreferenceGroup) findPreference("home"); + } + + @Override + public void onResume() { + super.onResume(); + buildHomeActivitiesList(); + } + + class HomeAppPreference extends Preference { + ComponentName activityName; + int index; + boolean isSystem; + HomeSettings fragment; + final ColorFilter grayscaleFilter; + boolean isChecked; + + public HomeAppPreference(Context context, ComponentName activity, + int i, Drawable icon, CharSequence title, + HomeSettings parent, boolean sys) { + super(context); + setLayoutResource(R.layout.preference_home_app); + setIcon(icon); + setTitle(title); + activityName = activity; + fragment = parent; + index = i; + isSystem = sys; + + ColorMatrix colorMatrix = new ColorMatrix(); + colorMatrix.setSaturation(0f); + float[] matrix = colorMatrix.getArray(); + matrix[18] = 0.5f; + grayscaleFilter = new ColorMatrixColorFilter(colorMatrix); + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + RadioButton radio = (RadioButton) view.findViewById(R.id.home_radio); + radio.setChecked(isChecked); + + Integer indexObj = new Integer(index); + + ImageView icon = (ImageView) view.findViewById(R.id.home_app_uninstall); + if (isSystem) { + icon.setEnabled(false); + icon.setColorFilter(grayscaleFilter); + } else { + icon.setOnClickListener(mDeleteClickListener); + icon.setTag(indexObj); + } + + View v = view.findViewById(R.id.home_app_pref); + v.setOnClickListener(mHomeClickListener); + v.setTag(indexObj); + } + + void setChecked(boolean state) { + if (state != isChecked) { + isChecked = state; + notifyChanged(); + } + } + } +} diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index e754f986d39..bcfffcb59ac 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -26,8 +26,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.INetworkManagementService; @@ -144,7 +146,8 @@ public class Settings extends PreferenceActivity R.id.about_settings, R.id.accessibility_settings, R.id.print_settings, - R.id.nfc_payment_settings + R.id.nfc_payment_settings, + R.id.home_settings }; private SharedPreferences mDevelopmentPreferences; @@ -558,6 +561,8 @@ public class Settings extends PreferenceActivity } else if (id == R.id.account_settings) { int headerIndex = i + 1; i = insertAccountsHeaders(target, headerIndex); + } else if (id == R.id.home_settings) { + updateHomeSettingHeaders(header); } else if (id == R.id.user_settings) { if (!UserHandle.MU_ENABLED || !UserManager.supportsMultipleUsers() @@ -658,6 +663,51 @@ public class Settings extends PreferenceActivity return headerIndex; } + private boolean isSystemApp(ResolveInfo ri) { + return ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0); + } + + private void updateHomeSettingHeaders(Header header) { + final PackageManager pm = getPackageManager(); + final ArrayList homeApps = new ArrayList(); + try { + ComponentName currentHome = pm.getHomeActivities(homeApps); + ResolveInfo iconSource = null; + if (currentHome == null) { + // no current default, so find the system home app and use that + for (int which = 0; which < homeApps.size(); which++) { + ResolveInfo ri = homeApps.get(which); + if (isSystemApp(ri)) { + iconSource = ri; + break; + } + } + } else { + // find the current-home entry in the returned set + for (int which = 0; which < homeApps.size(); which++) { + ResolveInfo ri = homeApps.get(which); + ComponentName riName = new ComponentName(ri.activityInfo.packageName, + ri.activityInfo.name); + if (riName.equals(currentHome)) { + iconSource = ri; + break; + } + } + } + if (iconSource != null) { + if (header.extras == null) { + header.extras = new Bundle(); + } + header.extras.putParcelable(HomeSettings.CURRENT_HOME, iconSource.activityInfo); + } else { + Log.v(LOG_TAG, "No home app icon found"); + } + } catch (Exception e) { + // Can't look up the home activity; bail on configuring the icon + Log.w(LOG_TAG, "Problem looking up home activity!", e); + } + } + private void getMetaData() { try { ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(), @@ -820,17 +870,17 @@ public class Settings extends PreferenceActivity //$FALL-THROUGH$ case HEADER_TYPE_NORMAL: - if (header.extras != null - && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) { + if (header.extras != null && + header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) { String accType = header.extras.getString( ManageAccountsSettings.KEY_ACCOUNT_TYPE); - ViewGroup.LayoutParams lp = holder.icon.getLayoutParams(); - lp.width = getContext().getResources().getDimensionPixelSize( - R.dimen.header_icon_width); - lp.height = lp.width; - holder.icon.setLayoutParams(lp); Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType); - holder.icon.setImageDrawable(icon); + setHeaderIcon(holder, icon); + } else if (header.extras != null && + header.extras.containsKey(HomeSettings.CURRENT_HOME)) { + ActivityInfo ai = header.extras.getParcelable(HomeSettings.CURRENT_HOME); + Drawable icon = ai.loadIcon(getContext().getPackageManager()); + setHeaderIcon(holder, icon); } else { holder.icon.setImageResource(header.iconRes); } @@ -848,6 +898,15 @@ public class Settings extends PreferenceActivity return view; } + private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) { + ViewGroup.LayoutParams lp = holder.icon.getLayoutParams(); + lp.width = getContext().getResources().getDimensionPixelSize( + R.dimen.header_icon_width); + lp.height = lp.width; + holder.icon.setLayoutParams(lp); + holder.icon.setImageDrawable(icon); + } + public void resume() { mWifiEnabler.resume(); mBluetoothEnabler.resume();