Merge "New design for instant apps in app details header"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fa9da424a8
@@ -87,6 +87,17 @@
|
||||
android:gravity="start"
|
||||
android:paddingTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/install_type"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||
android:textColor="?android:attr/textColorSecondary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_detail_summary"
|
||||
android:layout_width="match_parent"
|
||||
@@ -101,38 +112,4 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/instant_app_developer_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/instant_app_maturity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/instant_app_maturity_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="fitXY"/>
|
||||
<TextView
|
||||
android:id="@+id/instant_app_maturity_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/instant_app_monetization"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
@@ -8220,6 +8220,9 @@
|
||||
<!-- On status for the automatic storage manager. [CHAR_LIMIT=10] -->
|
||||
<string name="storage_manager_indicator_on">On</string>
|
||||
|
||||
<!-- Added as the value of a header field indicating this is an instant app (as opposed to installed normally) -->
|
||||
<string name="install_type_instant">Instant app</string>
|
||||
|
||||
<!-- Title of games app storage screen [CHAR LIMIT=30] -->
|
||||
<string name="game_storage_settings">Games</string>
|
||||
|
||||
|
@@ -37,7 +37,6 @@ import android.widget.TextView;
|
||||
import com.android.settings.AppHeader;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.instantapps.InstantAppDetails;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
@@ -81,7 +80,7 @@ public class AppHeaderController {
|
||||
@ActionType
|
||||
private int mRightAction;
|
||||
|
||||
private InstantAppDetails mInstantAppDetails;
|
||||
private boolean mIsInstantApp;
|
||||
|
||||
public AppHeaderController(Context context, Fragment fragment, View appHeader) {
|
||||
mContext = context;
|
||||
@@ -154,8 +153,8 @@ public class AppHeaderController {
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppHeaderController setInstantAppDetails(InstantAppDetails instantAppDetails) {
|
||||
mInstantAppDetails = instantAppDetails;
|
||||
public AppHeaderController setIsInstantApp(boolean isInstantApp) {
|
||||
this.mIsInstantApp = isInstantApp;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -220,26 +219,9 @@ public class AppHeaderController {
|
||||
bindAppHeaderButtons();
|
||||
}
|
||||
|
||||
if (mInstantAppDetails != null) {
|
||||
setText(R.id.instant_app_developer_title, mInstantAppDetails.developerTitle);
|
||||
View maturity = mAppHeader.findViewById(R.id.instant_app_maturity);
|
||||
|
||||
if (maturity != null) {
|
||||
String maturityText = mInstantAppDetails.maturityRatingString;
|
||||
Drawable maturityIcon = mInstantAppDetails.maturityRatingIcon;
|
||||
if (!TextUtils.isEmpty(maturityText) || maturityIcon != null) {
|
||||
maturity.setVisibility(View.VISIBLE);
|
||||
}
|
||||
setText(R.id.instant_app_maturity_text, maturityText);
|
||||
if (maturityIcon != null) {
|
||||
ImageView maturityIconView = (ImageView) mAppHeader.findViewById(
|
||||
R.id.instant_app_maturity_icon);
|
||||
if (maturityIconView != null) {
|
||||
maturityIconView.setImageDrawable(maturityIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
setText(R.id.instant_app_monetization, mInstantAppDetails.monetizationNotice);
|
||||
if (mIsInstantApp) {
|
||||
setText(R.id.install_type,
|
||||
mAppHeader.getResources().getString(R.string.install_type_instant));
|
||||
}
|
||||
|
||||
return mAppHeader;
|
||||
|
@@ -23,6 +23,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.settings.AppHeader;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
|
||||
import static com.android.settings.applications.AppHeaderController.ActionType;
|
||||
|
||||
@@ -52,6 +53,7 @@ public abstract class AppInfoWithHeader extends AppInfoBase {
|
||||
.setIcon(mPackageInfo.applicationInfo.loadIcon(mPm))
|
||||
.setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
|
||||
.setSummary(mPackageInfo)
|
||||
.setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
|
||||
.setPackageName(mPackageName)
|
||||
.setUid(mPackageInfo.applicationInfo.uid)
|
||||
.setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
|
||||
|
@@ -563,6 +563,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
.setLabel(mAppEntry)
|
||||
.setIcon(mAppEntry)
|
||||
.setSummary(getString(getInstallationStatus(mAppEntry.info)))
|
||||
.setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
|
||||
.done(false /* rebindActions */);
|
||||
mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
|
||||
} else {
|
||||
|
@@ -1,110 +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.instantapps;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Encapsulates state about instant apps that is provided by an app store implementation.
|
||||
*/
|
||||
public class InstantAppDetails {
|
||||
|
||||
// Most of these members are self-explanatory; the one that may not be is
|
||||
// monetizationNotice, which is a string alerting users that the app contains ads and/or uses
|
||||
// in-app purchases (this may eventually become two separate members).
|
||||
public final Drawable maturityRatingIcon;
|
||||
public final String maturityRatingString;
|
||||
public final String monetizationNotice;
|
||||
public final String developerTitle;
|
||||
public final URL privacyPolicy;
|
||||
public final URL developerWebsite;
|
||||
public final String developerEmail;
|
||||
public final String developerMailingAddress;
|
||||
|
||||
public static class Builder {
|
||||
private Drawable mMaturityRatingIcon;
|
||||
private String mMaturityRatingString;
|
||||
private String mMonetizationNotice;
|
||||
private String mDeveloperTitle;
|
||||
private URL mPrivacyPolicy;
|
||||
private URL mDeveloperWebsite;
|
||||
private String mDeveloperEmail;
|
||||
private String mDeveloperMailingAddress;
|
||||
|
||||
public Builder maturityRatingIcon(Drawable maturityRatingIcon) {
|
||||
this.mMaturityRatingIcon = maturityRatingIcon;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder maturityRatingString(String maturityRatingString) {
|
||||
mMaturityRatingString = maturityRatingString;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder monetizationNotice(String monetizationNotice) {
|
||||
mMonetizationNotice = monetizationNotice;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder developerTitle(String developerTitle) {
|
||||
mDeveloperTitle = developerTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder privacyPolicy(URL privacyPolicy) {
|
||||
mPrivacyPolicy = privacyPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder developerWebsite(URL developerWebsite) {
|
||||
mDeveloperWebsite = developerWebsite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder developerEmail(String developerEmail) {
|
||||
mDeveloperEmail = developerEmail;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder developerMailingAddress(String developerMailingAddress) {
|
||||
mDeveloperMailingAddress = developerMailingAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstantAppDetails build() {
|
||||
return new InstantAppDetails(mMaturityRatingIcon, mMaturityRatingString,
|
||||
mMonetizationNotice, mDeveloperTitle, mPrivacyPolicy, mDeveloperWebsite,
|
||||
mDeveloperEmail, mDeveloperMailingAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder() { return new Builder(); }
|
||||
|
||||
private InstantAppDetails(Drawable maturityRatingIcon, String maturityRatingString,
|
||||
String monetizationNotice, String developerTitle, URL privacyPolicy,
|
||||
URL developerWebsite, String developerEmail, String developerMailingAddress) {
|
||||
this.maturityRatingIcon = maturityRatingIcon;
|
||||
this.maturityRatingString = maturityRatingString;
|
||||
this.monetizationNotice = monetizationNotice;
|
||||
this.developerTitle = developerTitle;
|
||||
this.privacyPolicy = privacyPolicy;
|
||||
this.developerWebsite = developerWebsite;
|
||||
this.developerEmail = developerEmail;
|
||||
this.developerMailingAddress = developerMailingAddress;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
@@ -271,102 +269,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