Skip to content

Commit f03c4e2

Browse files
committed
feat(flutter): support channel methods
1 parent 355c9db commit f03c4e2

File tree

6 files changed

+151
-8
lines changed

6 files changed

+151
-8
lines changed

apps/demo/flutter_module/lib/main.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
23

34
void main() => runApp(const MyApp());
45

@@ -46,8 +47,12 @@ class MyHomePage extends StatefulWidget {
4647

4748
class _MyHomePageState extends State<MyHomePage> {
4849
int _counter = 0;
50+
MethodChannel platform = const MethodChannel("nativescript");
51+
void _incrementCounter() async {
52+
int level = await platform.invokeMethod("getBatteryLevel");
4953

50-
void _incrementCounter() {
54+
print("level $level");
55+
5156
setState(() {
5257
// This call to setState tells the Flutter framework that something has
5358
// changed in this State, which causes it to rerun the build method below

apps/demo/src/app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Application } from '@nativescript/core';
2-
import { FlutterDelegate } from '@nativescript/flutter';
3-
2+
import { FlutterDelegate, init } from '@nativescript/flutter';
3+
init();
44
// uncomment to test local notifications
55
// import "@nativescript/local-notifications";
66

apps/demo/src/modals/modal-flutter.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Observable, EventData, Page } from '@nativescript/core';
1+
import { Observable, EventData, Page, Device, Utils } from '@nativescript/core';
22
import { FlutterChannelType } from '@nativescript/flutter';
33

44
export function shownModally(args: EventData) {
@@ -17,6 +17,19 @@ export class DemoModel extends Observable {
1717
}
1818

1919
private _getBatteryLevel() {
20+
if (global.isAndroid) {
21+
let batteryLevel = 0;
22+
const context = Utils.android.getApplicationContext();
23+
if (parseInt(Device.sdkVersion) >= 19) {
24+
const batteryManager = context.getSystemService(android.content.Context.BATTERY_SERVICE) as android.os.BatteryManager;
25+
batteryLevel = batteryManager.getIntProperty(android.os.BatteryManager.BATTERY_PROPERTY_CAPACITY);
26+
} else {
27+
const intent = new android.content.ContextWrapper(context).registerReceiver(null, new android.content.IntentFilter(android.content.Intent.ACTION_BATTERY_CHANGED));
28+
batteryLevel = (intent!!.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, -1) * 100) / intent.getIntExtra(android.os.BatteryManager.EXTRA_SCALE, -1);
29+
}
30+
31+
return Promise.resolve(batteryLevel);
32+
}
2033
UIDevice.currentDevice.batteryMonitoringEnabled = true;
2134
const batteryLevel = (UIDevice.currentDevice.batteryLevel * 100) | 0;
2235
return Promise.resolve(batteryLevel);

packages/flutter/index.android.ts

Lines changed: 125 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,155 @@
1-
import { FlutterCommon } from './common';
1+
import { Utils, fromObject } from '@nativescript/core';
2+
3+
import { FlutterChannelType, FlutterCommon } from './common';
24

35
function makeFragmentName(viewId: number): string {
46
return 'android:flutter:' + viewId;
57
}
68

9+
let didInit = false;
10+
let flutterEngine: io.flutter.embedding.engine.FlutterEngine;
11+
let channel: io.flutter.plugin.common.MethodChannel;
12+
let listener;
13+
let MethodCallClazz: java.lang.Class<io.flutter.plugin.common.MethodCall>;
14+
let argumentsMethod;
15+
const channelMethods = new Map();
16+
export function init() {
17+
if (!didInit) {
18+
// todo remove remove after fixing runtime;
19+
MethodCallClazz = java.lang.Class.forName('io.flutter.plugin.common.MethodCall');
20+
argumentsMethod = MethodCallClazz.getDeclaredMethod('arguments', []);
21+
22+
flutterEngine = new io.flutter.embedding.engine.FlutterEngine(Utils.android.getApplicationContext());
23+
flutterEngine.getDartExecutor().executeDartEntrypoint(io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint.createDefault());
24+
io.flutter.embedding.engine.FlutterEngineCache.getInstance().put('default_nativescript', flutterEngine);
25+
io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
26+
channel = new io.flutter.plugin.common.MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), 'nativescript');
27+
listener = new io.flutter.plugin.common.MethodChannel.MethodCallHandler({
28+
onMethodCall(call: io.flutter.plugin.common.MethodCall, result: io.flutter.plugin.common.MethodChannel.Result) {
29+
const method = channelMethods.get(call.method);
30+
if (method) {
31+
const args = argumentsMethod.invoke(call, null); //call.arguments();
32+
const methodArgs = args ? Utils.dataDeserialize(args) : null;
33+
34+
method(methodArgs).then((value) => {
35+
console.log('value:', value);
36+
result.success(value);
37+
});
38+
} else {
39+
result.notImplemented();
40+
}
41+
},
42+
});
43+
44+
channel.setMethodCallHandler(listener);
45+
46+
didInit = true;
47+
}
48+
}
49+
750
export class Flutter extends FlutterCommon {
851
_fragment;
952
_androidViewId: number = -1;
53+
_activityCallbacks: android.app.Application.ActivityLifecycleCallbacks;
54+
55+
static _events = fromObject({});
56+
static get events() {
57+
return this._events;
58+
}
59+
1060
createNativeView(): Object {
1161
return new android.widget.FrameLayout(this._context);
1262
}
1363

64+
_channel: FlutterChannelType;
65+
66+
//@ts-ignore
67+
get channel(): FlutterChannelType {
68+
return this._channel;
69+
}
70+
71+
set channel(value: FlutterChannelType) {
72+
if (this._channel) {
73+
Object.keys(this._channel).forEach((key) => {
74+
channelMethods.delete(key);
75+
});
76+
}
77+
this._channel = value;
78+
if (value) {
79+
Object.keys(value).forEach((key) => {
80+
const val = value[key];
81+
channelMethods.set(key, val);
82+
});
83+
}
84+
}
85+
1486
initNativeView(): void {
1587
super.initNativeView();
1688
if (this._androidViewId < 0) {
1789
this._androidViewId = android.view.View.generateViewId();
1890
}
1991

92+
/*
93+
const ref = new WeakRef(this);
94+
Application.android.on('activityNewIntent', args =>{
95+
this._fragment?.onNewIntent?.(args.intent)
96+
});
97+
Application.android.on('activityRequestPermissions', args =>{
98+
this._fragment?.onRequestPermissionsResult(
99+
args.requestCode,
100+
args.permissions,
101+
args.grantResults
102+
);
103+
});
104+
this._activityCallbacks = new android.app.Application.ActivityLifecycleCallbacks(<any>{
105+
onActivityPostResumed(param0, param1?) {
106+
const owner = ref.get();
107+
if(owner){
108+
owner._fragment?.onPostResume?.();
109+
}
110+
}
111+
});
112+
113+
(Application.android.startActivity as android.app.Activity).registerActivityLifecycleCallbacks(
114+
this._activityCallbacks
115+
);
116+
117+
*/
118+
20119
this.nativeViewProtected.setId(this._androidViewId);
21120

22121
const fm = this._getFragmentManager() as androidx.fragment.app.FragmentManager;
23122

24-
this._fragment = io.flutter.embedding.android.FlutterFragment.createDefault();
123+
//this._fragment = io.flutter.embedding.android.FlutterFragment.createDefault() as any;
124+
125+
this._fragment = io.flutter.embedding.android.FlutterFragment.withCachedEngine('default_nativescript').build() as any;
25126

26127
const name = makeFragmentName(this._androidViewId);
27128

28129
const tr = fm.beginTransaction();
29130

30-
tr.replace(this._androidViewId, this._fragment, name);
131+
tr.replace(this._androidViewId, this._fragment as any, name);
132+
133+
tr.commit();
134+
}
135+
136+
invoke(name: string, args?: Array<any>, callback?: (value?: any) => void) {
137+
if (callback) {
138+
const result = new io.flutter.plugin.common.MethodChannel.Result({
139+
success(param0: any) {},
140+
error(param0: string, param1: string, param2: any): void {},
141+
notImplemented(): void {},
142+
});
143+
144+
// this.notify({
145+
// eventName: Flutter.invokeResultEvent,
146+
// object: this,
147+
// data: result,
148+
// });
31149

32-
tr.commitAllowingStateLoss();
150+
channel.invokeMethod(name, args, result);
151+
} else {
152+
channel.invokeMethod(name, Utils.dataSerialize(args, true));
153+
}
33154
}
34155
}

packages/flutter/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FlutterCommon } from './common';
22
export { FlutterChannelType } from './common';
33

4+
export function init();
5+
46
export declare class Flutter extends FlutterCommon {}
57

68
export declare class FlutterDelegate extends UIResponder {}

packages/flutter/index.ios.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { FlutterCommon } from './common';
33

44
let flutterEngineGroup: FlutterEngineGroup;
55

6+
export function init() {}
7+
68
export class Flutter extends FlutterCommon {
79
flutterViewController: FlutterViewController;
810
platformChannel: FlutterMethodChannel;

0 commit comments

Comments
 (0)