Flutter应用内URL Scheme跳转插件appscheme的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter应用内URL Scheme跳转插件appscheme的使用

配置说明

1、Android端配置说明

在您项目中 Android的AndroidManifest.xml文件中按照如下规范添加Scheme,例如android/app/src/main/AndroidManifest.xml

a、在需要启动的Activity中新增以下格式的代码

<!--Android Scheme-->
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <!--需要被网页拉起必须设置-->
  <category android:name="android.intent.category.BROWSABLE" />
  <category android:name="android.intent.category.APP_BROWSER" />
  <!--协议部分-->
  <data
    android:host="hong.com"
    android:path="/product"
    android:scheme="app" />
</intent-filter>

2、iOS端配置说明

在你的项目中,ios工程中Info.plist文件中按照如下规范添加Scheme,例如:ios/Runner/Info.plist

a、在Info.plist文件中添加如下格式的代码

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    ...
    <key>CFBundleURLTypes</key><!-- 表示添加Scheme相关信息 -->
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string>hong.com/product</string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>app</string><!-- 此处是Scheme -->
        </array>
      </dict>
    </array>
    ...
  </dict>
</plist>

使用方法

1、初始化

AppScheme appScheme = AppSchemeImpl.getInstance();

2、getInitScheme

appScheme.getInitScheme().then((value){
  if(value != null){
    setState(() {
      _platformVersion = "Init  ${value.dataString}";
    });
  }
});

3、getLatestScheme

appScheme.getLatestScheme().then((value){
  if(value != null){
    setState(() {
      _platformVersion = "Latest ${value.dataString}";
    });
  }
});

4、注册从外部打开的Scheme监听信息

appScheme.registerSchemeListener().listen((event) {
  if(event != null){
    setState(() {
      _platformVersion = "listen ${event.dataString}";
    });
  }
});

5、example中测试地址

测试地址

URL Scheme协议格式:

一个完整的URL Scheme协议格式由scheme、host、port、path和query组成,其结构如下所示

<scheme>://<host>:<port>/<path>?<query>

例如:

openapp://hhong:80/product?productId=10000007
  • openapp:即Scheme,该Scheme协议名称(必填)
  • hhong:即Host,代表Scheme作用于哪个地址域(必填)
  • 80:即port,代表端口号
  • product:即path,代表打开的页面
  • param:即query,代表传递的参数

传递参数的方法跟web端一样,通过问号?分隔,参数名和值之间使用等号=连接,多个参数之间使用&拼接。

Scheme使用

既然我们使用scheme来做打开app并跳转的逻辑,那这个scheme应该声明在哪里比较合适呢?如果你的应用在启动页(splash)或者在主界面(main)初始化了一些必要的设置,比如必要的token信息检查交易或者一些其它校验等,没有这些信息会造成崩溃的,这个时候我们就需要在启动页来声明这个scheme了,获取scheme信息保存起来,然后在主界面做处理逻辑,如跳转到其它界面等。当然你也可以声明scheme在其它地方,具体得需要看怎么实现业务比较方便。

HTML 示例

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>测试App Scheme</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
</head>
<body>
    <div>
        <a href="app://hong.com/product?productId=10000007">Android、iOS</a>
    </div>

    <div>
        <a href="app://">app:// 无host</a>
    </div>

    <div>
        <a href="app://hong.com">app:// 无path</a>
    </div>

    <div>
        <a href="app://hong.com/product">app:// 无query</a>
    </div>

    <div>
        <a href="intent://hong.com/product?productId=10000007#Intent;scheme=app;end">Android特殊机型</a>
    </div>

    <div style="text-align:center;">
        <h4>小熊有好货测试</h4>
        <div>
            <a href="xiaoxiongapp://xapi.xiaomanxiong.com/home?redirect_type=1&ios_redirect_url=www.baidu.com&android_redirect_url=www.baidu.com">测试类型1</a>
        </div>
        <div>
            <a href="intent://xapi.xiaomanxiong.com/home?redirect_type=1&ios_redirect_url=www.baidu.com&android_redirect_url=www.baidu.com#Intent;scheme=xiaoxiongapp;end">(Android特殊机型)测试类型1</a>
        </div>
    </div>
</body>
</html>

完整示例Demo

下面是一个简单的Flutter示例,演示如何使用appscheme插件进行URL Scheme跳转:

import 'package:flutter/material.dart';
import 'package:appscheme/appscheme.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';

  [@override](/user/override)
  void initState() {
    super.initState();
    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    AppScheme appScheme = AppSchemeImpl.getInstance();

    // Get the initial scheme
    appScheme.getInitScheme().then((value) {
      if (value != null) {
        setState(() {
          _platformVersion = "Init  ${value.dataString}";
        });
      }
    });

    // Register a listener for future schemes
    appScheme.registerSchemeListener().listen((event) {
      if (event != null) {
        setState(() {
          _platformVersion = "Listen ${event.dataString}";
        });
      }
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Text('Running on: $_platformVersion\n'),
        ),
      ),
    );
  }
}

更多关于Flutter应用内URL Scheme跳转插件appscheme的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用内URL Scheme跳转插件appscheme的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter应用中,使用URL Scheme(也称为自定义URL Scheme)可以实现应用内的页面跳转或与其他应用的交互。app_linksurl_launcher 是常用的Flutter插件,但专门用于处理应用内URL Scheme的插件之一是 flutter_app_scheme。尽管 flutter_app_scheme 并不是一个广泛认知的官方或主流插件(可能是因为它的功能可以被其他插件或方法覆盖),但我们可以展示一个类似的实现方法,利用 url_launcher 和一些路由管理来实现应用内URL Scheme跳转。

以下是一个使用 url_launcher 和 Flutter的路由管理实现应用内URL Scheme跳转的示例:

  1. 添加依赖: 在你的 pubspec.yaml 文件中添加 url_launcher 依赖。

    dependencies:
      flutter:
        sdk: flutter
      url_launcher: ^6.0.15  # 请检查最新版本
    
  2. 配置 AndroidManifest.xml(如果你需要处理来自其他应用的URL Scheme): 确保你的 AndroidManifest.xml 文件中声明了相应的 <intent-filter>

    <activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="yourappscheme" android:host="*" />
        </intent-filter>
    </activity>
    
  3. 实现路由管理: 在你的 Flutter 应用中设置路由,以处理特定的URL Scheme。

    import 'package:flutter/material.dart';
    import 'package:flutter_url_launcher/flutter_url_launcher.dart';
    import 'package:url_launcher/url_launcher_string.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter App Scheme Demo',
          initialRoute: '/',
          routes: {
            '/': (context) => HomeScreen(),
            '/details': (context) => DetailsScreen(),
          },
          onGenerateRoute: (settings) {
            // 处理自定义 URL Scheme
            if (settings.name == null || !settings.name!.startsWith('yourappscheme://')) {
              return null; // 如果不是我们的 scheme,返回 null
            }
    
            // 解析 URL
            Uri uri = Uri.parse(settings.name!);
            String path = uri.pathSegments.isNotEmpty ? uri.pathSegments.first : '/';
            Map<String, String> queryParams = uri.queryParameters;
    
            // 根据 path 和 queryParams 导航到相应的页面
            if (path == 'details') {
              return MaterialPageRoute(
                builder: (context) => DetailsScreen(id: queryParams['id']),
                settings: settings,
              );
            }
            return null; // 如果不匹配任何已知路径,返回 null
          },
        );
      }
    }
    
    class HomeScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Home Screen'),
          ),
          body: Center(
            child: ElevatedButton(
              onPressed: () async {
                // 打开应用内 URL Scheme
                await launch('yourappscheme://details?id=123');
              },
              child: Text('Open Details'),
            ),
          ),
        );
      }
    }
    
    class DetailsScreen extends StatelessWidget {
      final String? id;
    
      DetailsScreen({this.id});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Details Screen'),
          ),
          body: Center(
            child: Text('Details ID: ${id ?? 'Unknown'}'),
          ),
        );
      }
    }
    

在这个示例中,我们创建了一个简单的Flutter应用,它有两个屏幕:HomeScreenDetailsScreenHomeScreen 上有一个按钮,当点击时,它会尝试通过 yourappscheme://details?id=123 的URL Scheme打开 DetailsScreen

请注意,这只是一个基础示例,实际应用中你可能需要更复杂的URL解析和路由逻辑。此外,url_launcher 主要用于打开外部链接,但在这个例子中,我们通过路由系统内部处理了自定义的URL Scheme。如果你需要处理从外部应用通过URL Scheme打开你的Flutter应用的情况,确保在Android和iOS平台上正确配置你的应用。

回到顶部