mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbbd1b5f2c | ||
|
|
7f6ec2f732 | ||
|
|
e8649203cf | ||
|
|
765b0c3d6d | ||
|
|
248c40731c | ||
|
|
cde01a4863 | ||
|
|
1ee8a0188b | ||
|
|
32e8fc9bf5 | ||
|
|
3c87d895c5 | ||
|
|
82dd8a9b48 | ||
|
|
0996506fd1 |
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -71,6 +71,11 @@ jobs:
|
||||
env:
|
||||
DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY: ${{ secrets.DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY }}
|
||||
|
||||
- name: Decode Keystore
|
||||
run: |
|
||||
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/android.keystore;
|
||||
echo "${{ secrets.KEYSTORE_PROPERTIES }}" > android/keystore.properties;
|
||||
|
||||
#6 Building APK
|
||||
- name: Build APK
|
||||
run: flutter build apk --release
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,6 +12,8 @@
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
android/keystore.properties
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
### 1.0.6 (2025-03-29)
|
||||
- Another potential keyboard fix for Windows
|
||||
- Zwift Play: actually also use the dedicated shift buttons
|
||||
|
||||
### 1.0.5 (2025-03-29)
|
||||
- Zwift Ride: remap the shifter buttons to the correct values
|
||||
|
||||
### 1.0.0+4 (2025-03-29)
|
||||
- Zwift Ride: attempt to fix button parsing
|
||||
- Android: fix missing permissions
|
||||
- Windows: potential fix for key press issues
|
||||
|
||||
### 1.0.0+3 (2025-03-29)
|
||||
|
||||
- Windows: fix connection by using a different Bluetooth stack (issue #1)
|
||||
|
||||
@@ -9,8 +9,6 @@ import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED
|
||||
import android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED
|
||||
import android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
|
||||
|
||||
@@ -30,7 +28,6 @@ class AccessibilityService : AccessibilityService(), Listener {
|
||||
private val ignorePackages = listOf("com.android.systemui", "com.android.launcher", "com.android.settings")
|
||||
|
||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
||||
Log.w("Acc", "onAccessibilityEvent: ${event.packageName} ${event.eventType} ${event.contentChangeTypes}")
|
||||
if (event.packageName == null || rootInActiveWindow == null) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import java.io.FileInputStream
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
@@ -5,6 +8,11 @@ plugins {
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
|
||||
android {
|
||||
namespace = "de.jonasbark.swift_play"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
@@ -33,11 +41,18 @@ android {
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("config") {
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
storeFile = file("../${keystoreProperties["storeFile"] as String}")
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
signingConfig = signingConfigs.getByName("config")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,16 @@ import 'package:swift_control/utils/keymap/keymap.dart';
|
||||
class AndroidActions extends BaseActions {
|
||||
static const MYWHOOSH_APP_PACKAGE = "com.mywhoosh.whooshgame";
|
||||
static const TRAININGPEAKS_APP_PACKAGE = "com.indieVelo.client";
|
||||
static const validPackageNames = [MYWHOOSH_APP_PACKAGE, TRAININGPEAKS_APP_PACKAGE];
|
||||
|
||||
WindowEvent? windowInfo;
|
||||
|
||||
@override
|
||||
void init(Keymap? keymap) {
|
||||
streamEvents().listen((windowEvent) {
|
||||
windowInfo = windowEvent;
|
||||
if (validPackageNames.contains(windowEvent.packageName)) {
|
||||
windowInfo = windowEvent;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,18 +15,20 @@ class DesktopActions extends BaseActions {
|
||||
}
|
||||
|
||||
@override
|
||||
void decreaseGear() {
|
||||
Future<void> decreaseGear() async {
|
||||
if (keymap == null) {
|
||||
throw Exception('Keymap is not set');
|
||||
}
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.decrease);
|
||||
await keyPressSimulator.simulateKeyDown(_keymap!.decrease);
|
||||
await keyPressSimulator.simulateKeyUp(_keymap!.decrease);
|
||||
}
|
||||
|
||||
@override
|
||||
void increaseGear() {
|
||||
Future<void> increaseGear() async {
|
||||
if (keymap == null) {
|
||||
throw Exception('Keymap is not set');
|
||||
}
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.increase);
|
||||
await keyPressSimulator.simulateKeyDown(_keymap!.increase);
|
||||
await keyPressSimulator.simulateKeyUp(_keymap!.increase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ class Constants {
|
||||
static const RC1_LEFT_SIDE = 0x03;
|
||||
static const RC1_RIGHT_SIDE = 0x02;
|
||||
|
||||
// Zwift Ride
|
||||
static const RIDE_RIGHT_SIDE = 0x07;
|
||||
static const RIDE_LEFT_SIDE = 0x08;
|
||||
|
||||
// Zwift Click = BC1
|
||||
static const BC1 = 0x09;
|
||||
|
||||
@@ -33,7 +37,7 @@ class Constants {
|
||||
// not figured out the protobuf type this really is, the content is just two varints.
|
||||
static const int CLICK_NOTIFICATION_MESSAGE_TYPE = 55;
|
||||
static const int PLAY_NOTIFICATION_MESSAGE_TYPE = 7;
|
||||
static const int RIDE_NOTIFICATION_MESSAGE_TYPE = 35;
|
||||
static const int RIDE_NOTIFICATION_MESSAGE_TYPE = 35; // 0x23
|
||||
|
||||
// see this if connected to Core then Zwift connects to it. just one byte
|
||||
static const DISCONNECT_MESSAGE_TYPE = 0xFE;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:accessibility/accessibility.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:swift_control/utils/devices/zwift_click.dart';
|
||||
import 'package:swift_control/utils/messages/controller_notification.dart';
|
||||
import 'package:swift_control/utils/messages/play_notification.dart';
|
||||
|
||||
import '../../main.dart';
|
||||
import '../ble.dart';
|
||||
@@ -9,21 +9,23 @@ import '../ble.dart';
|
||||
class ZwiftPlay extends ZwiftClick {
|
||||
ZwiftPlay(super.scanResult);
|
||||
|
||||
ControllerNotification? _lastControllerNotification;
|
||||
PlayNotification? _lastControllerNotification;
|
||||
|
||||
@override
|
||||
List<int> get startCommand => Constants.RIDE_ON + Constants.RESPONSE_START_PLAY;
|
||||
|
||||
@override
|
||||
void processClickNotification(Uint8List message) {
|
||||
final ControllerNotification clickNotification = ControllerNotification(message);
|
||||
final PlayNotification clickNotification = PlayNotification(message);
|
||||
if (_lastControllerNotification == null || _lastControllerNotification != clickNotification) {
|
||||
_lastControllerNotification = clickNotification;
|
||||
actionStreamInternal.add(clickNotification);
|
||||
|
||||
if (clickNotification.rightPad && clickNotification.analogLR.abs() == 100) {
|
||||
if ((clickNotification.rightPad && clickNotification.buttonShift) ||
|
||||
(clickNotification.rightPad && clickNotification.analogLR.abs() == 100)) {
|
||||
actionHandler.increaseGear();
|
||||
} else if (!clickNotification.rightPad && clickNotification.analogLR.abs() == 100) {
|
||||
} else if ((!clickNotification.rightPad && clickNotification.buttonShift) ||
|
||||
(!clickNotification.rightPad && clickNotification.analogLR.abs() == 100)) {
|
||||
actionHandler.decreaseGear();
|
||||
}
|
||||
if (clickNotification.rightPad) {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import 'package:swift_control/utils/devices/zwift_play.dart';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:swift_control/main.dart';
|
||||
import 'package:swift_control/utils/devices/zwift_click.dart';
|
||||
import 'package:swift_control/utils/messages/ride_notification.dart';
|
||||
|
||||
import '../ble.dart';
|
||||
|
||||
class ZwiftRide extends ZwiftPlay {
|
||||
class ZwiftRide extends ZwiftClick {
|
||||
ZwiftRide(super.scanResult);
|
||||
|
||||
@override
|
||||
@@ -10,4 +14,33 @@ class ZwiftRide extends ZwiftPlay {
|
||||
|
||||
@override
|
||||
bool get supportsEncryption => false;
|
||||
|
||||
RideNotification? _lastControllerNotification;
|
||||
|
||||
@override
|
||||
void processClickNotification(Uint8List message) {
|
||||
final RideNotification clickNotification = RideNotification(message);
|
||||
if (_lastControllerNotification == null || _lastControllerNotification != clickNotification) {
|
||||
_lastControllerNotification = clickNotification;
|
||||
actionStreamInternal.add(clickNotification);
|
||||
|
||||
if (clickNotification.buttonShiftDownLeft || clickNotification.buttonShiftUpLeft || clickNotification.buttonZ) {
|
||||
actionHandler.decreaseGear();
|
||||
} else if (clickNotification.buttonShiftUpRight ||
|
||||
clickNotification.buttonShiftDownRight ||
|
||||
clickNotification.buttonOnOffLeft) {
|
||||
// TODO remove buttonZ once the assignment is fixed for real
|
||||
actionHandler.increaseGear();
|
||||
}
|
||||
/*if (clickNotification.buttonA) {
|
||||
actionHandler.controlMedia(MediaAction.next);
|
||||
} else if (clickNotification.buttonY) {
|
||||
actionHandler.controlMedia(MediaAction.volumeUp);
|
||||
} else if (clickNotification.buttonB) {
|
||||
actionHandler.controlMedia(MediaAction.volumeDown);
|
||||
} else if (clickNotification.buttonZ) {
|
||||
actionHandler.controlMedia(MediaAction.playPause);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import 'package:swift_control/utils/messages/notification.dart';
|
||||
|
||||
import '../../protocol/zwift.pb.dart';
|
||||
|
||||
class ControllerNotification extends BaseNotification {
|
||||
class PlayNotification extends BaseNotification {
|
||||
static const int BTN_PRESSED = 0;
|
||||
|
||||
late bool rightPad, buttonY, buttonZ, buttonA, buttonB, buttonOn, buttonShift;
|
||||
late int analogLR, analogUD;
|
||||
|
||||
ControllerNotification(Uint8List message) {
|
||||
PlayNotification(Uint8List message) {
|
||||
final status = PlayKeyPadStatus.fromBuffer(message);
|
||||
|
||||
rightPad = status.rightPad.value == BTN_PRESSED;
|
||||
@@ -41,7 +41,7 @@ class ControllerNotification extends BaseNotification {
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ControllerNotification &&
|
||||
other is PlayNotification &&
|
||||
runtimeType == other.runtimeType &&
|
||||
rightPad == other.rightPad &&
|
||||
buttonY == other.buttonY &&
|
||||
140
lib/utils/messages/ride_notification.dart
Normal file
140
lib/utils/messages/ride_notification.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:swift_control/utils/messages/notification.dart';
|
||||
|
||||
import '../../protocol/zwift.pb.dart';
|
||||
|
||||
enum _RideButtonMask {
|
||||
LEFT_BTN(0x00001),
|
||||
UP_BTN(0x00002),
|
||||
RIGHT_BTN(0x00004),
|
||||
DOWN_BTN(0x00008),
|
||||
A_BTN(0x00010),
|
||||
B_BTN(0x00020),
|
||||
Y_BTN(0x00040),
|
||||
|
||||
Z_BTN(0x00100),
|
||||
SHFT_UP_L_BTN(0x00200),
|
||||
SHFT_DN_L_BTN(0x00400),
|
||||
POWERUP_L_BTN(0x00800),
|
||||
ONOFF_L_BTN(0x01000),
|
||||
SHFT_UP_R_BTN(0x02000),
|
||||
SHFT_DN_R_BTN(0x04000),
|
||||
|
||||
POWERUP_R_BTN(0x10000),
|
||||
ONOFF_R_BTN(0x20000);
|
||||
|
||||
final int mask;
|
||||
|
||||
const _RideButtonMask(this.mask);
|
||||
}
|
||||
|
||||
class RideNotification extends BaseNotification {
|
||||
static const int BTN_PRESSED = 0;
|
||||
|
||||
late bool buttonLeft, buttonRight, buttonUp, buttonDown;
|
||||
late bool buttonA, buttonB, buttonY, buttonZ;
|
||||
late bool buttonShiftUpLeft, buttonShiftDownLeft;
|
||||
late bool buttonShiftUpRight, buttonShiftDownRight;
|
||||
late bool buttonPowerUpLeft, buttonPowerDownLeft;
|
||||
late bool buttonOnOffLeft, buttonOnOffRight;
|
||||
|
||||
int analogLR = 0, analogUD = 0;
|
||||
|
||||
RideNotification(Uint8List message) {
|
||||
final status = RideKeyPadStatus.fromBuffer(message);
|
||||
|
||||
buttonLeft = status.buttonMap & _RideButtonMask.LEFT_BTN.mask == BTN_PRESSED;
|
||||
buttonRight = status.buttonMap & _RideButtonMask.RIGHT_BTN.mask == BTN_PRESSED;
|
||||
buttonUp = status.buttonMap & _RideButtonMask.UP_BTN.mask == BTN_PRESSED;
|
||||
buttonDown = status.buttonMap & _RideButtonMask.DOWN_BTN.mask == BTN_PRESSED;
|
||||
buttonA = status.buttonMap & _RideButtonMask.A_BTN.mask == BTN_PRESSED;
|
||||
buttonB = status.buttonMap & _RideButtonMask.B_BTN.mask == BTN_PRESSED;
|
||||
buttonY = status.buttonMap & _RideButtonMask.Y_BTN.mask == BTN_PRESSED;
|
||||
buttonZ = status.buttonMap & _RideButtonMask.Z_BTN.mask == BTN_PRESSED;
|
||||
buttonShiftUpLeft = status.buttonMap & _RideButtonMask.SHFT_UP_L_BTN.mask == BTN_PRESSED;
|
||||
buttonShiftDownLeft = status.buttonMap & _RideButtonMask.SHFT_DN_L_BTN.mask == BTN_PRESSED;
|
||||
buttonShiftUpRight = status.buttonMap & _RideButtonMask.SHFT_UP_R_BTN.mask == BTN_PRESSED;
|
||||
buttonShiftDownRight = status.buttonMap & _RideButtonMask.SHFT_DN_R_BTN.mask == BTN_PRESSED;
|
||||
buttonPowerUpLeft = status.buttonMap & _RideButtonMask.POWERUP_L_BTN.mask == BTN_PRESSED;
|
||||
buttonPowerDownLeft = status.buttonMap & _RideButtonMask.POWERUP_R_BTN.mask == BTN_PRESSED;
|
||||
buttonOnOffLeft = status.buttonMap & _RideButtonMask.ONOFF_L_BTN.mask == BTN_PRESSED;
|
||||
buttonOnOffRight = status.buttonMap & _RideButtonMask.ONOFF_R_BTN.mask == BTN_PRESSED;
|
||||
|
||||
for (final analogue in status.analogButtons.groupStatus) {
|
||||
if (analogue.location == RideAnalogLocation.LEFT || analogue.location == RideAnalogLocation.RIGHT) {
|
||||
analogLR = analogue.analogValue;
|
||||
} else if (analogue.location == RideAnalogLocation.DOWN || analogue.location == RideAnalogLocation.UP) {
|
||||
analogUD = analogue.analogValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final allTrueParameters = [
|
||||
if (buttonLeft) 'buttonLeft',
|
||||
if (buttonRight) 'buttonRight',
|
||||
if (buttonUp) 'buttonUp',
|
||||
if (buttonDown) 'buttonDown',
|
||||
if (buttonA) 'buttonA',
|
||||
if (buttonB) 'buttonB',
|
||||
if (buttonY) 'buttonY',
|
||||
if (buttonZ) 'buttonZ',
|
||||
if (buttonShiftUpLeft) 'buttonShiftUpLeft',
|
||||
if (buttonShiftDownLeft) 'buttonShiftDownLeft',
|
||||
if (buttonShiftUpRight) 'buttonShiftUpRight',
|
||||
if (buttonShiftDownRight) 'buttonShiftDownRight',
|
||||
if (buttonPowerUpLeft) 'buttonPowerUpLeft',
|
||||
if (buttonPowerDownLeft) 'buttonPowerDownLeft',
|
||||
if (buttonOnOffLeft) 'buttonOnOffLeft',
|
||||
if (buttonOnOffRight) 'buttonOnOffRight',
|
||||
];
|
||||
return '{$allTrueParameters, analogLR: $analogLR, analogUD: $analogUD}';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RideNotification &&
|
||||
runtimeType == other.runtimeType &&
|
||||
buttonLeft == other.buttonLeft &&
|
||||
buttonRight == other.buttonRight &&
|
||||
buttonUp == other.buttonUp &&
|
||||
buttonDown == other.buttonDown &&
|
||||
buttonA == other.buttonA &&
|
||||
buttonB == other.buttonB &&
|
||||
buttonY == other.buttonY &&
|
||||
buttonZ == other.buttonZ &&
|
||||
buttonShiftUpLeft == other.buttonShiftUpLeft &&
|
||||
buttonShiftDownLeft == other.buttonShiftDownLeft &&
|
||||
buttonShiftUpRight == other.buttonShiftUpRight &&
|
||||
buttonShiftDownRight == other.buttonShiftDownRight &&
|
||||
buttonPowerUpLeft == other.buttonPowerUpLeft &&
|
||||
buttonPowerDownLeft == other.buttonPowerDownLeft &&
|
||||
buttonOnOffLeft == other.buttonOnOffLeft &&
|
||||
buttonOnOffRight == other.buttonOnOffRight &&
|
||||
analogLR == other.analogLR &&
|
||||
analogUD == other.analogUD;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
buttonLeft.hashCode ^
|
||||
buttonRight.hashCode ^
|
||||
buttonUp.hashCode ^
|
||||
buttonDown.hashCode ^
|
||||
buttonA.hashCode ^
|
||||
buttonB.hashCode ^
|
||||
buttonY.hashCode ^
|
||||
buttonZ.hashCode ^
|
||||
buttonShiftUpLeft.hashCode ^
|
||||
buttonShiftDownLeft.hashCode ^
|
||||
buttonShiftUpRight.hashCode ^
|
||||
buttonShiftDownRight.hashCode ^
|
||||
buttonPowerUpLeft.hashCode ^
|
||||
buttonPowerDownLeft.hashCode ^
|
||||
buttonOnOffLeft.hashCode ^
|
||||
buttonOnOffRight.hashCode ^
|
||||
analogLR.hashCode ^
|
||||
analogUD.hashCode;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:swift_control/main.dart';
|
||||
import 'package:swift_control/utils/requirements/platform.dart';
|
||||
|
||||
@@ -18,6 +19,36 @@ class AccessibilityRequirement extends PlatformRequirement {
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothScanRequirement extends PlatformRequirement {
|
||||
BluetoothScanRequirement() : super('Allow Bluetooth Scan');
|
||||
|
||||
@override
|
||||
Future<void> call() async {
|
||||
await Permission.bluetoothScan.request();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> getStatus() async {
|
||||
final state = await Permission.bluetoothScan.status;
|
||||
status = state.isGranted || state.isLimited;
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothConnectRequirement extends PlatformRequirement {
|
||||
BluetoothConnectRequirement() : super('Allow Bluetooth Connections');
|
||||
|
||||
@override
|
||||
Future<void> call() async {
|
||||
await Permission.bluetoothConnect.request();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> getStatus() async {
|
||||
final state = await Permission.bluetoothConnect.status;
|
||||
status = state.isGranted || state.isLimited;
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationRequirement extends PlatformRequirement {
|
||||
NotificationRequirement() : super('Allow adding persistent Notification');
|
||||
|
||||
|
||||
@@ -29,7 +29,14 @@ Future<List<PlatformRequirement>> getRequirements() async {
|
||||
} else if (Platform.isWindows) {
|
||||
list = [BluetoothTurnedOn(), KeyboardRequirement(), KeymapRequirement(), BluetoothScanning()];
|
||||
} else if (Platform.isAndroid) {
|
||||
list = [BluetoothTurnedOn(), AccessibilityRequirement(), NotificationRequirement(), BluetoothScanning()];
|
||||
list = [
|
||||
BluetoothTurnedOn(),
|
||||
AccessibilityRequirement(),
|
||||
NotificationRequirement(),
|
||||
BluetoothScanRequirement(),
|
||||
BluetoothConnectRequirement(),
|
||||
BluetoothScanning(),
|
||||
];
|
||||
} else {
|
||||
list = [UnsupportedPlatform()];
|
||||
}
|
||||
|
||||
48
pubspec.lock
48
pubspec.lock
@@ -367,6 +367,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.4.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.6"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: swift_control
|
||||
description: "SwiftControl - Control your virtual riding"
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+3
|
||||
version: 1.0.6+0
|
||||
|
||||
environment:
|
||||
sdk: ^3.7.0
|
||||
@@ -14,6 +14,7 @@ dependencies:
|
||||
flutter_local_notifications: ^19.0.0
|
||||
universal_ble: any
|
||||
protobuf: ^3.1.0
|
||||
permission_handler: ^11.4.0
|
||||
dartx: any
|
||||
pointycastle: any
|
||||
keypress_simulator: ^0.2.0
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <keypress_simulator_windows/keypress_simulator_windows_plugin_c_api.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <universal_ble/universal_ble_plugin_c_api.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
KeypressSimulatorWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("KeypressSimulatorWindowsPluginCApi"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UniversalBlePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UniversalBlePluginCApi"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
keypress_simulator_windows
|
||||
permission_handler_windows
|
||||
universal_ble
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user