vivo小窗适配指南

1、小窗功能介绍

vivo全局小窗在安卓原生的多窗口功能基础上,进行了一系列的优化和创新。以小窗的形式展现应用,并支持不同窗口形式(小窗、分屏、全屏)之间快速切换。
小窗入口包括但不限于:近期任务卡片“小窗”选项,应用内滑、悬浮通知下拉等。用户可以通过 设置-快捷与辅助-多任务 路径进入多窗口功能设置页,了解相关功能介绍。
(注:不同机型、不同版本表现可能有所差异)。

2、小窗应用适配关键点

应用适配全局小窗时,因一些容易被忽略的适配点,导致应用进入小窗模式后出现兼容性问题。为此,我们整理了全局小窗应用适配的五大关键点,帮助开发者快速适配。

2.1 声明支持多窗口模式
应用适配全局小窗需要先声明支持安卓原生多窗口,和多窗口适配策略相同,都需在 [activity] 或 [application] 节点中添加 android:resizeableActivity 属性。

参考代码:

<application
    android:name=".MyActivity"
    android:resizeableActivity="true" />

安卓官方多窗口适配参考链接:https://developer.android.com/guide/topics/ui/multi-window.html

2.2 正确处理Configuration变化
在应用横竖屏旋转和窗口大小变化时,如需自行处理多窗口配置,请设置android:configChanges属性,之后Activity和 Fragment将收到 onConfigurationChanged()方法回调,而不是先销毁再重建。
在管理视图更新、重新加载资源等工作时,注意不要沿用之前的Config信息,而需重新获取最新的资源信息。参考代码:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize 
		| screenLayout | orientation" />

2.3 正确启动Activity的task
应用需给Activity设置独立的android:taskAffinity属性,以防因继承rootActivity的多窗口属性导致无法启动到小窗模式。
因为task中的Activity会继承rootActivity的多窗口属性。如果启动该task的rootActivity是unresizable的,则即使要启动的Activity是resizable的也无法启动到小窗模式。
参考代码:

<activity
  android:name=".MyActivity"
  android:taskAffinity="com.test.example" />

2.4 正确使用Context
应用在适配小窗模式时,应使用Activity的Context加载合适的资源和计算相对位置。
在应用进程中,存在Application和Activity两类Context,其中Application Context对应的是屏幕资源信息,而Activity Context对应的是窗口的资源信息。
如果应用在小窗模式下使用的是 Application Context处理UI 相关的操作,会导致加载的资源因无法感知到小窗而显示异常。
Activity如何获取特定窗口类型下的窗口尺寸,参考代码:
java:

int screenWidthDp = getResources().getConfiguration().screenWidthDp;
int screenHeightDp = getResources().getConfiguration().screenHeightDp;

kotlin:

val screenWidthDp: Int = resources.configuration.screenWidthDp
val screenHeightDp: Int = resources.configuration.screenHeightDp

2.5 正确处理小窗下的沉浸式
小窗模式下,应用顶部有个功能bar,应用在沉浸式适配时需为此功能bar预留一定空间。因此应用在布局时,需要监听安卓原生的WindowInsetsListener接口回调,针对captionBarInsets变化来处理view高度,注意不要使用固定高度!!!

参考代码:
java:

getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
    //应用在回调中计算view高度
    return insets;
});

kotlin:

window.decorView.setOnApplyWindowInsetsListener { v: View?, insets: WindowInsets ->
    //应用在回调中计算view高度
    insets
}

2.6 其他界面布局建议
• 布局参数尽量使用相对的布局参数,不要使用固定尺寸
• 避免根据屏幕大小,输入法高度等计算view的布局参数,如设置popwindow、dialog等子窗口的位置时,避免使用整个屏幕的相对位置
• 避免对DecorView,content等根布局进行定制,比如设置DecorView的背景、在DecorView添加子布局等
• 注意生命周期处理,如小窗模式下出现页面点击、拖动无响应问题,可能跟布局或生命周期有关
• 避免根据物理屏幕方向设置当前功能或布局

vivo分屏适配指南

1. 适配背景

vivo分屏在原生分屏的基础上做了定制化处理,比如增加分屏方式(消息\三指\组合)、分屏小桌面列表、输入法边界定制、加密界面定制等

2. 适配指导

2.1 判断分屏的方式 

Activity判断:

isInMultiWindowMode方法,判断mIsInMultiWindowMode变量,该变量在oncreate和模式变化时赋值

onMultiWindowModeChanged方法,在模式发生变化时回调

Services判断:

Q以及之前可以通过

1. WindowManagerGlobal.getWindowManagerService().getDockedStackSide()  !=  WindowManager.DOCKED_INVALID

2. getStackInfo,判断WINDOWING_MODE_SPLIT_SCREEN_PRIMARY(分屏)的stack是否存在,存在处于分屏

R以及以后通过

1. isSplitScreenModeActivated方法判断

2. Settings.system. in_multi_window,  0非分屏,1进入分屏

2.2 配置支持分屏

应用AndroidManifest.xml中可以针对app或activity进行设置。

<application
        android:resizeableActivity="true">

        <activity
                    android:resizeableActivity="true" />
</application>

当应用targetSdkVersion >=24时,android系统默认设置android:resizeableActivity=”true”,不需要应用声明即可支持应用分屏。当应用targetSdkVersion < 24时,需要应用针对application或activity设置android:resizeableActivity=”true”。

应用设置application android:resizeableActivity=”true”时,会针对app的所有activity生效,因此如果应用只需要声明单独的activity时,可以只针对单个activity进行设置,系统侧建议针对application设置android:resizeableActivity=”true”,避免应用部分页面在分屏下的异常。

2.3 获取Activity实际显示的窗口大小和位置

使用:context.getResources().getDisplayMetrics()

不推荐使用:context.getWindowManager().getDefaultDisplay().getMetrics(outMetrics)

上述接口中,context为Activity对应的上下文句柄,每个Activity应该严格使用自己的context来进行布局,而不是使用application的context。

2.4 获取Activity的窗口布局方向

获取Activity窗口方向的的方法为:

context.getResources().getConfiguration().orientation

注:不要使用width /height的方法来判Activity为横竖屏布局,因为在多窗口状态下,支持应用的拖动,会改变宽高

获取设备的方向context.getWindowManager().getDefaultDisplay().getRotation()

2.5 Activity大小切换时不重启适配

应用在Activity窗口大小切换时不重启适配,在android:configChanges属性增加screenSize|screenLayout| orientation|smallestScreenSize,并在Activity的onConfigurationChanged回调中更新宽高刷新子布局。

应用复写onConfigurationChanged()方法,通过该方法的Configuration参数获得窗口高度等信息,并对界面布局做相应调整,如切换布局、调整控件位置和间距等。

2.6 状态栏位置

当处于分屏下屏,和小窗模式时,应用没有状态栏,此时不应该留出状态栏高度,需要从顶部开始布局。

可以通过configuration中windowingmode判断当前处于的模式,WINDOWING_MODE_FREEFORM和WINDOWING_MODE_SPLIT_SCREEN_SECONDARY不需要空出状态栏

安卓64位应用适配指南

一、应用64位适配

1.1 确定您的应用是否需要适配64位

使用了原生代码的应用才需要进行64位适配。

1.1.1 64位应用的特征

64位应用必须包含64位库。最简单的方法就是检查APK文件的结构,库文件会被打包在APK,针对ARM架构和x86架构具体目录结构如下:

平台32位库文件夹64位库文件夹
ARMlib/armeabi或者lib/armeabi-v7alib/arm64-v8a
x86lib/x86lib/x86_64

针对ARM架构,APK中库文件被打包在lib/arm64-v8a下面的应用是64位应用。

1.1.2 确定您的应用是否使用了原生代码 

如果您的应用符合以下情况,便是使用了原生代码:

  • 使用了任何 C/C++(原生)代码。
  • 与任何第三方原生库关联。
  • 通过使用原生库的第三方应用构建程序构建而成。

1.2 检验您的应用是否已经支持64位 

1.2.1 利用谷歌商店快速检查您的应用是否支持64位

要检查应用是否已满足 64 位要求,一种快速的方法是前往 Play 管理中心查看现有的版本,确定应用是否合规

如果您的草稿版本存在与 64 位要求相关的问题,Play 管理中心也会显示相应的警告。请看以下示例:

如果您看到提醒,表明您的应用是不支持64位的,需要进行相应的适配。

1.2.2 使用APK分析器查找原生库

APK分析器是一款可用于对构建的 APK 进行各方面评估的工具。针对我们目前所讨论的情况,我们将使用该工具查找原生库,以确定是否具备 64 位库。

1. 打开 Android Studio,然后打开任一项目。

2. 从菜单中依次选择 Build > Analyze APK…

3. 选择您要评估的APK。

4. 查看 lib 文件夹,您可以在其中找到“.so”文件。如果在您的应用中找不到任何“.so”文件,则说明该应用的相应库已准备就绪,您无需采取进一步措施。如果您看到 armeabi-v7a 或 x86,则说明您有 32 位库。

5. 检查是否 arm64-v8a 或 x86_64 文件夹中有类似的“.so”文件。

6. 如果您没有任何 arm64-v8a 或 x86_64 库,则需要更新构建流程以开始构建并打包APK中的这些工件。

7. 如果您看到32位和64位的库均已打包到软件包中,则可以跳至在64位硬件上测试应用。

1.2.3 通过解压缩 APK 查找原生库

APK文件的结构类似于ZIP文件,可以像ZIP文件一样解压缩。 如果您更喜欢使用命令行或任何其他解压缩工具,也可以采用解压缩APK的方法。

只需解压缩APK文件(根据您使用的解压缩工具,您可能需要将其重命名为.zip),然后按照上文中的指南浏览解压缩后的文件,即可确定您的应用是否已经为支持64位设备做好准备了。

例如,您可以从命令行中运行如下命令:

> zipinfo -1 YOUR_APK_FILE.apk | grep .so$
lib/armeabi-v7a/libmain.so
lib/armeabi-v7a/libmono.so
lib/armeabi-v7a/libunity.so
lib/arm64-v8a/libmain.so
lib/arm64-v8a/libmono.so
lib/arm64-v8a/libunity.so

请注意,此示例中存在 armeabi-v7a 库和 arm64-v8a 库,这表明该应用支持 64 位架构。

1.3 如何使用64位库构建应用

1.3.1 使用Android Studio或Gradle 进行构建

大多数Android Studio项目都使用Gradle作为底层构建系统,因此本部分适用于使用这两种工具进行构建的情况。针对原生代码进行构建很简单,只需将arm64-v8a 和/或 x86_64(视您要支持的架构而定)添加到应用

“build.gradle”文件中的 ndk.abiFilters 设置中即可:

// Your app's build.gradle
apply plugin: 'com.android.app'

android {
  compileSdkVersion 27
  defaultConfig {
      appId "com.google.example.64bit"
      minSdkVersion 15
      targetSdkVersion 28
      versionCode 1
      versionName "1.0"
      ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
// ...

1.3.2 使用CMake进行构建

如果您的应用是使用CMake构建的,那么您可以通过将 arm64-v8a 传递到“-DANDROID_ABI”参数来针对 64 位 ABI 进行构建:

    > cmake -DANDROID_ABI=arm64-v8a … or
   > cmake -DANDROID_ABI=x86_64 …

    在使用externalNativeBuild 时,此方法无效。请参阅使用Gradle进行构建部分。

1.3.3 使用ndk-build 进行构建

如果您的应用是使用 ndk-build 构建的,那么您可以使用 APP_ABI 变量修改“Application.mk”文件,从而针对 64 位 ABI 进行构建:

    APP_ABI := armeabi-v7a arm64-v8a x86 x86_64

在使用 externalNativeBuild 时,此方法无效。请参阅使用 Gradle 进行构建部分。

1.3.4 将32位代码移植到 64 位架构

如果您的代码已经可以在桌面或 iOS 平台上运行,那么您无需针对 Android 做额外的工作。如果这是第一次针对 64 位系统构建您的代码,那么您需要解决的主要问题是指针不再适合 int 这样的 32 位整数类型。您将需要更新以 int、unsigned 或 uint32_t 等类型存储指针的代码。在 Unix 系统上,long 对应的是指针大小,但在 Windows 上并非如此,因此您应该改用释意类型 uintptr_t 或 intptr_t。使用 ptrdiff_t 类型来存储两个指针之间的差异。

您应该始终选择使用 <stdint.h> 中定义的特定固定宽度整数类型,而不是 int 或 long 等传统类型,即便对于非指针也应如此。

使用以下编译器标记来捕捉代码在指针和整数之间转换不正确的情况:

    -Werror=pointer-to-int-cast
   -Werror=int-to-pointer-cast
   -Werror=shorten-64-to-32、

具有 int 字段(包含指向 C/C++ 对象的指针)的 Java 类也有同样的问题。在 JNI 源代码中搜索 jint,并确保切换到 long(Java 端)和 jlong(C++ 端)。

注意:因指针被截断而引起的崩溃将表现为 SIGSEGV,其中错误地址的前 32 位全部为零。

对于 64 位代码而言,隐式函数声明的危险性要高得多。C/C++ 假定隐式声明的函数(即编译器未检测到声明的函数)的返回值类型为 int。如果函数的实际返回值类型是指针,那么在 32 位系统上是可行的,因为在 32 位系统中指针的类型为 int,但在 64 位系统中,编译器会丢弃指针的前半部分。例如:

// This function returns a pointer:
// extern char* foo();

// If you don't include a header that declares it,
// when the compiler sees this:
char* result = foo();

// Instead of compiling that to:
result = foo();

// It compiles to something equivalent to:
result = foo() & 0xffffffff;

// Which will then cause a SIGSEGV if you try to dereference `result`.

以下编译器标记会将隐式函数声明警告变成错误,以便您能够更轻松地查找和解决此问题:-Werror=implicit-function-declaration

如果您有内联汇编程序,您需要重新编写该程序或使用普通的 C/C++ 实现。

如果您对类型大小进行了硬编码(例如,8 或 16 字节),请使用等效的 sizeof(T) 表达式(例如 sizeof(void*))来替换它们。

如果需要有条件地编译不同于 64 位的 32 位代码,则对于一般性的 32/64 差异,您可以使用 #if defined(__LP64__);对于 Android 支持的具体架构,可以使用 __arm__、__aarch64__ (arm64)、__i386__ (x86) 和 __x86_64__。

您需要调整类似 printf 或 scanf 的函数的格式字符串,因为如果使用传统的格式说明符,您无法以一种对 32 位和 64 位设备都正确的方式来指定 64 位类型。您可利用 <inttypes.h> 中的 PRI 和 SCN 宏来解决此问题,PRIxPTR 和 SCNxPTR 分别用于写入/读取十六进制指针,PRId64 和 SCNd64 分别用于以可移植的方式写入/读取 64 位值。

在移位时,您可能需要使用 1ULL 来获取要移位的 64 位常数,而不能使用仅支持 32 位的 1。

1.3.5 利用 Android App Bundle 减少大小增加量

为您的应用添加 64 位架构支持可能会导致 APK 的大小增加。我们强烈建议您利用 Android APP Bundle 功能,以尽量减小因在同一 APK 中同时包含 32 位和 64 位原生代码而对 APK 大小产生的影响。

实际上,将应用改为使用 Android App Bundle 可以缩减 APK 的大小,使其比现在更小。

1.3.6 游戏开发者

我们知道,迁移第三方游戏引擎是一个耗费人力的过程,并且需要很长的准备时间。庆幸的是,三大最常用的引擎目前都支持 64 位架构:

  • Unreal(自 2015 年起)
  • Cocos2d(自 2015 年起)
  • Unity(自 2018 年起)

1.3.7 Unity开发者

升级到支持的版本

Unity 自版本 2018.2 和 2017.4.16 开始提供 64 位支持。

如果您发现自己使用的Unity版本不支持64位架构,请确定要升级到的版本,并按照Unity提供的指南迁移您的环境,确保将您的应用升级到可构建 64位库的版本。Unity建议您升级到该编辑器的最新LTS版本,以获取最新的功能和更新。

下面的图表概述了Unity 的各个版本以及您应该采取的措施:

更改构建设置以输出 64 位库

如果您使用的 Unity 版本支持 64 位的 Android 库,那么您可以通过调整构建设置来生成 64 位版本的应用。您还需要使用 IL2CPP 后端作为 Scripting Backend(详见此处)。要为构建 64 位架构而设置 Unity 项目,请按以下步骤操作:

1.转到 Build Settings,然后确认 Unity 标志是否显示在 Platform 下的 Android 旁边,以确保您是在针对 Android 进行构建。

   a.如果 Unity 标志未显示在 Android 平台旁边,请选择 Android,然后点击 Switch Platform。

2.点击 Player Settings。

3.依次转到 Player Settings Panel > Settings for Android > Other Settings > Configuration

4.将 Scripting Backend 设为 IL2CPP。

5.依次选择 Target Architecture > ARM64 复选框。

照常构建!

请注意,针对ARM64进行构建需要您专门针对该平台构建您的所有资产。请按照 Unity 的指南来缩减 APK 大小,同时考虑利用 Android App Bundle 功能来减小大小增加量。

1.4 应用64位合规性检验

1.4.1 合并 APK 和 64 位合规性

如果您要使用 Google Play 的合并 APK 支持来发布应用,请注意在版本层面评估是否符合 64 位要求。不过,如果 APK 或 app bundle 不会分发给搭载 Android 9 Pie 或更高版本的设备,则不适用 64 位要求。

如果您的某个 APK 被标记为不合规,但该 APK 比较老旧且无法使其合规,一种策略是在该 APK 清单的 uses-sdk 元素中添加 maxSdkVersion=”27″ 属性。这样一来,此 APK 将不会被分发给搭载 Android 9 Pie 或更高版本的设备,因而也就不会再妨碍合规。

1.4.2 RenderScript和64位合规性

如果您的应用使用 RenderScript 并且是通过较低版本的 Android 工具构建的,该应用可能会存在 64 位合规性问题。使用版本低于 21.0.0 的构建工具时,编译器可能会将生成的位码放到外部 .bc 文件中。64 位架构不再支持这些旧的 .bc 文件,因此,如果您的APK 中有这类文件,就会造成合规性问题。

要解决此问题,请移除项目中的所有 .bc 文件,将环境升级到 build-tools-21.0.0 或更高版本,并将 Android Studio 中的 renderscriptTargetApi 设为 21+,以指示编译器不要生成 .bc 文件。然后,重新构建您的应用,检查是否有 .bc 文件,再将应用上传到 Play 管理中心。

二、64位应用测试

1.1 vivo远程真机调试

vivo云测平台提供Android 5.1及以后的部分真机调试,开发者可以直接通过以下链接进入远程真机进行试用体验:https://vcl.vivo.com.cn/#/home/index

vivo Android 7.0以后的大部分机器支持64位。

1.2 在64位设备上测试应用

64 位版本的应用应提供与 32 位版本相同的质量和功能集。请对您的应用进行测试,以确保使用最新的 64 位设备的用户能够在您的应用中获得优质的体验。

最简单的 APK 测试方法就是使用 adb 安装该应用。大多数情况下,您可以提供 –abi 作为参数,用以指示要将哪些库安装到设备上。这样在设备上安装该应用时便会仅包含 64 位库。

# A successful install:
> adb install --abi armeabi-v7a YOUR_APK_FILE.apk
Success

# If your APK does not have the 64-bit libraries:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
adb: failed to install YOUR_APK_FILE.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

# If your device does not support 64-bit, an emulator, for example:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
ABI arm64-v8a not supported on this device

安装成功后,请照常对应用进行测试,以确保其质量与 32 位版本相同。

三、64位应用发布

如果您觉得应用已准备妥当,请照常发布。与往常一样,请继续遵循部署应用的最佳做法。也务必要先在支持 64 位的设备上进行全面测试,然后再面向更广泛的受众群体发布。

四、参考链接

(1)Google指南:支持64位架构

https://developer.android.com/distribute/best-practices/develop/64-bit?hl=zh-cn

(2) 64-bit and Data Size Neutrality

https://unix.org/whitepapers/64bit.html

(3)20 issues of porting C++ code on the 64-bit platform

https://pvs-studio.com/en/a/0004/

vivo 折叠屏三方应用开发适配指南

一、vivo 多窗口(分屏小窗)功能适配指南

1.1 适配背景

随着大屏手机的普及,用户对于多窗口功能的使用越来越频繁,尽管google 已经推出了多窗口功能,但是很多应用还没有适配多窗口功能,因此,我们输出《vivo 多窗口(分屏小窗)功能适配指南》提供给应用侧进行适配,让三方应用开发者能够更清楚多窗口功能的适配开发流程。

1.2 适配指导

1.2.1 配置支持多窗口功能

应用AndroidManifest.xml 中可以针对 app 或 activity 进行设置。

代码实例:

<application
  android:resizeableActivity="true">
  <activity
      android:resizeableActivity="true" />
</application>

当应用 targetSdkVersion >=24 时,android 系统默认设置 android:resizeableActivity=”true”,不需要应用声明即可支持应用使用多窗口功能。当应用 targetSdkVersion < 24 时,需要应用针对 application 或 activity 设置 android:resizeableActivity=”true”。

1.2.2 获取Activity 实际显示的窗口大小和位置

Android11 及以上(API 级别为30 及以上)推荐使用:

WindowManager#getCurrentWindowMetrics() : 针对系统的当前窗口状态, 返回WindowMetrics 对象

WindowManager#getMaximumWindowMetrics():针对系统可能的最大窗口状态,返回 WindowMetrics

代码实例:

获取当前activity 的窗口指标

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

Android10(API 级别为29)推荐使用:

context.getResources().getDisplayMetrics()

不推荐使用:

context.getWindowManager().getDefaultDisplay().getMetrics(outMetrics)

上述接口中,context 为 Activity 对应的上下文句柄,每个 Activity 应该严格使用自己的context 来进行布局,而不是使用 application 的 context。

备注:

Display 方法 getSize() 和 getMetrics() 在 API 级别 30 中已被弃用,取而代之的是新的 WindowManager# getCurrentWindowMetrics() 方法。

Android 12(API 级别 31)弃用了 Display 方法 getRealSize() 和 getRealMetrics(),并更新了它们的行为以使其更接近 getMaximumWindowMetrics() 的行为。

getSize():获取context 显示的尺寸,不包括状态栏等系统显示区域的尺寸

getRealSize():获取手机屏幕的真实尺寸,包括状态栏等系统显示区域的尺寸

getMetrics():获取context 显示区域的屏幕元素,例如屏幕尺寸、屏幕密度等屏幕元素信息,不包括状态栏等系统显示区域的屏幕元素信息

getRealMetrics():获取context 显示区域的屏幕元素信息,例如屏幕尺寸、屏幕密度等屏幕元素信息,包括状态栏等系统显示区域的屏幕元素信息

Android10 上,我们推荐使用getSize 和getMetrics 来获取显示区域的大小。在多窗口(分屏小窗)模式下,getSize 和getMetrics 获取出来的是context 显示区域的大小,getRealSize和getRealMetrics 获取出来的是手机屏幕的真实大小,getSize 和getMetrics 获取出来的尺寸值要小于getRealSize 和getRealMetrics 的尺寸值。

1.2.3 获取Activity 的窗口布局方向

获取Activity 窗口方向的的方法为:

context.getResources().getConfiguration().orientation

注:不要使用width /height 的方法来判Activity 为横竖屏布局,因为在多窗状态下,支持应用的拖动,会改变宽高。

获取设备方向的方法如下:

context.getWindowManager().getDefaultDisplay().getRotation()。

1.2.4 Activity 大小切换时不重启适配

1. 应用在Activity 窗口大小切换时不重启适配,在android:configChanges 属性增加 screenSize|screenLayout| orientation|smallestScreenSize

代码示例:

<activity
 android:name=".MyActivity"
 android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation" />

2. 在Activity 的onConfigurationChanged 回调中更新宽高刷新子布局。

代码示例:

@Override
public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(newConfig);
   ……
}

应用复写 onConfigurationChanged() 方法,通过该方法的 Configuration 参数获得窗口高度等信息,并对界面布局做相应调整,如切换布局、调整控件位置和间距等。

1.2.5 状态栏位置

当处于分屏下屏,和小窗模式时,应用没有状态栏,此时不应该留出状态栏高度,需要从顶部开始布局。

可以通过configuration 中windowingmode 判断当前处于的模式,WINDOWING_MODE_FREEFORM 和WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 不需要空出状态栏。

1.2.6 分屏下ActivityRecord 动画问题

很多应用会重写

<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>

分屏下containingWidth/containingHeight 为分屏窗口的尺寸, width/height 为displaycontent 尺寸(全屏)

initialize(containingWidth, containingHeight, width, height);

对于动画类型有 ABSOLUTE/RELATIVE_TO_SELF/RELATIVE_TO_PARENT

如果应用配置的xml 中带了p,使用的displaycontent 尺寸,会导致分屏下位移动画问题。没有p 为 RELATIVE_TO_SELF 类型

1.2.7 正确处理分屏小窗的沉浸式

分屏或小窗模式下,应用顶部有个功能bar,应用在沉浸式适配时需为此功能bar 预留一定空间。因此应用在布局时,需要监听安卓原生的WindowInsetsListener 接口回调,针对captionBarInsets 变化来处理view 高度,注意不要使用固定高度!!!

参考代码:

java:

getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
  //应用在回调中计算view 高度
  return insets;
});

kotlin:

window.decorView.setOnApplyWindowInsetsListener { v: View?, insets: WindowInsets ->
  //应用在回调中计算view 高度
  insets
}

1.2.8 其他布局建议

•  布局参数尽量使用相对的布局参数,不要使用固定尺寸

•  避免根据屏幕大小,输入法高度等计算view 的布局参数,如设置popwindow、dialog 等子窗口的位置时,避免使用整个屏幕的相对位置

•  避免对DecorView,content 等根布局进行定制,比如设置DecorView 的背景、在DecorView 添加子布局等

•  注意生命周期处理,如小窗模式下出现页面点击、拖动无响应问题,可能跟布局或生命周期有关

•  避免根据物理屏幕方向设置当前功能或布局

二、折叠屏前后屏切换适配指南

2.1 屏幕兼容性

2.1.1 应用布局优化

折叠屏有主屏(展开态)和副屏(折叠态)两种形态,以X Fold 为例,主屏和副屏的分辨率分别是1916×2160 和1080×2520,densityDpi 是480,应用程序需要针对不同的屏幕尺寸进行布局适配和优化。

2.1.1.1 屏幕兼容显示

在对不同尺寸屏幕适配过程中,为了确保在折叠屏各个屏幕形态下获取最佳的布局显示效果,例如页面无明显的拉伸放大、布局错位、重叠和显示更多更清晰的内容,建议您对布局进行优化。应用界面正确、美观的布局和显示,包含如下:

•  确保您的布局能够根据屏幕适当地调整大小

•  根据屏幕配置提供合适的 UI 布局

•  确保对正确的屏幕应用正确的布局

•  提供可正常缩放的位图

    详细适配方法请参考Android 开发者适配指导:https://developer.android.com/training/multiscreen/screensizes?hl=zh-cn

    基于折叠屏的特性,用户经常会在主屏(大屏)玩游戏或全屏看视频,以X Fold 为例,主屏有前置摄像头,因此应用程序页面需要针对打孔屏做适配,避免页面显示时摄像头区域出现白边或黑边,影响显示效果。参考vivo 手机全屏适配开发指导:https://developers.vivo.com/doc/d/52a902cf33fa72efeeeaf5197d60efa5

2.1.1.2 支持横竖屏切换

以X Fold 为例,主屏(展开态)屏幕尺寸接近4:3,桌面应用支持横竖屏显示,因此用户会在任何形态下打开应用。因此我们建议应用程序支持横竖屏切换,提高用户体验。横竖屏切换适配建议如下:

1、 横竖屏切换涉及到方向、尺寸和键盘隐藏/ 显示, 因此需要在Activity 配置

android:configChanges=”orientation|screenSize|screenLayout|smallestScreenSize|keyboard|keyboardHidden”

2、 在onConfigurationChanged 函数收到config 变化后,动态加载横竖屏布局以及完成其他任务

public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(newConfig);
   if(newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
      //switch to port and load layout
      setContentView(R.layout.activity_main);
      //TODO something
   }else{
      //switch to land and load layout
      setContentView(R.layout.activity_main_land);
      //TODO something
   }
}

2.1.2 应用resizeable 能力支持

折叠屏状态切换时,涉及到分辨率和像素密度的动态变化。若应用程序界面不支持resizeable 能力,在切屏时会存在应用程序界面未全屏显示的问题,如下图所示:

展开态

折叠态

因此我们期望应用程序界面在切屏后可以全屏显示,应用程序支持resiszeable 需要在 AndroidManifest.xml 针对Application 或Activity 设置android:resizeableActivity。

<application
  android:resizeableActivity="true"> ->对应用内所有activity 生效
  <activity
      android:resizeableActivity="true" /> ->仅对此activity 生效
</application>

开发者需要根据应用面向的API Level (targetSdkVersion)进行支持resizeable 能力的申明。

•  如果应用程序面向API Level 24 以上(targetSdkVersion>=24),系统将默认应用支持resizeable 能力。

•  如果应用程序面向API Level 24 以下(targetSdkVersion< 24),需要应用在manifest 中显式的声明android:resizeableActivity=true, 才可以支持resizeable 能力。

    备注:虽然安卓提供了申请受限屏幕能力,但强烈建议您为应用设计resizeable 能力,因为一旦您声明了受限屏幕比例(最大或最小)这意味着,当您的app 运行在一个屏幕比例超出了您声明的范围,您的应用程序在屏幕上将出现黑边等现象。

    受限屏幕支持开发者适配指导:https://developer.android.com/guide/practices/screens-distribution?hl=zh-cn

2.2 应用连续性

为了保证应用程序在折叠屏展开/折叠过程无缝切换,开发者需要做应用连续性的设计,以确保应用程序任务不中断。以X Flod 为例,最佳的体验为,应用在展开切换过程中,不发生应用的重启,且切换之前的任务和应用相关状态得以保存和延续。

折叠屏切屏时会触发对smallestscreensize、screensize 和screenlayout 的配置更改。每当发生配置更改时,默认情况下会销毁并重新创建整个activity。开发者可以通过注册监听系统configchanges 消息,不重启应用的情况下处理配置更改,应用程序需要向manifest 中添加android:configchanges 属性,其中至少包含以下值:

android: configChanges = “screenSize|smallestScreenSize|screenLayout” 应用程序需要复

写 onConfigurationChanged() 方法,通过该方法的Configuration 参数获得屏幕的分辨率等信息,就可以针对不同比例屏幕下的应用界面布局做相应调整,如切换布局、调整控件位置和间距等。

public void onConfigurationChanged(Configuration newConfig) {
   super.onConfigurationChanged(newConfig);
if(newConfig.screenWidthDp > xxx) //判定屏幕尺寸
  //load layout
    setContentView(R.layout.activity_main);
    ...
}

如果您的应用必须进行重新走生命周期来以响应屏幕切换,需要进行状态的保存和恢复。

您可以通过OnSaveInstanceState()和ViewModel 对象来进行之前状态保存和后续的恢复。即,在销毁activity 之前,通过onSaveInstancesState()存储状态, 在onCreate() or onRestoreInstanceState()进行状态的恢复。

Note:不要在OnDestroy()中调用finish()或其他自行终止进程。这将导致应用程序在设备折叠或展开时关闭、闪退等问题。

其他适配事项可以参考Android 开发者适配指导(例如链接中提到的 保存界面状态和支持配置变更 部分):

https://developer.android.com/guide/topics/ui/foldables?hl=zhcn#%E5%BA%94%E7%94%A8%E8%BF%9E%E7%BB%AD%E6%80%A7

2.3.判定折叠屏设备方法

根据应用程序判定折叠屏设备的需求,提供了两种判定折叠屏设备的方法。

2.3.1 根据model 机型判定

此方法适用于应用程序已经针对部分折叠屏设备适配且支持新折叠屏设备在线配置生效场景,否则强烈建议开发者通过方法2 判定折叠屏设备。

以X Fold 为例,可以获取如下属性获取model 名

λ adb shell getprop ro.product.model

V2178A

2.3.2 通过接口判定

建议开发者使用此方法判定设备类型,接口说明如下:

类 :android.util.FtDeviceInfo

public static String getDeviceType

返回目前是三种类型:phone、tablet 和foldable

可以通过反射的方式获取设备类型,返回值foldable 表示折叠屏设备。

反射代码示例:

private static boolean isVivoFoldableDevice(){
     try{
       Class<?> c= Class.forName("android.util.FtDeviceInfo");
       Method m = c.getMethod("getDeviceType");
       Object dType = m.invoke(c);
       Log.d("fold","getDeviceType="+dType);
       return "foldable".equals(dType);
     }catch(Exception e){
       e.printStackTrace();
     }
     return false;
}

2.4.调试和验证

2.4.1 通过命令模拟调试

开发者可以在非折叠屏手机上面通过命令修改手机的屏幕分辨率和densityDpi 来进行模拟调试,如下以X Fold 屏幕配置为例模拟切屏(主屏->展开态,副屏->折叠态):

副屏切主屏模拟方法:

(1)预先在手机设置如下屏幕配置:

  adb shell wm size 1080×2520

  adb shell wm density 480

(2)adb shell wm size 1916×2160

主屏切副屏模拟方法:

(1)预先在手机设置如下屏幕配置:

  adb shell wm size 1916×2160

  adb shell wm density 480

(2)adb shell wm size 1080×2520

配置恢复方法:

adb shell wm size reset

adb shell wm density reset

2.4.2 通过模拟器调试

2.4.2.1 Android 折叠屏模拟器

除了通过手机动态切换分辨率的方式来进行调试外,也可以通过模拟器的方式进行调试和验证,Android Studio 模拟器Phone 分类支持8 英寸和7.3 英寸的折叠屏调试,但是无法克隆,即无法修改模拟器的物理尺寸和分辨率,且模拟器System image 如果是x86 的系统,只支持32 位应用的安装和运行,如果是纯64 位的应用,模拟器需要选择arm64-v8a,否则无法安装和运行应用。

Note:

1. Android Studio Foldable 模拟器无法修改物理尺寸、分辨率和densityDpi,因此在适配时,无法完全模拟vivo 折叠屏手机,在app 或activity resizeableActivity = true 时,为了验证切屏是否有黑边可以在Android 原生模拟器查看效果。

展开态
折叠态

2. 64 位模拟器需要PC 主机支持,部分PC 无法正常启动64 位模拟器。

2.4.2.2 折叠屏展开态模拟器

Android 折叠屏模拟器无法修改物理尺寸、分辨率和densityDpi,若应用在进行《2.2 不同分辨率布局适配》时,需要100%模拟折叠屏展开态的屏幕进行调试时,可以通过克隆Tablet分类的Nexus 10,然后修改vivo 折叠屏手机对应的物理尺寸、分辨率和DPI 进行调试和验证。

Note:

1. 应用UI 兼容性适配对物理尺寸有强关联时,请务必修改Screen size 为8.03,分辨率是展开态分辨率

2. 64 位模拟器是否可以运行需要PC 主机支持

3. 若手机模拟densityDpi 和分辨率调试无问题后,无法在模拟器运行,可以发包给vivo 接口人,在vivo 折叠屏真机运行点检。

4. 模拟器无法修改densityDpi,需要启动模拟器后,通过adb shell 命令设置。

此时打开终端,可以看到模拟器设备已经挂载和连接,可以进行adb 操作。

λ adb devices

List of devices attached

emulator-5554 device

模拟器无法直接修改densityDpi,需要启动模拟器后单独设置。

adb shell wm density 480

2.4.3 远程真机调试

目前vivo 已经支持X Fold 远程真机调试,开发者可以访问如下链接使用远程真机

https://vcl.vivo.com.cn/#/machine/picking

远程真机主屏效果图

远程真机副屏效果图

2.4.4 测试用例建议

2.4.4.1 用例1

应用在展开态下页面显示正常

测试步骤:

(1)在屏幕展开的状态下,打开应用,查看应用各个页面显示效果;

预期结果:

(1)应用的所有页面可以全屏显示,页面没有发生截断、拉伸变形、放大模糊,按钮缺失等问题;

2.4.4.2 用例2

应用在展开态下核心页面功能正常

测试步骤:

(1)在屏幕展开的状态下,打开应用;

(2)遍历应用核心页面的控件按钮,所有功能按钮可用,无失效/crash/anr 等问题;

预期结果:

(1)应用在折叠屏展开后,核心页面功能可用

2.4.4.3 用例3

应用在折叠和展开状态切换时业务不中断,应用页面显示和控件点击正常。

测试步骤:

(1)在展开态下,打开应用的测试页面;

(2)在应用的测试页面切换到折叠态,观察页面显示;

(3)点击测试页面的所有控件和按钮;

(4)在折叠态下,打开应用的测试页面;

(5)在应用的测试页面切换到展开态,观察页面显示;

(6)点击测试页面的所有控件和按钮。

预期结果:

(1)应用页面在状态切换过程中,不要出现页面重启、闪退;页面显示正常,不要出

现页面截断、拉伸变形、放大模糊,按钮缺失等问题;

(2)测试页面按钮和控件点击都能正常响应;

(3)应用页面在状态切换过程中,不要出现页面重启、闪退;页面显示正常,不要出

现页面截断、拉伸变形、放大模糊,按钮缺失等问题;

(4)测试页面按钮和控件点击都能正常响应。

三、vivo 多窗模式适配指南

3.1 适配规则

窗口在左右两边拆分显示以Activity 为基本单位,如果要实现拆分,应用窗口需要用Activity 实现和启动,子布局或者非Activity 实现的窗口,无法拆分。以下提供Pad 设备上在横屏时应用不同界面分屏显示的适配方法和规则

3.1.1 AndroidManifest 增加meta-data

在app 的AndroidManifest.xml 文件中 <application>标签内新增

<meta-data android:name=”VivoMultiWindow” android:value=”true” />

3.1.2 Assert 目录新增vivo_multiwindow.json 配置文件

“vivo_multiwindow.json”模板

在 assert 目录下新建配置文件 “vivo_multiwindow.json”,模板示例如下:

{         “funtouchPlugVersion”: “1.1”,       “package”:   “com.vivo.test”,       “elements”:   [                 {                        “fun”: {                                 “name”: “multi-landscape”,                                 “enable”: “true”                        },                        “config”: {                                 “mode”: 1,                                 “action”: [                                         {                                                  “pages”: “com.vivo.test.MainActivity”,                                                  “attachedPage”: “com.vivo.test.primaryActivity1”                                         },                                         {                                                  “from”: “com.vivo.test.FromActivity1”,                                                  “to”: “com.vivo.test.ToActivity”                                         },                                         {                                                “from”:   “com.vivo.test.FromActivity2”,                                                  “to”: “*”                                         }                               ],                               “Activities”:   {                                         “fullscreenActivities”: [                                                  “com.vivo.test.fullScreenActivity1”,                                                  “com.vivo.test.fullScreenActivity2”                                         ],                                         “transitActivities”: [                                                  “com.vivo.test.transitionActivity1”,                                                  “com.vivo.test.transitionActivity2”,                                                  “com.vivo.test.transitionActivity3”                                         ],                               },                               “EX”:   {                                         “draggable”:   “true”,                                         “statusBarVisible”:   “true”,                                         “videoAutoFullscreen”:   “true”,                                         “isRelaunchForResizing”:   “false”,                                         “supportDoubleResume”:   “true”,                                         “windowsGravity”: [                                                {                                                         “deviceType”: “FOLD”,                                                         “gravity”: “1|2”                                                },                                                {                                                         “deviceType”: “PAD”,                                                         “gravity”: “900|1654”                                                }                               ],                               “splitBarColor”:   “0xffe5e5e5”                        }                  }           }      ]}

“vivo_multiwindow.json”字段描述

“vivo_multiwindow.json”具体字段描述如下:

参数描述
funtouchPlugVersion1.0vivo 多窗口功能版本,目前固定1.0
package应用包名
fun.namemultilandscapevivo 多窗口功能名称,固定为multi-landscape
fun.enablefalse/是否启用该配置
false 关闭
true 启用
config.mode0/1默认模式
0 购物模式
1 自定义模式
config.action应用冷启动时默认打开的双界面配置
config.action.pages默认双屏主页面列表
注:可以指定多个,分号隔开,应用冷起动启动该页面,自动在副页面位置启动attachedPage页面
config.action.attachedPage默认双屏副页面
config.action.from(自定义模式生效)触发多窗口的源activity
config.action.to(自定义模式生效)触发多窗口的目标activity
“*”表示任意activity
注:当从源Activity启动目标Activity,自动在主副位置打开对应Activity
config.Activities.fullscreenActivities0/1是否需要全屏启动
0 非全屏
1 全屏
config.Activities.transitActivities过渡页面列表
注:无固定窗口位置,跟随启动时上一级页面窗口位置
config.EX特殊属性配置
config.EX.draggable0/1是否支持窗口拖动
0 不支持
1 支持
config.EX.statusBarVisible0/1是否支持状态栏可见
0 不支持
1 支持
config.EX.videoAutoFullscreen0/1是否支持默认视频全屏播放
0 不支持
1 支持
config.EX.isRelaunchForResizing0/1是否支持重启
0 不支持
1 支持
config.EX.windowsGravity窗口比例
config.EX.windowsGravity.deviceTypeFOLD/PAD设备类型
FOLD 折叠屏
PAD 平板
config.EX.windowsGravity.gravity1|2 /
900|1654
窗口比例
FOLD 默认1|2
PAD 默认900|1654
config.EX.supportDoubleResume0/1是否支持两个界面同时resume
config.EX.splitBarColor分隔条的颜色

3.2 适配建议

3.2.1 状态判断

获取Activity 是否运行在模式下:

String config = context.getResources().getConfiguration().toString();

boolean isInMagicWindow = config.contains(“multi-landscape”);

context 为Activity 的context

配置了Fullscreen 的页面,显示为全屏,但也运行在模式下

3.2.2 获取Activity 显示大小

推荐使用:context.getResources().getDisplayMetrics()

不推荐使用:context.getWindowManager().getDefaultDisplay().getMetrics(outMetrics)

context 为Activity 对应的上下文句柄,每个Activity 应该严格使用自己的context 来进行布局,而不是使用application 的context。

3.2.3 获取Activity 窗口布局方向

获取Activity 窗口方向的方法为:context.getResources().getConfiguration().orientation

当Activity 处于横屏应用显示状态下时,获取的orientation 统一为竖屏;如果Activity是在状态下全屏显示,其orientation 为值为横屏。

获取设备的方向context.getWindowManager().getDefaultDisplay().getRotation()。

3.2.4 指定Activity 全屏显示

横屏应用显示状态下,Activity 希望以全屏展示,有三种方法:

方法一:动态全屏显示,Activity 首先以横屏应用显示非全屏显示,调用Activity 类的如下接口申请横屏方向可进入全屏显示状态:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

在此状态下,调用Activity 类申请竖屏方向即可退出全屏状态:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

此场景广泛应用于视频全屏播放场景。

方法二:在配置文件fullscreenActivities 中添加想要全屏的Activity,即可实现Activity默认以全屏启动,此方法中,Activity 会一直以全屏状态显示

方法三:在“AndroidManifest.xml”文件中将Activity 的方向配置为横屏,此方法中,Activity 会一直以全屏状态显示

android:screenOrientation = “landscape”

或android:screenOrientation = “sensorLandscape”

3.2.5 开发建议

•  应用主界面Activity 的启动以singleTask 的模式来启动,保证其在栈内的唯一性。

•  应用内不要存在两个及以上组件名不一样的主界面Activity,例如某个应用在登录前的主界面Activity 组件名与登录后的Activity 组件名不同,会导致新的主界面Activity显示在右半边

•  尽量避免或减少过渡Activity 的使用,尽量避免或者减少使用过渡Activity 来实现Activity 的启动,如果一定要使用,建议使用ActivityA->ActivityB->ActivityC 的启动方式,而不是(ActivityA->ActivityB) + (ActivityA->ActivityC)的方式(示例中,ActivityB 为过渡Activity ) 。过渡Activity 的数量不能超过1 个, 例如ActivityA->ActivityB->ActivityC->ActivityD,其中ActivityB 和ActivityC 是过渡窗口,建议从ActivityA 直接启动ActivityC。

•  Activity 大小切换时不重启适配,建议应用在Activity 窗口大小切换时不重启适配,在android:configChanges 属性增加screenSize|screenLayout|orientation|

smallestScreenSize,并在Activity 的onConfigurationChanged 回调中更新宽高刷新子布局。

•  避免Activity 子布局的缺省重用,由于左右Activity 同时显示,左右显示的两个Activity中不能同时存在单实例的公共布局模块

•  避免左右两个Activity 共用一个播放器,左右两个Activity 同时显示,建议两边使用的播放器资源相互独立,互不影响。

•  建议Camera 相关的Activity 界面配置为全屏显示

3.3 启动返回显示逻辑

基于目前横屏应用显示模式,在模式中启动或者回退链条展示。

3.4 三方适配多窗模式过程中需要注意:

应用更新json 文件后安装不生效,可以通过下面两种方式更新:

1. 修改完之后,升级应用版本号,重新安装应用

2. 把数据库都删除,重新创建,需要root 权限删除数据库之后重启。

adb vivoroot

adb shell rm -rf data/data/com.vivo.smartmultiwindow/*

adb shell rm -rf data/user_de/0/com.vivo.smartmultiwindow/*

建议使用第一种。

vivo折叠屏适配指南2

跨应用拖拽

跨应用拖拽可以让用户将一个应用中的图像、文档或文件拖拽到另一个应用中。

通过分屏和悬浮小窗实现在大屏的跨应用拖拽,减少用户在应用之间来回切换,更高效地进行多任务处理,提高生产力。

关于跨应用拖拽的适配:https://developer.android.com/guide/topics/ui/drag-drop

三、典型场景

3.1 影音娱乐

影音娱乐类场景以大量影音内容资源带来的沉浸式体验为主。

3.1.1 视频资源平台

首页推荐

视频列表页

3.1.2 短视频/直播互动页

3.1.3 音乐播放界面

3.1.4 视频播放界面(悬停)

3.2 资讯阅读

资讯阅读类场景以信息的聚合为主,需利用屏幕优势,确保用户对关键信息浏览、理解的完整和高效。

3.2.1 首页布局:左右图文结构

3.2.2 首页布局:上下图文结构

3.2.3 资讯详情页

3.3 生活服务

生活服务类场景广泛地包含了购物、饮食、出行、学习等用户日常生活的各个方面。

3.3.1 首页列表

3.3.2 详情页面

3.4 通讯社交

社交通讯类场景主要包括:文字交流为主的IM对话、图像视频通话、社交动态等场景。

3.4.1 文字交流为主(IM对话)

3.4.2 图像·视频通话

3.4.3 社交动态

首页结构:推荐

详情页

可根据实际情况,自由选择应用多窗的两种交互规则。请参考基础适配原则-交互方式-多窗口交互(2.7)

3.5 效率办公

效率办公类场景以高效的体验,辅助和提升工作者的办公效率为主。

3.6 H5页面

H5页面以其便利的特性,广泛应用于小程序和网页版应用。

3.7 金融理财

用户在金融理财类场景中,需确保大屏信息呈现所带来的高效与舒适。

同时,需保障用户办理金融业务过程中的易用性。

3.7.1 首页布局

3.7.2 股票·走势详情页

3.8 游戏

根据不同的游戏类型和场景,优化大屏布局,在呈现与交互层面给用户带来愉悦的体验。

同时,考虑到用户在玩游戏时长时间握持设备,在设计展开态布局时,应根据不同的交互区做适配优化。

请参考交互方式(2.5)-合适的交互区

四、测试应用

4.1 设备尺寸

可在 Android Studio 中基于以下设备规格信息进行测试。

屏幕类型对角线长度(英寸)比例分辨率(像素)
主屏(展开态)8.034:3.551916*2160
副屏(折叠态)6.5321:9 1080*2520

vivo折叠屏适配指南1

一、概述

1.1 折叠屏简介

折叠屏手机作为一种具有特殊形态的设备,具备折叠使用的外屏(副屏),和展开使用的内屏(主屏),通常展开使用的内屏尺寸相对较大。

本文主要提供针对折叠屏大屏的适配建议,帮助设计师及开发者能够更简单、快速地将应用适配至折叠屏设备,以确保用户在不同设备中保持应用的一致体验所带来的愉悦感。

1.2 折叠屏形态

    1. 折叠态(副屏):外屏尺寸接近普通直屏手机,其设计规范可与直屏手机基本保持一致。

    2. 展开态(主屏):内屏较外屏有更大的屏幕宽度,需充分利用大屏优势,在信息呈现和交互方式上利用合适的布局方式对应用进行优化调整。

    3. 悬停态:折叠屏设备处于完全展开和折叠的中间状态,可平稳放置。可悬停角度:5°-160°

1.3 折叠屏特性

1.3.1 大屏内容呈现

折叠屏手机的展开态具有以下三个优势:

    1. 展示更多内容:提升信息呈现丰富度与交互效率。

    2. 提升沉浸感:在游戏、电影、视频通话、图片浏览等应用和场景下减少干扰,提升专注度。

    3. 多窗口、多任务:通过展示更多窗口和内容,实现多任务的并行,以丰富体验场景。

1.3.2 主副屏的体验连续

体验连续是指:从一种窗口大小转换为另一种窗口大小时带来无缝的用户体验。无论用户当前置身于什么体验,都应继续进行而不中断,防止用户感知无法接续。

通常情况下,从折叠态切换至展开态时,应用默认在主屏显示运行,并维持在副屏时的应用与任务状态。

同时,用户可在 “设置-显示与亮度-合上屏幕后熄屏” 中选择在展开态切换至折叠态后,是否自动熄屏:

    1. 开启的情况下,折叠设备后,副屏自动熄屏。

    2. 关闭的情况下,折叠设备后,副屏不熄屏并维持在主屏时的应用与任务状态。

二、基础适配原则

2.1 概述

为了避免应用在普通直屏手机移植到折叠屏手机时,缺少针对大屏的优化,导致布局混乱、信息呈现不完整等问题,大幅降低用户体验,建议基于以下三个核心指导建议优化设计:

    1. 适合展开态的界面元素为了发挥折叠屏展开态的大屏优势,在设计时需要基于屏幕特性和业务场景,优化界面布局结构,以提高用户的交互效率与愉悦感。原则上,更大的屏幕应当呈现更多的内容;在页面适配上,应当优先保证所有界面元素显示为适宜的大小,不应将界面单纯的整体放大,导致单屏信息呈现的减少,影响界面的使用效率。

    2. 灵活的响应式布局通过响应式布局建构页面,能够在可用空间发生变化时及时、灵活地进行调整优化。本文提供了多种布局建议,可根据业务场景和具体需求,使用其中一种或多种布局进行最优组合。关于布局的具体介绍,请参考界面布局(2.6)。

    3. 高效利用多窗口交互通过在更大的屏幕上同时展示多个窗口,用户可以高效、直观地处理多个任务,提升使用体验的价值。建议应用为用户在折叠屏展开态中提供更加丰富高效的使用方式,让用户体验得到不同维度的增值。

具体来说,基础适配原则从“信息呈现”与“交互方式”两个维度提供指导建议

2.2 信息呈现

界面中的信息呈现包括图片、视频、卡片、按钮、字体、控件等通用基础体验元素的展示。

屏幕展开前后,通用基础体验元素需保持一致。如:元素不发生变形、裁剪、信息显示不全或者模糊等情况,避免信息呈现的不一致。

2.3 基础元素适配

需将所有界面元素显示为适宜的大小。不应过大或过小,影响显示效率。

不应从折叠态到展开态直接等比放大文字图标、图片视频等要素,图片与文章的比例与在直屏手机的界面设计出入过大,导致用户在大屏界面中与在直屏手机中的感知不符合预期。

2.4 弹出框适配

建议应用在展开态下的弹出框尺寸与折叠态下弹出框尺寸保持一致,如因特殊需求,需要进行放大,则不应超过原尺寸的1.3倍

2.5 交互方式

2.5.1 合适的交互区

在展开态时,由于用户双手握持设备的情况较为常见,手指会难以顺利在屏幕所有区域进行交互。为了确保户的交互体验的高效与愉悦,在设计展开态布局时,应考虑到以下三个交互区域:

        ① 用户易于触达的区域。操作频率最高的控件元素建议放在此区域。

        ② 用户可以触达的区域。但有时候可能会造成一定不便,有一定操作频率的控件元素建议放在此区域。

        ③ 用户较难触达的区域。除特殊情况,不建议将需要交互的控件元素放在此区域。

2.3.2 折叠屏手机形态

折叠屏手机形态分为折叠态、展开态与悬停态:

    1. 折叠态:折叠屏手机折叠后的形态,折叠后屏幕尺寸变小。

    2. 展开态:折叠屏手机展开后的形态,展开后屏幕尺寸变大。

    3. 悬停态:折叠屏设备处于完全展开和折叠的中间状态,可平稳放置。可悬停角度为:5°-160°

在悬停状态下,建议“上半屏显示内容,下半屏展示操作”。

例如在视频播放的悬停态中,上半屏为播放页,下半屏为操作区,更方便地进行拖动播放进度、暂停、调节亮度音量等操作。

2.6 界面布局

由于折叠屏在展开态下,屏幕尺寸和比例与直屏手机差异较大,需根据不同需求调整合适的布局,确保用户在不同形态上保持一致的体验。

界面布局主要分为“相对拉伸”、“相对缩放”、“挪移”、“延伸”、“分栏布局”5个类别。

相对拉伸

布局中元素的高度为固定值,元素的宽度对比参照物确定,元素的显示宽度或者元素之间的间距随着屏幕变大而相对变大。

相对拉伸适用于文字内容、输入框、搜索框等。需要注意的是,随着拉伸而改变比例的图片是一种延展,不应因拉伸而变形。

相对缩放

布局中元素的大小比例保持固定,通过对比参照物确定尺寸,显示宽度随着屏幕变大而放大。

相对缩放适用于全屏状态下有固定比例的元素,如图片、视频等。页面中的图片比例不建议放太大,应保持合适的比例。

挪移

当屏幕宽度发生变化时,部分模块的布局可以挪动位置,例如将原先的上下布局切换成左右布局,用以提供屏幕的利用率。

挪移适用于信息层级相对较少的页面,例如歌单详情页等。

延伸

布局中元素横向布局,元素间的距离固定,可显示元素的数量随着显示宽度的改变而变化。

延伸布局适用于资讯TAB、内容推荐卡片、可视化数据等。

瀑布为延伸的拓展用法,将原来单列纵向布局,切分为两列或多列的纵向布局,在⼤屏上呈现更多内容。

分栏布局

具有 “父子和父父关系层级”的列表应用,可以左侧展示一级页面右侧展示其优先级高的子页面。

分栏布局适用于 IM、笔记、信息、邮件等列表类应用。

2.7 多窗口交互

多窗口类别优势适用场景
悬浮小窗通过减少跳转,更快处理临时任务,且广泛适用于各种场景多应用多任务单应用多任务
分屏双应用/任务的并行处理,且广泛适用于各种场景多应用多任务单应用多任务
应用多窗以多实例实现应用内的双窗口单应用多任务

悬浮小窗

悬浮小窗以小窗的形式展现应用,并支持不同窗口形式(小窗、分屏、全屏)之间快速切换。

小窗入口包括但不限于:近期任务卡片“小窗”选项,应用内滑、悬浮通知下拉等。

悬浮小窗能通过减少跳转,更快处理临时任务,且广泛适用于各种场景。

悬浮小窗技术接入规范:https://dev.vivo.com.cn/documentCenter/doc/582

分屏

vivo分屏在原生分屏的基础上做了定制化处理,例如增加分屏方式(消息三指组合)、分屏小桌面列表、输入法边界定制、加密界面定制等。

分屏的优势在于多应用/任务的并行处理,且广泛适用于各种场景。

vivo分屏的手势分屏方式为:三指上滑

分屏技术接入规范:https://dev.vivo.com.cn/documentCenter/doc/573

应用多窗

应用多窗以多实例实现应用内的双窗口,根据应用自身特性进行界面组合,减少频繁切换窗口的行为,提升效率。

应用多窗的优势主要分为以下两个:

    1. 同时比较两个同类型内容的不同信息。比如两个不同的图像、文档、商品详情等。

    2. 同时显示多级页面,呈现相同信息的不同维度。通常为主次关系,比如左半屏展示列表页面,右半屏为选中项的详情页面。适用于电商购物、通讯社交、效率办公等频繁切换窗口的应用场景。

应用多窗-左静右变

应用多窗提供了“左静右变”和“左变右变”两种交互规则:

左静右变的规则为:左侧固定页面,右侧可变,进行内容切换,右侧窗口是最终窗口。

适用于效率办公和通讯社交类应用。

应用多窗-左变右变

左变右变的规则为:左侧右侧皆可变。在右侧交互后启动新窗口时,把右侧界面往左推,新的界面在右侧展示。

适用于购物场景类应用。

跨应用拖拽

跨应用拖拽可以让用户将一个应用中的图像、文档或文件拖拽到另一个应用中。

通过分屏和悬浮小窗实现在大屏的跨应用拖拽,减少用户在应用之间来回切换,更高效地进行多任务处理,提高生产力。

关于跨应用拖拽的适配:https://developer.android.com/guide/topics/ui/drag-drop

三、典型场景

3.1 影音娱乐

影音娱乐类场景以大量影音内容资源带来的沉浸式体验为主。

3.1.1 视频资源平台

首页推荐

视频列表页

3.1.2 短视频/直播互动页

3.1.3 音乐播放界面

3.1.4 视频播放界面(悬停)

3.2 资讯阅读

资讯阅读类场景以信息的聚合为主,需利用屏幕优势,确保用户对关键信息浏览、理解的完整和高效。

3.2.1 首页布局:左右图文结构

3.2.2 首页布局:上下图文结构

3.2.3 资讯详情页

3.3 生活服务

生活服务类场景广泛地包含了购物、饮食、出行、学习等用户日常生活的各个方面。

3.3.1 首页列表

3.3.2 详情页面

3.4 通讯社交

社交通讯类场景主要包括:文字交流为主的IM对话、图像视频通话、社交动态等场景。

3.4.1 文字交流为主(IM对话)

3.4.2 图像·视频通话

3.4.3 社交动态

首页结构:推荐

详情页

可根据实际情况,自由选择应用多窗的两种交互规则。请参考基础适配原则-交互方式-多窗口交互(2.7)

3.5 效率办公

效率办公类场景以高效的体验,辅助和提升工作者的办公效率为主。

3.6 H5页面

H5页面以其便利的特性,广泛应用于小程序和网页版应用。

3.7 金融理财

用户在金融理财类场景中,需确保大屏信息呈现所带来的高效与舒适。

同时,需保障用户办理金融业务过程中的易用性。

3.7.1 首页布局

3.7.2 股票·走势详情页

3.8 游戏

根据不同的游戏类型和场景,优化大屏布局,在呈现与交互层面给用户带来愉悦的体验。

同时,考虑到用户在玩游戏时长时间握持设备,在设计展开态布局时,应根据不同的交互区做适配优化。

请参考交互方式(2.5)-合适的交互区

四、测试应用

4.1 设备尺寸

可在 Android Studio 中基于以下设备规格信息进行测试。

屏幕类型对角线长度(英寸)比例分辨率(像素)
主屏(展开态)8.034:3.551916*2160
副屏(折叠态)6.5321:9 1080*2520

Android 8.0适配指南

安卓8.0的适配问题主要都是兼容性适配问题,我们在vivo云测平台(VCL)上对一些APP进行了检测,总结出以下三类问题。

一、安装失败 

导致游戏安装失败的原因众多,目前我们检测到的主要是咪咕游戏SDK问题。

▪ 问题描述

此类问题主要是游戏没有集成最新版本的咪咕游戏SDK导致。

▪ 适配建议

目前咪咕游戏SDK最新版本已经兼容安卓8.0版本,建议游戏开发者尽快完成集成适配工作。

二、启动失败 

原因1:应用加壳不兼容

▪ 问题描述

此类问题主要是由于开发者使用了第三方不兼容8.0系统的加固服务导致(360加固、百度加固等)。定位此类问题,一般可在Android 8.0机器上分别安装未加固的应用和加固后的应用,通过应用表现来判定。如果未加固的应用能正常启动,而加固后的应用不能正常启动,则说明加固服务不兼容Android 8.0。

▪ 适配建议

目前360加固已兼容Android 8.0版本。如果开发者要使用加固服务,请咨询加固服务提供商其服务是否兼容Android 8.0版本,如不兼容请取消加固或者使用兼容Android 8.0版本的加固服务。

原因2:联通支付SDK不兼容

▪ 问题描述

主要是APP没有集成最新版本的联通支付SDK导致,也存在其他类型的SDK不兼容8.0系统导致APP启动失败的情况发生。

▪ 适配建议

目前联通支付SDK已经兼容安卓8.0版本,建议开发者尽快完成集成适配工作。APP启动失败时,应考虑检查SDK是否兼容。

原因3:链接了非NDK公开的SO库

▪ 问题描述

主要是应用动态链接了非NDK公开的SO库(如libpixelflinger.so、libcutils.so、libsqlite.so、libcrypto.so、libssl.so等),导致APP在运行中找不到SO而启动失败。

▪ 适配建议

解决此类问题可拷贝非NDK公开的SO库副本到项目中。确保APP在运行时可以找到对应的SO。为避免出现不兼容的问题,开发者应尽量不要使用此类非NDK公开的SO库。

三、运行异常 

目前平台检测出,导致APP运行异常的原因大多集中在腾讯米大师支付SDK问题上。

▪ 问题描述

此类问题主要是由于APP没有集成最新版本的腾讯米大师支付SDK导致。

▪ 适配建议

目前腾讯米大师支付SDK(1.6.6c)已经兼容安卓8.0版本,建议开发者尽快完成集成适配工作。

Android P应用适配指南

一、如何体验升级android P

1.1 x21升级android P指导

请开发者更新到市场最新系统版本进行对应调试。

1.2 vivo远程真机服务

vivo云测平台已经提供关于vivo x21 androidP的远程真机服务,开发者可以直接通过以下链接进入远程真机进行试用体验:

https://vcl.vivo.com.cn/#/home/index

1.3 pixel升级android P

开发者持有Pixel系列的机器可以直接ota升级,或则下载镜像升级,具体见链接:

https://developers.google.com/android/images

二、AndroidP兼容性变化

2.1 对非 SDK 接口的限制

2.1.1 介绍

非sdk的接口存在着稳定性问题,随着android版本的变化随时都有可能被移除,AndroidP开始,为了更好的提升app的兼容性,正对隐藏的非sdk接口进行限制,通过名单控制进行使用限制,具体规则限制如下:

白名单SDK标准接口,不受限制
浅灰名单仍可以访问的非 SDK 函数/字段
深灰名单对于目标 SDK 低于 API 级别 28 的应用,允许使用深灰名单接口。对于目标 SDK 为 API 28 或更高级别的应用:行为与黑名单相同
黑名单受限,无论目标 SDK 如何。 平台将表现为似乎接口并不存在。 例如,无论应用何时尝试使用接口,平台都会引发 NoSuchMethodError/NoSuchFieldException,即使应用想要了解某个特殊类别的字段/函数名单,平台也不会包含接口

2.1.2 影响范围

所有运行在AndroidP系统上的应用

2.1.3 如何适配

(1)对于黑名单及深灰名单中的接口,应用及时调整新的方案进行适配;

(2)黑名单及灰名单是在源码构建的时候生成的,在此提供一份,文件下载链接:【黑名单】点此下载   | 【灰名单】点此下载

(3)应用可以直接adb logcat命令中过滤”Accessing hidden”查看当前应用使用非sdk的情况

2.2 刘海屏适配指导(cutout)

2.2.1 介绍

随着X21后各种刘海屏相继出现,但没有一致的接口,AndroidP开始提供规范化的接口,应用可以使用标准接口,获取当前是否有刘海,控制应用在刘海屏上的布局显示区域。AndroidP的设备支持模拟刘海效果,持有P的设备的可以打开“开发者选项”,找到“模拟巨有凹口的显示屏”进行模拟调试。

2.2.2 影响范围

所有运行在AndroidP系统上的应用,不分targetsdkversion

2.2.3 如何适配

■ 怎么判断是否刘海支持与否?

View.getRootWindowInsets().getDisplayCutout()

返回DisplayCutout对象,为刘海的描述信息,不支持则返回空

■ 怎么获取刘海信息?

DisplayCutout.getSafeInsets() 返回安全区域Rect

DisplayCutout.getBounds()  返回刘海的区域的Region

■ 如何控制应用的布局显示?

通过控制窗口布局的layoutInDisplayCutoutMode属性可以达到控制应用在刘海屏下布局区域,具体可以设置以下值

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

没有设置的情况下默认此标记,只有状态栏区域可见的情况下,才意味着加了FLAG_FULLSCREEN or SYSTEM_UI_FLAG_FULLSCREEN标记的应用窗口都会被切边放在刘海以下

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

此flag下不进行应用窗口的限制,窗口可以显示到刘海区域

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

此flag下应用窗口一直被限制在刘海区域以下

应用也可以通过theme来达到同样的效果

<item name=”android:windowLayoutInDisplayCutoutMode”>default</item>

对应LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

<item name=”android:windowLayoutInDisplayCutoutMode”>shortEdges</item>

对应LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

<item name=”android:windowLayoutInDisplayCutoutMode”>never</item>

对应LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

应用遇到窗口显示被限制在刘海以下区域的可以调整

layoutInDisplayCutoutMode 设置为

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,再通过获取

DisplayCutout 关于刘海区域信息,调整UI达到更好的满屏体验。

2.3 应用待机分组策略

2.3.1 介绍

应用待机分组为AndroidP上新的电源管理功能,它将应用归为五类,没有采用不同的限制策略,来控制应用的访问资源的能力。

具体分以下五类:

活跃如果用户当前正在使用应用,应用将被归到“活跃”群组中,例如:
应用已启动一个 Activity
应用正在运行前台服务
应用的同步适配器与某个前台应用使用的 content provider 关联
用户在应用中点击了某个通知
工作集如果应用经常运行,但当前未处于活跃状态,它将被归到“工作集”群组中。 例如,用户在大部分时间都启动的某个社交媒体应用可能就属于“工作集”群组。 如果应用被间接使用,它们也会被升级到“工作集”群组中。
常用如果应用会定期使用,但不是每天都必须使用,它将被归到“常用”群组中。 例如,用户在健身房运行的某个锻炼跟踪应用可能就属于“常用”群组。
极少使用如果应用不经常使用,那么它属于“极少使用”群组。 例如,用户仅在入住酒店期间运行的酒店应用就可能属于“极少使用”群组。
从未使用安装但是从未运行过的应用会被归到“从未使用”群组中,此类应用不具备运行条件。

限制策略如下:

分类jobs*Alarns NetworkFirebase Cloud Messaging
活跃无限制无限制无限制无限制
工作集2小时每次6分钟每次无限制无限制
常用 8小时每次30分每次无限制High priority: 10/day
极少使用24小时每次2小时每次24小时每次High priority: 5/day
1. jobs在限制的情况下,只有10分钟窗口时间执行,超出十分钟将被停止
2. alarms在限制的情况下,只有10s中的执行时间
3. 网络被限制的情况下,每次10分钟的窗口时间访问网络资源

2.3.2 影响范围

所有运行在AndroidP系统上的应用,不分targetsdkversion,受此影响为主要为应用的后台行为受限制,特别如闹钟,地图导航,后台下载,健康类应用。

2.3.3 如何适配

■ 应用根据Android的限制策略,点检应用的后台行为是否被限制。

■ 如何确认是否因为应用待机分组导致的后台行为限制?

(1)先确认应用的待机分组

            adb shell am get-standby-bucket [packagename]  //查下当前应用的分组情况;

(2)如果不在活跃组(active)

            adb shell am set-standby-bucket packagename active  //强制切换应用到活跃分组;

确认在此情况下用户的行为是否依然受限制,如果是的话,才确认为待机分组策略导致的后台行为限制。

■ 应用可以通过

            adb shell am set-standby-bucket packagename active|working_set|frequent|rare 在不同分组见强制进行切换,调试自身应用。

■ 对于由于后台分组策略导致的后台限制,应用需要进行相关策略上的调整详细见:https://developer.android.com/about/versions/pie/power

2.4 Crypto JCA 提供程序已被移除,弃用 Bouncy Castle 加密

2.4.1 介绍

Crypto JCA 提供程序已被移除。调用 SecureRandom.getInstance(“SHA1PRNG”,”Crypto”) 将会引发 NoSuchProviderException,调用Bouncy Castle 提供程序的 getInstance(),会生成 NoSuchAlgorithmException 错误。

2.4.2 影响范围

(1)Crypto JCA 提供程序已被移除,此影响所有运行AndriodP系统的所有应用;

(2)Bouncy Castle 提供程序异常的问题,影响所有targetsdkversion>=28的应用;

2.4.3 如何适配

模块应该在getInstance()的时候不指派提供程序,采用默认实现即可

2.5 FLAG_ACTIVITY_NEW_TASK被强制要求

AndroidP上,从非 Activity 环境中启动 Activity,除非传递 Intent 标志 FLAG_ACTIVITY_NEW_TASK。 如果尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,此限制对所有运行AndroidP的应用生效。

2.6 禁止空闲应用访问相机、麦克风和传感器

Android 9 限制后台应用访问用户输入和传感器数据的能力。 如果您的应用在运行 Android 9 设备的后台运行,系统将对您的应用采取以下限制:

(1)应用不能访问麦克风或摄像头。

(2)使用连续报告模式的传感器(例如加速度计和陀螺仪)不会接收事件。

(3)使用变化或一次性报告模式的传感器不会接收事件。

2.7 前台服务的应用必须请求 FOREGROUND_SERVICE 权限

targetsdkversion>=28的应用在使用前台服务的都需要进行必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

<uses-permission ndroid:name=”android.permission.FOREGROUND_SERVICE”/>

2.8 默认情况下启用网络传输层安全协议

AndroidP上,对应targetsdkversion>=28的应用需要为特定域名启用明文,必须在应用的网络安全性配置中针对这些域名将 cleartextTrafficPermitted 显式设置为 true,默认情况下明文传输会直接抛出“java.io.IOException: Cleartext HTTP traffic to xxx.com not permitted”异常。

2.9 Apache HTTP 客户端弃用,bootclasspath 中已移除

AndroidP开始org.apache.http.legacy.jar这个包不在打包进bootclasspath,对于targetsdkversion>=28的,继续引用此包的应用将直接出现NoClassDefFoundError,对于targetsdkversion低于28的,系统会将此包加载到应用的classloader中,如果应用采用系统的classloader加载应用,将同样会出现NoClassDefFoundError,建议模块使用 HttpURLConnection 类,更加高效。

2.10 移除对 Build.serial 的直接访问

Build.SERIAL字段已经被废弃,AndroidP上值一直为“UNKNOWN”, 如果您的应用需要访问设备的硬件序列号,您应请求 READ_PHONE_STATE 权限,然后调用 getSerial()。

2.11 不允许共享 WebView 数据目录

targetsdkversion>=28的应用不允许在不同进程之间共享一个 WebView 数据目录。如果应用有多个进程使用 WebView、CookieManager 或 android.webkit 软件包中的任何其他 API,则在第二个进程调用 WebView 函数时,应用将会崩溃。

2.12 应用禁止访问xt_qtagui目录的文件

AndroidP后,不再允许应用直接读取 /proc/net/xt_qtaguid 文件夹中的文件。 这样做是为了确保与某些根本不提供这些文件的设备保持一致。应用应该采用标准 API TrafficStats 和 NetworkStatsManager 进行访问,此限制对所有运行AndroidP系统上的应用生效。

2.13 SELinux 禁止访问应用的数据目录

对于targetsdkversion>=28的应用,系统强制每个应用的 SELinux 沙盒对每个应用的私有数据目录强制执行逐个应用的 SELinux 限制。现在,不允许直接通过路径访问其他应用的数据目录。应用可以继续使用进程间通信 (IPC) 机制(包括通过传递 FD)共享数据,例如可以采用FileProvider

三、参考链接

(1)AndroidP所有应用行为变更:https://developer.android.com/about/versions/pie/android-9.0-changes-all

(2)AndroidP targetSDK 28应用行为变更:https://developer.android.com/about/versions/pie/android-9.0-changes-28

(3)AndroidP 电源管理:https://developer.android.com/about/versions/pie/power

(4)pixles系列镜像升级:https://developers.google.com/android/images

Android Q应用适配指南

一、如何体验升级android Q

1.1 vivo机器升级android Q指导

vivo NEX S, vivo NEX A,vivo X27已经提供有可升级到Android Q的开发者预览版本,开发者可以直接通过以下链接指导进行升级试用:

https://dev.vivo.com.cn/documentCenter/doc/210

1.2 vivo远程真机调试

vivo云测平台已经提供关于vivo NEX S, vivo NEX A,vivo X27 Android Q的远程真机服务,开发者可以直接通过以下链接进入远程真机进行试用体验:

https://vcl.vivo.com.cn/#/home/index

1.3 google原生机升级android Q

开发者持有Pixel系列的机器可以直接ota升级,或者下载镜像升级,具体见链接:

https://developer.android.google.cn/preview/download

二、Android Q兼容性变化

2.1 非SDK接口限制

Android 平台开始限制您的应用在 Android 9(API 级别 28)中使用非 SDK 接口,灰名单和白名单的非 SDK 接口已有更新。

适配建议: 

依赖非SDK接口的应用应尽快迁移到 SDK 替代方案,如部分非SDK接口无替代方案,则请求新的公共API。

2.2 重大隐私权变更

2.2.1 分区存储

以 Android Q 为目标平台的应用(以及选择接受这些变更的应用),Android Q 更改了应用对设备外部存储设备中的文件(例如存储在路径 /sdcard 下的文件)的访问方式,只有满足相关条件,应用才能访问其他应用创建的文件。

适配建议: 

如果应用以 Android Q 为目标平台,则在访问外部存储设备中的文件时会进入过滤视图,具有过滤视图的应用对其创建的文件始终拥有读/写权限,无论文件位于特定于此应用的目录以内还是以外。只有在满足以下两个条件时,您的应用才能访问其他应用创建的文件:

(1)您的应用已获得 READ_EXTERNAL_STORAGE 权限。

(2)这些文件位于以下其中一个明确定义的媒体集合中:

照片:存储在 MediaStore.Images 中。

视频:存储在 MediaStore.Video 中。

音乐文件:存储在 MediaStore.Audio 中。

2.2.2 设置位置信息

Android Q 引入了新的位置权限,区分应用前台和后台获取位置信息。如果您的应用在后台时请求访问设备位置信息,则会影响您的应用。如果用户只授权前台获取位置信息权限, 应用在返回后台后则不能再获取位置信息。

适配建议: 

使用新权限在后台访问位置信息,并在没有后台位置信息更新的情况下确保优雅降级。应用应向用户说明他们需要允许该应用始终都能访问设备位置信息,以确保正常运行,然后请求在后台访问位置信息。

2.2.3 后台应用启动

Android Q 对应用可启动 Activity 的时间施加了限制,只有在满足相关条件时才能启动 Activity。此项行为变更适用于在 Android Q 上运行的所有应用。

适配建议: 

检查activity是否符合启动的条件,后台应用都应创建通知以便向用户提供信息。

2.2.4 硬件标识符获取

从 Android Q 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号),会对应用依赖device id的功能产生影响。影响在 Android Q 上运行的所有应用,即使这些应用以 Android 9(API 级别 28)或更低版本为目标平台。

适配建议: 

请关注厂商近期发布的适配指导。

2.3 加固版本兼容

Android每个大版本升级,加固方案商都会对android大版本适配和兼容。依赖加固固件的应用需要及时更新最新的加固固件来适配Android新版本,避免加固导致应用无法正常使用或影响应用稳定性。

2.4 第三方SDK兼容

应用会依赖第三方的SDK Jar或Native so库等第三方SDK,Android大版本升级第三方SDK会存在不兼容的问题,需要推动以及更新依赖的第三方SDK适配android Q。

三、参考链接

(1)Android Q所有应用行为变更:https://developer.android.google.cn/preview/behavior-changes-all

(2)Android Q targetSDK 29应用行为变更:https://developer.android.google.cn/about/versions/10/behavior-changes-10

(3)Android Q 中的隐私权:https://developer.android.google.cn/preview/privacy

(4)google pixel系列镜像升级包:https://developer.android.google.cn/preview/download

Android 11应用适配指南

1、如何体验升级Android 11

1.1 vivo机器升级Android 11指导

请开发者更新到市场最新系统版本进行对应调试。

1.2 vivo远程真机调试

vivo云测平台上线了搭载有Android 11开发者预览版的测试机,提供了iQOO3、NEX 3S两款测试机型。vivo开发者云测平台官网链接:vcl.vivo.com.cn

1.3 google原生机升级Android 11

开发者持有Pixel系列的机器可以直接ota升级,或者下载镜像升级,具体见此链接。 

2、Android 11上的主要变更

2.1 兼容性

2.1.1 分区存储

说明:分区存储机制使得应用在外部存储空间能有一块属于自己的专用存储区域,这块区域是私有的,因此,这块区域非常适用于保存用户的私有数据。当然,应用无法访问其他应用的专用存储区域。但如果应用需要将自己专用存储区域的特定文件让其他应用也访问得到,可以通过设置文件分享的方式,去为这些文件做可共享的标记。分区存储将在文件管理、应用程序保护、用户隐私数据保护等方面上有很好的作用。

影响范围:

1) targetSdkVersion为30的应用。

2) targetSdkVersion为29,且未将requestLegacyExternalStorage设为true以停用分区存储的应用。

适配建议:

若您的应用依然使用旧版存储机制,现则需要将数据迁移到与分区存储兼容的目录。

访问文件的位置所需权限访问方法
应用的私有目录无需权限即可访问getExternalFilesDir()
其他应用的私有目录无,但目标文件要被其应用使用FileProvider标记为可共享文件通过ParcelFileDescriptor与FileDescriptor获取
媒体文件目录(音频、照片、视频文件)READ_EXTERNAL_STORAGE(仅当访问其他应用的文件时需要)MediaStore   API
下载目录(文档文件等)无需权限即可访问存储访问框架SAF

分区存储的详细介绍:https://developer.android.google.cn/preview/privacy/storage

2.1.2 单次授权

说明:Android 11开发者预览版本对权限进行了更细颗粒度的划分,引入了“单次授权”的概念。用户可以进行单次授权,让应用获得对用户位置、相机或麦克风的临时性访问权限,如下图所示。在获得本次的授权后,应用可以在以下时间段内获得对应数据的访问:

1) 当应用的Activity可见时。

2) 应用转为后台运行后的一小段时间。

3) Activity可见时启动了一项前台服务,并且随后将应用转到后台,那么应用可以继续访问相关数据,直到该前台服务停止。

影响范围:运行于Android 11上的所有应用。

适配建议:如果您的应用已遵循与权限相关的最佳做法(https://developer.android.google.cn/privacy/best-practices),您无需更改应用即可支持单次授权。

图:应用内的权限申请窗口提供一次性权限选项

2.1.3 后台位置信息访问权限获取方式

说明:当应用申请后台位置信息访问权限时,让用户授予权限的弹窗中,将不再提供“始终允许”的选项,这个选项只存在于设置中的应用权限授予页面,一定程度上能减少应用的“走后门”情况发生,如下图所示,并且后台位置权限的申请需要应用已经拥有前台位置权限。

影响范围:运行于Android 11开发者预览版本上的所有应用

适配建议:若您的应用确定需要获得后台位置信息访问的权限,现在则需要分为两个步骤,因为已无法在没有前台位置信息访问权限的时候直接申请后台位置信息访问权限。

1) 先申请前台位置信息访问权限

2) 再申请后台位置信息访问权限,也就是所谓的“始终允许”,而用户将被引导到设置中进行授予

图:申请后台位置信息访问权限时,应用内的权限申请弹框不再包含“始终允许”

图:后台位置信息访问权限的授予只能在设置中进行

2.1.4 软件包可见性

说明:Android 11开发者预览版本更改了应用查询同一设备上的其他已安装应用的方式,以及与之交互的方式。

影响范围:targetSdkVersion为30的应用

适配建议:应用需要在应用的清单文件中添加<queries>元素,以便系统了解应向其显示哪些其他已安装的应用。如果您的应用执行与其他应用的常见互动,那么您无需更改应用。更多关于Android 11开发者预览版本软件包可见性的信息可参考https://developer.android.google.cn/preview/privacy/package-visibility

2.1.5 新的前台服务类型

说明: Android 11更改了前台服务访问摄像头和麦克风相关数据的方式以进一步保护用户隐私。

影响范围:targetSdkVersion为30的应用

适配建议:您需要在该前台服务声明的foregroundServiceType属性中添加新的camera和microphone类型,否则将无法获取摄像头与麦克风的数据。

2.1.6 自定义视图消息框使用受限

说明:从后台发布的自定义视图消息框将会被系统屏蔽。这类消息框使用setView()为自己定义了一个布局,如图所示。出于安全与用户体验上的考虑,系统屏蔽了从后台发起的自定义视图消息框。但从前台发布的自定义视图消息框依然可以正常生效,且使用Toast.makeText()创建的文本消息框不受影响,在前后台发布均可正常生效。

影响范围:targetSdkVersion为30的应用

适配建议:建议使用信息提示控件(Snackbar)来做代替。

图:Android Q上从后台发布的自定义视图消息框示例

2.1.7 非SDK接口名单更新

说明:Android 11有大量的非SDK接口名单更新,各接口名单更新情况可查询https://developer.android.google.cn/about/versions/11/non-sdk-11。这些变更可能会对一些依赖了非SDK接口的应用带来不同程度的兼容性问题,特别是依赖了Android Q灰名单接口的应用,因为这些接口有一部分已经在Android 11中已归入黑名单中。

影响范围:运行于Android 11上的所有应用。

适配建议:如果您的应用依赖于Android 11的受限接口,您应该开始计划升级SDK并迁移到SDK替代方案。

2.2 新的交互体验和方式

每次Android系统的升级,几乎都会在交互体验上带来一些新变化,此次Android 11也不例外。

例如:

2.2.1 聊天气泡

聊天气泡(chat bubbles)的会话方式正式推出,不再是实验性功能,该特性支持会话窗口最小化为一个或多个悬浮气泡,气泡可以展开为小窗口模式的页面;

图:气泡形式的消息通知

图:气泡展开为会话小窗口

2.2.2 新的输入法键盘过渡动画

借助两个新的API接口——边衬区动画监听器(Insets Animation Listener)与窗口动画控制器(WindowInsets Animation Controller),Android 11为每天都要与我们打交道的输入法键盘带来了新的过渡动画,这些API可让您更轻松地调整应用内容,与IME的出现和消失以及状态和导航栏等其他元素保持同步。这是一个谷歌所提供的示例https://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation。和当前主流版本中直接从底部弹出的动画相比,新的输入法键盘动画可以跟随我们手指的实际划动逐帧变换,呈现出更加流畅也更加自然的滑入、滑出效果等等。

2.3 硬件层面的新支持

2.3.1 Android 11将更好地支持各类手机屏幕,以提升用户体验

● 瀑布屏:瀑布屏的“瀑布”区域,会带来边缘内容显示失真和误触的情况。在Android 11上,开发者已可以控制“瀑布”区域的交互,现有的DisplayCutout.getSafeInset…()方法现在会返回能够避开瀑布区域以及刘海的安全边衬区。

● 高刷屏:Android 11加入了新的API——Surface.setFrameRate()来允许应用设置自身运行的首选刷新率,以发挥高刷屏的优势获得更好的使用体验,同时也帮助系统在运行应用时智能切换,从系统层面解决高刷新率可能会带来的功耗问题。

2.3.2 Android 11支持并发使用多个摄像头

开发者可以通过新的API以查询对同时使用多个摄像头(包括前置摄像头和后置摄像头)的支持。如需在运行应用的设备上检查支持情况,可以使用以下2个方法,getConcurrentCameraIds()方法可返回摄像头ID的组合,isConcurrentSessionConfigurationSupported()可查询摄像头设备是否可以并发支持相应的会话配置。

2.4 增强5G支持

Android 11 带来了针对5G的“动态计量”和“带宽估算”,更好地发挥5G的高带宽和低延迟特性。灵活地针对不同的场景,不同的网络情况,自适应流媒体质量。

2.5 其他功能

2.5.1 ADB增量APK安装

在设备上安装大型APK可能需要很长的时间。ADB增量APK安装可以安装足够的APK以启动应用,同时在后台流式传输剩余数据,从而加速这一过程。如果设备支持该功能,并且您安装了最新的SDK平台工具,adb install命令将自动使用此功能。或运行此命令adb install –incremental以使用该功能。在运行ADB增量APK安装之前,您必须先为APK签名并创建一个APK签名方案v4文件。且必须将v4签名文件放在APK旁边,才能使此功能正常运行。

2.5.2 应用进程退出原因

Android 11引入了ActivityManager.getHistoricalProcessExitReasons()方法,用于报告近期任何进程终止的原因。应用可以使用此方法收集崩溃诊断信息,例如进程终止是由于ANR、内存问题还是其他原因所致。此外,您还可以使用新的setProcessStateSummary()方法存储自定义状态信息,以便日后进行分析。

2.5.3 动态资源加载器

Android 11引入了两个新API类ResourcesLoader和ResourcesProvider,用来支持应用动态扩展资源的搜索和加载方式。主要的一个用例就是让应用去访问APK外特定目录的资源。

3、参考链接

[1] Android 11中的存储机制更新:https://developer.android.google.cn/preview/privacy/storage

[2] 遵循权限方面的最佳做法:https://developer.android.google.cn/privacy/best-practices

[3] Android 11中的软件包可见性:https://developer.android.google.cn/preview/privacy/package-visibility

[4] Android 11中消息框的更新:https://developer.android.google.cn/guide/topics/ui/notifiers/toasts

[5] 非SDK接口名单更新:https://developer.android.google.cn/about/versions/11/non-sdk-11

[6] 新的输入法键盘过渡动画示例:https://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation

[7] Android 11中的重大隐私权变更:https://developer.android.google.cn/preview/privacy

[8] Android 11新的功能和API概览:https://developer.android.google.cn/preview/features

Android 12应用适配指南

1.Android 12上的主要变更

1.1 兼容性

1.1.1 前台服务启动限制

说明:除少数特殊情况外,以Android 12为目标的应用程序无法在后台运行时启动前台服务。如果应用程序在后台运行时尝试启动前台服务,并且前台服务不满足以下特殊情况之一,则系统将抛出ForegroundServiceStartNotAllowedException异常。具体情况可查询  https://developer.android.com/about/versions/12/foreground-services 。

注意:如果一个应用程序调用Context.startForegroundService()启动另一个应用程序拥有的前台服务,则只有两个应用程序的API级别都为Android 12时,此页面上描述的限制才有效。

影响范围:targetSdkVersion为31的应用。

适配建议:如果您的应用想要在后台运行时启动前台服务但又不符合以上几种特例时,您可以尝试使用WorkManager启动优先级更高的后台任务。在Android 12中WorkManager将支持一种新作业-加急作业,它允许应用执行重要任务,同时使系统能够更好地控制对资源的访问权限。但是加急作业并不是万能的,在系统负载过高或者已超出加急作业配额限制的时候,系统会延迟启动新的加急作业。

1.1.2 前台服务通知延迟

为了在 Android 12 上提供针对短时间运行的前台服务的流畅体验,系统可以为某些前台服务延迟 10 秒显示前台服务通知。此更改使某些短期任务在显示通知之前完成。如果某项前台服务至少具有以下特征之一,则系统会在服务启动后立即显示相关通知:

1.该服务与包含操作按钮的通知相关联。

2.该服务的 foregroundServiceType 为mediaPlayback、mediaProjection 或 phoneCall。

3.该服务根据通知的类别属性中的定义,提供与通话、导航或媒体播放相关的用例。

注意:在未来的 Android 12 开发者预览版中,这些用例可能会发生变化。

4.该服务通过在设置通知时调用 setShowForegroundImmediately(),以停用行为变更。

1.1.3 待处理 intent 必须声明可变性

说明:如果您的应用以 Android 12 为目标平台,您必须为您的应用创建的每个 PendingIntent 对象指定可变性。这项额外的要求可提高应用的安全性。如需声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException。 

影响范围:targetSdkVersion为31的应用。

适配建议:您必须为您的应用创建的每个 PendingIntent 对象指定可变性。

1.1.4 非SDK接口名单更新

说明:Android 12相较于Android11有大量的非SDK接口名单更新,这些改变可分为两种: 

1.Android 11(API 级别 30)中不受支持的(已被列入灰名单)的非 SDK 接口现已在 Android 12 中被屏蔽;

2.在 Android 12 中被添加到 Android SDK 的非 SDK 接口。

各接口名单更新情况可查询https://developer.android.com/about/versions/12/non-sdk-12 。这些变更可能会对一些依赖了非SDK接口的应用带来不同程度的兼容性问题,特别是依赖了Android 11灰名单接口的应用,因为这些接口有一部分已经在Android 12中已归入屏蔽名单中。

影响范围:运行于Android 12上的所有应用。

适配建议:如果您的应用依赖于Android 12的受限接口,您应该开始计划升级SDK并迁移到SDK替代方案。

1.2 用户体验

每次Android系统的升级,几乎都会在交互体验上带来一些变化,此次Android 12也不例外。

1.2.1 接收内容的统一API

对于用户来说,目前还没什么方法在应用中插入和移动图片、视频和其他富有表现力的内容。为了使您的应用能够轻松接收富媒体内容,我们引入了全新的统一 API,便于您接受来自任何来源的内容。在Android 12上,您可以用粘贴板复制粘贴、键盘输入或者拖放图片或者视频等内容。

在Android 11以及之前的版本,每个界面机制(例如长按菜单或拖放)都有对应的 API。这意味着您必须单独与每个API集成,并为每种插入内容的机制添加类似的代码:

而在Android 12上,统一API会通过创建一个要实现的单一 API 来整合这些不同的代码路径,这样您就可以专注于应用特定的逻辑,而让平台处理其余的工作。

您可以向界面组件附加新接口 OnReceiveContentListener,并在通过任何机制插入内容时获得回调。此回调会成为您的代码处理接收所有内容(从纯文本和样式文本到标记、图片、视频、音频文件等)的唯一位置。

1.2.2 自定义通知变更

以前,自定义通知能够使用整个通知区域并提供自己的布局和样式。由此产生的反模式可能会令用户困惑,或在不同设备上引发布局兼容性问题。Android 12 改变了完全自定义通知的外观。

对于以 Android 12 为目标平台的应用,包含自定义内容视图的通知将不再使用完整通知区域;相反,系统会应用标准模板。此模板可确保自定义通知在所有状态下都与其他通知相同,例如,在收起状态下的通知图标和展开功能,以及在展开状态下的通知图标、应用名称和收起功能。

通过这种方式,Android 12 通过为用户提供可看到且熟悉的通知展开功能,使所有通知保持外观一致且易于浏览。

如果您的应用使用的是完全自定义的通知,我们建议您尽快使用新模板进行测试,并进行必要的调整:

1.启用自定义通知变更:

a.将应用的 targetSdkVersion 变更为 S 以启用新行为。

b.重新编译。

c.在搭载 Android 12 的设备或模拟器上安装您的应用。

2.测试所有使用自定义视图的通知,确保这些通知在通知栏中看起来符合预期。

3.请注意自定义视图规格。一般来说,提供给自定义通知的高度比之前小。在收起状态下,自定义内容的最大高度已从 106dp 减少到 48dp。此外,水平空间也减小了。

4.为了确保“浮动通知”状态看起来符合您的预期,请勿忘记将通知渠道的重要性提升至“高”(在屏幕中弹出)。

1.2.3 配套设备的权限授予

连接到手表时,面向Android 12及更高版本的开发者们现在可以使用配置文件将特定于设备类型的一组权限捆绑在一起,让用户在手机连接上设备时将一次性授予所有权限,从而简化了设置过程。用户删除应用程序或删除关联之后,系统也会删除相关权限。

1.3 图形、图像和媒体

1.3.1 更轻松的模糊,滤色器和其他效果

Android 12添加了新功能RenderEffect ,可将常见的图形效果(例如模糊,滤色器,Android着色器效果等)应用于Views和渲染层次结构。效果可以组合为链式效果(组成内部和外部效果)或混合效果。由于处理能力有限,部分的Android设备可能不支持该功能。通过调用View.setRenderEffect(RenderEffect),效果也可以适用于View的底层的RenderNode。

实施RenderEffect:view.setRenderEffect(RenderEffect.createBlurEffect(radiusX, radiusY, SHADER_TILE_MODE))。

1.3.2音频和触觉耦合效果

Android 12应用程序可以使用手机的振动器从音频会话中生成触觉反馈。这为更身临其境的游戏和音频体验提供了机会。例如,触觉增强的铃声可以帮助识别呼叫者,或者驾驶游戏可以模拟崎岖地形的感觉。

1.4 安全性与隐私

1.4.1 更安全地导出组件

说明:如果您的应用以 Android 12 为目标平台,且包含使用 intent 过滤器的 activity、服务或广播接收器,您必须为这些应用组件显式声明 android:exported 属性。如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明 android:exported 的值,则您的应用将无法在搭载 Android 12 的设备上进行安装。

影响范围:targetSdkVersion为31的应用。

适配建议:您必须为包含intent过滤器的应用组件显式声明 android:exported 属性。

1.4.2 adb 备份限制

说明:为了保护私有应用数据,Android 12 变更了 adb backup 命令的默认行为。对于以 Android 12 为目标平台的应用,用户运行 adb backup 命令时,从设备导出的任何其他系统数据都不包含应用数据。

影响范围:targetSdkVersion为31的应用。

适配建议:如果您的测试或开发工作流程依赖于使用 adb backup 的应用数据,现在您可以选择通过在应用的清单文件中将 android:debuggable 设置为 true 来导出应用数据。

注意:为了帮助保护应用数据,请务必在发布应用前将 android:debuggable 设置为 false。

1.4.3 以不安全的方式启动嵌套 intent

说明:嵌套 intent 是在其他 intent 中作为 extra 传递的 intent。如果您的应用同时执行以下两项操作,就会发生 StrictMode 违规行为。

1.您的应用从已传递的 intent 的 extra 中解封嵌套 intent。

2.您的应用立即使用该嵌套 intent 启动应用组件,例如将 intent 传递给 startActivity()、startService() 或 bindService()。

为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动嵌套 intent,此功能便会发出警告。如需检查您的应用中是否会以不安全的方式启动嵌套 intent,请在配置 VmPolicy 时调用 detectUnsafeIntentLaunch()。如果您的应用检测到 StrictMode 违规行为,您可能需要停止应用的执行以保护潜在的敏感信息。

影响范围:targetSdkVersion为31的应用。

适配建议:您的应用可能会启动嵌套 intent,以便在应用的各个组件之间导航,或代表其他应用执行操作。如需在这两种情况下最大限度地降低出现 StrictMode 违规行为的可能性,请执行以下操作:

1.嵌套 intent 的内部启动:确保这些组件不会被导出。

2.嵌套 intent 的跨应用启动:使用 PendingIntent 代替嵌套 intent。如此一来,当 PendingIntent 从包含它的 Intent 中解封时,应用组件可以使用调用进程的身份启动 PendingIntent。该配置允许提供程序应用向调用应用的任何组件(包括未导出的组件)发送回调。

1.4.4 应用无法关闭系统对话框

说明:为了加强用户与应用和系统互动时的控制,从 Android 12 开始,弃用了 ACTION_CLOSE_SYSTEM_DIALOGS intent 操作。除了一些特殊情况之外,当应用尝试调用包含此操作的 intent 时,系统会基于应用的目标 SDK 版本执行以下操作之一:

1.如果应用以 Android 12 为目标平台,则会发生 SecurityException。

2.如果应用以 Android 11或更低版本为目标平台,则系统不会执行 intent,并且打印log。

在以下情况下,应用仍然可以在 Android 12 上关闭系统对话框:

1.您的应用运行的是插桩测试。

2.您的应用以 Android 11 或更低版本为目标平台,并在抽屉式通知栏顶部显示一个窗口。

如果您的应用以 Android 12 为目标平台,在这种情况下您无需使用 ACTION_CLOSE_SYSTEM_DIALOGS。这是因为,如果在窗口位于抽屉式通知栏的顶部时您的应用调用 startActivity(),系统会自动关闭抽屉式通知栏。

3. 您的应用以 Android 11 或更低版本为目标平台。此外,用户已与通知互动,可能使用了通知的操作按钮,您的应用正在处理服务或广播接收器来响应该用户操作。

影响范围:运行于Android 12上的所有应用。

1.4.5 不受信任的触摸事件被屏蔽

说明:为了维持系统安全并保持良好的用户体验,Android 12 会阻止应用使用触摸事件,使用触摸事件时叠加层会以不安全的方式遮掩应用。换言之,系统会屏蔽穿透某些窗口的触摸操作。此变更会影响选择让触摸操作穿透其窗口的应用,例如使用 FLAG_NOT_TOUCHABLE 标志。包括但不限于以下示例:

1.需要 SYSTEM_ALERT_WINDOW 权限并使用 FLAG_NOT_TOUCHABLE 标志的叠加层,例如使用 TYPE_APPLICATION_OVERLAY 的窗口。

2.使用 FLAG_NOT_TOUCHABLE 标志的 activity 窗口。

3.消息框消息。

在以下情况下,允许执行“穿透”触摸操作:

1.应用中的互动。您的应用会显示叠加层,并且只有当用户与您的应用进行互动时才会显示叠加层。

2.可信窗口。包括但不限于以下窗口:

    a.无障碍窗口

    b.输入法 (IME) 窗口

    c.Google 助理窗口

    注意:类型为 TYPE_APPLICATION_OVERLAY 的窗口不受信任。

3.不可见窗口。窗口的根视图是 GONE 或 INVISIBLE。

4.全透明窗口。窗口的 alpha 属性为 0.0。

5.足够半透明的系统警报窗口。当组合后的不透明度小于或等于系统针对触摸的最大遮掩不透明度时,系统会将一组系统警报窗口视为足够半透明。如果系统屏蔽触摸操作,Logcat 会记录以下消息:Untrusted touch due to occlusion by PACKAGE_NAME。

影响范围:运行于Android 12上的所有应用。

1.4.6 隐藏应用程序覆盖窗口

为了使开发人员能够更好地控制用户与开发人员的应用进行交互时所看到的内容,Android 12引入了隐藏已授予SYSTEM_ALERT_WINDOW 权限的应用的叠加窗口的功能 。

声明 HIDE_OVERLAY_WINDOWS 许可后,应用程序可以调用 setHideOverlayWindows() 以指示当该应用程序自己的窗口可见时,所有TYPE_APPLICATION_OVERLAY类型的窗口都应隐藏。在显示敏感内容(例如交易确认)时,应用程序可能会选择执行此操作。

显示TYPE_APPLICATION_OVERLAY窗口类型的应用应考虑可能更适合其用例的替代方案,例如画中画或气泡。

1.4.7 安全锁屏通知操作

Android 12在Notification.Action.Builder中添加了新的setAuthenticationRequired 标志。您可以使用该标志为锁定设备上的通知添加额外的安全保护。

当通知操作(notificaiton action)中的setAuthenticationRequired值为true时,用户必须先完成身份认证之后才能在锁定设备上进行通知操作。在这之前,仅当用户通知操作启动Activity或直接答复时,系统才会要求在锁定的设备上进行身份验证。要实现此功能,请添加setAuthenticationRequired到通知操作中。

1.5 其他功能

1.5.1 圆角API

Android 12引入了RoundedCorner 和WindowInsets.getRoundedCorner(int position) API,提供了屏幕圆角的半径和中心点。使用这些API,您的应用程序可以避免UI元素在带有圆角的屏幕上被截断。这些API在非圆角屏幕的设备上不生效。

1.5.2 运动传感器的速率限制

为了保护用户的潜在敏感信息,如果您的应用以 Android 12 为目标平台,则系统会将来自某些运动传感器和位置传感器的数据刷新率限制为200 Hz。该数据包括由设备的加速度计,陀螺仪和地磁场传感器记录的值 。

如果您的应用程序以Android 12为目标平台并且需要以更高的速率收集运动传感器数据,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。如果您的应用尝试在未声明此权限的情况下以更高的速率收集运动传感器数据, 系统会抛出SecurityException异常。

2.参考链接

[1]前台服务启动设置:https://developer.android.com/about/versions/12/foreground-services

[2]非SDK接口名单更新:https://developer.android.com/about/versions/12/non-sdk-12

[3]接收内容的统一API:https://developer.android.com/about/versions/12/features/unified-content-api

[4]自定义通知变更:https://developer.android.com/about/versions/12/behavior-changes-12#custom-notifications

vivo Android 13应用适配指南

1. Android 13上的主要变更

1.1 兼容性

1.1.1 使用 JobScheduler 改进预提取作业处理

说明:利用 JobScheduler,应用可使用 JobInfo.Builder.setPrefetch() 将特定作业标记为“预提取”作业,这意味着,理想情况下这些作业应该在应用下一次启动前提前一点运行,以提升用户体验。过去,JobScheduler 仅使用该信号让预提取作业有机会使用免费或多余的数据。

在 Android 13 中,系统现在会尝试确定应用下次启动的时间,并根据该估算值运行预提取作业。应用应尝试使用预提取作业来完成他们想要在下次应用启动前完成的任何工作。

影响范围:运行于Android 13上的所有应用。

1.1.2 停止使用共享用户 ID

说明:如果应用使用已废弃的 android:sharedUserId 属性,并且不再依赖于该属性的功能,可以将 android:sharedUserMaxSdkVersion 属性设置为 32。

这个新属性会告知系统,应用不再依赖于共享用户 ID。如果应用声明 android:sharedUserMaxSdkVersion 并且首次安装在搭载 Android 13 或更高版本的设备上,则应用的行为就像从未定义过 android:sharedUserId 一样,更新后的应用仍会使用现有的共享用户ID。

如果已在清单中定义了 android:sharedUserId 属性,请不要将其移除。这样做会导致应用更新失败。

共享用户 ID 会在软件包管理器中导致具有不确定性的行为。应用应使用适当的通信机制(例如服务和 content provider),在共享组件之间实现互操作性。

影响范围:运行于Android 13上的所有应用。

1.2 用户体验

每次Android系统的升级,几乎都会在交互体验上带来一些变化,此次Android 13也不例外。

1.2.1 前台服务(FGS)任务管理器

无论应用targetSdkVersion为多少,Android 13 都允许用户从抽屉式通知栏中停止前台服务。这项新功能称为前台服务 (FGS) 任务管理器,它会显示当前正在运行前台服务的应用列表。此列表的标签为使用中的应用,每个应用旁边都有一个停止按钮。

1.2.2 放置快捷设置图块API

借助新的图块放置API,应用现在可以提示用户直接将自定义图块添加到通知栏中的快捷设置图块中。借助新的系统对话框,用户只需一步即可不离开应用就添加图块,而不必转到“快捷设置”来添加图块。

1.2.3 按应用设置的语言偏好设置

在许多情况下,多语言用户会将其系统语言设置为某一种语言,但又想为特定应用选择其他语言。为了帮助应用为这些用户提供更好的体验,Android 13 针对支持多种语言的应用引入了以下新功能:

1. 应用可在运行时在界面中设置使用其他语言

2. 用户可在系统设置里为每个应用选择首选语言

1.3 图形、图像和媒体

1.3.1 可编程的着色器

Android 13 添加了对可编程 RuntimeShader 对象的支持,其行为是使用 Android 图形着色语言 (AGSL) 定义的。AGSL 与 GLSL 共用大部分语法,但可用于 Android 渲染引擎中以自定义 Android 画布中的绘制行为以及过滤 View 内容。Android 在内部使用这些着色器来实现涟漪效果、模糊以及拉伸滚动,并且 Android 13 让您能为应用制作类似的高级效果。

1.3.2 蓝牙低功耗音频

低功耗 (LE) 音频是新一代无线音频,旨在取代传统蓝牙并支持新的使用情形和连接拓扑。通过该技术,用户能够与朋友和家人分享音频内容以及播放音频给他们听,也可以订阅信息、娱乐或无障碍用途的公共广播内容。这项新技术可以确保用户接收到高保真度的音频,而不必牺牲电池续航时间,并且还可以在不同使用情形之间无缝切换,这是传统蓝牙技术无法实现的。

1.4 安全性与隐私

1.4.1 通知运行时权限

说明:Android 13 中引入了新的运行时权限,用于从应用发送非豁免通知:POST_NOTIFICATIONS。

1. 限对话框中可执行以下操作:

 ●  选择“允许”

如果用户选择允许选项,应用可以执行以下操作:

①发送通知。可以使用所有通知渠道。

②发送与前台服务相关的通知。这些通知会显示在抽屉式通知栏中。

 ●  用户选择“不允许”

如果用户选择不允许选项,应用将无法发送通知。除了几个特定情况之外,所有通知渠道都会被屏蔽。这类似于用户在系统设置中手动关闭应用的所有通知后发生的行为。

 ●  用户滑开对话框

滑开对话框(即既没有选择允许,也没有选择不允许),会发生以下行为:

①如果应用符合获得临时通知授权的条件,系统会保留临时授权。

②如果应用没有临时授权,则将无法发送通知。

2. 安装的应用的影响

在搭载 Android 13 的设备上安装应用,应用的通知默认处于关闭状态。在请求新的权限且用户向应用授予该权限之前,应用都将无法发送通知。

权限对话框的显示时间取决于应用的目标 SDK 版本:

 ●  应用targetSdkVersion为33或者更高版本时,应用将可以完全自行控制权限对话框的显示时间。应用可以借此机会向用户说明应用需要此权限的原因,进而鼓励他们授予该权限。

 ●  应用targetSdkVersion低于33时,系统会在应用创建第一个通知渠道时显示权限对话框。这通常是在应用启动时。

3. 对已安装应用的影响

为最大限度地减少与新通知权限相关的中断,系统会自动向系统升级前用户设备上已安装的所有符合条件的应用临时授予新通知权限。此临时授权的持续时间取决于应用的目标 SDK 版本:

 ●  如果应用targetSdkVersion为33或者更高版本时,则临时授权将持续到应用首次启动 activity 为止。

     应用可以完全自行控制权限对话框的显示时间。应用可以借此机会向用户说明应用需要此权限的原因,进而鼓励他们授予该权限。

 ●  如果应用targetSdkVersion低于33时,则临时授权将一直有效,直到用户在通知权限运行时对话框中明确选择一个选项。也就是说,如果用户在未做出选择的情况下关闭了权限提示,系统会保留应用的临时授权。

影响范围:运行于Android 13上的所有应用。

适配建议:

1. 更新应用的目标 SDK 版本。

2. 等待一段时间再显示通知权限提示。等到用户熟悉您的应用之后,再请求他们授予任何权限。新用户可能想要探索您的应用,并切身体会每项通知请求可以带来的好处。

3. 在上下文中请求权限。在应用内请求通知权限时,请在正确的上下文中请求,以便用户明确了解通知的用途以及应该选择接收通知的原因。

4. 检查您的应用能否发送通。用户必须为应用启用通知,应用才能发送通知。要确认用户是否已启用通知,请调用 areNotificationsEnabled()。

5. 以负责任的方式使用权限。获得发送通知的许可后,请负责任地使用该权限。用户可以查看您的应用每天发送的通知数量,并且可以随时撤消该权限。

1.4.2 针对附近 Wi-Fi 设备的新运行时权限

说明:在以前的 Android 版本中,用户需要向应用授予 ACCESS_FINE_LOCATION 权限,应用才能完成与热点相关的多个常见 Wi-Fi 用例、Wi-Fi 直连、Wi-Fi RTT 等。

由于用户很难将位置信息权限与 Wi-Fi 功能相关联,因此 Android 13 在 NEARBY_DEVICES 权限组中引入了新的运行时权限,适用于管理设备与附近 Wi-Fi 接入点连接情况的应用。此权限 (NEARBY_WIFI_DEVICES) 可满足这些 Wi-Fi 用例。

只要应用不会通过 Wi-Fi API 推导物理位置,那么当targetSdkVersion为33或更高版本的应用使用Wi-Fi API时,就可以请求 NEARBY_WIFI_DEVICES 而不是 ACCESS_FINE_LOCATION。

影响范围:targetSdkVersion为33的应用。

1.4.3 在后台使用身体传感器需要新的权限

说明:Android 13 中引入了“在使用时”访问身体传感器(例如心率、体温和血氧饱和度)的概念。如果应用targetSdkVersion为33并且在后台运行时需要访问身体传感器信息,那么除了现有的 BODY_SENSORS 权限外,还必须声明新的 BODY_SENSORS_BACKGROUND 权限。

影响范围:targetSdkVersion为33的应用。

1.4.4 intent 过滤器会屏蔽不匹配的 intent

说明:当应用向targetSdkVersion为33或更高版本的其他应用的导出组件发送 intent 时,仅当该 intent 与接收应用中的 <intent-filter> 元素匹配时,系统才会传送该 intent。系统会屏蔽所有不匹配的 intent,以下情况除外:

 ●  发送给其他应用的未声明任何 intent 过滤器的组件的 intent。

 ●  发送给应用中的其他组件的 intent。

 ●  由系统发送的 intent。

 ●  由具有根级特权的用户发送的 intent。

影响范围:targetSdkVersion为33的应用。

1.4.5 更安全地导出上下文注册的接收器

说明:为了帮助提高运行时接收器的安全性,Android 13 允许指定应用中的特定广播接收器是否应被导出以及是否对设备上的其他应用可见。如果导出广播接收器,其他应用将可以向应用发送不受保护的广播。

在以前的 Android 版本中,设备上的任何应用都可以向动态注册的接收器发送不受保护的广播,除非该接收器受签名权限的保护。要实现此安全增强措施,请执行以下操作:

 ●  启用 DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED 兼容性框架更改。

 ●  在应用的每个广播接收器中,明确指明其他应用是否可以向其发送广播。

注意:如果启用了 DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED 兼容性框架更改,则必须为每个广播接收器指定 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。否则,当注册广播接收器时,系统会抛出 SecurityException。

影响范围:targetSdkVersion为33的应用。

1.4.6 可主动降级的权限

说明:从 Android 13 开始,应用可以撤消先前由系统或用户授予的运行时权限。此 API 可以帮助应用保护用户的隐私。如需撤消特定运行时权限,请将该权限的名称传入 revokeOwnPermissionOnKill()。如需同时撤消一组运行时权限,请将这组权限的名称传入 revokeOwnPermissionsOnKill()。撤消是异步发生的,会终止与应用的 UID 相关联的所有进程。

系统只有在安全的情况下才会触发撤消操作。当有应用组件仍在前台运行,或者有另一个应用正在访问应用的组件时,不会发生撤消。如果想立即撤消权限,可以调用 exit()。但是,对 exit() 进行此类调用可能会导致当前正在访问应用的其他应用出现未定义的行为或崩溃。

1.4.7 使用精确闹钟的新权限

说明:应用可以使用自动授予应用的 USE_EXACT_ALARM 权限。不过,应用若要使用此权限,必须至少满足以下条件之一:

1.应用是闹钟应用或计时器应用。

2.应用是日历应用,可显示即将进行的活动的通知。

即将推出的 Google Play 政策会阻止应用使用 USE_EXACT_ALARM 权限,除非应用满足前面列表中显示的任一情况。

影响范围:targetSdkVersion为33的应用。

1.4.8 精细媒体权限

说明:如果应用以 Android 13 为目标平台,则必须请求一项或多项新权限,而不是 READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE 权限。

请求的权限集取决于您的应用需要访问的媒体类型:

媒体类型请求许可
图片和照片READ_MEDIA_IMAGES
视频READ_MEDIA_VIDEO
音频文件READ_MEDIA_AUDIO

如果用户之前授予应用READ_EXTERNAL_STORAGE权限,系统会自动将每个新权限授予您的应用。否则,当应用请求上表中显示的任何权限时,系统会显示一个面向用户的对话框。在下图 中,应用程序请求READ_MEDIA_AUDIO权限。如果同时请求 READ_MEDIA_IMAGES权限和READ_MEDIA_VIDEO权限,则只会出现一个系统权限对话框。

2. 参考链接

[1]Android 13开发者预览版:https://developer.android.com/about/versions/13/overview

vivo Android 13 开发者体验版

1、计划概览

欢迎加入vivo Android 13 开发者体验版,此计划将给开发者提供适配 Android 13系统的体验。

注:vivo Android 13 开发者体验版本仅面向开发者,极客用户,对于普通用户,我们强烈建议不要使用。

● 硬件和系统

开发者体验版本可以在iQOO 10、iQOO 10 Pro、X80 Pro设备系统上运行并体验。

● 开发和测试

如果您在vivo Android 13 开发者体验版本进行开发和测试工作, 您将可以针对新的软件变更测试您的应用,请参阅迁移指南,了解让应用与新平台兼容的简单步骤。更多详细的Android 13 相关的介绍,点击这里

感谢您加入vivo Android 13 开发者体验版!

2、获取vivo Android 13 开发者体验版

您可以通过如下方式下载使用iQOO 10、iQOO 10 Pro、X80 Pro设备的软件包固件,然后升级测试自己的应用。

注意:为避免在vivo设备上安装开发者体验版出现异常,升级前请务必先备份数据。

2.1 下载Android 13 开发者体验版

如下升级包下载链接:

设备下载链接MD5校验值
iQOO 10PD2217_A_13.1.7.10.W10.V000L1-update-full.zipd60e54b4ab3d3562f1a15f11d800f2c7
iQOO 10 ProPD2217_A_13.1.7.10.W10.V000L1-update-full.zipd60e54b4ab3d3562f1a15f11d800f2c7
X80 ProPD2185_A_13.0.12.6.W10.V000L1-update-full.zip594caad95190b4454b3237359186df26

2.2 升级Android 13 开发者体验版

您可以将下载到的开发者体验版本软件包固件,按照以下步骤,烧写到对应的vivo设备。手动烧写固件的步骤以X80 Pro为例,具体如下:

(1)下载X80 Pro开发者体验版本软件包固件。

(2)设备连接电脑后将手机USB设置切换到文件传输模式,将已下载好的软件包固件拷贝到X80 Pro手机存储根目录。

(3)按照以上步骤,在设置->系统升级->本地升级中点击升级包,待校验完成后开始升级。

(4)等待手机自动升级完成。

2.3 回退Android 13 开发者体验版

如果您已经手动升级到iQOO 10、iQOO 10 Pro、X80 Pro的开发者体验版,想对应降级到Android 12.0正常系统版本,请使用降级工具进行降级工作,具体请参考:

https://bbs.vivo.com.cn/newbbs/thread/32215628?show_title=1

3、反馈

如果您在使用中遇到严重问题,请进入对应的群进行反馈,群验证信息请填写手机的IMEI号

iQOO 10、iQOO 10 Pro QQ群 : 854374916

X80 Pro QQ群 : 759578505

4、Android 13 特性:

新增特性功能,包括但不限于:

  • 照片选择器

提供了一种更安全的媒体共享方式,而无需向应用授予整个媒体库的访问权限。

  • 控制中心

允许应用主动添加开关至控制中心,方便用户便捷地添加应用的控制中心开关。

  • 前台服务管理器

新增 前台服务管理功能,您可以通过控制中心查看运行中的前台服务及服务的运行时长,并随时停用前台服务。

5、已知问题

iQOO 10、iQOO 10 Pro:

1、当前系统版本有较多常用三方应用与 Android 13 不兼容,升级后可能会出现第三方应用无法正常使用的情况(如闪退、卡顿、黑屏、耗电等),建议您谨慎升级。

2、下拉状态栏,低概率背景透明,自动恢复。

3、健康APP概率定位异常,无法形成轨迹。

4、部分应用未同步深色模式。

X80 Pro:

1、当前系统版本有较多常用三方应用与 Android 13 不兼容,升级后可能会出现第三方应用无法正常使用的情况(如闪退、卡顿、黑屏、耗电等),建议您谨慎升级。

2、部分系统弹框主题样式不一致

3、分屏时,移动分屏,存在低概率性动画不连贯,出现黑屏

4、连续快速多次人像拍摄时,手机相机出现低概率的闪退

VIVO开放平台团队账号操作手册

VIVO开放平台团队账号操作手册

为提升合作开发者伙伴的团队协作能力及协作效率,vivo上线“团队账号”功能。开发者可根据团队协作需求,邀请添加团队成员,并根据实际需求,灵活分配不同应用的开发、测试、分发、运营推广等操作权限,在保证账号信息安全的前提下,方便团队成员共同使用开发者账号,协同管理应用。

具体操作如下:

一、开通团队账号功能

1、注册审核通过的开发者账号登录开放平台(https://id.vivo.com.cn/),点击账号-【团队账号】,或点击【产品】-【应用分发】-【团队账号】,进入团队账号页面。

2、主账号(即团队管理员)补充签署账号协议,即可完成团队账号功能开通。

二、添加子帐号

1、设置子账号信息

点击【添加团队成员】,输入成员账号信息,包括:账号名称、成员姓名、邮箱、手机号。

2、设置子账号的角色信息、可操作的功能权限以及应用数据权限

3、确认子账号信息,完成创建

主账号确认子账号信息无误后,点击【确认】,则子账号创建成功,系统将自动发送激活邮件到成员账号的邮箱。

邀请邮件有效期为72小时,如果邀请邮件过期,主帐号可点击【重新邀请】再次邀请激活。

三、激活子账号

团队成员收到激活邮件后,点击邮件中“点击激活”,即可完成账号激活,激活后即可登录使用子账号。

四、团队账号FAQ

1、主账号可添加多少子账号?

一个主账号下最多添加99个子账号。

2、子账号拥有哪些权限信息,如何查看?

1) 子账号只能使用主账号赋予权限的功能,并享有与主账号同等的操作权限,未被赋予权限的功能,不可查看且不可使用。

2) 子账号只能登录有权限的vivo平台,未赋予权限的平台不可登录。

3) 如需查看自己拥有的权限信息,子账号可登录开放平台,点击团队账号功能,查看拥有的功能权限。

3、子账号密码如何修改?

子账号登录后,点击【账号】-【团队账号】-【成员账号信息-密码】进行修改。

注:若子账号忘记密码,可由主账号在团队账号列表页对子账号操作【重置密码】,新密码会通过系统邮件发送至子账号邮箱。

4、子账号如何冻结&解冻?

主帐号可在团队账号列表页对子账号进行冻结、解冻。子帐号被冻结后,将无法再登录,需主账号解冻后才能登录。

注:如果主帐号被冻结,该主帐号下的所有子帐号将会被冻结。主账号解封流程,详见《账号冻结及解封流程》。

5、子帐号如何注销?

1) 子账号操作:登录平台,在团队账号列表页点击【退出团队】,即可完成子账号注销。

2) 主账号操作:登录平台,在团队账号列表页对某个子帐号进行删除,即可完成子账号注销。

VIVO开放平台企业开发者注册教程

VIVO开放平台企业开发者注册教程

一、温馨提示

1.vivo开放平台暂不支持个人开发者或个体工商户注册,感谢您的支持

2.开发者认证账号必须绑定邮箱(暂不支持绑定手机号),建议使用公共邮箱或企业邮箱绑定,以免人员离职造成交接问题

3.账号注册成功后需先填写联系人信息,请如实填写并及时更新,以便我们与您联系

二、开发者类型及认证材料准备

类型认证材料准备
普通企业二选一:(1)营业执照、组织机构代码证、税务登记证、法定代表人手持身份证照片(2)营业执照(三证合一)、法定代表人手持身份证照片
事业单位事业单位法人证书/组织机构代码证书、法定代表人手持身份证照片
社会团体社会团体登记证书/组织机构代码证书/税务登记证、法定代表人手持身份证照片
机关单位统一社会信用代码证书/发证机关证明函、法定代表人手持身份证照片

PS:“三证合一”,就是将企业依次申请的工商营业执照、组织机构代码证和税务登记证三证合为一证,证件名称为“营业执照”。对应的证件号码为18位数字+字母的统一社会信用代码。

资质图片上传要求如下:

(1)优先提供彩色照片,黑白件需加盖公司公章

(2)证照必须在有效期内,公章清晰可见

(3)所有证照主体必须保持一致

(4)关键信息必须清晰,格式支持:JPG/PNG,每张图片大小20M以内

(5)需企业法定代表人本人手持身份证,法定代表人需与营业执照一致

三、开发者账号注册流程

1.在首页右上角选择注册

2.填写注册信息

3.完善账户信息,上传企业资质,提交审核

注:目前仅vivo核心代理商选择【代理商】,非核心代理请联系核心代理商进行沟通合作;游戏代理商请选择【开发者】,其他开发者请选择【开发者】。

注:法定代表人手持示例

申请著作权质权变更登记的要求是什么?

申请著作权质权变更登记的要求是什么?

申请变更登记的,应持质权变更登记申请表、变更协议、《著作权质权登记证书》或《计算机软件著作权质押合同登记证明》以及其他有关文件向原登记机关办理著作权质权变更登记。登记机构自受理之日起10日内完成审查。经审查符合要求的,对变更事项予以登记。
    当申请变更的范围可以包括出质人和质权人的基本信息、著作权的基本信息、质权担保数额、质权担保范围等事项。涉及质权登记证App软著怎么写书内容变更的,应交回app电子版权认证免费原登记证书,由登记机构发放新的证书。