diff --git a/android_doc.md b/android_doc.md
index a809c8a9d..96a18f438 100644
--- a/android_doc.md
+++ b/android_doc.md
@@ -97,6 +97,15 @@ MediaProjectionManager -> MediaProjection
+### 3.获取音频输入
+https://developer.android.google.cn/guide/topics/media/playback-capture?hl=zh-cn
+
+目前谷歌只开放了Android10系统同步音频内录功能
+10之前录音的时候会截取原本系统的音频输出
+即 开启内录时候无法在手机上正常使用耳机扬声器输出
+
+
+
### 其他
- Kotlin 与 compose 版本设置问题
- https://stackoverflow.com/questions/67600344/jetpack-compose-on-kotlin-1-5-0
diff --git a/lib/home_page.dart b/lib/home_page.dart
index 8d5cde352..dcb858510 100644
--- a/lib/home_page.dart
+++ b/lib/home_page.dart
@@ -22,7 +22,6 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State {
final _idController = TextEditingController();
var _updateUrl = '';
- static const toAndroidChannel = MethodChannel("mChannel");
@override
void initState() {
@@ -55,15 +54,21 @@ class _HomePageState extends State {
items: [
PopupMenuItem(
child: Text(translate('ID Server')),
+ value: 'id_server'),
+ PopupMenuItem(
+ child: Text(translate('Share My Screen')),
value: 'server'),
+ // TODO only android
PopupMenuItem(
child: Text(translate('About') + ' RustDesk'),
value: 'about'),
],
elevation: 8,
);
- if (value == 'server') {
+ if (value == 'id_server') {
showServer(context);
+ } else if (value == 'server') {
+ Navigator.pushNamed(context, "server_page");
} else if (value == 'about') {
showAbout(context);
}
@@ -98,29 +103,9 @@ class _HomePageState extends State {
fontWeight: FontWeight.bold)))),
getSearchBarUI(),
getPeers(),
- ElevatedButton(onPressed:_toAndroidGetPer, child: Text("获取权限事件")),
- ElevatedButton(onPressed:_toAndroidStartSer, child: Text("开启录屏服务")),
- ElevatedButton(onPressed:_toAndroidStopSer, child: Text("停止录屏服务")),
- ElevatedButton(onPressed:_toAndroidCheckInput, child: Text("检查输入权限")),
]),
));
}
- Future _toAndroidGetPer() async{
- bool res = await toAndroidChannel.invokeMethod("getPer");
- debugPrint("_toAndroidGetPer:$res");
- }
- Future _toAndroidStartSer() async{
- bool res = await toAndroidChannel.invokeMethod("startSer");
- debugPrint("_toAndroidStartSer:$res");
- }
- Future _toAndroidStopSer() async{
- bool res = await toAndroidChannel.invokeMethod("stopSer");
- debugPrint("_toAndroidStopSer:$res");
- }
- Future _toAndroidCheckInput() async{
- bool res = await toAndroidChannel.invokeMethod("checkInput");
- debugPrint("_toAndroidStopSer:$res");
-}
void onConnect() {
var id = _idController.text.trim();
diff --git a/lib/main.dart b/lib/main.dart
index c16780ca2..62abe4b25 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:flutter_hbb/server_page.dart';
import 'package:provider/provider.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_analytics/observer.dart';
@@ -31,6 +32,9 @@ class App extends StatelessWidget {
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(title: 'RustDesk'),
+ routes: {
+ "server_page":(context) => ServerPage(),
+ },
navigatorObservers: [
FirebaseAnalyticsObserver(analytics: analytics),
],
diff --git a/lib/server_page.dart b/lib/server_page.dart
new file mode 100644
index 000000000..7e76874b8
--- /dev/null
+++ b/lib/server_page.dart
@@ -0,0 +1,218 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_hbb/model.dart';
+
+import 'common.dart';
+
+class ServerPage extends StatefulWidget {
+ @override
+ _ServerPageState createState() => _ServerPageState();
+}
+
+class _ServerPageState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: MyTheme.grayBg,
+ appBar: AppBar(
+ centerTitle: true,
+ title: const Text("Share My Screen"),
+ ),
+ body: SingleChildScrollView(
+ child: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ ServerInfo(),
+ PermissionChecker(),
+ ],
+ ),
+ ),
+ ));
+ }
+}
+
+class ServerInfo extends StatefulWidget {
+ @override
+ _ServerInfoState createState() => _ServerInfoState();
+}
+
+class _ServerInfoState extends State {
+ var _passwdShow = true;
+
+ // TODO set ID / PASSWORD
+ var _serverId = "";
+ var _serverPasswd = "";
+
+ @override
+ void initState() {
+ super.initState();
+ _serverId = FFI.getByName("server_id");
+ _serverPasswd = FFI.getByName("server_password");
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return myCard(Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ TextFormField(
+ readOnly: true,
+ style: TextStyle(
+ fontSize: 25.0,
+ fontWeight: FontWeight.bold,
+ color: MyTheme.accent),
+ initialValue: _serverId,
+ decoration: InputDecoration(
+ icon: const Icon(Icons.perm_identity),
+ labelText: '服务ID',
+ labelStyle:
+ TextStyle(fontWeight: FontWeight.bold, color: MyTheme.accent50),
+ ),
+ onSaved: (String value) {},
+ ),
+ TextFormField(
+ readOnly: true,
+ obscureText: _passwdShow,
+ style: TextStyle(
+ fontSize: 25.0,
+ fontWeight: FontWeight.bold,
+ color: MyTheme.accent),
+ initialValue: _serverPasswd,
+ decoration: InputDecoration(
+ icon: const Icon(Icons.lock),
+ labelText: '密码',
+ labelStyle: TextStyle(
+ fontWeight: FontWeight.bold, color: MyTheme.accent50),
+ suffix: IconButton(
+ icon: Icon(Icons.visibility),
+ onPressed: () {
+ debugPrint("icon btn");
+ setState(() {
+ _passwdShow = !_passwdShow;
+ });
+ })),
+ onSaved: (String value) {},
+ ),
+ ],
+ ));
+ }
+}
+
+class PermissionChecker extends StatefulWidget {
+ @override
+ _PermissionCheckerState createState() => _PermissionCheckerState();
+}
+
+class _PermissionCheckerState extends State {
+ static const toAndroidChannel = MethodChannel("mChannel");
+
+ var videoOk = false;
+ var inputOk = false;
+ var audioOk = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return myCard(Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ cardTitle("权限列表"),
+ PermissionRow("视频权限", videoOk, _toAndroidGetPer),
+ const Divider(height: 0),
+ PermissionRow("音频权限", videoOk, () => {debugPrint("获取视频权限")}),
+ const Divider(height: 0),
+ PermissionRow("输入权限", inputOk, _toAndroidCheckInput),
+ const Divider(),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ TextButton.icon(
+ icon: Icon(Icons.play_arrow),
+ onPressed: _toAndroidStartSer,
+ label: Text("Start")),
+ TextButton.icon(
+ icon: Icon(Icons.stop),
+ onPressed: _toAndroidStopSer,
+ label: Text("Stop")),
+ ],
+ )
+ ],
+ ));
+ }
+
+ Future _toAndroidGetPer() async {
+ bool res = await toAndroidChannel.invokeMethod("getPer");
+ debugPrint("_toAndroidGetPer:$res");
+ }
+
+ Future _toAndroidStartSer() async {
+ bool res = await toAndroidChannel.invokeMethod("startSer");
+ debugPrint("_toAndroidStartSer:$res");
+ }
+
+ Future _toAndroidStopSer() async {
+ bool res = await toAndroidChannel.invokeMethod("stopSer");
+ debugPrint("_toAndroidStopSer:$res");
+ }
+
+ Future _toAndroidCheckInput() async {
+ bool res = await toAndroidChannel.invokeMethod("checkInput");
+ debugPrint("_toAndroidStopSer:$res");
+ }
+}
+
+class PermissionRow extends StatelessWidget {
+ PermissionRow(this.name, this.isOk, this.onPressed);
+
+ final String name;
+ final bool isOk;
+ final VoidCallback onPressed;
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text.rich(TextSpan(children: [
+ TextSpan(
+ text: name + ":",
+ style: TextStyle(fontSize: 16.0, color: MyTheme.accent50)),
+ TextSpan(
+ text: isOk ? "已开启" : "未开启",
+ style: TextStyle(
+ fontSize: 16.0, color: isOk ? Colors.green : Colors.red)),
+ ])),
+ TextButton(
+ onPressed: onPressed,
+ child: const Text(
+ "去开启",
+ style: TextStyle(fontWeight: FontWeight.bold),
+ )),
+ ],
+ );
+ }
+}
+
+Widget cardTitle(String text) {
+ return Padding(
+ padding: EdgeInsets.symmetric(vertical: 5.0),
+ child: Text(
+ text,
+ style: TextStyle(
+ fontFamily: 'WorkSans',
+ fontWeight: FontWeight.bold,
+ fontSize: 25,
+ color: Color(0xFF00B6F0),
+ ),
+ ));
+}
+
+Widget myCard(Widget child) {
+ return Card(
+ margin: EdgeInsets.all(15.0),
+ child: Padding(
+ padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0),
+ child: child,
+ ),
+ );
+}