YehudaKremer / msix

Create Msix installer for flutter windows-build files.
https://pub.dev/packages/msix
MIT License
276 stars 68 forks source link

[BUG] Custom URI Stops Working after MSIX Packaging #187

Closed cliftonlabrum closed 1 year ago

cliftonlabrum commented 1 year ago

:information_source: Info

Version: 3.9.1

:speech_balloon: Description

I can't get my Flutter app's custom URI to work after I package my app with MSIX, and I'm trying to figure out if it's a bug with protocol_handler that creates and registers the URI, or if it's something to do with MSIX.

Here's what I've done:

  1. I run my Flutter app which registers a custom URI.
  2. I run the app in the debugger.
  3. Hitting my custom URI in a web browser, such as myapp://test opens my app.
  4. After packaging with flutter pub run msix:create and signing the MSIX, then running the app on another computer, the app runs, but hitting the custom URI does not open the app.

I have confirmed the issue across two apps:

  1. The first app uses a redirect from the Dropbox API – works in debug mode, fails after MSIX packaging.
  2. The second app uses an auth redirect from Supabase – works in debug mode, fails after MSIX packaging.

:scroll: Pubspec.yaml

msix_config:
  display_name: Pilot Pro
  publisher_display_name: Labrum Co
  identity_name: LabrumCo.PilotPro
  publisher: CN=<*****>
  msix_version: 5.7.7.0
  logo_path: C:\Users\clift\OneDrive\Desktop\PilotPro\assets\images\windows.png
  store: true

🖥️ Sample Project

Below is a minimal sample project. You will need to add these two packages:

flutter pub add msix
flutter pub add protocol_handler

After building the app on Windows, visit uritest://test in a web browser, and it should show this:

uritest

After clicking Open uri_test it will bring the app to the forefront and you should see this in the debug console:

Got it: uritest://test/

Here are the contents of main.dart:

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

void main() async {
  // Must add this line.
  WidgetsFlutterBinding.ensureInitialized();

  // Register a custom protocol
  await protocolHandler.register('uritest');

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'URI Test App',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with ProtocolListener {
  @override
  void initState() {
    protocolHandler.addListener(this);
    super.initState();
  }

  @override
  void dispose() {
    protocolHandler.removeListener(this);
    super.dispose();
  }

  @override
  void onProtocolUrlReceived(String url) {
    //::::: Confirm URL is received :::::
    String log = 'Got it: $url';
    print(log);
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('Custom URI Test'),
      ),
    );
  }
}

You have to add the following to /windows/runner/main.cpp:

//Add this include at the top...
#include <protocol_handler/protocol_handler_plugin.h>

//Just inside the existing method here...
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t *command_line, _In_ int show_command) {

  //Add this...
  HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"uri_test");
  if (hwnd != NULL) {
   DispatchToProtocolHandler(hwnd);

    ::ShowWindow(hwnd, SW_NORMAL);
    ::SetForegroundWindow(hwnd);
    return EXIT_FAILURE;
  }
...

After you package this with MSIX, you must launch it on another user account or computer. This is because (as far as I can tell) the registry edits are already made on your machine with the debug version of the app running.

Could you please check if this is something to do with MSIX or not? This is blocking me on launching two apps on Windows. 😅 Thank you!

YehudaKremer commented 1 year ago

Hello @cliftonlabrum

You can add this functionality for Msix by using the app_uri_handler_hosts configuration, see app_uri_handler_hosts under the MSIX configuration (click to expand) in the README file.

Please update if its working for you. BTW great detailed question 👍

cliftonlabrum commented 1 year ago

@YehudaKremer Thanks so much for your reply!

I added this to the end of my msix configuration:

app_uri_handler_hosts: myapp

But it fails during packaging with:

'myapp' violates pattern constraint of '([0-9a-zA-Z]+(-[0-9a-zA-Z]+)*.)+[a-zA-Z]{1,63}'. The attribute 'Name' with value 'myapp' failed to parse.

My regex is rusty, but it seems it's expecting a domain name formatted like myapp.com. But a custom URI is like a protocol itself, not a domain (i.e. myapp://).

Any idea what I'm doing wrong?

cliftonlabrum commented 1 year ago

Is app_uri_handler_hosts expecting the domain that does the redirecting? So if I'm using the Dropbox API, do I put dropbox.com as that value so that it's allowed to redirect to my app?

cliftonlabrum commented 1 year ago

Looking through the MSIX README again, I think I may actually want protocol_activation instead of app_uri_handler_hosts. I'll give it a try.

YehudaKremer commented 1 year ago

My bad sorry

cliftonlabrum commented 1 year ago

Adding protocol_activation worked and my app passed Microsoft's app review. Thank you very much for your help! 😄