Android 13 应用适配指南2,安卓13新功能和API

2.新功能和API

2.1 照片选择器

Android 13 包含对新照片选择器工具的支持。此工具为用户提供了一种安全的内置媒体文件选择方式,让其无需向应用授予对整个媒体库的访问权限。注意

:即将发布的 Google Play 系统更新预计会包含与照片选择器有关的新功能。在一项此类更新中,该库将增加对以 Android 11(API 级别 30)或更高版本为目标平台的应用(不包括 Android Go 设备)的支持。

2.1.1 选择媒体

照片选择器提供了一个可浏览、可搜索的界面,其中按日期(从最近到最早)顺序向用户呈现其媒体库中的文件。您可以指定用户只能看到照片或只能看到视频,并且默认情况下,允许的媒体选择量上限设置为 1。

2.1.2 定义分享限制

应用可以声明android.provider.extra.PICK_IMAGES_MAX的值,该值表示在向用户显示时照片选择器中显示的媒体文件数量上限。例如,如果您提示用户为其帐号选择要求的个人资料照片,请将一张照片设置为分享要求上限。注意

:如果您选择的上限为 1 张,照片选择器会以半屏模式打开。

如需在单选模式下启动照片选择器,请执行以下操作:

// Launches photo picker in single-select mode.
// This means that the user can select one photo or video.
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
startActivityForResult(intent, PHOTO_PICKER_REQUEST_CODE);

2.1.3 选择多张照片或多个视频

如果应用的用例需要用户选择多张照片或多个视频,您可以使用EXTRA_PICK_IMAGES_MAX extra 指定照片选择器中应显示照片的数量上限,如以下代码段中所示:

// Launches photo picker in multi-select mode.
// This means that user can select multiple photos/videos, up to the limit
// specified by the app in the extra (10 in this example).
final int maxNumPhotosAndVideos = 10;
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNumPhotosAndVideos);
startActivityForResult(intent, PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE);

请注意,可指定为文件数量上限的最大数字存在平台限制。如需访问此限制,请调用MediaStore#getPickImagesMaxLimit()。

2.1.4 处理照片选择器结果

照片选择器启动后,使用新的ACTION_PICK_IMAGES intent 来处理结果。该选择器会返回一组 URI:

// onActivityResult() handles callbacks from the photo picker.
@Override
protected void onActivityResult(
    int requestCode, int resultCode, final Intent data) {
    if (resultCode != Activity.RESULT_OK) {
        // Handle error
        return;
    }
    switch(requestCode) {
        case REQUEST_PHOTO_PICKER_SINGLE_SELECT:
            // Get photo picker response for single select.
            Uri currentUri = data.getData();
            // Do stuff with the photo/video URI.
            return;
        case REQUEST_PHOTO_PICKER_MULTI_SELECT:
            // Get photo picker response for multi select
            for (int i = 0; i < data.getClipData().getItemCount(); i++) {
                Uri currentUri = data.getClipData().getItemAt(i).getUri();
                // Do stuff with each photo/video URI.
            }
            return;
    }
}

默认情况下,照片选择器会既显示照片又显示视频。您还可以在 setType() 方法中设置 MIME 类型,以便按“仅显示照片”或“仅显示视频”进行过滤。例如,如需在照片选择器中仅显示视频,请将video/*传入setType():

// Launches photo picker for videos only in single select mode.
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.setType("video/*");
startActivityForResult(intent, );
// Apps can also change the mimeType to allow users to select
// images only - intent.setType("images/*");
// or a specific mimeType - intent.setType("image/gif");

注意:您的应用不能持续访问从此 intent 返回的 URI。当应用的进程结束后,该应用将无法访问 URI。

2.2 应用内语言选择器

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

使用自定义应用内语言选择器的应用应当使用这些新 API,以确保无论用户通过何种方式选择其语言偏好设置,都能获得一致的用户体验。这些新的 API 还有助于减少样板代码的编写。

为了向后兼容以前的 Android 版本,我们还会从Appcompat 1.6.0-alpha01开始在 AndroidX 中提供这些 API。

  • 允许用户为每个应用选择首选语言的系统设置

不支持多种语言的应用不受这些变更的影响。

2.2.1 API 实现

对于当前未使用自定义应用内语言选择器的应用,无需执行任何其他操作。

对于具有或想要使用应用内语言选择器的应用,请使用这些新 API(而非应用的自定义逻辑)来处理相关设置和获取用户对应用的首选语言设置。

使用 AndroidX 支持库来实现

为了向后兼容以前的 Android 版本,建议使用 AndroidX 支持库来实现应用内语言选择器。使用Appcompat 1.6.0-alpha01或更高版本中提供的setApplicationLocales()方法。

例如,如需设置用户的首选语言,您需要让用户在语言选择器中选择语言区域,然后在系统中设置该值:

LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("xx-YY");
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale);

使用 Android 框架 API 来实现

您还可以通过setApplicationLocales()getApplicationLocales()方法,使用 Android 框架 API 来实现应用内语言选择器。

例如,如需设置用户的首选语言,您需要让用户在语言选择器中选择语言区域,然后在系统中设置该值:

// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its localem
Context.getSystemService(LocaleManager.class).setApplicationLocales(newLocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language

如需获取用户当前的首选语言以显示在语言选择器中,您的应用可以从系统中取回该值:

// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales = mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user

2.2.2 面向用户的系统设置

用户可以通过新的系统设置为每个应用选择首选语言。他们可以通过以下两种方式访问这些设置:

  • 通过系统设置访问

设置 > 系统 > 语言和输入法 > 应用语言 >(选择应用)

  • 通过应用设置访问

设置 > 应用 >(选择一款应用)> 语言

已知问题

在测试应用时,有一些已知问题需要注意。

  • 可用语言列表中可能不包含您的应用支持的语言。
  • 如果您的应用使用拆分 APK,当应用语言区域发生变化时,系统不会自动下载这些 APK。
  • 现在的界面只是一个初步版本,在后续版本中会不断更改。

2.2.3 DEMO演示

2.3 可由开发者降级的权限

从 Android 13 开始,应用可以撤消先前由系统或用户授予的运行时权限。此 API 可以帮助应用保护用户的隐私。

如需撤消特定运行时权限,请将该权限的名称传入revokeSelfPermissionOnKill()。如需同时撤消一组运行时权限,请将这组权限的名称传入revokeSelfPermissionsOnKill()。撤消是异步发生的,会终止与应用的 UID 相关联的所有进程。

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

:为了让系统设置表明您的应用不会访问特定权限组中的数据,您必须撤消该权限组中的所有

权限。在这种情况下,调用revokeSelfPermissionsOnKill()

会很有帮助。

2.4 可编程的着色器

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

基于可编程着色器实现的一个简单的绘制效果如下:

2.5 更快断字

断字让分行的文本更易于阅读,并且有助于使界面更具自适应性。在 Android 13 中,我们将断字性能优化了多达 200%,因此您现在可以在TextView中启用断字功能,这几乎不影响渲染性能。如需启用更快断字功能,请在setHyphenationFrequency()中使用新的fullFastnormalFast频率。

2.5.1 API变化

Android 13在已有断字模式基础上新增两种Fast模式:fullFastnormalFast,在原有基础上测量更快。

2.5.2 使用建议

在布局中添加属性android:hyphenationFrequency:

<!--少量快速断字模式-->
<TextView android:hyphenationFrequency="fullFast"/>
<!--标准快速断字模式-->
<TextView android:hyphenationFrequency="normalFast"/>

代码中直接设置:

//标准快速断字模式
mTextView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL_FAST)
//少量快速断字模式
mTextView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL_FAST)

3.影响应用的行为变更

3.1 行为变更:所有应用

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

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

下图说明了搭载 Android 13 的设备上的 FGS 任务管理器的工作流程:

3.1.1.1 用户操作会停止您的整个应用

当用户在 FGS 任务管理器中按您应用旁边的停止按钮时,系统会停止您的整个应用,而不仅仅是正在运行的前台服务。

比较“向上滑动”用户操作和“强行停止”用户操作的行为:

请参见下表中 FGS 任务管理器与现有功能的比较:从最近用过屏幕“向上滑动”和“强行停止”出现异常的应用

用户从 FGS 任务管理器停止应用时,不会发送任何回调。

当用户按停止按钮时,系统不会向您的应用发送任何回调。当应用启动备份时,建议您检查一下现有ApplicationExitInfoAPI 中的新REASON_USER_REQUESTED原因,这可能会很有帮助。

3.1.1.2 与长时间运行的前台服务相关的系统提示

如果系统检测到您的应用长时间运行某项前台服务(在 24 小时的时间段内至少运行 20 小时),便会发送通知邀请用户与 FGS 任务管理器互动。详细了解就长时间运行的前台服务提醒用户的新系统通知

小米开发平台 双开应用修改头像失败等场景适配说明

小米开发平台 双开应用修改头像失败等场景适配说明

背景

在Android 11及以上版本,当应用双开后,双开应用中启动系统剪裁页面,实现修改头像等场景时,会出现剪裁保存图片失败问题。此场景需要应用适配双开。

应用双开功能

手机设置-应用设置-应用双开

适配说明

在应用启动剪裁页面时,intent中放入的输出路径的uri需要带上userId,具体如下:

/**
* 反射获取getCallingUserId
*/
private int getCallingUserId(){
        Class UserHandleClass = UserHandle.class;
        int userId = 0;
        try {
            userId = (int)UserHandleClass.getMethod("getCallingUserId").invoke(UserHandleClass);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e){
            e.printStackTrace();
        }
            return userId;
    }
/**
* @param uri: 需要剪裁uri,如图库等返回的uri
* 拉起系统剪裁页面
*/
private void cropImage(Uri uri) {
        if(uri == null) {
           return;
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.putExtra("scale", true);
        intent.putExtra("aspectX", XXX);
        intent.putExtra("aspectY", XXX);
        intent.putExtra("outputX", XXX);
        intent.putExtra("outputY", XXX);
        intent.putExtra("outputFormat", XXX);
        intent.putExtra("return-data", XXX);
        File tmpFile = new File(getExternalFilesDir(null), System.currentTimeMillis()+".jpg");
        try {
            tmpFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Uri mCutUri = FileProvider.getUriForFile(MainActivity.this,
                "com.xxx.fileprovider", tmpFile);
        //生成带userId的uri
        Uri.Builder builder = mCutUri.buildUpon();
        Uri newUri = builder.encodedAuthority("" + getCallingUserId() + "@" + mCutUri.getEncodedAuthority()).build();
 
        intent.putExtra(MediaStore.EXTRA_OUTPUT, newUri);
        //调用grantUriPermission给newUri授权
        grantUriPermission("packaName", newUri,  Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.setDataAndType(uri, "image/*");
        startActivityForResult(intent, REQUEST_CROP);
  
    }

小米开发平台 禁止应用获取MAC地址说明

小米开发平台 禁止应用获取MAC地址说明

一、变更说明:

在Android 11及以上机型中,应用无法通过

NetworkInterface#getHardwareAddress

二、获取到设备mac地址

对于targetSdkVersion<30的App,将会返回一个占位符02:00:00:00:00:00;

对于targetSdkVersion>=30的App,将会直接返回null(与原生特性一致)。

三、应用适配

本功能自身无需适配,但需要开发者检查验证是否影响应用正常使用,并进行相应调整。

四、功能体验

若想体验该功能,机型和版本要求如下:

小米11-21.7.13以上的开发版

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

getCurrentPosition 实时连续定位 APP开发高德定位 实现连续定位能力

用做网页的技术做APP
一门提供标准化的jsbridge-mini.js库,您只需要在页面引用执行JS即可实现各种原生APP、原生PC的功能能力。

==================APP端==================
【APP端】(安卓版&苹果版)目前提供200+原生功能,2000+JS映射接口,用做网站的技术即可实现各种原生APP能力、APP demo地址https://www.yimenapp.com/doc/demo.cshtml下载教程:
♦ JS-SDK 引用方式:
♦ 普通网页 script 方式加载:下载最新版,请在页面上调用 jsBridge 接口之前引用 jsbridge-mini.js 库;
♦ js module 方式引用:npm install ym-jsbridge 具体请参考 npm package
一门APP开发平台通用JS

getCurrentPosition 实时连续定位 APP开发高德定位 实现连续定位能力

1. watch 参数设为 true 即为实时连续定位,当用户位置发生变化时会收到回调通知;

2. Android 8 以上会在手机状态通知栏放置持续定位的前台服务通知,以降低应用被系统杀掉的概率;部分设备默认禁止了 APP 通知,可打包 本地通知 插件,调用 jsBridge.notification.requestAuth 检查是否开启了通知权限,如果没有通知权限可调用 jsBridge.appSettings() 引导用户开启权限;

3. Android 10 以上系统会申请后台定位权限(ACCESS_BACKGROUND_LOCATION),用户可选择 “始终允许” 或 “仅在使用该应用期间允许”;

4. Android 11 申请后台定位权限时不再出现 “始终允许” 选项,此时只能引导用户进入应用设置授予始终允许后台定位的权限;

5. 调用 jsBridge.appSettings() 可以打开应用设置;

6. 详细说明请参考 高德定位

核心代码示例,详情参阅demo

var i = 0;
var cnt = $("#cnt").show().text("");
var result = $("#result").text("定位中...");    
$('html,body').animate({scrollTop: $('#view').offset().top}, 1200);

//发起定位,开启后请拿着手机走起来
//在室外开启GPS定位会更准确
jsBridge.amapLoc.getCurrentPosition({
  watch: true,
  watchInterval: 1,
  //不需要地址信息时的定位速度更快,消耗更少的流量
  notAddress   : true,
  notifyTitle  : "我的APP",
  notifyContent: "持续定位中..."
}, function(succ, data){
  cnt.text("第 " + (++i) + " 次位置回调: ");
  result.JSONView({
    succ: succ,
    data: data
  });
});

A标签执行JS示例代码

<a href="javascript:void(0)" onclick="zhixing()">执行</a> 
<!-- 写入一个A标签href值为"javascript:void(0)",定义点击事件onclick;-->
<script src="您的服务器URL/jsbridge-mini.js"></script>
<!-- 在您的服务器引入一门JS地址,请下载jsbridge-mini.js上传您自己的服务器获取链接;-->
<script type="text/javascript">
function zhixing() {


<!--这里可以直接复制JS核心代码到此{}括号内-->
var i = 0;
var cnt = $("#cnt").show().text("");
var result = $("#result").text("定位中...");    
$('html,body').animate({scrollTop: $('#view').offset().top}, 1200);

//发起定位,开启后请拿着手机走起来
//在室外开启GPS定位会更准确
jsBridge.amapLoc.getCurrentPosition({
  watch: true,
  watchInterval: 1,
  //不需要地址信息时的定位速度更快,消耗更少的流量
  notAddress   : true,
  notifyTitle  : "我的APP",
  notifyContent: "持续定位中..."
}, function(succ, data){
  cnt.text("第 " + (++i) + " 次位置回调: ");
  result.JSONView({
    succ: succ,
    data: data
  });
});
}
</script>
<!--执行核心代码;
//如果需要进入页面就执行,去掉点击事件即可;-->

按钮执行JS示例代码

<button onclick="zhixing()" >执行</button>
<!-- //写一个按钮,定义点击执行事件; -->
<script src="您的服务器URL/jsbridge-mini.js"></script>
<!-- //在您的服务器引入一门JS地址,请下载jsbridge-mini.js上传您自己的服务器获取链接; -->
<script type="text/javascript">
function zhixing() {


<!--这里可以直接复制JS核心代码到此{}括号内-->
var i = 0;
var cnt = $("#cnt").show().text("");
var result = $("#result").text("定位中...");    
$('html,body').animate({scrollTop: $('#view').offset().top}, 1200);

//发起定位,开启后请拿着手机走起来
//在室外开启GPS定位会更准确
jsBridge.amapLoc.getCurrentPosition({
  watch: true,
  watchInterval: 1,
  //不需要地址信息时的定位速度更快,消耗更少的流量
  notAddress   : true,
  notifyTitle  : "我的APP",
  notifyContent: "持续定位中..."
}, function(succ, data){
  cnt.text("第 " + (++i) + " 次位置回调: ");
  result.JSONView({
    succ: succ,
    data: data
  });
});

}
</script>
<!-- //执行核心代码;
//如果需要进入页面就执行,去掉点击事件即可; -->