mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
Compare commits
2 Commits
a798ae0761
...
b543459f8d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b543459f8d | ||
|
|
d0609024df |
@@ -16,7 +16,7 @@ The Bitwarden mobile application is written in C# using .NET MAUI.
|
||||
|
||||
# Build/Run
|
||||
|
||||
Please refer to the [Mobile section](https://contributing.bitwarden.com/getting-started/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
||||
Please refer to the [Legacy Contributing Documentation](https://github.com/bitwarden/mobile/tree/main/docs/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
||||
|
||||
# We're Hiring!
|
||||
|
||||
|
||||
79
docs/architecture/index.mdx
Normal file
79
docs/architecture/index.mdx
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# .NET MAUI (legacy)
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
This represents the **legacy** mobile app architecture done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
The mobile .NET MAUI clients are Android and iOS applications with extensions and watchOS. They are
|
||||
all located at https://github.com/bitwarden/mobile.
|
||||
|
||||
Principal structure is a follows:
|
||||
|
||||
- `App`: Main .NET MAUI project that shares code between both platforms (Android & iOS). One can see
|
||||
specific platform code under the `Platforms` folder.
|
||||
- `Core`: Shared code having both logical and UI parts of the app. Several classes are a port from
|
||||
the Web Clients to C#. Here one can find most of the UI and logic since it's shared between App
|
||||
and the iOS extensions.
|
||||
- `iOS.Core`: Shared code used by the main iOS app and its extensions
|
||||
- `iOS.Autofill`: iOS extension that handles Autofill
|
||||
- `iOS.Extensions`: iOS extension that handles Autofill from the bottom sheet extension
|
||||
- `iOS.ShareExtension`: iOS extension that handles sharing files through Send
|
||||
- `watchOS`: All the code specific to the watchOS platform
|
||||
- `bitwarden`: Stub iOS app so that the watchOS app has a companion app on Xcode
|
||||
- `bitwarden WatchKit App`: Main Watch app where we set assets.
|
||||
- `bitwarden WatchKit Extension`: All the logic and presentation logic for the Watch app is here
|
||||
|
||||
## Dependencies diagram
|
||||
|
||||
Below is a simplified dependencies diagram of the mobile repository.
|
||||
|
||||
```kroki type=plantuml
|
||||
@startuml
|
||||
skinparam BackgroundColor transparent
|
||||
skinparam componentStyle rectangle
|
||||
skinparam linetype ortho
|
||||
|
||||
title Simplified Dependencies Diagram
|
||||
|
||||
component "Core"
|
||||
component "App"
|
||||
component "iOS.Core"
|
||||
component "iOS.Autofill"
|
||||
component "iOS.Extension"
|
||||
component "iOS.ShareExtension"
|
||||
component "watchOS" {
|
||||
component "bitwarden"
|
||||
component "bitwarden WatchKit App"
|
||||
component "bitwarden WatchKit Extension"
|
||||
}
|
||||
|
||||
[App] --> [Core]
|
||||
|
||||
[iOS.Core] --> [App]
|
||||
|
||||
[App] --> [iOS.Core]
|
||||
[App] --> [iOS.Autofill]
|
||||
[App] --> [iOS.Extension]
|
||||
[App] --> [iOS.ShareExtension]
|
||||
[App] --> [bitwarden WatchKit App]
|
||||
|
||||
[iOS.Autofill] --> [Core]
|
||||
[iOS.Autofill] --> [iOS.Core]
|
||||
|
||||
[iOS.Extension] --> [Core]
|
||||
[iOS.Extension] --> [iOS.Core]
|
||||
|
||||
[iOS.ShareExtension] --> [Core]
|
||||
[iOS.ShareExtension] --> [iOS.Core]
|
||||
|
||||
[bitwarden] --> [bitwarden WatchKit App]
|
||||
[bitwarden WatchKit App] --> [bitwarden WatchKit Extension]
|
||||
|
||||
@enduml
|
||||
```
|
||||
26
docs/architecture/overview.md
Normal file
26
docs/architecture/overview.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
This represents the **legacy** mobile app overview architecture done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
The overall architecture of the mobile applications is pretty similar to the
|
||||
[web clients](../../clients/overview.md) one following a layered architecture:
|
||||
|
||||
- State
|
||||
- Services
|
||||
- Presentation
|
||||
|
||||
Even though the State and Services layers are pretty similar to the web ones the Presentation layer
|
||||
differs:
|
||||
|
||||
## Presentation
|
||||
|
||||
The presentation layer is implemented using .NET MAUI for the mobile apps, except for the watchOS
|
||||
one which uses SwiftUI [see ADR](../../adr/0017-watchOS-use-swift.md)
|
||||
186
docs/architecture/watchOS.md
Normal file
186
docs/architecture/watchOS.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# watchOS
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
This represents the **legacy** watchOS app architecture done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
## Overall architecture
|
||||
|
||||
The watchOS application is organized as follows:
|
||||
|
||||
- `src/watchOS`: All the code specific to the watchOS platform
|
||||
- `bitwarden`: Stub iOS app so that the watchOS app has a companion app on Xcode
|
||||
- `bitwarden WatchKit App`: Main Watch app where we set assets.
|
||||
- `bitwarden WatchKit Extension`: All the logic and presentation logic for the Watch app is here
|
||||
|
||||
So almost all the things related to the watch app will be in the **WatchKit Extension**, the
|
||||
WatchKit App one will be only for assets and some configs.
|
||||
|
||||
Then in the Extension we have a layered architecture:
|
||||
|
||||
- State (it's a really simplified version of the iOS state)
|
||||
- Persistence (here we use `CoreData` to interact with the Database)
|
||||
- Services (totp generation, crypto services and business logic)
|
||||
- Presentation (use `SwiftUI` for the UI with an MVVM pattern)
|
||||
|
||||
## Integration with iOS
|
||||
|
||||
The watchOS app is developed using `Xcode` and `Swift` and we need to integrate it to the .NET MAUI
|
||||
iOS application.
|
||||
|
||||
For this, the `iOS.csproj` has been adapted taking a
|
||||
[solution](https://github.com/xamarin/xamarin-macios/issues/10070#issuecomment-1033428823) provided
|
||||
in the `Xamarin.Forms` GitHub repository and modified to our needs:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products</WatchAppBuildPath>
|
||||
<WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath>
|
||||
<WatchAppBundle>Bitwarden.app</WatchAppBundle>
|
||||
<WatchAppConfiguration Condition=" '$(Platform)' == 'iPhoneSimulator' ">watchsimulator</WatchAppConfiguration>
|
||||
<WatchAppConfiguration Condition=" '$(Platform)' == 'iPhone' ">watchos</WatchAppConfiguration>
|
||||
<WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath>
|
||||
<WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath>
|
||||
</PropertyGroup>
|
||||
|
||||
...
|
||||
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' AND Exists('$(WatchAppBundleFullPath)') ">
|
||||
<_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(Configuration)' != 'Debug' ">
|
||||
<_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(_ResolvedWatchAppReferences)' != '' ">
|
||||
<CodesignExtraArgs>--deep</CodesignExtraArgs>
|
||||
</PropertyGroup>
|
||||
<Target Name="PrintWatchAppBundleStatus" BeforeTargets="Build">
|
||||
<Message Text="WatchAppBundleFullPath: '$(WatchAppBundleFullPath)' exists" Condition=" Exists('$(WatchAppBundleFullPath)') " />
|
||||
<Message Text="WatchAppBundleFullPath: '$(WatchAppBundleFullPath)' does NOT exist" Condition=" !Exists('$(WatchAppBundleFullPath)') " />
|
||||
</Target>
|
||||
```
|
||||
|
||||
So on the `PropertyGroup` the `WatchAppBundleFullPath` is assembled together depending on the
|
||||
Configuration and the Platform taking the output of the Xcode watchOS app build. Then there are some
|
||||
`ItemGroup` to include the watch app depending on if it exists and the Configuration. The task
|
||||
`_ResolvedWatchAppReferences` is the one responsible to peek into the `Bitwarden.app` built by Xcode
|
||||
and if it finds a Watch app, it will just bundle it to the Xamarin iOS application. Finally, if the
|
||||
Watch app is bundled, deep signing is enabled and the build path is printed.
|
||||
|
||||
:::caution
|
||||
|
||||
As one can see in the csproj, to bundle the watchOS app into the iOS app one needs to target the
|
||||
correct platform. So if one is going to use a device, target the device on Xcode to build the
|
||||
watchOS app and after the build is done one can go to VS4M to build the iOS app (which will bundle
|
||||
the watchOS one) and run it on the device.
|
||||
|
||||
:::
|
||||
|
||||
## Synchronization between iPhone and Watch
|
||||
|
||||
In order to sync data between the iPhone and the Watch apps the
|
||||
[Watch Connectivity Framework](https://developer.apple.com/documentation/watchconnectivity) is used.
|
||||
|
||||
So there is a Watch Connectivity Manager on each side that is the interface used for the services on
|
||||
each platform to communicate.
|
||||
|
||||
For the sync communication, mainly
|
||||
[updateApplicationContext](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615621-updateapplicationcontext)
|
||||
is used given that it always have the latest data sent available, it's sent in the background and
|
||||
the counterpart device doesn't necessarily needs to be in range (so it's cached until it can be
|
||||
delivered). Additionally,
|
||||
[sendMessage](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615687-sendmessage)
|
||||
is also used to signal the counterpart of some action to take quickly (like triggering a sync from
|
||||
the Watch).
|
||||
|
||||
The `WatchDTO` is the object that is sent in the synchronization that has all the information for
|
||||
the Watch.
|
||||
|
||||
```kroki type=plantuml
|
||||
title= iOS part
|
||||
@startuml
|
||||
|
||||
title iOS
|
||||
|
||||
participant C as "Caller"
|
||||
participant BWDS as "BaseWatchDeviceService"
|
||||
participant WDS as "WatchDeviceService"
|
||||
participant WCSM as "WCSessionManager"
|
||||
boundary WCF as "Watch Connectivity Framework"
|
||||
|
||||
group Sync
|
||||
C->>BWDS: SyncDataToWatchAsync(...)
|
||||
BWDS->BWDS: GetStateAsync(...)
|
||||
BWDS->>WDS: SendDataToWatchAsync(...)
|
||||
WDS->>WCSM: SendBackgroundHighPriorityMessage(...)
|
||||
WCSM->>WCF: UpdateApplicationContext(...)
|
||||
end
|
||||
@enduml
|
||||
```
|
||||
|
||||
```kroki type=plantuml
|
||||
title= iOS part
|
||||
@startuml
|
||||
|
||||
title watchOS
|
||||
|
||||
boundary WCF as "Watch Connectivity Framework"
|
||||
participant WCM as "WatchConnectivityManager"
|
||||
participant SS as "StateService"
|
||||
participant ES as "EnvironmentService"
|
||||
participant CS as "CipherService"
|
||||
participant WCS as "watchConnectivitySubject"
|
||||
|
||||
group Sync
|
||||
WCF->>WCM: didReceiveApplicationContext(...)
|
||||
WCM->>SS: update state
|
||||
WCM->>ES: update environment
|
||||
WCM->>CS: saveCiphers(...)
|
||||
WCM->>WCS: fire notification change to subscribers
|
||||
end
|
||||
@enduml
|
||||
```
|
||||
|
||||
## States
|
||||
|
||||
The next ones are the states in which the Watch application can be at a given time:
|
||||
|
||||
- **Valid:** Everything it's ok and the user can see the vault ciphers with TOTP
|
||||
- **Need Login:** The user needs to log in using the iPhone
|
||||
- **Need Setup:** The user needs to set up an account with "Connect to Watch" enabled on their
|
||||
iPhone
|
||||
- **Need Premium:** The current account is not a premium account
|
||||
- **Need 2FA item:** The current account doesn't have any cipher with TOTP set up
|
||||
- **Syncing:** Displayed when changing accounts and syncing the new vault TOTPs
|
||||
- **Need Device Owner Auth:** The user needs to set up an Apple Watch Passcode in order to use the
|
||||
app
|
||||
|
||||
## Persistence and encryption
|
||||
|
||||
On the Watch [CoreData](https://developer.apple.com/documentation/coredata) is used as persistence
|
||||
for the ciphers. So in order to encrypt the data in them a Value Transformer in each encrypted
|
||||
attribute is used: `StringEncryptionTransformer`.
|
||||
|
||||
Inside the transformer a call to the `CryptoService` is used that ends up using
|
||||
[AES.GCM](https://developer.apple.com/documentation/cryptokit/aes/gcm) to encrypt the data with a
|
||||
256 bits [SymmetricKey](https://developer.apple.com/documentation/cryptokit/symmetrickey). The key
|
||||
is generated/loaded the first time something needs to be encrypted and stored in the device
|
||||
Keychain.
|
||||
|
||||
## Crash reporting
|
||||
|
||||
On all the other mobile applications, [AppCenter](https://appcenter.ms/) is being used as Crash
|
||||
reporting tool. However, it doesn't have support for watchOS (nor its internal library to handle
|
||||
crashes).
|
||||
|
||||
So, on the watchOS app [Firebase Crashlytics](https://firebase.google.com/docs/crashlytics) is used
|
||||
with basic crash reporting enabled (there is no handled error logging here yet). For this to work a
|
||||
`GoogleService-Info.plist` file is needed which is injected on the CI.
|
||||
|
||||
At the moment of writing this document, no plist is configured for dev environment so `Crashlytics`
|
||||
is enabled on **non-DEBUG** configurations.
|
||||
|
||||
There is a `Log` class to log errors happened in the app, but it's only enabled in **DEBUG**
|
||||
configuration.
|
||||
BIN
docs/getting-started/android/android-sdk.png
Normal file
BIN
docs/getting-started/android/android-sdk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 350 KiB |
177
docs/getting-started/android/index.md
Normal file
177
docs/getting-started/android/index.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Android
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
Getting started the **legacy** Android app done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
## Requirements
|
||||
|
||||
Before you start, you should have the recommended [Tools and Libraries](../../../tools/index.md)
|
||||
installed. You will also need to install:
|
||||
|
||||
1. Visual Studio 2022 / VS Code
|
||||
2. [.NET 8 (latest)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||
- Note: Even if you have an ARM64 based Mac (M1, M2, M3, etc.), you can install all x64 SDKs to
|
||||
run Android
|
||||
- On Visual Studio for Mac you may need to turn on the feature for .NET 8 by going to Visual
|
||||
Studio > Preferences > Preview Features > Use the .NET 8 SDK
|
||||
3. .NET MAUI Workload
|
||||
- You can install this by running `dotnet workload install maui`
|
||||
4. Android SDK 34
|
||||
- You can use the SDK manager in [Visual Studio][xamarin-vs], or [Android
|
||||
Studio][android-studio] to install this
|
||||
|
||||
To make sure you have the Android SDK and Emulator installed:
|
||||
|
||||
1. Open Visual Studio
|
||||
2. Click Tools > SDK Manager (under the Android subheading)
|
||||
3. Click the Tools tab
|
||||
4. Make sure the following items are installed:
|
||||
|
||||
- Android SDK tools (at least one version of the command-line tools)
|
||||
- Android SDK Platform-Tools
|
||||
- Android SDK Build Tools (at least one version)
|
||||
- Android Emulator
|
||||
|
||||
5. Click Apply Changes if you've marked anything for installation
|
||||
|
||||
If you've missed anything, Visual Studio should prompt you anyway.
|
||||
|
||||
## Android Development Setup
|
||||
|
||||
To set up a new virtual Android device for debugging:
|
||||
|
||||
1. Click Tools > Device Manager (under the Android subheading)
|
||||
2. Click New Device
|
||||
3. Set up the device you want to emulate - you can just choose the Base Device and leave the
|
||||
default settings if you're unsure
|
||||
4. Visual Studio will then download the image for that device. The download progress is shown in
|
||||
the progress in the Android Device Manager dialog.
|
||||
5. Once this has completed, the emulated Android device will be available as a build target under
|
||||
App > Debug > (name of device)
|
||||
|
||||
### ARM64 Macs
|
||||
|
||||
1. Install and open Android Studio
|
||||
2. In the top navbar, click on Android Studio > Settings > Appearance & Behavior (tab) > System
|
||||
Settings > Android SDK
|
||||
3. In the SDK Platforms tab, ensure the "Show Package Details" checkbox is checked (located in the
|
||||
bottom-right)
|
||||
4. Bellow each Android API you'll see several System Images, pick one of the `ARM 64 v8a` and wait
|
||||
for it to download
|
||||
5. Go to View > Tool Windows > Device Manager
|
||||
6. Inside Device Manager, create a device using the previously downloaded system image
|
||||
|
||||

|
||||
|
||||
## F-Droid
|
||||
|
||||
On `App.csproj` and `Core.csproj` we can now pass `/p:CustomConstants=FDROID` when
|
||||
building/releasing so that the `FDROID` constant is added to the defined ones at the project level
|
||||
and we can use that with precompiler directives, e.g.:
|
||||
|
||||
```c#
|
||||
#if FDROID
|
||||
// perform operation only for FDROID.
|
||||
#endif
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
There are currently a few problems on Visual Studio for Mac for building correctly the projects, so
|
||||
if you encounter some errors build using the CLI (previously removing bin/obj folders):
|
||||
|
||||
```
|
||||
dotnet build -f net8.0-android -c Debug
|
||||
```
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
### Using the Android Emulator
|
||||
|
||||
In order to access `localhost:<port>` resources in the Android Emulator when debugging using Visual
|
||||
Studio on your Mac natively, you'll need to configure the endpoint addresses using
|
||||
`<http://10.0.2.2:<port>`\> in order to access `localhost`, which maps the Android proxy by design.
|
||||
|
||||
[xamarin-vs]: https://learn.microsoft.com/en-us/xamarin/android/get-started/installation/android-sdk
|
||||
[android-studio]: https://developer.android.com/studio/releases/platforms
|
||||
|
||||
### Using Server Tunneling
|
||||
|
||||
Instead of configuring your device or emulator, you can instead use a
|
||||
[proxy tunnel to your local server](../../../server/tunnel.md) and have your app connect to it
|
||||
directly.
|
||||
|
||||
### Push Notifications
|
||||
|
||||
The default configuration for the Android app is to register itself to the same environment as
|
||||
Bitwarden's QA Cloud. This means that if you try to debug the app using the production endpoints you
|
||||
won't be able to receive Live Sync updates or Passwordless login requests.
|
||||
|
||||
<Bitwarden>
|
||||
|
||||
So, in order to receive notifications while debugging, you have two options:
|
||||
|
||||
- Use QA Cloud endpoints for the Api and Identity, or
|
||||
- Use a local server setup where the Api is connected to QA Azure Notification Hub
|
||||
|
||||
</Bitwarden>
|
||||
|
||||
### Testing Passwordless Locally
|
||||
|
||||
Before you can start testing and debugging passwordless logins, make sure your local server setup is
|
||||
running correctly ([server setup](../../../server/guide.md)). You should also be able to deploy your
|
||||
Android app to your device or emulator.
|
||||
|
||||
:::note
|
||||
|
||||
Debugging and testing passwordless authentication is limited by
|
||||
[push notifications](#push-notifications).
|
||||
|
||||
:::
|
||||
|
||||
Testing passwordless notifications:
|
||||
|
||||
1. Start your local server (`Api`, `Identity`, `Notifications`)
|
||||
2. Make sure your mobile device can [connect to your local server](#using-server-tunneling)
|
||||
3. [Start the web client](../../../clients/web-vault/index.mdx), as you will need it to make login
|
||||
requests
|
||||
4. Deploy the Android app to your device or emulator
|
||||
5. After deployment, open the app, login to your QA account and activate passwordless login requests
|
||||
in settings
|
||||
6. Open the web vault using your preferred browser (ex: http://localhost:8080)
|
||||
7. Enter the email address of an account that has previously authenticated on that device (i.e. is a
|
||||
"known device") and click Continue. When presented with the login options, click click Login with
|
||||
Device.
|
||||
8. Check mobile device for the notification
|
||||
|
||||
<Bitwarden>
|
||||
|
||||
## AndroidX Credentials
|
||||
|
||||
Currently, the
|
||||
[androidx.credentials](https://developer.android.com/jetpack/androidx/releases/credentials) official
|
||||
binding has some bugs and we cannot use it yet. Because of this, we made a binding ourselves which
|
||||
is located in here:
|
||||
[Xamarin.AndroidX.Credentials](https://github.com/bitwarden/xamarin.androidx.credentials).
|
||||
|
||||
As of today, we are using version 1.2.0.
|
||||
|
||||
In the projects, the package is added as a local NuGet package located in
|
||||
`lib/android/Xamarin.AndroidX.Credentials` and this source is already configured in the
|
||||
`nuget.config` file.
|
||||
|
||||
In the case a change is needed on the binding, create a new local NuGet package and replace it in
|
||||
the aforementioned source.
|
||||
|
||||
:::warning
|
||||
|
||||
Do not add the project to the solution and as a project reference to the `App.csproj` /
|
||||
`Core.csproj` this will strangely make the iOS app crash on start because of solution configuration.
|
||||
Even though we couldn't find the root cause, this is the effect caused by this action.
|
||||
|
||||
:::
|
||||
|
||||
</Bitwarden>
|
||||
107
docs/getting-started/index.md
Normal file
107
docs/getting-started/index.md
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# .NET MAUI (legacy)
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
Getting started the **legacy** mobile app done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
## Configure Git blame
|
||||
|
||||
We recommend that you configure git to ignore the Prettier revision:
|
||||
|
||||
```bash
|
||||
git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
```
|
||||
|
||||
## Android Development
|
||||
|
||||
See the [Android Mobile app](./android/index.md) page to set up an Android development environment.
|
||||
|
||||
## iOS Development
|
||||
|
||||
<Bitwarden>
|
||||
|
||||
See the [iOS Mobile app](./ios/index.mdx) page to set up an iOS development environment.
|
||||
|
||||
</Bitwarden>
|
||||
|
||||
<Community>
|
||||
|
||||
Unfortunately, iOS development requires provisioning profiles and other capabilities only available
|
||||
to internal team members. We do not have any documentation for community developers at this time.
|
||||
|
||||
</Community>
|
||||
|
||||
## watchOS Development
|
||||
|
||||
<Bitwarden>
|
||||
|
||||
See the [watchOS app](./watchos) page to set up an watchOS development environment.
|
||||
|
||||
</Bitwarden>
|
||||
|
||||
<Community>
|
||||
|
||||
Unfortunately, watchOS development requires provisioning profiles and other capabilities only
|
||||
available to internal team members. We do not have any documentation for community developers at
|
||||
this time.
|
||||
|
||||
</Community>
|
||||
|
||||
## Unit tests
|
||||
|
||||
:::info TL;DR;
|
||||
|
||||
In order to run unit tests add the argument `/p:CustomConstants=UT` on the `dotnet` command for
|
||||
building/running. To work on Unit testing or use a Test runner uncomment the `CustomConstants` line
|
||||
on the `Directory.Build.props`
|
||||
|
||||
:::
|
||||
|
||||
Given that the `Core.csproj` is a MAUI project with `net8.0-android;net8.0-ios` target frameworks
|
||||
and we need `net8.0` for the tests we need a way to add that. The `Core.Test.csproj` has `net8.0` as
|
||||
a target so by adding the the argument `/p:CustomConstants=UT` we add `UT` as a constant to use in
|
||||
the projects. With that in place the next things happen:
|
||||
|
||||
- `UT` is added as a constant to use by precompiler directives
|
||||
- `Core.csproj` is changed to add `net8.0` as a target framework for unit tests
|
||||
- `FFImageLoading` is removed as a reference given that it doesn't support `net8.0`. Because of
|
||||
this, now we have a wrapped `CachedImage` that uses the library one if it's not `UT` and a custom
|
||||
one with NOOP implementation for `UT`
|
||||
|
||||
So if one wants to build the test project, one needs to go to `test/Core.Test` and run:
|
||||
|
||||
```bash
|
||||
dotnet build -f net8.0 /p:CustomConstants=UT
|
||||
```
|
||||
|
||||
and to run the tests go to the same folder and run:
|
||||
|
||||
```bash
|
||||
dotnet test -f net8.0 /p:CustomConstants=UT
|
||||
```
|
||||
|
||||
Finally, when working on the `Core.Test` project or when wanting to use a Test runner, go to the
|
||||
`Directory.Build.props` (located in the root) and uncomment the line referencing `CustomConstants`
|
||||
so that everything is loaded accordingly in the project. Because of some issues, the referenced
|
||||
projects, e.g. `Core`, are only included when the `UT` constant is in place. By uncommenting this
|
||||
line the projects will be referenced and one can work on that project or run the tests from a Test
|
||||
runner.
|
||||
|
||||
## Custom constants
|
||||
|
||||
There are custom constants to be used by the parameter `/p:CustomConstants={Value}` when
|
||||
building/running/releasing:
|
||||
|
||||
- `FDROID`: This is used to indicate that it's and F-Droid build/release
|
||||
([want to know more?](./android/index.md#f-droid))
|
||||
- `UT`: This is used when building/running the test projects or when working on one of them
|
||||
([want to know more?](#unit-tests))
|
||||
|
||||
These constants are added to the defined ones, so anyone can use them in the code with precompiler
|
||||
directives.
|
||||
440
docs/getting-started/ios/index.mdx
Normal file
440
docs/getting-started/ios/index.mdx
Normal file
@@ -0,0 +1,440 @@
|
||||
---
|
||||
sidebar_custom_props:
|
||||
access: bitwarden
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
# iOS
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
Getting started the **legacy** iOS app done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
## Requirements
|
||||
|
||||
1. Visual Studio 2022 / VS Code
|
||||
2. [.NET 8 (latest)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||
- On Visual Studio for Mac you may need to turn on the feature for .NET 8 by going to Visual
|
||||
Studio > Preferences > Preview Features > Use the .NET 8 SDK
|
||||
3. .NET MAUI Workload
|
||||
- You can install this by running `dotnet workload install maui`
|
||||
4. A Mac with Xcode 15.0 installed
|
||||
|
||||
## Apple Developer Account Setup
|
||||
|
||||
1. Accept your invite to the Bitwarden Apple Developer team. You should get a request in your email
|
||||
with the subject "You're invited to join a development team." Click the link, "Accept Invitation"
|
||||
and you'll be prompted to create an Apple ID for your Bitwarden email address. If you didn't
|
||||
receive this email, contact the IT department (@IT in slack). Accept the terms and conditions and
|
||||
complete the sign up flow
|
||||
|
||||
2. Go to [Apple ID Online](https://appleid.apple.com/) and log in with your new Apple ID. Set up
|
||||
2-factor authentication (using mobile phone and/or trusted device) - this is critical because
|
||||
Apple no longer allows "developer" accounts without MFA, but it won't tell you that when your
|
||||
build fails locally
|
||||
|
||||
3. Go to [App Store Connect](https://appstoreconnect.apple.com/) and accept the terms and conditions
|
||||
|
||||
4. Ensure you have access to the Bitwarden team and team app profiles
|
||||
|
||||
5. Go to [Apple Developer Account](https://developer.apple.com/account/) and go to the
|
||||
"Certificates, IDs & Profiles" menu item. Check that you can see the 8bit Solutions LLC
|
||||
Certificates in the Certificates section, and the Bitwarden profiles in the Profiles section. If
|
||||
any of this is missing, ask the IT department (@IT #tech-support in slack) for the additional
|
||||
roles / permissions
|
||||
|
||||
## macOS Setup
|
||||
|
||||
Next, you need to get your Mac environment set up for building and running the Bitwarden iOS mobile
|
||||
project. This requires creating the necessary developer provisioning profiles for code signing and
|
||||
execution on your Mac through Xcode. Visual Studio has a simple process to get all of the
|
||||
provisioning profiles, however this is prone to fail without much feedback. Try the Visual Studio
|
||||
instructions ("The Easy Way") first, and fallback to the Xcode instructions (“The Hard Way”) if
|
||||
required.
|
||||
|
||||
### Visual Studio: The Easy Way
|
||||
|
||||
1. Open Visual Studio for Mac
|
||||
|
||||
2. Go to Preferences > Publishing > Apple Developer Accounts
|
||||
|
||||
3. Click “Add”, choose "Enterprise Account", and sign in with your previously configured Apple
|
||||
Developer account
|
||||
|
||||
:::note
|
||||
|
||||
If you receive a "Failed to synchronize with Apple Developer Portal" error, you’re missing
|
||||
additional roles / permissions.
|
||||
|
||||
:::
|
||||
|
||||
After signing in successfully, you should see your account in the list and “Bitwarden Inc” in
|
||||
the account teams list
|
||||
|
||||
4. Click “View Details…”
|
||||
|
||||
5. If you don’t have a valid Apple Development certificate, click Create certificate > Apple
|
||||
Development
|
||||
|
||||
6. Click “Download All Profiles”
|
||||
|
||||
7. You should now be able to run the app by setting
|
||||
`iOS > Debug | iPhone Simulator > [pick any iOS Simulator]` in the top left corner and pressing
|
||||
Play
|
||||
|
||||

|
||||
|
||||
If this worked, you can skip the next section.
|
||||
|
||||
If you only have the option "Generic Simulator", with a message to lower the 'Deployment Target',
|
||||
your version of MAUI may not yet support the version of Xcode that you are using (as discussed
|
||||
[here](https://github.com/xamarin/xamarin-macios/issues/15954#issuecomment-1246025735)).
|
||||
|
||||

|
||||
|
||||
To work around this issue, try [downloading](https://developer.apple.com/download/all/) and
|
||||
installing an older version of Xcode from Apple (you can look for guidance on which Xcode version to
|
||||
use from the Xamarin.iOS [release notes](https://github.com/xamarin/xamarin-macios/releases) (this
|
||||
applies to MAUI as well). After installing the new version of Xcode, restart Visual Studio and load
|
||||
your project to verify your available simulator options.
|
||||
|
||||
:::note
|
||||
|
||||
If you need multiple versions of Xcode installed on your development machine, you can rename the
|
||||
`Xcode.app` file extracted from your download to something else (e.g. "Xcode_14_2.app") before
|
||||
placing it in your Applications folder. You can then switch between Xcode versions by using
|
||||
`xcode-select` from the command line. e.g.:
|
||||
|
||||
```shell
|
||||
sudo xcode-select -s /Applications/Xcode_14_2.app
|
||||
```
|
||||
|
||||
You may achieve similar results with tooling such as
|
||||
[Xcodes.app](https://github.com/XcodesOrg/XcodesApp)
|
||||
|
||||
:::
|
||||
|
||||
### Xcode: The Hard Way
|
||||
|
||||
:::note
|
||||
|
||||
If you're the next person to follow these instructions, please commit and upload the Xcode project
|
||||
files you create so we can streamline this process.
|
||||
|
||||
:::
|
||||
|
||||
Only try these instructions if the Visual Studio instructions above didn't work for you.
|
||||
|
||||
1. Open Xcode
|
||||
|
||||
2. Accept any defaults, ensure any extensions/add-ons have been installed, etc.
|
||||
|
||||
3. Create new project... > iOS > App
|
||||
|
||||
4. Use the following options for your new project:
|
||||
|
||||
- Product Name: "bitwarden"
|
||||
|
||||
- Team: Bitwarden Inc (if this is missing, double check your Apple Developer Account setup
|
||||
above)
|
||||
|
||||
- Organization Identifier: "com.8bit"
|
||||
|
||||
- Bundle Identifier (automatically generated): "com.8bit.bitwarden"
|
||||
|
||||
- Language: Objective-C
|
||||
|
||||
- User Interface: Storyboard
|
||||
|
||||
- Leave all other checkboxes unchecked (or uncheck them)
|
||||
|
||||

|
||||
|
||||
5. Click Next, save to the default location and then click "Create"
|
||||
|
||||
6. On the project configuration page, click the "Signing & Capabilities" tab
|
||||
|
||||
7. Make sure you have the following defaults:
|
||||
|
||||
- Automatically manage signing: (checked)
|
||||
|
||||
- Team: Bitwarden Inc
|
||||
|
||||
- Provisioning Profile: Xcode Managed Profile
|
||||
|
||||
- Signing Certificate: your Apple ID/Name
|
||||
|
||||

|
||||
|
||||
8. From the menu bar, click Product > Build
|
||||
|
||||
9. Repeat Steps 3-8, with the following changes in step 4:
|
||||
|
||||
- Product Name: "find-login-action-extension"
|
||||
|
||||
- Organization Identifier: "com.8bit.bitwarden"
|
||||
|
||||
- Bundle Identifier (automatically generated): "com.8bit.bitwarden.find-login-action-extension"
|
||||
|
||||
10. Repeat Steps 3-8, with the following changes in step 4:
|
||||
|
||||
- Product Name: "autofill"
|
||||
|
||||
- Organization Identifier: "com.8bit.bitwarden"
|
||||
|
||||
- Bundle Identifier (automatically generated): "com.8bit.bitwarden.autofill"
|
||||
|
||||
11. Repeat Steps 3-8, with the following changes in step 4:
|
||||
|
||||
- Product Name: "share-extension"
|
||||
|
||||
- Organization Identifier: "com.8bit.bitwarden"
|
||||
|
||||
- Bundle Identifier (automatically generated): "com.8bit.bitwarden.share-extension"
|
||||
|
||||
12. If you have a physical device (e.g. iPhone or iPad) that you want to use for testing, you will
|
||||
also need to do the following for each of the Xcode projects you just created:
|
||||
|
||||
- connect the device with a cable
|
||||
|
||||
- select your device as as the build target in Xcode
|
||||
|
||||
- from the menu bar, click Product > Build
|
||||
|
||||
- agree to register your device if asked
|
||||
|
||||
:::note
|
||||
|
||||
Sometimes these profiles can mess up. If you have issues running on your physical device (or
|
||||
simulator) try running `rm -r ~/Library/MobileDevice/Provisioning\ Profiles` to clear them out.
|
||||
Build each Xcode project again to regenerate them.
|
||||
|
||||
:::
|
||||
|
||||
## Visual Studio
|
||||
|
||||
Next, we need to configure your Visual Studio environment for development.
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="win" label="Windows" default>
|
||||
|
||||
1. Connect to the Mac that you just completed the above steps on
|
||||
|
||||
2. Open Visual Studio and click Tools > iOS > Pair to Mac
|
||||
|
||||
3. Scan for and select your machine. If you don't see it, click the "Add Mac..." button and put in
|
||||
the Mac name or IP address. If you don't know your Mac name (or you're in a Windows VM on your
|
||||
Mac), go to your Mac and open System Preferences > Sharing and look for the ".local" address of
|
||||
your machine
|
||||
|
||||
4. Provide your Username and Password for macOS when prompted
|
||||
|
||||
5. Once paired, close the Pair Mac window
|
||||
|
||||
6. Change your active build profile to Debug > iPhoneSimulator > iOS
|
||||
|
||||
7. Rebuild the iOS project from Solution Explorer
|
||||
|
||||
8. You can now debug using the iOS Simulator
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="mac" label="macOS">
|
||||
|
||||
1. Check that command line tools are installed:
|
||||
|
||||
1. Open Xcode
|
||||
|
||||
2. From the menu bar, click Xcode > Preferences > Locations
|
||||
|
||||
3. Make sure an Xcode version is selected under "Command Line Tools"
|
||||
|
||||
2. Open Visual Studio for Mac
|
||||
|
||||
3. Open the mobile solution file (`bitwarden-mobile.sln`) in the root of your local mobile
|
||||
repository
|
||||
|
||||
4. In the top bar, you should be able to select App > Debug > select your model and click run (or
|
||||
your physical device if you set one up)
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Building
|
||||
|
||||
To build from the CLI, navigate to the application directory:
|
||||
|
||||
For device:
|
||||
|
||||
```
|
||||
cd src/App
|
||||
dotnet build -f net8.0-ios -c Debug -r ios-arm64
|
||||
```
|
||||
|
||||
For simulator:
|
||||
|
||||
```
|
||||
cd src/App
|
||||
dotnet build -f net8.0-ios -c Debug -r iossimulator-x64
|
||||
```
|
||||
|
||||
You can also use the IDE but keep in mind:
|
||||
|
||||
:::tip Visual Studio for Mac
|
||||
|
||||
There are currently a few problems on Visual Studio for Mac for building correctly the projects, so
|
||||
if you encounter some errors, build using the CLI being into the `src/App` folder (previously
|
||||
removing bin/obj folders).
|
||||
|
||||
:::
|
||||
|
||||
:::tip Argon2Id
|
||||
|
||||
If you find any errors regarding argon2Id library when building for simulator, please be sure that
|
||||
you are building for runtime identifier `iossimulator-x64` as currently the library doesn't support
|
||||
`iossimulator-arm64`.
|
||||
|
||||
:::
|
||||
|
||||
:::tip Troubleshooting common mistakes
|
||||
|
||||
If you find the next error:
|
||||
|
||||
> `error NETSDK1134`: Building a solution with a specific RuntimeIdentifier is not supported. If you
|
||||
> would like to publish for a single RID, specify the RID at the individual project level instead
|
||||
|
||||
you almost surely are trying to build the app from the root folder. Instead go to `src/App` and try
|
||||
building again.
|
||||
|
||||
:::
|
||||
|
||||
### Argon2Id library loading
|
||||
|
||||
The Argon2Id library (`libargon2.a`) is loaded using `MTouchExtraArgs` in almost all projects of the
|
||||
solution. In order to make this simpler a property was added into **Directory.Build.props** called
|
||||
`Argon2IdLoadMtouchExtraArgs` which has the code to fill in the extra args parameter. Each project
|
||||
is configured with this property so this is only added on the correct runtime identifiers and we can
|
||||
build the app successfully on each case.
|
||||
|
||||
### Ignoring extensions / watchOS app
|
||||
|
||||
Sometimes we need to quickly build the app or maybe some configuration on the iOS extensions or the
|
||||
watchOS app gets in the way. In order to have a fast way to only care about the main app two
|
||||
properties were added to the **Directory.Build.Props** to help with this:
|
||||
|
||||
- `IncludeBitwardeniOSExtensions`: If `True` then all the iOS extensions will be included on the
|
||||
building of the main app, otherwise they will be skipped.
|
||||
- `IncludeBitwardenWatchOSApp`: If `True` then the watchOS app will be included on the building of
|
||||
the main app, otherwise it will be skipped.
|
||||
|
||||
:::warning Shared code
|
||||
|
||||
Toggling these off can provide a faster developer experience which is really useful in a lot of
|
||||
scenarios, but always bear in mind that a lot of things are shared between the main app and the
|
||||
extensions so before pushing your work, test again with everything enabled just in case.
|
||||
|
||||
:::
|
||||
|
||||
### Release mode locally
|
||||
|
||||
There are some issues that require us to build the app on **Release** configuration but locally
|
||||
without going through the CI/CD pipeline. The problem is that we don't have the code signing details
|
||||
for Distribution locally. To overcome this we can use the same `CodesignProvision` and `CodesignKey`
|
||||
we use for **Debug** but on the **Release** config. The thing is that it's a bit cumbersome to
|
||||
change that on every project so two properties were added to the **Directory.Build.Props** to help
|
||||
with this:
|
||||
|
||||
- `ReleaseCodesignProvision`: `CodesignProvision` for Release config on all projects
|
||||
- `ReleaseCodesignKey`: `CodesignKey` for Release config on all projects
|
||||
|
||||
By replacing their values, all projects will have their values applied so it's easier to build the
|
||||
app in **Release** mode locally.
|
||||
|
||||
## Debugging
|
||||
|
||||
### iPhone Simulator
|
||||
|
||||
The iPhone Simulator has access to localhost and you can point the client at your local dev server
|
||||
as usual. However, the app will require https by default. To allow http for testing purposes, follow
|
||||
these steps.
|
||||
|
||||
1. Open `src/App/Platforms/iOS/Info.plist` in Visual Studio Code or another editor so that you can
|
||||
edit the raw XML. (Don't use the Property List Editor in Visual Studio.)
|
||||
|
||||
2. Add the following code in the top-level `<dict>` element:
|
||||
|
||||
```xml
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<false/>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
<key>NSIncludesSubdomains</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
```
|
||||
|
||||
3. Save and exit `Info.plist`
|
||||
|
||||
4. Press <kbd>Command</kbd> + <kbd>B</kbd> to force a new build before launching
|
||||
|
||||
5. Don't push these changes :)
|
||||
|
||||
### iPhone device
|
||||
|
||||
The device doesn’t have direct access to your Mac’s localhost, so you can follow
|
||||
[this guide to connect them](https://ymoondhra.medium.com/how-to-run-localhost-on-your-iphone-4110a54d1896).
|
||||
|
||||
After you do that, you’ll have to also modify the `Info.plist` to allow http for testing purposes as
|
||||
explained before on the simulator testing.
|
||||
|
||||
It’s also highly likely that you need to change the `launchSettings.json` on Server, on `Properties`
|
||||
of each project. There you need to change the `applicationUrl` of `iisSettings -> iisExpress` and of
|
||||
`profiles -> Identify` so that instead of `localhost` it says `name.local` where `name` is the
|
||||
computer name you set on Mac’s Sharing config.
|
||||
|
||||
Before you actually test on the app, open a browser and try to connect to the `Api` by going to
|
||||
`http://name.local:4000/alive` . If this doesn’t work then review the steps on the guide or the
|
||||
server configuration. Make sure you have your `User secrets` up to date as well.
|
||||
|
||||
Finally, you’ll have to configure the `Api` and `Identity` urls on the phone to use
|
||||
`http://name.local:4000` and `http://name.local:33656` where `name` is the computer name you set on
|
||||
Mac’s Sharing config.
|
||||
|
||||
### iOS Extensions
|
||||
|
||||
1. Set the iOS Extension project as Startup project
|
||||
|
||||
2. Press Run
|
||||
|
||||
3. You will receive a popup saying "Waiting for the debugger to connect..."
|
||||
|
||||
4. Don’t open the Bitwarden app (otherwise the debugger will connect to it instead of the
|
||||
extension). Instead trigger the extension
|
||||
|
||||
5. Your extension breakpoints should now be hit
|
||||
|
||||
For example: if you want to debug the **iOS.Autofill** extension, you would complete steps 1 - 3,
|
||||
then go to your iOS device, open a browser, go to a login, tap the key icon and open Bitwarden from
|
||||
the bottom popup.
|
||||
|
||||
### Using Server Tunneling
|
||||
|
||||
Instead of configuring your device or emulator to ignore SSL certificates, you can instead use a
|
||||
[proxy tunnel to your local server](../../../server/tunnel.md) and have your app connect to it
|
||||
directly.
|
||||
|
||||
### Push Notifications (Live Sync & Passwordless)
|
||||
|
||||
Push notifications are not currently available for debug deployments. They are only supported on
|
||||
TestFlight and production builds.
|
||||
BIN
docs/getting-started/ios/new-project-options.png
Normal file
BIN
docs/getting-started/ios/new-project-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
docs/getting-started/ios/run-debug.png
Normal file
BIN
docs/getting-started/ios/run-debug.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/getting-started/ios/signing-and-capabilities.png
Normal file
BIN
docs/getting-started/ios/signing-and-capabilities.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 307 KiB |
BIN
docs/getting-started/ios/troubleshoot-generic-simulator.png
Normal file
BIN
docs/getting-started/ios/troubleshoot-generic-simulator.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
101
docs/getting-started/watchos/index.mdx
Normal file
101
docs/getting-started/watchos/index.mdx
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
sidebar_custom_props:
|
||||
access: bitwarden
|
||||
---
|
||||
|
||||
# watchOS
|
||||
|
||||
:::warning Legacy
|
||||
|
||||
Getting started the **legacy** watchOS app done in .NET MAUI.
|
||||
|
||||
:::
|
||||
|
||||
## Requirements
|
||||
|
||||
Follow the [iOS Setup](../ios/index.mdx).
|
||||
|
||||
In order for everything to work properly **devices** are needed. On simulators the synchronization
|
||||
won't work (and some other parts may not work as well). Also, have Bluetooth enabled if possible to
|
||||
ease the sync between devices and the debugging communication.
|
||||
|
||||
It's recommended to read the
|
||||
[Watch Architecture](../../../../../architecture/mobile-clients/net-maui-legacy/watchOS) as well.
|
||||
|
||||
## macOS Setup
|
||||
|
||||
Having followed the macOS setup of iOS, no additional configuration is needed given that when the
|
||||
project is opened in Xcode it will automatically have the provisioning profiles set up.
|
||||
|
||||
## Debugging
|
||||
|
||||
There are two parts from where to debug:
|
||||
|
||||
- From Visual Studio for Mac (the iOS app)
|
||||
- From Xcode (the watchOS app)
|
||||
|
||||
For now, there is no way to debug both apps (iOS and watchOS) at the same time given that from MAUI
|
||||
there is no access to debug information of the watchOS app and from Xcode an iOS stub app is
|
||||
installed on the iPhone to debug it. So, at the moment of debugging one needs to choose which part
|
||||
to have information about, therefore whether to debug from VS4M or from Xcode.
|
||||
|
||||
:::caution
|
||||
|
||||
When debugging from Xcode the MAUI iOS app will be replaced with the stub one from Xcode. So any
|
||||
configuration on the iOS app will be lost (like server urls)
|
||||
|
||||
When debugging from VS4M, uninstall the previous watchOS app (if any) from the Apple Watch in
|
||||
between builds to have it always up to date (there are times that if one doesn't uninstall the
|
||||
previous watchOS app it doesn't get updated)
|
||||
|
||||
:::
|
||||
|
||||
:::tip
|
||||
|
||||
If one needs to get the logs or use the _Console_ app to see the logs from the watch then one needs
|
||||
to install the `sysdiagnose` profile for watchOS from Apple Developer site
|
||||
[here](https://developer.apple.com/bug-reporting/profiles-and-logs/?name=sysdiagnose) into the
|
||||
paired iPhone and after that restart both devices in order for the logs to work.
|
||||
|
||||
:::
|
||||
|
||||
### Building
|
||||
|
||||
Given that the MAUI iOS app needs the output of the build of Xcode, one needs to build the watchOS
|
||||
app from Xcode first and then from VS4M build the iOS app to run it on the device.
|
||||
|
||||
The output of Xcode build is stored in a location pretty similar to the next one that is configured
|
||||
in the `iOS.csproj`:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products</WatchAppBuildPath>
|
||||
```
|
||||
|
||||
It's highly likely that the folder `bitwarden-cbtqsueryycvflfzbsoteofskiyr` won't be the same on
|
||||
every Mac. So one needs to change that part in `iOS.csproj` to the one created automatically by
|
||||
Xcode locally.
|
||||
|
||||
To know exactly which is the path: Open the Project in Xcode -> Go to Product -> Show Build Folder
|
||||
in Finder.
|
||||
|
||||
_This needs to be improved to have a fixed location or an easier way to get it automatically._
|
||||
|
||||
:::caution
|
||||
|
||||
One needs to take special attention to target the same platform on both IDEs. Therefore when running
|
||||
on a device, target the device both in Xcode and on VS4M when building so that the watchOS app is
|
||||
bundled correctly. Also one needs to make sure that "bitwarden WatchKit app" scheme is selected.
|
||||
|
||||
:::
|
||||
|
||||
### Synchronization
|
||||
|
||||
There is no way to debug the synchronization completely at the same time for the reasons
|
||||
aforementioned.
|
||||
|
||||
So one can debug one end (iOS) or the other (watchOS).
|
||||
|
||||
If needed to check something on both ends "at the same time" (like to check why a message is not
|
||||
sent/arrived), one needs to use console logging or adapt part of the MAUI code to the iOS stub app
|
||||
on Xcode and debug the synchronization from Xcode.
|
||||
Reference in New Issue
Block a user