У меня есть живой пример здесь Я делал это несколько раз назад.
Нужно ли имя должно быть определенного формата?Например, могу ли я назвать свой канал просто старой батареей?Или это что-то вроде формата 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();
}
}
});
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),
],
)),
),