url_luacher适配指南

27 阅读5分钟

ohos平台适配flutter三方库指导url_launcher

1. 准备工作

下载待适配的三方插件:官方插件库

本指导书, 以适配 url_launcher 6.3.1 为例

2. 插件目录

image-20250627100055822

lib:是对接dart端代码的入口,由此文件接收到参数后,通过channel将数据发送到原生端;

android:安卓端代码实现目录;

ios:ios原生端实现目录;

example:一个依赖于该插件的Flutter应用程序,来说明如何使用它;

README.md:介绍包的文件;

CHANGELOG.md:记录每个版本中的更改;

LICENSE:包含软件包许可条款的文件。

3. 创建插件的ohos模块

命令:flutter create --platforms ohos,android,ios --org <org> <appName>

步骤:

  1. 用Android Studio打开刚刚下载好的插件。

  2. 打开Terminal,cd到插件目录下。

  3. 执行命令flutter create --platforms ohos url_launcher_ohos 创建一个ohos平台的flutter模块。

    flutter create --platforms ohos url_launcher_ohos
    Creating project url_launcher_ohos...
    Resolving dependencies in `url_launcher_ohos`... 
    Downloading packages... 
    Got dependencies in `url_launcher_ohos`.
    Wrote 46 files.
    
    All done!
    You can find general documentation for Flutter at: https://docs.flutter.dev/
    Detailed API documentation is available at: https://api.flutter.dev/
    If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev
    
    In order to run your application, type:
    
      $ cd url_launcher_ohos
      $ flutter run
    
    Your application code is in url_launcher_ohos/lib/main.dart.
    
    jianguo@nutpi url_launcher % 
    

    执行创建命令前:

    image-20250627100529361

    执行创建命令后,可以将url_launcher_ohos目录下的.dart_tool和.ldea文件删除。

    image-20250627100606266

4. 编写ohos插件的dart接口和pubspec.yaml文件

可直接复制url_launcher_android目录下lib的dart代码和pubspec.yaml文件进行修改。

dart代码基本不需要修改,只需要将android字样改为ohos。

lib目录dart代码:

img

pubspec.yaml文件:

name: url_launcher_ohos
description: Android implementation of the url_launcher plugin.
repository: https://gitcode.com/openharmony-tpc/flutter_packages/tree/master/packages/url_launcher/url_launcher_ohos
issue_tracker: https://gitcode.com/openharmony-tpc/flutter_packages/issues
version: 6.3.16
environment:
  sdk: ^3.6.0
  flutter: ">=3.27.0"

flutter:
  plugin:
    implements: url_launcher
    platforms:
      ohos:
        package: io.flutter.plugins.urllauncher
        pluginClass: UrlLauncherPlugin
        dartPluginClass: UrlLauncherOhos

dependencies:
  flutter:
    sdk: flutter
  url_launcher_platform_interface: ^2.3.1

dev_dependencies:
  flutter_test:
    sdk: flutter
  mockito: ^5.4.4
  pigeon: ^22.4.1
  plugin_platform_interface: ^2.1.7
  test: ^1.16.3

topics:
  - links
  - os-integration
  - url-launcher
  - urls

5. 编写ohos插件的原生ets模块

5.1 创建ohos的插件模块

由于是写ohos平台的flutter插件,而不是写一个应用,需要将原来的entry模块删除,新建一个url_launcher插件的静态模块,用来写ets原生代码逻辑。

步骤:

  1. 用DevEco Studio打开url_launcher_ohos下的ohos项目:

  2. 新建一个名称为url_launcher的静态模块:

    在DevEco Studio左上角点击Flie > New > Module > Static Library > Next,module name填写为url_launcher,其他选项为默认,点击Finish,完成创建。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 删除entry以及其他多余目录:

    entry目录(entry是用来写应用的,现在是要写插件,此处已不需要,应该删除),将url_launcher > src > main > ets目录下的文件全部删除(此处是一些模板代码可删除)。

5.2 修改相关配置文件

  1. 在url_launcher目录内的oh-package.json5添加libs/flutter.har 依赖:

    {
      "name": "url_launcher",
      "version": "1.0.0",
      "description": "Please describe the basic information.",
      "main": "Index.ets",
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "@ohos/flutter_ohos": "file:libs/flutter.har"  //此处为添加的依赖
      }
    }
    
  2. 将url_launcher目录外侧的oh-package.json5的dependencies中的flutter.har依赖删除:

    {
      "name": "url_launcher_ohos",
      "version": "1.0.0",
      "description": "Please describe the basic information.",
      "main": "",
      "author": "",
      "license": "",
      "dependencies": {
      },
      "devDependencies": {
        "@ohos/hypium": "1.0.6"
      },
    }
    
  3. 在url_launcher目录下添加flutter.har:

    img

5.3 编写ets代码

文件结构,和代码逻辑可参考安卓或ios:gitcode.com/openharmony…

ohos的api可以参考:gitcode.com/openharmony…

img

5.4 修改index文件

import UrlLauncherPlugin from './src/main/ets/plugin/UrlLauncherPlugin';
export default UrlLauncherPlugin;

5.5 打har

写完代码,改完配置文件后,即可打har包。

打包工具:DevEco Studio。

打包步骤:

  1. 鼠标定位到url_launcher目录。
  2. 点击DevEco Studio中的Build。
  3. 点击Make Module 'url_launcher'选项。
  4. 等待打包完成。

预期结果:

url_launcher > build > default > outputs 中有url_launcher.har生成,即为打har包成功。

img

6. 编写example

6.1 创建一个ohos平台的flutter example应用,用来验证刚刚适配的插件功能

cd 到url_launcher_ohos目录下 ;

命令:flutter create --platforms ohos example

工具:Android Studio

6.2 修改dart代码

复制url_launcher_android\example\lib下的main.dart代码,替换url_launcher_ohos\example\lib下的main.dart代码。

6.3 修改example pubspec.yaml文件

name: url_launcher_example
description: Demonstrates how to use the url_launcher plugin.
publish_to: none

environment:
  sdk: ^3.6.0
  flutter: ">=3.27.0"

dependencies:
  flutter:
    sdk: flutter
  url_launcher_ohos:
    # When depending on this package from a real application you should use:
    #   url_launcher_android: ^x.y.z
    # See https://dart.dev/tools/pub/dependencies#version-constraints
    # The example app is bundled with the plugin so we use a path dependency on
    # the parent directory to use the current plugin's version.
    path: ../
  url_launcher_platform_interface: ^2.3.1

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  mockito: ^5.4.4
  plugin_platform_interface: ^2.1.7

flutter:
  uses-material-design: true

7. 修改url_launcher的pubspec.yaml文件

flutter: plugin:platforms添加ohos。

dependencies:添加url_launcher_ohos依赖。

name: url_launcher
description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories.
repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
version: 2.1.0

environment:
  sdk: ">=2.18.0 <4.0.0"
  flutter: ">=3.3.0"

flutter:
  plugin:
    platforms:
      android:
        default_package: url_launcher_android
      ios:
        default_package: url_launcher_foundation
      linux:
        default_package: url_launcher_linux
      macos:
        default_package: url_launcher_foundation
      windows:
        default_package: url_launcher_windows
      ohos:
        default_package: url_launcher_ohos   #此处为添加

dependencies:
  flutter:
    sdk: flutter
  url_launcher_android: ^2.1.0
  url_launcher_foundation: ^2.3.0
  url_launcher_linux: ^2.2.0
  url_launcher_platform_interface: ^2.1.0
  url_launcher_windows: ^2.2.0
  url_launcher_ohos:
    path: ../url_launcher_ohos    #此处为添加

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  plugin_platform_interface: ^2.0.0
  test: ^1.16.0

8. 运行example

8.1 签名

Deveco Studio 打开三方库的 example > ohos 目录。

单击 File > Project Structure > Project > Signing Configs 界面勾选 Automatically generate signature,等待自动签名完成即可,单击 OK

8.2 运行

cd到url_launcher_ohos\example > ohos目录,使用下列指令运行:

flutter pub get
flutter run -d <device-id>

运行成功效果如下:


// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';
import 'package:url_launcher_platform_interface/link.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';

import 'src/messages.g.dart';

/// An implementation of [UrlLauncherPlatform] for Android.
class UrlLauncherAndroid extends UrlLauncherPlatform {
  /// Creates a new plugin implementation instance.
  UrlLauncherAndroid({
    @visibleForTesting UrlLauncherApi? api,
  }) : _hostApi = api ?? UrlLauncherApi();

  final UrlLauncherApi _hostApi;

  /// Registers this class as the default instance of [UrlLauncherPlatform].
  static void registerWith() {
    UrlLauncherPlatform.instance = UrlLauncherAndroid();
  }

  @override
  final LinkDelegate? linkDelegate = null;

  @override
  Future<bool> canLaunch(String url) async {
    final bool canLaunchSpecificUrl = await _hostApi.canLaunchUrl(url);
    if (!canLaunchSpecificUrl) {
      final String scheme = _getUrlScheme(url);
      // canLaunch can return false when a custom application is registered to
      // handle a web URL, but the caller doesn't have permission to see what
      // that handler is. If that happens, try a web URL (with the same scheme
      // variant, to be safe) that should not have a custom handler. If that
      // returns true, then there is a browser, which means that there is
      // at least one handler for the original URL.
      if (scheme == 'http' || scheme == 'https') {
        return _hostApi.canLaunchUrl('$scheme://flutter.dev');
      }
    }
    return canLaunchSpecificUrl;
  }

  @override
  Future<void> closeWebView() {
    return _hostApi.closeWebView();
  }

  // TODO(stuartmorgan): Implement launchUrl, and make this a passthrough
  // to launchUrl. See also https://github.com/flutter/flutter/issues/66721
  @override
  Future<bool> launch(
    String url, {
    required bool useSafariVC,
    required bool useWebView,
    required bool enableJavaScript,
    required bool enableDomStorage,
    required bool universalLinksOnly,
    required Map<String, String> headers,
    String? webOnlyWindowName,
  }) async {
    final bool succeeded;
    if (useWebView) {
      succeeded = await _hostApi.openUrlInWebView(
          url,
          WebViewOptions(
              enableJavaScript: enableJavaScript,
              enableDomStorage: enableDomStorage,
              headers: headers));
    } else {
      succeeded = await _hostApi.launchUrl(url, headers);
    }
    // TODO(stuartmorgan): Remove this special handling as part of a
    // breaking change to rework failure handling across all platform. The
    // current behavior is backwards compatible with the previous Java error.
    if (!succeeded) {
      throw PlatformException(
          code: 'ACTIVITY_NOT_FOUND',
          message: 'No Activity found to handle intent { $url }');
    }
    return succeeded;
  }

  // Returns the part of [url] up to the first ':', or an empty string if there
  // is no ':'. This deliberately does not use [Uri] to extract the scheme
  // so that it works on strings that aren't actually valid URLs, since Android
  // is very lenient about what it accepts for launching.
  String _getUrlScheme(String url) {
    final int schemeEnd = url.indexOf(':');
    if (schemeEnd == -1) {
      return '';
    }
    return url.substring(0, schemeEnd);
  }
}