/ Google Play 谷歌开发者
我们被大家的热情惊到了 —— 事实上我们发出上一篇 Instant App 的文章没几天就收到了一大堆问题。由于涉及到的类目太多,我们这里简单归纳了一下,方便大家查看。如果还有更多问题也请随时通过留言的方式与我们取得联系。
1. 基础类问题
Q: 哪些设备兼容 Android Instant App?
A: Android Instant App 在运行 Android 6.0(API 级别 23)或更高版本的设备上可用,此外还计划为 Android 5.0(API 级别 21)添加额外的支持。例如,现在您可以在 Google Pixel、Google Nexus、Samsung Galaxy S7 等人气设备上开发 Instant App。
Q: 哪些国家和地区支持 Android Instant App?
A: 您可以在支持页面中找到完整的支持国家和地区列表:
(https://support.google.com/googleplay/android-developer/answer/7381861#production)
Q: 开发者现在需要构建两套不同的 Android 应用吗?
A: 正相反,开发者只需使用一个源代码树维护一个项目即可。通过对项目进行配置,创造出两套架构工件:可安装版本和免安装版本。在可安装应用基础上添加免安装支持需要的工作量大小取决于可安装应用的当前架构。
* 请注意,免安装应用的版本号必须等于或小于上次发布的可安装应用版本。
Q: Instant App 都能使用什么 Android API 和功能?
A: Android Instant App 设计的目的是扩展现存 App 的使用场景,而非取代它们。所以Android Instant App 使用同样的 Android API,同样的项目,同样的源代码。当然,由于Android Instant App 的 “免安装” 特性,可能会无法符合用户针对 “已安装” 应用所抱有的一些期待。例如,免安装应用无法使用后台服务,无法激活后台通知,也无法使用设备唯一标识符。
Q: 用户可以选择永久安装应用吗?
A: 当然!开发者可以允许用户从 Google Play 安装应用。在安装完成后,当用户离开应用时,它仍会留在用户的手机上 —— 就和现在大家正在做的事情一样。
Q: Android Instant App 的权限需求是怎样的?
A: Android Instant App 使用自 Android 6.0 (API 级别 23)以来采用的运行时权限。
Q: 免安装应用可以获取哪些权限?
A:免安装应用可以使用下列 Android 权限。没有出现在下方列表中的权限将无法在免安装应用中使用。
BILLING
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ACCESS_NETWORK_STATE
CAMERA
INSTANT_APP_FOREGROUND_SERVICE 仅限 Android O
INTERNET
READ_PHONE_NUMBERS 仅限 Android O
RECORD_AUDIO
VIBRATE
Q:免安装应用对网络访问有哪些限制?
A:来自免安装应用的一切网络流量均必须使用 HTTPS,不支持 HTTP。
Q:开发者要如何发布这些应用?
A:开发者需要经由 Google Play Console 发布免安装应用,这一点与现有的 Android 应用并无两样。想要了解更多信息,请参阅 “发布您的免安装应用” :
(https://support.google.com/googleplay/android-developer/answer/7381861)
Q:免安装应用必须使用 Smart Lock 么?
A:是的,我们规定在免安装中的登录体验必须使用 Smart Lock。想要进一步了解如何在应用中使用 Smart Lock,请参阅 “为您的 Android 密码使用 Smart Lock” :
(https://developers.google.cn/identity/smartlock-passwords/android/)
Q:我能不能在没有可安装版本 Android 应用的情况下实现一个免安装应用?
A:不能。您必须首先在 Google Play 中拥有一个该 App 的可安装版本。
Q:我们能在里面使用 WebP 图片格式吗?
A:当然可以,我们推荐使用 WebP 格式的图片。想要了解更多信息,请参阅 “如何缩减下载图片的大小” :
(https://developer.android.google.cn/topic/performance/network-xfer.html#webp)
Q:免安装应用在 Google 网页搜索中将会如何呈现?
A:免安装应用与可安装应用的搜索显示结果并无不同。在搜索结果中,免安装应用会显示出应用图标,如果该 URL 已与免安装应用相关联,则还会显示 “Instant” 标签,正如搜索结果中的可安装应用会在图标上显示 “Installed” 标签一样。
Q:我能使用 Android Instant App 的形式来承载我的游戏吗?
A:游戏是极为特别的一类应用,它们通常拥有独特的工具库和庞大的资产库,对性能表现的要求也很高。即使如此,我们对探索游戏用户的使用案例也充满兴趣。请前往 StackOverflow 浏览有关 Android Instant App 的帖子,不少人也在讨论这个话题。
2. 项目结构、功能和架构
Q:免安装应用和可安装应用是否拥有不同的 build.gradle 文件?
A:如果您的可安装应用和免安装应用来自同一个 Android Studio 项目,那么答案是肯定的,两种应用需要不同的 build.gradle 文件。您必须使用符合 com.android.application 构建规则的模块来构建您的可安装应用,而当您构建免安装应用时则需要使用符合 com.android.instantapp 构建规则的模块。想要了解更多信息,请参阅 “项目结构” :
(https://developer.android.google.cn/topic/instant-apps/getting-started/structure.html#structure_of_a_basic_instant_app)
Q:我能独立编译可安装与免安装应用吗?
A:正如上面 “项目结构” 中所展示的那样,我们推荐采用的工程结构应该优先将独立的功能封装成模块,这样可安装应用和免安装应用都可以依赖这些库模块。如果您遵循我们推荐的工程结构,您就可以独立编译每个功能而不涉及其他。
Q:我应该如何在免安装应用中的不同页面之间进行导航?
A:您可以通过进入一条目标页面的 URL 来导航过去。由于这个原因,免安装应用中的页面均需满足这个条件:可被 URL 寻址。想要了解更多如何让app页面可被 URL 寻址的内容,请参阅 “如何从 Google Play 请求功能” :
(https://developer.android.google.cn/topic/instant-apps/overview.html#play_store)
和 “实现应用链接” :
(https://developer.android.google.cn/topic/instant-apps/getting-started/index.html#app-links)
Q:我能在我的主应用里处理深度链接(Deep Link),然后再调用其他免安装应用的页面吗?
A:免安装应用需要在功能上实现模块化,通过主应用集中处理与此相矛盾。使用 App Link 即可进行您需要的链接跳转功能,同时保持免安装应用的模块化特性。
Q:我能在一个功能内包含多个页面吗?
A:您可以在一个功能内包含多个页面。但您需要留意的是,免安装应用下载有 4MB 的大小限制。同时,每个功能都需要用一个页面作为入口。
Q:我能在不同功能之间共享资源吗?
A:可以,基本功能(Base Feature)内的资源可以被所有功能分享。包含在附加功能之内的资源则只能被这个功能所使用。想要了解更多关于如何搭建您的项目资源,以及如何在不同功能之间共享资源,请参阅上面提到的 “项目结构”。
额外再说一点,您必须把位于附加功能和基本功能之间的资源 ID 区分开来。例如,如果您的基本功能提供了一个名为 R.id.feature_layout 的资源 ID,但您的附加功能却定义了另一个同 ID 资源,那么免安装应用就会使用来自基本功能的资源,而不会使用来自附加功能的资源。
此外,所有随着功能模块的产生而被引用的资源都必须在基本功能模块内出现。
Q:如果应用内有两个功能,它们是否会共享存储?
A:会,多个功能会在同一进程中运行,并共享应用上下文,只要它们属于同一个免安装应用。但是,免安装应用相较于可安装 APK 而言拥有一些限制。想要了解更多信息,请参阅 “了解受限和不受支持的功能” :
(https://developer.android.google.cn/topic/instant-apps/prepare.html#restricted)
Q:我能在同一页面内的 view-pager 中拥有多个分段(Fragment)吗?
A:可以,您能在单一页面中拥有多个分段,并在功能内定义与页面相关的分段。但请记住分段不能与深链接相关,并且不能独立于页面启动。
Q:免安装应用应该拥有独立的应用图标吗?
A:不,免安装应用和可安装应用应该使用同一个图标。可安装应用和免安装应用应该为用户提供一致的体验,因此它们应该使用同样的视觉元素(如图标)。
想要了解更多关于如何关联免安装应用和可安装应用的信息,请参阅 “同一个应用,安装前与安装后”:
(https://developer.android.google.cn/topic/instant-apps/ux-best-practices.html#instant-v-installed)
Q:我如何才能分辨出我的应用正在以可安装模式还是免安装模式运行?
A:您可以使用静态的 InstantApps.isInstantApp ( ) 方法。如果接受测试的进程属于一个免安装应用,这个方法的返回值将为 True 。
Q:我要如何鼓励用户从免安装应用中安装我的应用?
A:您可以使用静态的 InstantApps.showInstallPrompt ( ) 方法。这种方法会鼓励用户安装常规 APK 版本的应用。
Q:为各种功能使用的不同的 APK 会不会在 Google Play 里显示为不同的产品?
A:不会,免安装应用与可安装应用共享相同的包装名和产品列表。
Q:我在免安装应用内为功能命名时,会不会受到限制?
A:功能模块遵循 Java 命名规则。例如,您不能在功能名称中使用连字符。想要了解更多关于 Java 命名规则的内容,请参阅对应的 Java 文献:
(https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html)
3. Google 分析、Google Play 与部署
Q:我能让我的免安装应用只在限定的几个国家内发布吗?
A:免安装应用的使用范围限定于相应的可安装应用所在的国家和地区。在这些国家和地区的范围内,开发者可以选择在特定地区内发布自己的免安装应用。
Q:如果我想要通过 Google Play 在发布前测试我的免安装应用,我还需要首先发布可安装应用的 APK 吗?
A:想要通过 Google Play 在开发阶段测试您的免安装应用的部署情况,您就必须在 Google Play Console 中拥有 “草稿” 形式的可安装版本应用。
想要了解更多关于对您的免安装应用的进行部署,以及对其部署情况进行测试的信息,请参阅上面提到的 “发布您的免安装应用”。
4. 应用大小
Q:4MB 的总下载限制是什么意思?
A:免安装应用的大小(基本功能加上任何附带的附加功能)应该越小越好。您的应用越小,用户下载使用起来就越容易。但是,当您的免安装应用已经运行在用户的设备上时,您就可以使用用户的设备来下载并储存额外的数据。如果是用这种方式在用户的设备上使用数据,则不存在 4MB 的硬限制。
想要计算应用大小的话,只需解压免安装应用的 APK 并检查 APK 文件。您可以使用 APK 文件的磁盘容量,或是打开 APK Analyzer 并观察 Raw File Size 值。
对于那些拥有多个功能的免安装应用,您必须把基本功能 APK 的大小与单一功能 APK 合并计算。基本功能与单一功能 APK 文件大小之和必须小于 4MB。
Q:用户每次下载同一个免安装应用时都需要下载基本功能 APK 和附加功能 APK 吗?
A:当用户首次下载免安装应用时,他们会下载基本功能和附加功能两个 APK。当用户请求其他功能的 APK 时,用户只会收到与所请求功能的 APK。在这种情况下,基本功能 APK 不需要被重复下载。
* 注意:系统会在垃圾整理期间根据需要清理免安装应用的缓存。如果手机重启,缓存会清空。如果免安装应用的缓存被清空,用户就必须重新下载基本功能的 APK。
Q:何时会触发 4MB 验证?
A:当您在制作阶段将免安装应用上传到 Google Play Console 时就会触发验证。
5. 应用链接、深链接与 URL 处理
Q:用户从一些应用点击链接时,链接并没有打开我的免安装应用,而是在应用内浏览器中打开了。有没有办法能保证用户被带到免安装应用里面去?
A:App Link 只是普通的 URL,所以应用可以强迫它们在应用内浏览器中打开。请考虑使用 Firebase Dynamic Links 来包装您的 URL,确保用户在点击您的链接时总能被带到您的免安装应用里去。
Q:我的主应用 manifest 里包括其他 URL 和其他 URL 域名,但我并不拥有这些域名。这样会产生什么后果?
A:很遗憾,如果一个 URL 的域名所有权未经确认,则会导致免安装应用发布失败。
6. 在设备上运行免安装应用
Q:用户能否放弃使用 Android Instant App?
A:能。用户在首次启动免安装应用时可以选择放弃。用户还可以选择打开 Settings 并点击 Google > Instant Apps 进行设置。
Q:两个免安装应用可以同时运行吗?
A:可以。免安装应用可以同时运行,用户可以在多个应用之间切换。只有位于前台的免安装应用会在通知栏内显示图标。
Q:用户能否在 “最近使用” 栏和设备主屏上结束和重启免安装应用的进程?
A:免安装应用可以从 “最近使用” 栏重启,用户还可以点击之前运行过的启动 URL 来重启应用。
当用户停止与免安装应用互动时,免安装应用的进程即被终止。但是,应用的内部存储,如 SQLite DB 还有共享偏好会保留下来。如果设备存储空间告急,免安装应用可能会被删除,它的内部存储也会一同被删除。虽然这种情况不太可能出现,但当它出现的时候还想恢复用户的使用状态和偏好信息的话,开发者需要从服务端解决。
Q:免安装应用能不能启动用户设备上安装的其他应用?
A:免安装应用可以通过发出隐式意图 (implicit intent) 来启动一个可安装应用,但无法使用显式意图 (explicit intent) 来启动大多数可安装应用。但可安装应用可选择对那些发出显式意图的免安装应用开放。
Q:如果用户安装了较旧版本的应用,并点击了与较新版本免安装应用相关联的 URL,会打开哪个应用?
A:可安装应用永远优先于免安装应用打开。
Q:用户如何接收我的免安装应用的最新版本? Google 会不会在用户的设备上自动对它进行更新?
A:最新版本的免安装应用将提供给新用户使用,现有用户的免安装应用缓存过期时,也会获取最新版本的应用。
看个锚点定位的例子
发现页面唰的一些就到顶部了,快到我们懵逼了。。。
开始解决
CSS属性 scroll-behavior 为一个滚动框指定滚动行为,其他任何的滚动,例如那些由于用户行为而产生的滚动,不受这个属性的影响。在根元素中指定这个属性时,它反而适用于视窗。
scroll-behavior:smooth 写在滚动容器元素上,可以让容器的滚动变得平滑。
在网页默认滚动是在<html>标签上,移动端大多数在<body>标签上。
我们可以这样加:
html, body { scroll-behavior:smooth; }
加了以后的效果如下:
这是录制的GIF图,效果没那么好。 大家可以动手试一下,滑动体验非常不错。
兼容性不够好
当然我们可以通过js来做个类似
DOM元素的scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内,通过触发滚动容器的定位实现。
DOM元素的scrollIntoView()方法 是原生JS 兼容到IE6,兼容性非常好。
参数如下
{ behavior: "auto" | "instant" | "smooth", // 默认 auto block: "start" | "center" | "end" | "nearest", // 默认 center inline: "start" | "center" | "end" | "nearest", // 默认 nearest }
解释一下这三个参数:
用法:
html:
<div class="wrap"> <div onClick="onScrollIntoView()">点击让黑色块到顶部</div> <ul class="body"> <li>1</li> <li>2</li> <li id="box">我是黑色</li> <li>3</li> <li>4</li> </ul> </div>
js:
function onScrollIntoView () { var element = document.getElementById("box"); element.scrollIntoView({behavior: "smooth"}); }
效果:
这回大家再也不用害怕做锚点定位啦。
最后我们在说一个关于页面滚动问题吧,那就是 返回顶部 功能实现
我们常用定时器 setInterval 来不断减去高度。
如:当前距离顶部 1000, 我们每10毫秒减50,
var timer = setInterval(function() { // 定时器 每10毫秒执行一次 // 顶部距离 document.body.scrollTop = 1000 var speed = 50 // 返回顶部速度 document.body.scrollTop = document.body.scrollTop - speed if (document.body.scrollTop === 0) { // 返回到达顶部后, 销毁定时器 clearInterval(timer) } }, 10)
效果:
大家会发现,页面返回是滚动起来很干。 没10毫秒减50. 很平均,在交互上效果并不好。
借鉴上面 scroll-behavior:smooth 的交互效果。 缓动的返回顶部。
改一下计算方式:1000/2 = 500, 500/2 =250, 250/2 = ...... 这样滑动起来是不是就平滑了呢?
换算成公式:开始位置 = 开始位置 + (结束位置 - 开始位置) / 速度
document.body.scrollTop = 1000 + (0 - 1000) / 2
公式太烦了还是上代码吧:
var onTop = function (a, b, c, d) { if (a == b || typeof a != 'number') { return } b = b || 0 c = c || 2 var speed = function () { a = a + (b - b) / c if (a < 1) { d(b, true) return } d(a, false) requestAnimationFrame(speed) } speed() }
调用:
var target = document.body.scrollTop ? document.body : document.documentElement onTop(target.scrollTop, 0, 4, function (value) { target.scrollTop = value })
效果:
Ps: gif录制效果不好,大家可以动手写一下DEMO
、目录
1:centos 环境准备
2:instant client 下载
3:instant client 安装
4:instant client 配置
5:测试连接
二、安装步骤
1:zip,unzip命令安装,等待centos安装完成
yum install -y unzip zip
2:下载instant client并上传到centos系统某个目录下
一般都是上传/opt/instantclient目录下
下载地址:https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html
下载 instanct client zip包:
instantcient-basic-linux.x64-11.2.0.4.0.zip required(必须下载)
instantcient-sqlplus-linux.x64-11.2.0.4.0.zip (可选,主要是使用sqlplus命令)
instantcient-sdk-linux.x64-11.2.0.4.0.zip (可选,主要是oracle头文件)
3:安装instant client
a. 进入/opt/instantclient目录中,执行如下命令:
unzip instantclient-basic-linux-11.2.0.4.0.zip
unzip instantclient-sqlplus-linux-11.2.0.4.0.zip
unzip instantclient-sdk-linux-11.2.0.4.0.zip
执行上面三个命令完成后,所有文件默认都放在当前目录instantclient_11_2目录下
b. 进入instantclient_11_2目录,创建libclntsh.so.11.1的链接文件,防止报错:找不到libclntsh.so文件。命令如下:
ln -s libclntsh.so.11.1 libclntsh.so
c. 建立相关目录,在instantclient_11_2目录下建立network/admin目录,执行如下命令:
mkdir -p network/admin
d. 配置环境变量
使用vi命令打开当前用户配置文件:
vi ~/.bash_profile
在配置文件中增加下面信息:
export ORACLE_HOME=/opt/instantclient/instantclient_11_2
if [ "$LD_LIBRARY_PATH" = "" ]; then
export LD_LIBRARY_PATH=$ORACLE_HOME
else
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
fi
export PATH=$PATH:$ORACLE_HOME:$ORACLE_HOME/sdk
export NLS_LANG="AMERICAN_AMERICA.AL32UTF8"
export TNS_ADMIN=$ORACLE_HOME/network/admin
保存退出vi编辑配置文件
e. 使用环境变更生效
source ~/.bash_profile
f. 配置数据库连接串
进行network/admin目录,创建tnsnames.ora文件。
vi tnsnames.ora
输入oracle数据库连接串:
客户端服务名 = //连接别名,随便定义
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 数据库IP地址)(PORT = 数据库端口号))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = 数据库连接服务名)
)
)
保存退出。
4:连接测试
sqlplus 用户名/密码@客户端服务名
出现SQL> 提示符,即登录数据库成功
*请认真填写需求信息,我们会在24小时内与您取得联系。