В каком формате должно быть название канала для каналов платформы Flutter? - PullRequest
0 голосов
/ 21 декабря 2018

Я добавляю создание своего собственного канала платформы (в частности, Method Channel для Android) и следую https://flutter.io/docs/development/platform-integration/platform-channels#step-1-create-a-new-app-project

Я вижу:

Все имена каналов, используемые в одномприложение должно быть уникальным;мы рекомендуем использовать префикс имени канала с уникальным префиксом домена, например samples.flutter.io/battery.

Должно ли имя иметь определенный формат?Например, я могу назвать свой канал просто "1010"?Или это должно быть что-то около формата my_company.flutter.io/battery?Или что-то другое?Я перепробовал все виды строк, но каждый раз получаю:

MissingPluginException(No implementation found for method getBattery on channel battery)

Так что мне интересно, может быть, мой формат названия канала неправильный.Я думаю, что мое имя метода getBattery является правильным.Но чтобы уточнить, я хочу сделать:

final result = await platform.invokeMethod('getBattery');

не с префиксом плагина, верно?:

final result = await platform.invokeMethod('battery.getBattery'); 

1 Ответ

0 голосов
/ 22 декабря 2018

У меня есть живой пример здесь Я делал это несколько раз назад.

Нужно ли имя должно быть определенного формата?Например, могу ли я назвать свой канал просто старой батареей?Или это что-то вроде формата my_company.flutter.io/battery?Или что-то еще?

Поскольку название канала должно быть уникальным, хорошей практикой является добавление префикса к вашему bundle(iOS)/package(Android) id.

Так, например:

static const platform =
      const MethodChannel('it.versionestabile.flutterapp000001/pdfViewer');

В любом случае вы можете называть его так, как хотите, но он должен быть уникальным и равным на вашей стороне Dart и Android / iOS.

private static final String CHANNEL = "it.versionestabile.flutterapp000001/pdfViewer";

Но "вызывать" его - это все равно, что помещать внутрь канала что-то.

Поскольку канал - это канал (представьте себе трубу), и то, что вы помещаете в него, чтобы проходить через негоиз стороны в сторону (дартс) в другую (Android / iOS) совершенно другая сказка ^ _ ^.

А то, что вы положили в него, должно быть одинаковым с другой стороны.

platform.invokeMethod('viewPdf', args);

То, что вы отправляете по каналам, это просто сообщения .

Вы положили бутылку с буквой в трубу ^ _ ^

Теперь вам нужно перехватить это сообщение на вашей стороне исходного кода, например 'viewPdf'.

new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
            new MethodChannel.MethodCallHandler() {
              @Override
              public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                if (call.method.equals("viewPdf")) {
                  if (call.hasArgument("url")) {
                    String url = call.argument("url");
                    File file = new File(url);
                    //*
                    Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
                            BuildConfig.APPLICATION_ID + ".provider",
                            file);
                            //*/
                    Intent target = new Intent(Intent.ACTION_VIEW);
                    target.setDataAndType(photoURI,"application/pdf");
                    target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                    target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    startActivity(target);
                    result.success(null);
                  }
                } else {
                  result.notImplemented();
                }
              }
            });
  }

В противном случае вы попадете в ловушку

} else {
   result.notImplemented();
}

Если вы следовали примеру, у вас должно быть это на стороне вашего собственного кода Android:

@Override
public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getBatteryLevel")) {
        int batteryLevel = getBatteryLevel();

        if (batteryLevel != -1) {
            result.success(batteryLevel);
        } else {
            result.error("UNAVAILABLE", "Battery level not available.", null);
        }
    } else {
        result.notImplemented();
    }
}

ТакВы должны позвонить:

platform.invokeMethod('getBatteryLevel');

Поскольку код примера ожидает, что сообщение 'getBatteryLevel' будет проходить через канал.

Усиление концепций

Итак, просто для усиления всех этих концепций я пойду дальше и скажу вам, что вы можете решить использовать канал для обслуживания одной операции или для обслуживания нескольких операций.Выбор за вами.

Таким образом, вы можете иметь

Сторона дротика:

  static const singleChannel =
      const MethodChannel('it.versionestabile.flutterapp000001/single');
  static const multiChannel =
      const MethodChannel('it.versionestabile.flutterapp000001/multi');

Собственная сторона (Android):

  private static final String SINGLE_CHANNEL = "it.versionestabile.flutterapp000001/single";
  private static final String MULTI_CHANNEL = "it.versionestabile.flutterapp000001/multi";

А вот некоторые обработчики игрушек:

new MethodChannel(getFlutterView(), MULTI_CHANNEL).setMethodCallHandler(
        new MethodChannel.MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, MethodChannel.Result result) {
            if (call.method.equals("op1")) {
              new AlertDialog.Builder(MainActivity.this)
                      .setTitle(call.method)
                      .setMessage("I'm the " + call.method + " of the by design multi operation channel!")
                      .create()
                      .show();
            } else if (call.method.equals("op2")) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle(call.method)
                        .setMessage("I'm the " + call.method + " of the by design multi operation channel!")
                        .create()
                        .show();
            } else {
              result.notImplemented();
            }
          }
        });

new MethodChannel(getFlutterView(), SINGLE_CHANNEL).setMethodCallHandler(
        new MethodChannel.MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, MethodChannel.Result result) {
            if (call.method.equals("hello")) {
              new AlertDialog.Builder(MainActivity.this)
                      .setTitle("hello!")
                      .setMessage("I'm the by design single operation channel!")
                      .create()
                      .show();
            } else {
              result.notImplemented();
            }
          }
        });

enter image description here

  void _invokeMultiChannelOp2() {
    multiChannel.invokeMethod('op2');
  }

  void _invokeMultiChannelOp1() {
    multiChannel.invokeMethod('op1');
  }

  void _invokeSingleChannel() {
    singleChannel.invokeMethod('hello');
  }

floatingActionButton: SafeArea(
    child: Padding(
        padding: EdgeInsets.only(left: 8.0),
        child: Row(
          children: <Widget>[
            new IconButton(
                icon: new Icon(Icons.library_music),
                onPressed: _invokeMultiChannelOp1),
            new IconButton(
                icon: new Icon(Icons.note),
                onPressed: _invokeMultiChannelOp2),
            new IconButton(
                icon: new Icon(Icons.plus_one),
                onPressed: _invokeSingleChannel),
          ],
        )),
  ),
...