Merge "UI Refresh: a new app info header for app/notification."

This commit is contained in:
TreeHugger Robot
2016-10-27 22:43:51 +00:00
committed by Android (Google) Code Review
14 changed files with 665 additions and 10 deletions

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.support.annotation.IntDef;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.applications.ApplicationsState;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class AppHeaderController {
@IntDef({ActionType.ACTION_APP_INFO,
ActionType.ACTION_APP_PREFERENCE,
ActionType.ACTION_STORE_DEEP_LINK,
ActionType.ACTION_NOTIF_PREFERENCE})
@Retention(RetentionPolicy.SOURCE)
@interface ActionType {
int ACTION_APP_INFO = 0;
int ACTION_STORE_DEEP_LINK = 1;
int ACTION_APP_PREFERENCE = 2;
int ACTION_NOTIF_PREFERENCE = 3;
}
private static final String TAG = "AppDetailFeature";
private final Context mContext;
public AppHeaderController(Context context) {
mContext = context;
}
public void bindAppHeader(View appSnippet, PackageInfo packageInfo,
ApplicationsState.AppEntry appEntry) {
final String versionName = packageInfo == null ? null : packageInfo.versionName;
final Resources res = appSnippet.getResources();
// Set Icon
final ImageView iconView = (ImageView) appSnippet.findViewById(android.R.id.icon);
if (appEntry.icon != null) {
iconView.setImageDrawable(appEntry.icon.getConstantState().newDrawable(res));
}
// Set application name.
final TextView labelView = (TextView) appSnippet.findViewById(android.R.id.title);
labelView.setText(appEntry.label);
// Version number of application
final TextView appVersion = (TextView) appSnippet.findViewById(android.R.id.summary);
if (!TextUtils.isEmpty(versionName)) {
appVersion.setSelected(true);
appVersion.setVisibility(View.VISIBLE);
appVersion.setText(res.getString(R.string.version_text, String.valueOf(versionName)));
} else {
appVersion.setVisibility(View.INVISIBLE);
}
}
public void bindAppHeaderButtons(Fragment fragment, View appLinkButtons, String packageName,
@ActionType int leftAction, @ActionType int rightAction) {
ImageButton leftButton = (ImageButton) appLinkButtons.findViewById(R.id.left_button);
ImageButton rightButton = (ImageButton) appLinkButtons.findViewById(R.id.right_button);
bindAppDetailButton(fragment, packageName, leftButton, leftAction);
bindAppDetailButton(fragment, packageName, rightButton, rightAction);
}
private void bindAppDetailButton(Fragment fragment, String packageName,
ImageButton button, @ActionType int action) {
if (button == null) {
return;
}
switch (action) {
case ActionType.ACTION_APP_INFO: {
if (packageName == null || packageName.equals(Utils.OS_PKG)) {
button.setVisibility(View.GONE);
} else {
// TODO
button.setImageResource(com.android.settings.R.drawable.ic_info);
button.setVisibility(View.VISIBLE);
}
return;
}
case ActionType.ACTION_STORE_DEEP_LINK: {
final Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO)
.setPackage(getInstallerPackageName(mContext, packageName));
final Intent result = resolveIntent(intent);
if (result == null) {
button.setVisibility(View.GONE);
} else {
result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
button.setImageResource(R.drawable.ic_sim_sd);
button.setOnClickListener(v -> fragment.startActivity(intent));
button.setVisibility(View.VISIBLE);
}
return;
}
case ActionType.ACTION_NOTIF_PREFERENCE: {
// TODO
return;
}
case ActionType.ACTION_APP_PREFERENCE: {
final Intent intent = resolveIntent(
new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(packageName));
if (intent == null) {
button.setVisibility(View.GONE);
return;
}
button.setOnClickListener(v -> fragment.startActivity(intent));
button.setVisibility(View.VISIBLE);
return;
}
}
}
private String getInstallerPackageName(Context context, String packageName) {
try {
return context.getPackageManager().getInstallerPackageName(packageName);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Exception while retrieving the package installer of " + packageName, e);
return null;
}
}
private Intent resolveIntent(Intent i) {
ResolveInfo result = mContext.getPackageManager().resolveActivity(i, 0);
if (result != null) {
return new Intent(i.getAction())
.setClassName(result.activityInfo.packageName, result.activityInfo.name);
}
return null;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
public interface ApplicationFeatureProvider {
AppHeaderController getAppHeaderController();
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.content.Context;
public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
private final Context mContext;
private AppHeaderController mAppHeaderController;
public ApplicationFeatureProviderImpl(Context context) {
mContext = context.getApplicationContext();
}
@Override
public AppHeaderController getAppHeaderController() {
if (mAppHeaderController == null) {
mAppHeaderController = new AppHeaderController(mContext);
}
return mAppHeaderController;
}
}

View File

@@ -84,6 +84,7 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.datausage.AppDataUsage;
import com.android.settings.datausage.DataUsageList;
import com.android.settings.datausage.DataUsageSummary;
@@ -92,6 +93,7 @@ import com.android.settings.fuelgauge.PowerUsageDetail;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
@@ -138,6 +140,7 @@ public class InstalledAppDetails extends AppInfoBase
private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
private static final String KEY_HEADER = "header_view";
private static final String KEY_FOOTER = "header_footer";
private static final String KEY_NOTIFICATION = "notification_settings";
private static final String KEY_STORAGE = "storage_settings";
private static final String KEY_PERMISSION = "permission_settings";
@@ -148,11 +151,15 @@ public class InstalledAppDetails extends AppInfoBase
private static final String NOTIFICATION_TUNER_SETTING = "show_importance_slider";
private final HashSet<String> mHomePackages = new HashSet<String>();
private final HashSet<String> mHomePackages = new HashSet<>();
private DashboardFeatureProvider mDashboardFeatureProvider;
private AppHeaderController mAppHeaderController;
private boolean mInitialized;
private boolean mShowUninstalled;
private LayoutPreference mHeader;
private LayoutPreference mFooter;
private Button mUninstallButton;
private boolean mUpdatedSysApp = false;
private Button mForceStopButton;
@@ -164,6 +171,7 @@ public class InstalledAppDetails extends AppInfoBase
private Preference mMemoryPreference;
private boolean mDisableAfterUninstall;
// Used for updating notification preference.
private final NotificationBackend mBackend = new NotificationBackend();
@@ -306,9 +314,16 @@ public class InstalledAppDetails extends AppInfoBase
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Activity activity = getActivity();
mDashboardFeatureProvider =
FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
mAppHeaderController = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity).getAppHeaderController();
setHasOptionsMenu(true);
addPreferencesFromResource(R.xml.installed_app_details);
addPreferencesFromResource(mDashboardFeatureProvider.isEnabled()
? R.xml.installed_app_details_ia
: R.xml.installed_app_details);
addDynamicPrefs();
if (Utils.isBandwidthControlEnabled()) {
@@ -366,7 +381,18 @@ public class InstalledAppDetails extends AppInfoBase
if (mFinishing) {
return;
}
handleHeader();
if (!mDashboardFeatureProvider.isEnabled()) {
handleHeader();
} else {
mHeader = (LayoutPreference) findPreference(KEY_HEADER);
mAppHeaderController.bindAppHeaderButtons(
this,
mHeader.findViewById(R.id.app_detail_links),
mPackageName,
AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
AppHeaderController.ActionType.ACTION_APP_PREFERENCE);
prepareUninstallAndStop();
}
mNotificationPreference = findPreference(KEY_NOTIFICATION);
mNotificationPreference.setOnPreferenceClickListener(this);
@@ -404,7 +430,6 @@ public class InstalledAppDetails extends AppInfoBase
private void handleHeader() {
mHeader = (LayoutPreference) findPreference(KEY_HEADER);
// Get Control button panel
View btnPanel = mHeader.findViewById(R.id.control_buttons_panel);
mForceStopButton = (Button) btnPanel.findViewById(R.id.right_button);
@@ -429,6 +454,13 @@ public class InstalledAppDetails extends AppInfoBase
}
}
private void prepareUninstallAndStop() {
mForceStopButton = (Button) mFooter.findViewById(R.id.right_button);
mForceStopButton.setText(R.string.force_stop);
mUninstallButton = (Button) mFooter.findViewById(R.id.left_button);
mForceStopButton.setEnabled(false);
}
private Intent resolveIntent(Intent i) {
ResolveInfo result = getContext().getPackageManager().resolveActivity(i, 0);
return result != null ? new Intent(i.getAction())
@@ -511,8 +543,12 @@ public class InstalledAppDetails extends AppInfoBase
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
final View appSnippet = mHeader.findViewById(R.id.app_snippet);
mState.ensureIcon(mAppEntry);
setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
pkgInfo != null ? pkgInfo.versionName : null);
if (mDashboardFeatureProvider.isEnabled()) {
mAppHeaderController.bindAppHeader(appSnippet, pkgInfo, mAppEntry);
} else {
setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
pkgInfo != null ? pkgInfo.versionName : null);
}
}
private boolean signaturesMatch(String pkg1, String pkg2) {
@@ -917,6 +953,12 @@ public class InstalledAppDetails extends AppInfoBase
}
addAppInstallerInfoPref(screen);
if (mDashboardFeatureProvider.isEnabled()) {
mFooter = new LayoutPreference(screen.getContext(), R.layout.app_action_buttons);
mFooter.setOrder(10000);
mFooter.setKey(KEY_FOOTER);
screen.addPreference(mFooter);
}
}
private void addAppInstallerInfoPref(PreferenceScreen screen) {