How I remade AirDrop from iOS on Windows
Tags: python, firebase, windows, ios
Published: 2021-03-27 22:40:13

AirDrop has always been a truly useful feature of Apple's ecosystem, as it lets you share text, files, and images between Apple devices with ease. However, if you're like me and prefer using a Windows PC with an iOS device, there's no way to seamlessly share data between the two devices, without having to email yourself or something like that.

So, I came up with this idea, to recreate iOS's famous AirDrop, but available for Windows as well.
The project's architecture I opted for was the following:
1. An iOS shortcut sends data to a database when something is shared
2. A Python program on my PC picks up that data
3. Then the data is presented in a notification
4. If that notification is clicked the data is copied to the clipboard

Easy, right?

The database I chose was [Firebase's realtime database](https://firebase.google.com/docs/database), by Google, as it is incredibly easy to use, and is completely free.
Once the realtime database was set up, I had to make the iOS shortcut.
An interesting feature that fit exactly my needs, was the "Show in Share Sheets" feature for shortcuts. As the name says, it shows the shortcut in the Share menu, which lets you create a shortcut that does various stuff with the shared data as input. Exactly what I needed!

![Enabling Share Sheets for shortcuts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wkqb5m7ullljbof5ybj.jpeg)

As you can see the shortcut appears in share sheets:

![The shortcut in share sheets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcmyr9jszw4smp3ki401.jpeg)

Then, the shortcut would simply make an HTTP POST request to Firebase, with the shortcut's input passed in the body of the request.

![The HTTP request of the shortcut](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92108rjd8mrdkw8dmsr8.jpeg)

So now, I had a shortcut that could send anything shareable on iOS, to Firebase. Now my PC just had to pick up that data.

First things first, so I started with creating a connection to Firebase. For that a single dependency was needed:
```py
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
```
Imported using `pip` like so:
```
pip install firebase-admin
```

Then, my Python script had to get authenticated in order to access Firebase, which was done using an authentication JSON file. If you’re following this article as a tutorial, the method to get that JSON file is explained [here](https://firebase.google.com/docs/database/admin/start#python). So here’s the code for authentication:
```py
configFile = 'config.json'
cred = credentials.Certificate(configFile)
app = firebase_admin.initialize_app(cred, {
  'databaseURL': 'myDataBaseUrl' # this is not my actual database URL, for security purposes
})
```

Once that was done, my script had to listen for new data in the real-time database. That was easily done with the `listen` method, however one issue remained. The listen method actually sends the entire contents of the database the first time it is executed, which wasn’t the behaviour I was looking for. That was easily fixed though, whit a boolean toggle, like so:
```py
hasGotFirst = False

def listener(data):
  global hasGotFirst
  if hasGotFirst:
    # Here we’ll use the fetched data
  hasGotFirst = True

# Here we just listen at the root of the database
db.reference('/').listen(listener)
```
Then, I wanted the data to be displayed in a beautiful notification when it was received, and then copied to the clipboard when that notification was clicked. For that, I added another two dependencies:
```py
from win10toast_click import ToastNotifier # Notifications
import pyperclip # Clipboard
```
Imported using `pip` like so:
```
pip install win10toast-click
pip install pyperclip
```
Then, the Python script would display a notification when data was retrieved and copy that data to the clipboard in the notification’s click callback. Here’s the full code:
```py
def listener(data):
  global hasGotFirst
  if hasGotFirst:
    msg = str(data.data['value']) # Get the 'value' property from the data
    toaster.show_toast("Data Sent From Phone", msg, callback_on_click=click, icon_path='')
  hasGotFirst = True

def click(data):
  pyperclip.copy(data)
```

So now the AirDrop was basically working! I could share a string of text from my phone and it would magically appear in a notification on my PC that I could copy by clicking on it!

If I were to share a note containing the text "Hello from iOS!", a notification would appear, like this:
![Example notification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d6752kutr3x6uztm48l2.png)

However to make the process even smoother, I added automatic URL detection, which added a couple more packages:
```py
import re
import webbrowser
```
Both are available by default, so no installing is needed for those two.

As for the code, it simply checks for a URL pattern when data is retrieved using the `re` module, and if it evaluates to true, that URL is then opened using the `webbrowser` module, like so:
```py
def listener(data):
  global hasGotFirst
  if hasGotFirst:
    msg = str(data.data['value'])
    matches = re.match(r'https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)', msg)
    if matches:
      webbrowser.open(msg)
    else:
      toaster.show_toast("Data Sent From Phone", msg, callback_on_click=lambda val=msg: click(val), icon_path='')
  hasGotFirst = True
```

And now we’re completely done! With the Python script running in the background, I can now share data between my iOS phone and my Windows computer with ease.

If you want the full source code, it is available on GitHub: https://github.com/oskar-codes/windows-airdrop