flutter与android
android启动flutter
- 导入flutter的aar或者module后指定android中的一个空activity继承FlutterActivty,该Activity就是启动flutter main.dart的入口
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.start_flutter);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SecondActivty.class));
}
});
}
}
public class SecondActivity extends FlutterActivity {
}
- 如需要打开特定的flutter page,则首先要在main.dart中制定好对应的路由routes
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
routes: {
'one_page':(context){
return OnePage();
}
},
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
在启动flutteractivty时传入路由值启动
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.start_flutter);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(SecondActivity.withNewEngine().initialRoute("one_page").build(MainActivity.this));
}
});
}
}
flutter与native的通信
flutter与native之间的消息传递通过MethodChannel进行,以下演示如何在flutter端调用native方法获取手机电量,代码引用flutter实战,针对使用的flutter版本稍作改动;
Flutter端:首先需要与native端共用一个MethodChannel,因此构造MethodChannel时,要用同一个通道名称;
static const platform = const MethodChannel('samples.flutter.io/battery');
然后在此通道中指定native的方法名以进行调用(其实也不是传入方法名,只是可识别出要调用方法的字符串,可以理解成通道明是一个大标题,invoke的内容是该大标题底下的一系列小标题),但存在可能失败的调用情况(我认为这有点类似java中的反射,有可能会找不到native端的方法名而调用失败),因此需要捕获一下
Future<Null> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
之后就是UI部分问题
@override
Widget build(BuildContext context) {
return new Material(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new RaisedButton(
child: new Text('Get Battery Level'),
onPressed: _getBatteryLevel,
),
new Text(_batteryLevel),
],
),
),
);
}
native端
笔者这里与原作不同之处在于使用的flutter版本可能较新(2.0+),因此启动FlutterActivity的方式已不需要重写onCreate以及获取FlutterView,而原作中的getFlutterView方法也已经被移除;native端构建MethodChannel的方式也已改变,因此改用configureFlutterEngine实现MethodChannel,再设置对应的MethodHandler;
public class SecondActivity extends FlutterActivity {
private static final String CHANNEL = "samples.flutter.io/battery";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull 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();
}
}
}
);
}
private int getBatteryLevel() {
int batteryLevel = -1;
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
} else {
Intent intent = new ContextWrapper(getApplicationContext()).
registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
}
return batteryLevel;
}
}