创建自定义商店布局

借助 Google Play 企业版,您可以为企业客户设计和创建商店布局。您可以通过以下方式自定义商店布局:将应用分组,设置商店页面,以及添加快捷链接(以便用户轻松访问商店中的多个页面)。

在 Google Play 企业版商店中向最终用户提供的所有应用都必须先经过管理员批准,然后获得用户的批准,并添加到集群中。(如需详细了解此过程,请参阅将应用添加到商店布局)。

商店布局的元素

商店布局通常由在 Google Play 企业版中向用户显示的一系列页面组成。每个页面可以包含一个或多个应用组,即集群。每个集群包含一个或多个应用。

通过集群,您可以对相关应用进行分组。例如,您可以为工作相关应用创建一个页面,其中包含一个 Essentials 集群和一个 Get Things Done 集群。基本功能版集群可以包含 Notepad+、Google 幻灯片等应用。“完成事项”集群可能包括 OneNote、Wunderlist、Any.do 等应用以及其他跟踪、日历和会议规划应用(参见图 1)。

创建页面时,您还可以在页面顶部添加最多 10 个快速链接。快捷链接可让用户轻松跳转到其他页面。例如,图 1 显示了“商业”“通信”和“财经”页面的快速链接。

图 1 显示了在设备上显示的商店布局的一些关键元素:

用户设备的示例屏幕,显示商店布局的元素,包括快速链接、页面和应用集群。
  • 快捷链接:可选链接,可让用户轻松访问其他页面。快速链接会采用其所指向的网页的名称。
  • 网页:由多个应用集群构成的已命名且可垂直滚动的页面。
  • 集群(也称为“集合”):一个可横向滚动的已命名应用的轮播界面。如果页面包含一个集群,则展开为整页(或点击“更多”可使页面可垂直滚动)。

存储布局元素的限制

在为客户设计和实现商店布局时,请注意以下限制(这些限制大多是因为良好的界面设计原则):

  • 每个集群 100 个应用
  • 每页 30 个集群
  • 每页 10 个快速链接
  • 每家商店 100 页
  • 每个企业 1,000 个产品(获得批准的应用)

本地化的页面和集群名称

Google Play 企业版商店布局支持商店页面和商店集群的本地化名称。创建页面或集群时,您需要提供支持的语言区域列表(以 IETF 语言标记表示)以及关联的本地化名称。如果用户的语言区域不在支持列表中,系统会选择最接近的可用语言区域。例如,如果 en-GB 不可用,系统会改为选择 en-US。如果没有近似匹配项,系统会选择列表中的第一个名称。

将应用添加到商店布局

如果企业使用基本商店布局,系统会自动添加 policy.productPolicy 中的所有应用。 如果企业使用自定义商店布局,则设备上只会显示自定义布局和 productPolicy 列表中显示的应用。 “policy.productPolicy”中的所有内容均可在 Play 商店中搜索到。

为了让最终用户能够安装 Google Play 企业版商店中的应用,应用必须与用户的设备兼容并满足以下条件: * 已添加到用户许可名单中(设备资源上的 policy.productPolicy),且 policy.productAvailabilityPolicy 设为“白名单”,或 policy.productAvailabilityPolicy 设为“全部”(允许搜索和安装任何应用)。

用户可以使用 Google Play 企业版内置的搜索功能来查找并安装满足这些条件的任何应用。不过,只有在基本商店布局中或者将应用添加到集合/集群后,该应用才会显示。

已撤消的审批应用

管理员可以随时取消批准应用程序(撤消批准)。已撤消批准的应用仍然可以添加到集群和用户的允许列表中,但用户不会看到这些应用,也无法从 Google Play 企业版商店中安装这些应用。如果获得批准的应用重新获得批准,该应用将在 Google Play 企业版商店中重新供用户使用。

基本商店布局

默认情况下,系统会为您的每位客户启用基本商店布局。基本布局有 1 个页面和 1 个集群,最多显示 1000 个应用。页面上的应用会按照其 product ID 值进行排序。如果您通过设置 storeLayoutType =“custom” 创建自定义商店布局,系统会停用基本商店布局。

创建自定义商店布局

EMM 可以为各个企业客户创建自定义商店布局。借助自定义商店布局,您可以设置应用集群、将特定集群添加到页面,以及指定快速链接。由于您定义了构成每个集群的应用,因此可以使用集群对相关应用进行分组(例如“基本功能版”和“处理事项”)。用户只能看到管理员已接受权限的那些应用。

Google Play EMM API 参考文档介绍了您用于创建自定义商店布局的资源和关联方法,具体而言,就是 StorelayoutpagesStorelayoutclusters。以下各部分中列出的步骤将引导您完成一个基本示例。

编程任务

要为客户创建自定义 Google Play 企业版商店布局,您必须:

  1. 创建页面
  2. 在页面中创建一个或多个集群
  3. 设置主页

对于商店布局,您必须至少创建一个由一个集群组成的页面,并且该集群必须至少包含一个应用。您还必须设置首页。如果您创建了多个页面,可以选择设置显示在每个页面顶部的快速链接。

下面介绍了创建自定义 Play 企业版商店布局的编程任务,其后提供了商店布局的完整示例

创建页面

一个页面由一个或多个集群组成。每个集群至少包含一个应用。页面是针对特定企业创建的,因此您必须在特定企业实例 (enterpriseId) 上调用操作。您可以为每个页面提供方便用户使用的名称和本地化信息,以及用户可以从该页面访问的 pageId 列表。可通过 insert 操作 (Storelayoutpages.insert) 创建新页面,如下所示:

public StorePage createPage(String enterpriseId, String name)
    throws IOException {
  List<LocalizedText> names =
      ImmutableList.of(
          new LocalizedText().setLocale("en").setText(name));
  StorePage storePage = new StorePage();
  storePage.setName(names);
  return androidEnterprise.storelayoutpages()
    .insert(enterpriseId, storePage)
    .execute();
}

创建集群

集群包含应用组。您可以先创建集群,然后才能将其添加到页面中。如需创建集群,请调用 Storelayoutclustersinsert 操作,并传递以下属性的值:

  • 集群应包含的 productId 的列表(例如,Gmail 的 productIdapp:com.google.android.gm
  • 为集群指定一个简单易记的名称,例如“做事”
  • 应与集群关联的 enterpriseId
  • pageId(针对应包含该集群的页面)
  • 该页面上的集群展示位置(第一个、第二个,依此类推)

示例如下:

private String insertCluster(String enterpriseId, String pageId, String name,
    List<String> productIds, String orderInPage) throws IOException {
  StoreCluster storeCluster = new StoreCluster();
  storeCluster.setName(
      ImmutableList.of(
          new LocalizedText().setLocale("en").setText(name)));
  storeCluster.setProductId(productIds);
  storeCluster.setOrderInPage(orderInPage);
  return androidEnterprise.storelayoutclusters()
    .insert(enterpriseId, pageId, storeCluster)
    .execute()
    .getId();
}

设置主页

用户设备上 Google Play 企业版中显示的第一个网页是首页。作为 EMM,您可以为每位客户定义一个首页。该页面始终可见(即使页面为空),并且无法删除。

在以下示例中,系统会为指定的 enterpriseId 提取首页的 ID:

public StoreLayout getStoreLayout(String enterpriseId) throws IOException {
  return androidEnterprise
    .enterprises()
    .getStoreLayout(enterpriseId)
    .execute();
}

下例通过提供客户的 enterpriseId 和该客户首页的 pageId 来设置客户的首页:

public StoreLayout setStoreLayout(String enterpriseId, String homepageId)
    throws IOException {
  StoreLayout storeLayout = new StoreLayout();
  storeLayout.setHomepageId(homepageId);

  return androidEnterprise
    .enterprises()
    .setStoreLayout(enterpriseId, storeLayout)
    .execute();
}

快速链接会显示在每个页面的顶部,让用户能够轻松地在商店的各个页面之间导航。如需使用快速链接,请先获取该网页的 pageId(由 insert 返回),然后将该链接添加到该网页。例如,如果您创建了三个页面,其 pageId 分别为 p1p2p3,则可以添加从第一个页面到其他两个页面的快速链接,如下所示:

StorePage storePage = new StorePage();
storePage.setName(
    ImmutableList.of(new LocalizedText().setLocale("en").setText(title)));
storePage.setLink(ImmutableList.of("p2", "p3");
return androidEnterprise.storelayoutpages()
  .update(enterpriseId, "p1", storePage)
  .execute();

示例

下面是一个完整示例,它创建了一个由三个相互链接的页面组成的基本存储区。每个网页都由类似的应用集群构成。创建每个页面时,需要指定客户的 enterpriseId 并仅设置页面 name,以获取其 pageId,然后使用后者来创建指向该页面的快速链接。

// Create a basic page and return the pageId.
private String insertPage(String enterpriseId, String title,
    List<String> links) throws IOException {
  List<LocalizedText> names =
      ImmutableList.of(new LocalizedText().setLocale("en").setText(title));
  StorePage page = new StorePage();
  page.setName(names);
  page.setLink(links);
  return enterprise.storelayoutpages().insert(enterpriseId, page).execute().getId();
}

public StoreLayout setStoreLayout(String enterpriseId, String homepageId)
    throws IOException {
  StoreLayout storeLayout = new StoreLayout();
  storeLayout.setHomepageId(homepageId);

  return androidEnterprise
      .enterprises()
      .setStoreLayout(enterpriseId, storeLayout)
      .execute();
}

private String insertCluster(String enterpriseId, String pageId, String name,
    List<String> productIds, String orderInPage) throws IOException {
  StoreCluster cluster = new StoreCluster();
  List<LocalizedText> names =
      ImmutableList.of(new LocalizedText().setLocale("en").setText(name));
  cluster.setName(names);
  cluster.setProductId(productIds);
  cluster.setOrderInPage(orderInPage);
  return androidEnterprise.storelayoutclusters()
      .insert(enterpriseId, pageId, cluster)
      .execute()
      .getId();
}

private void updatePage(String enterpriseId, String pageId, String title,
    List<String> links) throws IOException {
  List<LocalizedText> names =
      ImmutableList.of(new LocalizedText().setLocale("en").setText(title));
  StorePage page = new StorePage();
  page.setName(names);
  page.setLink(links);
  enterprise.storelayoutpages()
      .update(enterpriseId, pageId, page).execute();
}

private void makeStore(String enterpriseId) throws IOException {
  // Create the pages.
  String page1 = insertPage(enterpriseId, "Home");
  String page2 = insertPage(enterpriseId, "Productivity");
  String page3 = insertPage(enterpriseId, "Accounting");

  // Set the homepage (page that displays by default when store is opened).
  setStoreLayout(enterpriseId, page1);

  // Add the links to the pages. This makes a small tree.
  updatePage(enterpriseId, page1, "Home", ImmutableList.of(page2, page3));
  updatePage(enterpriseId, page2, "Productivity", ImmutableList.of(page1));
  updatePage(enterpriseId, page3, "Accounting", ImmutableList.of(page1));

  // Add clusters with contents.
  insertCluster(
      enterpriseId,
      page1,
      "Getting Things Done",
      ImmutableList.of(
          "app:com.mytodolist",
          "app:com.google.android.gm",
          "app:com.google.android.docs"),
      "1");
  insertCluster(
      enterpriseId,
      page1,
      "Strategy",
      ImmutableList.of(
          "app:com.myplanner",
          "app:com.stratego"),
      "2");
  insertCluster(
      enterpriseId,
      page2,
      "Editors",
      ImmutableList.of(
          "app:com.myeditor",
          "app:com.betteredit",
          "app:com.lazyguy"),
      "1");
  insertCluster(
      enterpriseId,
      page2,
      "Time Management",
      ImmutableList.of(
          "app:com.mytimetracker",
          "app:com.lazygal",
          "app:com.lazyguy"),
      "2");
  insertCluster(
      enterpriseId,
      page2,
      "Accounting",
      ImmutableList.of(
          "app:com.mymoney",
          "app:com.taxpro",
          "app:com.balances"),
      "3");
}