Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,18 @@ Four things follow:

- **One source of truth.** A path that needs the identity reads it; it does not compose its own.
`AdiDeviceIdentity.Hardware` is it — Python reads the six values across the bridge rather than
keeping a copy, because there is no single right answer to keep: an install from before the
choice existed must present the Mac its ADI was provisioned with, while a fresh one presents
the iPhone.
keeping a copy, because the profile is a runtime choice and not a constant: an install must
present the hardware its ADI was provisioned with, whatever that was.

**Today that is always `LEGACY_MAC`.** `Hardware.DEFAULT` is it, a fresh install gets it, and
`IPHONE` is built and deliberately not chosen — see `generate()`. So every entry this project
registers currently appears as a `MacBookPro` on macOS 13.1, and the serial `0PENTAGVIEWR` is
the only thing distinguishing it from real hardware. The exporter is separately a MacBook Pro
on macOS 13.4.1, FindMy.py's own default, with serial `0PENTAGXPORT`.

Changing which profile a fresh install gets is not a cosmetic edit: it registers a *second*
device rather than renaming the first, for anybody who reinstalls. That is why `IPHONE` exists
unused rather than being switched on.
- **The parts must agree with each other.** Model, OS version, build, CFNetwork and Darwin
describe one real release ([findmy-export §2.2](./docs/findmy-export/01-authentication.md)).
Claiming a Mac in one string and an iPhone in another is a contradiction Apple's own clients
Expand Down
86 changes: 37 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@
[![Exporter tests](https://github.com/parawanderer/OpenTagViewer/actions/workflows/macos-scripts-python.yml/badge.svg?branch=main)](https://github.com/parawanderer/OpenTagViewer/actions/workflows/macos-scripts-python.yml)
[![Release](https://github.com/parawanderer/OpenTagViewer/actions/workflows/build-release.yml/badge.svg)](https://github.com/parawanderer/OpenTagViewer/actions/workflows/build-release.yml)
[![Apple's ADI libraries](https://github.com/parawanderer/OpenTagViewer/actions/workflows/check-adi-libraries.yml/badge.svg)](https://github.com/parawanderer/OpenTagViewer/actions/workflows/check-adi-libraries.yml)
[![Project Status: Inactive](https://www.repostatus.org/badges/latest/inactive.svg)](https://www.repostatus.org/#inactive)

<sub>That last one is checked weekly against Apple's own APK, and is the only badge here that
can go red without anybody changing anything — see
<a href="./CONTRIBUTING.md#continuous-integration">what it watches</a>.</sub>

Apparently, this is the first **<img src="https://github.com/user-attachments/assets/aa0531f6-6a5e-4c9f-b3c4-dfc3899c8a49" width="20"/> Android App** to allow you to view/track your **<img src="https://github.com/user-attachments/assets/fa3b912f-d204-4252-9449-465eb62f128c" height="20"/> official Apple AirTags**.
> [!NOTE]
> This app is feature-complete as of app version `1.1.0` as far as the original author is concerned. Contributions are welcome and will be reviewed - get started through reading [CONTRIBUTING.md](./CONTRIBUTING.md) (and optionally having your agent read [AGENTS.md](./AGENTS.md)) which contain all details to get up and running.

I made this because I couldn't find any app or webpage that lets me do this
<br>

This is an **<img src="https://github.com/user-attachments/assets/aa0531f6-6a5e-4c9f-b3c4-dfc3899c8a49" width="20"/> Android App** to allow you to view/track your **<img src="https://github.com/user-attachments/assets/fa3b912f-d204-4252-9449-465eb62f128c" height="20"/> official Apple AirTags**. It was made because Apple does not make any official app or webpage that lets you do this.
<br>

This project is a relatively polished looking Android/Java UI-wrapper around the Python [FindMy.py](https://github.com/malmeloo/FindMy.py) library, which is a derivative of the [openhaystack](https://github.com/seemoo-lab/openhaystack) project.

<br>

> [!WARNING]
> This project is not afilliated with Apple Inc. or Android/Google LLC in any capacity
> This project is not affiliated with Apple Inc. or Android/Google LLC in any capacity


|Video Demo|Demo: ☀️ Light Mode|Demo: 🌑 Dark Mode|
Expand All @@ -36,30 +35,27 @@ This project is a relatively polished looking Android/Java UI-wrapper around the

## Features ⭐

- View current "live" location of your AirTags **on Android**
- View current "live" location of your AirTags (or other FindMy devices) **on Android**
- Track & (automatically) save historical location history of your AirTags (a feature notably missing from the iOS FindMy apps!)
- UI customisation options


## What it works with 🏷️

**The short version: if it shows up under _Items_ in Apple's own Find My app, it is in scope.**
AirTags are not a special case — they are just the most common thing in that list, and third-party
trackers that advertise "Works with Apple Find My" use the same network and the same keys.
**If it shows up under _Items_ in Apple's own Find My app, it works.**

| What | Works? | |
| --- | --- | --- |
| **AirTag** | ✅ Yes | What most people are here for |
| **Third-party trackers that work with Apple Find My** Chipolo, Pebblebee, Mili MiTag, eufy and similar | ✅ Should work | Same network, same keys, nothing special about them. Not tested by the maintainers, who do not own any — [reports welcome](https://github.com/parawanderer/OpenTagViewer/issues) |
| **AirPods, and other Find My accessories** | ✅ Mostly | Works where Apple stores a usable key for it. Lightly tested |
| **Your own iPhone, iPad or Mac** | ✅ Yes | They are findable devices too, and appear alongside your tags |
| **Self-made tags** — [OpenHaystack](https://github.com/seemoo-lab/openhaystack), [Macless Haystack](https://github.com/dchristl/macless-haystack) | ⚠️ Exporter only | The exporter can package them; the app cannot read them yet ([#45](https://github.com/parawanderer/OpenTagViewer/issues/45)) |
| **A tag someone shared with you** through Apple's own sharing | ❌ No | Only the account that *owns* a tag can export it. Ask the owner to export it and send you the zip |
| **Tile, Samsung SmartTag, Google Find My Device trackers** | ❌ No | Different networks entirely, with nothing in common with Apple's. Out of scope |
| **AirTag** | ✅ | What most people are here for |
| **Third-party trackers that work with Apple Find My** (Chipolo, Pebblebee, Mili MiTag, eufy and similar) | ✅ | Should work; [reports welcome](https://github.com/parawanderer/OpenTagViewer/issues) |
| **AirPods, and other Find My accessories** | ✅ | Works where Apple stores a usable key for it. Lightly tested |
| **Self-made tags** ([OpenHaystack](https://github.com/seemoo-lab/openhaystack), [Macless Haystack](https://github.com/dchristl/macless-haystack)) | ✅ | Works; requires creating an export by [CLI](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Export-AirTags-With-The-CLI) or [Wizard](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Export-AirTags) |
| **Your own iPhone, iPad or Mac** | ⚠️ | Partial coverage (see issue [#131](https://github.com/parawanderer/OpenTagViewer/issues/131)) |
| **A tag someone shared with you** through Apple's own sharing | ❌ | Only the account that *owns* a tag can export it. Ask the owner to export it and send you the zip |
| **Tile, Samsung SmartTag, Google Find My Device trackers** | ❌ | Different networks entirely, with nothing in common with Apple's. This is an open feature request that can be contributed to the app if wanted. |

> [!NOTE]
> This app reads Apple's Find My network. Anything not on that network cannot be tracked with it,
> no matter how similar the device looks.
> This app (currently) reads Apple's Find My network. Anything not on that network cannot be tracked with it, no matter how similar the device looks.


## How To Use 📖
Expand All @@ -68,49 +64,41 @@ trackers that advertise "Works with Apple Find My" use the same network and the

1. An Android phone with [the `OpenTagViewer` app installed](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Install-App)
2. A (free) [Apple Account](https://account.apple.com/) with 2FA enabled to be via either `SMS` or `Trusted Device`
3. One or more **AirTags** — or any other tracker that appears under *Items* in Apple's `FindMy` app (see [what it works with](#what-it-works-with-)) — already registered to an Apple account you own
4. Any computer to run the exporter on — Windows, Linux or a Mac (only needed once/initially). See [the export guide](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Export-AirTags#prerequisites)
3. One or more of:
1. **AirTags**;
2. Any other "FindMy-compatible Accessory" or tracker that appears under *Items* in Apple's `FindMy` app
3. [OpenHaystack](https://github.com/seemoo-lab/openhaystack)-like custom devices (see [what it works with](#what-it-works-with-))

**And then one of two routes**:
1. Read them from iCloud, in the app (requires only your Android phone)
2. Export a zip on a computer, import it (requires a computer once during export)

👉 [Which route should I use?](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Get-AirTags-into-App)


### How to view my AirTag on my Android Phone?!

See [📖 wiki](https://github.com/parawanderer/OpenTagViewer/wiki) for more details:

1. [Install the app](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Install-App) and log in to your Apple Account
2. Create an export `.zip` file by following [this wiki guide](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Export-AirTags#the-export-wizard--recommended)
3. Import the `.zip` file in the app
4. Profit: you can now track your AirTags on your Android Phone indefinitely!
1. [Install the app](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Install-App) and log in to your Apple Account, and either (or both):
1. Use the **iCloud login method** (when you are the owner of official FindMy-compatible devices that show up in the official FindMy app):
1. Follow the steps [here](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Connect-Your-iCloud-Account) explaining how to link your account
2. Use the **zip method**:
1. Create an export `.zip` file by following [this wiki guide](https://github.com/parawanderer/OpenTagViewer/wiki/How-To:-Export-AirTags#the-export-wizard--recommended)
2. Import the `.zip` file in the app
2. Profit: you can now track your AirTags on your Android Phone indefinitely!

-------------

## Contributing

Contributions/MRs are more than welcome.

This started as a "hackathony" thing thrown together ASAP and made presentable for layusers,
and plenty can still be improved.

There are tests: Android unit and instrumented tests, tests for the Python bridge that talks
to Apple, and tests for the macOS export wizard. CI runs all of them, including the
instrumented tests on an emulator it provisions itself. New useful test contributions are welcome!

📋 **[CONTRIBUTING.md](./CONTRIBUTING.md)** covers getting set up — the JDK, the SDK, the Maps
API key, the git hook — and how to run every test suite: the Android unit and instrumented
tests, the Chaquopy bridge tests, and the desktop wizard tests, plus what CI runs and a few
offline diagnostic scripts that need no Apple account.
This started as a "hackathony" thing thrown together ASAP and made presentable for layusers, and plenty can still be improved. Contributions/MRs are more than welcome.

📐 **[AGENTS.md](./AGENTS.md)** is the rules a change has to satisfy — migrations, Anisette,
API keys, attribution. Written for automated contributors, but it applies to people too.
To get started with the repo, see:

**I think it would be nice if the app could support the following features:**
📋 **[CONTRIBUTING.md](./CONTRIBUTING.md)**: covers getting set up (the JDK, the SDK, the Maps API key, the git hook) and how to run every test suite, as well as the CI setup.

- [`🔴 BLOCKED due to 🐛Bug`](https://github.com/malmeloo/FindMy.py/issues/118) Locate Nearby AirTags using Low-Power Bluetooth & display the latest update in that case
- [`🔴 BLOCKED by 🙏Feature Request`](https://github.com/malmeloo/FindMy.py/issues/88) "Ring"/"Make Noise" button
- `🟡 Doable` Support showing unofficial "AirTags" created using [openhaystack](https://github.com/seemoo-lab/openhaystack)
- `🟠 Doable with enough effort` Integrate with projects that query **Google**'s/**Samsung**'s network and also show these in the same UI:
- See [thread](https://github.com/malmeloo/FindMy.py/discussions/30), [thread](https://github.com/seemoo-lab/openhaystack/discussions/210) and repo [GoogleFindMyTools](https://github.com/leonboe1/GoogleFindMyTools). TL;DR: I think this (these two?) are separate projects with their own repos.
- `🟢 Easy` If you'd like to contribute a Language or make corrections in my Translations, feel free to do that too
- Current list of languages can be found back [here](./app/src/main/res/xml/locales_config.xml), translation files can be found back at paths like [`./app/src/main/res/values-en/strings.xml`](./app/src/main/res/values-en/strings.xml) (replace `values-en` with `values-<your locale>`)
📐 **[AGENTS.md](./AGENTS.md)**: the rules a change has to satisfy migrations, Anisette, API keys, attribution. Written for automated contributors, but contains useful information for people too (best queried via a coding assistant rather than read directly).

### Credits

Expand Down