New design for instant apps in app details header
Bug: 35098444 Test: make RunSettingsRoboTests In the previous design for instant apps, some metadata about the app such as developer title, maturity rating, etc. was going to be shown in the app header. In the latest design, we instead are just showing a little label that says "Instant app". The two CL's for this topic work together to change this: frameworks/base : adds code to work around the problem that robolectric doesn't know about the new isInstantApp method of the ApplicationInfo class, so we need to avoid calling it during tests. pacakges/apps/Settings: removes the code that previously displayed the instant app metadata, and instead just insert the "Instant app" label. Change-Id: I2cbc70bf4827c401e862c58ea4ca7f8f9ba1cf58
This commit is contained in:
@@ -36,8 +36,6 @@ import android.widget.TextView;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.applications.InstantDataBuilder.Param;
|
||||
import com.android.settings.applications.instantapps.InstantAppDetails;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -251,102 +249,27 @@ public class AppHeaderControllerTest {
|
||||
.isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
// Ensure that no instant app related information shows up when the AppHeaderController's
|
||||
// InstantAppDetails are null.
|
||||
// Ensure that the instant app label does not show up when we haven't told the controller the
|
||||
// app is instant.
|
||||
@Test
|
||||
public void instantApps_nullInstantAppDetails() {
|
||||
public void instantApps_normalAppsDontGetLabel() {
|
||||
final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
|
||||
mController = new AppHeaderController(mContext, mFragment, appHeader);
|
||||
mController.setInstantAppDetails(null);
|
||||
mController.done();
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_developer_title).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_maturity).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_monetization).getVisibility())
|
||||
assertThat(appHeader.findViewById(R.id.install_type).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
// Ensure that no instant app related information shows up when the AppHeaderController has
|
||||
// a non-null InstantAppDetails, but each member of it is null.
|
||||
// Test that the "instant apps" label is present in the header when we have an instant app.
|
||||
@Test
|
||||
public void instantApps_detailsMembersNull() {
|
||||
public void instantApps_expectedHeaderItem() {
|
||||
final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
|
||||
mController = new AppHeaderController(mContext, mFragment, appHeader);
|
||||
|
||||
InstantAppDetails details = InstantDataBuilder.build(mContext, EnumSet.noneOf(Param.class));
|
||||
mController.setInstantAppDetails(details);
|
||||
mController.setIsInstantApp(true);
|
||||
mController.done();
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_developer_title).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_maturity).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
assertThat(appHeader.findViewById(R.id.instant_app_monetization).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
// Helper to assert a TextView for a given id is visible and has a certain string value.
|
||||
private void assertVisibleContent(View header, @IdRes int id, String expectedValue) {
|
||||
TextView view = (TextView)header.findViewById(id);
|
||||
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(view.getText()).isEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
// Helper to assert an ImageView for a given id is visible and has a certain Drawable value.
|
||||
private void assertVisibleContent(View header, @IdRes int id, Drawable expectedValue) {
|
||||
ImageView view = (ImageView)header.findViewById(id);
|
||||
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(view.getDrawable()).isEqualTo(expectedValue);
|
||||
}
|
||||
|
||||
// Test that expected items are present in the header when we have a complete InstantAppDetails.
|
||||
@Test
|
||||
public void instantApps_expectedHeaderItems() {
|
||||
final View header = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
|
||||
mController = new AppHeaderController(mContext, mFragment, header);
|
||||
|
||||
InstantAppDetails details = InstantDataBuilder.build(mContext);
|
||||
mController.setInstantAppDetails(details);
|
||||
mController.done();
|
||||
|
||||
assertVisibleContent(header, R.id.instant_app_developer_title, details.developerTitle);
|
||||
assertVisibleContent(header, R.id.instant_app_maturity_icon,
|
||||
details.maturityRatingIcon);
|
||||
assertVisibleContent(header, R.id.instant_app_maturity_text,
|
||||
details.maturityRatingString);
|
||||
assertVisibleContent(header, R.id.instant_app_monetization,
|
||||
details.monetizationNotice);
|
||||
}
|
||||
|
||||
// Test having each member of InstantAppDetails be null.
|
||||
@Test
|
||||
public void instantApps_expectedHeaderItemsWithSingleNullMembers() {
|
||||
final EnumSet<Param> allParams = EnumSet.allOf(Param.class);
|
||||
for (Param paramToRemove : allParams) {
|
||||
EnumSet<Param> params = allParams.clone();
|
||||
params.remove(paramToRemove);
|
||||
final View header = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
|
||||
mController = new AppHeaderController(mContext, mFragment, header);
|
||||
InstantAppDetails details = InstantDataBuilder.build(mContext, params);
|
||||
mController.setInstantAppDetails(details);
|
||||
mController.done();
|
||||
|
||||
if (params.contains(Param.DEVELOPER_TITLE)) {
|
||||
assertVisibleContent(header, R.id.instant_app_developer_title,
|
||||
details.developerTitle);
|
||||
}
|
||||
if (params.contains(Param.MATURITY_RATING_ICON)) {
|
||||
assertVisibleContent(header, R.id.instant_app_maturity_icon,
|
||||
details.maturityRatingIcon);
|
||||
}
|
||||
if (params.contains(Param.MATURITY_RATING_STRING)) {
|
||||
assertVisibleContent(header, R.id.instant_app_maturity_text,
|
||||
details.maturityRatingString);
|
||||
}
|
||||
if (params.contains(Param.MONETIZATION_NOTICE)) {
|
||||
assertVisibleContent(header, R.id.instant_app_monetization,
|
||||
details.monetizationNotice);
|
||||
}
|
||||
}
|
||||
TextView label = (TextView)appHeader.findViewById(R.id.install_type);
|
||||
assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(label.getText()).isEqualTo(
|
||||
appHeader.getResources().getString(R.string.install_type_instant));
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -37,6 +39,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -88,7 +91,8 @@ public class AppInfoWithHeaderTest {
|
||||
mScreen = mock(PreferenceScreen.class);
|
||||
mPackageInfo = new PackageInfo();
|
||||
mPackageInfo.applicationInfo = new ApplicationInfo();
|
||||
|
||||
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
|
||||
(InstantAppDataProvider) (info -> false));
|
||||
when(mManager.getContext())
|
||||
.thenReturn(ShadowApplication.getInstance().getApplicationContext());
|
||||
}
|
||||
|
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2017 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;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.instantapps.InstantAppDetails;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Utility class for generating fake InstantAppDetails data to use in tests.
|
||||
*/
|
||||
public class InstantDataBuilder {
|
||||
public enum Param {
|
||||
MATURITY_RATING_ICON,
|
||||
MATURITY_RATING_STRING,
|
||||
MONETIZATION_NOTICE,
|
||||
DEVELOPER_TITLE,
|
||||
PRIVACY_POLICY,
|
||||
DEVELOPER_WEBSITE,
|
||||
DEVELOPER_EMAIL,
|
||||
DEVELOPER_MAILING_ADDRESS
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an InstantAppDetails with any desired combination of null/non-null members.
|
||||
*
|
||||
* @param context An optional context, required only if MATURITY_RATING_ICON is a member of
|
||||
* params
|
||||
* @param params Specifies which elements of the returned InstantAppDetails should be non-null
|
||||
* @return InstantAppDetails
|
||||
*/
|
||||
public static InstantAppDetails build(@Nullable Context context, EnumSet<Param> params) {
|
||||
Drawable ratingIcon = null;
|
||||
String rating = null;
|
||||
String monetizationNotice = null;
|
||||
String developerTitle = null;
|
||||
URL privacyPolicy = null;
|
||||
URL developerWebsite = null;
|
||||
String developerEmail = null;
|
||||
String developerMailingAddress = null;
|
||||
|
||||
if (params.contains(Param.MATURITY_RATING_ICON)) {
|
||||
ratingIcon = context.getDrawable(R.drawable.ic_android);
|
||||
}
|
||||
if (params.contains(Param.MATURITY_RATING_STRING)) {
|
||||
rating = "everyone";
|
||||
}
|
||||
if (params.contains(Param.MONETIZATION_NOTICE)) {
|
||||
monetizationNotice = "Uses in-app purchases";
|
||||
}
|
||||
if (params.contains(Param.DEVELOPER_TITLE)) {
|
||||
developerTitle = "Instant Apps Inc.";
|
||||
}
|
||||
if (params.contains(Param.DEVELOPER_EMAIL)) {
|
||||
developerEmail = "developer@instant-apps.com";
|
||||
}
|
||||
if (params.contains(Param.DEVELOPER_MAILING_ADDRESS)) {
|
||||
developerMailingAddress = "1 Main Street, Somewhere, CA, 94043";
|
||||
}
|
||||
|
||||
if (params.contains(Param.PRIVACY_POLICY)) {
|
||||
try {
|
||||
privacyPolicy = new URL("https://test.com/privacy");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
if (params.contains(Param.DEVELOPER_WEBSITE)) {
|
||||
try {
|
||||
developerWebsite = new URL("https://test.com");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return InstantAppDetails.builder()
|
||||
.maturityRatingIcon(ratingIcon)
|
||||
.maturityRatingString(rating)
|
||||
.monetizationNotice(monetizationNotice)
|
||||
.developerTitle(developerTitle)
|
||||
.privacyPolicy(privacyPolicy)
|
||||
.developerWebsite(developerWebsite)
|
||||
.developerEmail(developerEmail)
|
||||
.developerMailingAddress(developerMailingAddress)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to create an InstantAppDetails with all non-null members.
|
||||
*
|
||||
* @param context a required Context for loading a test maturity rating icon
|
||||
* @return InstantAppDetails
|
||||
*/
|
||||
public static InstantAppDetails build(Context context) {
|
||||
return build(context, EnumSet.allOf(Param.class));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user