Compare commits
4 Commits
03469446e1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b07f498dd | ||
|
|
3bfb256026 | ||
|
|
1a0550523f | ||
|
|
29d38f3ad6 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
BIN
HealthImport.jpg
BIN
HealthImport.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 461 KiB After Width: | Height: | Size: 432 KiB |
BIN
HealthImport.key
BIN
HealthImport.key
Binary file not shown.
@@ -11,7 +11,6 @@
|
||||
8850025D2B5C273C00E7D4DB /* WorkoutTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8850025C2B5C273C00E7D4DB /* WorkoutTab.swift */; };
|
||||
8850025F2B5C273E00E7D4DB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8850025E2B5C273E00E7D4DB /* Assets.xcassets */; };
|
||||
885002622B5C273E00E7D4DB /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 885002612B5C273E00E7D4DB /* Preview Assets.xcassets */; };
|
||||
885002772B5C2FC400E7D4DB /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = 885002762B5C2FC400E7D4DB /* SQLite */; };
|
||||
885002792B5C320400E7D4DB /* Optional+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885002782B5C320400E7D4DB /* Optional+Extensions.swift */; };
|
||||
8850028D2B5D0B5000E7D4DB /* WorkoutDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8850028C2B5D0B5000E7D4DB /* WorkoutDetailView.swift */; };
|
||||
8850028F2B5D0EAF00E7D4DB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8850028E2B5D0EAF00E7D4DB /* Date+Extensions.swift */; };
|
||||
@@ -33,6 +32,8 @@
|
||||
E27BC6942B5FD587003A8873 /* Workout+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27BC6932B5FD587003A8873 /* Workout+Mock.swift */; };
|
||||
E27BC6962B5FD61D003A8873 /* WorkoutEvent+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27BC6952B5FD61D003A8873 /* WorkoutEvent+Mock.swift */; };
|
||||
E27BC6982B5FD76F003A8873 /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27BC6972B5FD76F003A8873 /* Data+Extensions.swift */; };
|
||||
E29E17BF2D4D04A200E0EE54 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = E29E17BE2D4D04A200E0EE54 /* SQLite */; };
|
||||
E29E17C22D4D04B900E0EE54 /* HealthDB in Frameworks */ = {isa = PBXBuildFile; productRef = E29E17C12D4D04B900E0EE54 /* HealthDB */; };
|
||||
E2A38EA32B9A024500BAD02E /* Workout+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A38EA22B9A024500BAD02E /* Workout+Extensions.swift */; };
|
||||
E2A38EA52B9C6EA900BAD02E /* SearchHealthStoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A38EA42B9C6EA900BAD02E /* SearchHealthStoreView.swift */; };
|
||||
E2A38EA82B9C6EE800BAD02E /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = E2A38EA72B9C6EE800BAD02E /* SFSafeSymbols */; };
|
||||
@@ -60,7 +61,6 @@
|
||||
E2E552902BA236A000BF5E9B /* DatabaseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5528F2BA236A000BF5E9B /* DatabaseList.swift */; };
|
||||
E2E552922BA236D000BF5E9B /* DatabaseFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552912BA236D000BF5E9B /* DatabaseFile.swift */; };
|
||||
E2E5529B2BA3935600BF5E9B /* HKWorkout+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5529A2BA3935600BF5E9B /* HKWorkout+Extensions.swift */; };
|
||||
E2E5529E2BA47BA600BF5E9B /* HealthDB in Frameworks */ = {isa = PBXBuildFile; productRef = E2E5529D2BA47BA600BF5E9B /* HealthDB */; };
|
||||
E2E552A12BA4B14600BF5E9B /* HeartRateSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552A02BA4B14600BF5E9B /* HeartRateSample.swift */; };
|
||||
E2E552A32BA4B58F00BF5E9B /* HeartRateGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552A22BA4B58F00BF5E9B /* HeartRateGraph.swift */; };
|
||||
E2E552A72BA7531C00BF5E9B /* Event+Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552A62BA7531C00BF5E9B /* Event+Identifiable.swift */; };
|
||||
@@ -122,6 +122,7 @@
|
||||
E2D82B4C2BCD5F780075EAF0 /* SymptomsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SymptomsList.swift; sourceTree = "<group>"; };
|
||||
E2D82B4E2BCD61590075EAF0 /* VitalsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VitalsList.swift; sourceTree = "<group>"; };
|
||||
E2D82B502BCD626D0075EAF0 /* OtherSamplesList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherSamplesList.swift; sourceTree = "<group>"; };
|
||||
E2D82B522BCD6CC10075EAF0 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
E2E552882BA2194400BF5E9B /* DatabasesTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabasesTab.swift; sourceTree = "<group>"; };
|
||||
E2E5528B2BA21C0700BF5E9B /* Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = "<group>"; };
|
||||
E2E5528D2BA21C5900BF5E9B /* FileManager+Directory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Directory.swift"; sourceTree = "<group>"; };
|
||||
@@ -153,10 +154,10 @@
|
||||
files = (
|
||||
885002A62B5D296700E7D4DB /* Collections in Frameworks */,
|
||||
E20881D32B76912000D41D95 /* HealthKitExtensions in Frameworks */,
|
||||
885002772B5C2FC400E7D4DB /* SQLite in Frameworks */,
|
||||
885002AA2B5D296700E7D4DB /* OrderedCollections in Frameworks */,
|
||||
E2E5529E2BA47BA600BF5E9B /* HealthDB in Frameworks */,
|
||||
885002A82B5D296700E7D4DB /* DequeModule in Frameworks */,
|
||||
E29E17C22D4D04B900E0EE54 /* HealthDB in Frameworks */,
|
||||
E29E17BF2D4D04A200E0EE54 /* SQLite in Frameworks */,
|
||||
E2A38EA82B9C6EE800BAD02E /* SFSafeSymbols in Frameworks */,
|
||||
E2FDFF202B6BE34C0080A7B3 /* SwiftProtobuf in Frameworks */,
|
||||
);
|
||||
@@ -168,6 +169,7 @@
|
||||
8850024E2B5C273C00E7D4DB = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2D82B522BCD6CC10075EAF0 /* README.md */,
|
||||
885002592B5C273C00E7D4DB /* HealthImport */,
|
||||
885002582B5C273C00E7D4DB /* Products */,
|
||||
E2E5529C2BA47BA600BF5E9B /* Frameworks */,
|
||||
@@ -333,14 +335,14 @@
|
||||
);
|
||||
name = HealthImport;
|
||||
packageProductDependencies = (
|
||||
885002762B5C2FC400E7D4DB /* SQLite */,
|
||||
885002A52B5D296700E7D4DB /* Collections */,
|
||||
885002A72B5D296700E7D4DB /* DequeModule */,
|
||||
885002A92B5D296700E7D4DB /* OrderedCollections */,
|
||||
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */,
|
||||
E20881D22B76912000D41D95 /* HealthKitExtensions */,
|
||||
E2A38EA72B9C6EE800BAD02E /* SFSafeSymbols */,
|
||||
E2E5529D2BA47BA600BF5E9B /* HealthDB */,
|
||||
E29E17BE2D4D04A200E0EE54 /* SQLite */,
|
||||
E29E17C12D4D04B900E0EE54 /* HealthDB */,
|
||||
);
|
||||
productName = HealthImport;
|
||||
productReference = 885002572B5C273C00E7D4DB /* HealthImport.app */;
|
||||
@@ -371,12 +373,12 @@
|
||||
);
|
||||
mainGroup = 8850024E2B5C273C00E7D4DB;
|
||||
packageReferences = (
|
||||
885002752B5C2FC400E7D4DB /* XCRemoteSwiftPackageReference "SQLite" */,
|
||||
885002A42B5D296700E7D4DB /* XCRemoteSwiftPackageReference "swift-collections" */,
|
||||
E2FDFF1E2B6BE34C0080A7B3 /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
||||
E20881D12B76912000D41D95 /* XCRemoteSwiftPackageReference "HealthKitExtensions" */,
|
||||
E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
|
||||
E2E552972BA3748500BF5E9B /* XCRemoteSwiftPackageReference "HealthDB" */,
|
||||
E29E17BD2D4D04A200E0EE54 /* XCRemoteSwiftPackageReference "SQLite" */,
|
||||
E29E17C02D4D04B900E0EE54 /* XCRemoteSwiftPackageReference "HealthDB" */,
|
||||
);
|
||||
productRefGroup = 885002582B5C273C00E7D4DB /* Products */;
|
||||
projectDirPath = "";
|
||||
@@ -686,14 +688,6 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
885002752B5C2FC400E7D4DB /* XCRemoteSwiftPackageReference "SQLite" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/stephencelis/SQLite.swift";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.14.1;
|
||||
};
|
||||
};
|
||||
885002A42B5D296700E7D4DB /* XCRemoteSwiftPackageReference "swift-collections" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-collections.git";
|
||||
@@ -710,6 +704,22 @@
|
||||
minimumVersion = 0.4.0;
|
||||
};
|
||||
};
|
||||
E29E17BD2D4D04A200E0EE54 /* XCRemoteSwiftPackageReference "SQLite" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/stephencelis/SQLite.swift";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.15.3;
|
||||
};
|
||||
};
|
||||
E29E17C02D4D04B900E0EE54 /* XCRemoteSwiftPackageReference "HealthDB" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/christophhagen/HealthDB";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.4.4;
|
||||
};
|
||||
};
|
||||
E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/SFSafeSymbols/SFSafeSymbols";
|
||||
@@ -718,14 +728,6 @@
|
||||
minimumVersion = 5.2.0;
|
||||
};
|
||||
};
|
||||
E2E552972BA3748500BF5E9B /* XCRemoteSwiftPackageReference "HealthDB" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/christophhagen/HealthDB";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.4.0;
|
||||
};
|
||||
};
|
||||
E2FDFF1E2B6BE34C0080A7B3 /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
||||
@@ -737,11 +739,6 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
885002762B5C2FC400E7D4DB /* SQLite */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 885002752B5C2FC400E7D4DB /* XCRemoteSwiftPackageReference "SQLite" */;
|
||||
productName = SQLite;
|
||||
};
|
||||
885002A52B5D296700E7D4DB /* Collections */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 885002A42B5D296700E7D4DB /* XCRemoteSwiftPackageReference "swift-collections" */;
|
||||
@@ -762,16 +759,21 @@
|
||||
package = E20881D12B76912000D41D95 /* XCRemoteSwiftPackageReference "HealthKitExtensions" */;
|
||||
productName = HealthKitExtensions;
|
||||
};
|
||||
E29E17BE2D4D04A200E0EE54 /* SQLite */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E29E17BD2D4D04A200E0EE54 /* XCRemoteSwiftPackageReference "SQLite" */;
|
||||
productName = SQLite;
|
||||
};
|
||||
E29E17C12D4D04B900E0EE54 /* HealthDB */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E29E17C02D4D04B900E0EE54 /* XCRemoteSwiftPackageReference "HealthDB" */;
|
||||
productName = HealthDB;
|
||||
};
|
||||
E2A38EA72B9C6EE800BAD02E /* SFSafeSymbols */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */;
|
||||
productName = SFSafeSymbols;
|
||||
};
|
||||
E2E5529D2BA47BA600BF5E9B /* HealthDB */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E2E552972BA3748500BF5E9B /* XCRemoteSwiftPackageReference "HealthDB" */;
|
||||
productName = HealthDB;
|
||||
};
|
||||
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E2FDFF1E2B6BE34C0080A7B3 /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"originHash" : "5b8e27ff27b74293d3ae2085172fcc80a2317825fae6f3e7879caab9728af319",
|
||||
"originHash" : "853d27802fcd1b74fc9030c3fd718aa74e5a159d9bd4e67bca057ac38d56b364",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "healthdb",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/christophhagen/HealthDB",
|
||||
"state" : {
|
||||
"revision" : "cd077d034d88d31cf283bcf5c0663cb027496a66",
|
||||
"version" : "0.4.1"
|
||||
"revision" : "b02391d12d52623fa15fa79a097c7fefd16ddf32",
|
||||
"version" : "0.4.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -33,8 +33,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/stephencelis/SQLite.swift",
|
||||
"state" : {
|
||||
"revision" : "7a2e3cd27de56f6d396e84f63beefd0267b55ccb",
|
||||
"version" : "0.14.1"
|
||||
"revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8",
|
||||
"version" : "0.15.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
BIN
HealthImport.xcodeproj/project.xcworkspace/xcuserdata/ch.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
HealthImport.xcodeproj/project.xcworkspace/xcuserdata/ch.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 461 KiB After Width: | Height: | Size: 432 KiB |
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
extension HKWorkoutEvent: Identifiable {
|
||||
extension HKWorkoutEvent: @retroactive Identifiable {
|
||||
|
||||
public var id: Int {
|
||||
Int(dateInterval.start.timeIntervalSinceReferenceDate) << 16 +
|
||||
|
||||
@@ -10,7 +10,7 @@ private let df: DateFormatter = {
|
||||
return df
|
||||
}()
|
||||
|
||||
extension Workout: Identifiable {
|
||||
extension Workout: @retroactive Identifiable {
|
||||
|
||||
public var id: Int {
|
||||
dataId
|
||||
|
||||
@@ -83,7 +83,7 @@ struct SearchHealthStoreView: View {
|
||||
SearchHealthStoreView()
|
||||
}
|
||||
|
||||
extension HKQuantityTypeIdentifier: Identifiable {
|
||||
extension HKQuantityTypeIdentifier: @retroactive Identifiable {
|
||||
|
||||
public var id: String {
|
||||
rawValue
|
||||
|
||||
@@ -449,7 +449,7 @@ struct WorkoutDetailView: View {
|
||||
}
|
||||
}
|
||||
|
||||
extension String: Identifiable {
|
||||
extension String: @retroactive Identifiable {
|
||||
|
||||
public var id: Self { self }
|
||||
}
|
||||
|
||||
43
README.md
Normal file
43
README.md
Normal file
@@ -0,0 +1,43 @@
|
||||

|
||||
|
||||
# HealthImport
|
||||
|
||||
This iOS app is a prototype to open the raw databases containing Apple Health data. These `healthdb_secure.sqlite` files can be extracted from (encrypted ) iOS Backups.
|
||||
The structure of the database has been reverse-engineered so that most health data can be viewed and extracted.
|
||||
|
||||
This app is a front-end for [HealthDB](https://github.com/christophhagen/healthdb), which provides the interface to access the database files.
|
||||
|
||||
## Features
|
||||
|
||||
HealthImport offers a view basic features to view and extract health data, mostly centered around workouts.
|
||||
|
||||
### Managing databases
|
||||
|
||||
Multiple databases can be imported into the app.
|
||||
The databases can be renamed and a default database can be selected.
|
||||
One database can be opened at a time, so that the contents can be viewed.
|
||||
|
||||
### Workouts
|
||||
|
||||
The existing workouts contained in each database can be viewed in the "Workouts" tab.
|
||||
The interface has been designed to be similar to the Apple Fitness app.
|
||||
|
||||
A filter allows selecting only those workouts of a specific activity type, and the details of a workout can be viewed.
|
||||
It shows the workout route, heart rate, and statistics for each workout.
|
||||
|
||||
If the app has the required permissions then it also checks if a similar workout already exists on the phone, and can add missing workouts from the database to `Health`.
|
||||
This feature is useful to restore workouts that have been deleted from an existing backup.
|
||||
|
||||
### Samples
|
||||
|
||||
The tab "Health" is structured similar to the Apple Health app, and allows to view different samples stored in the database.
|
||||
Each supported type can be searched by start and end date, and shows a simple list of the samples found.
|
||||
|
||||
## Roadmap
|
||||
|
||||
In the future, additional features are envisioned:
|
||||
|
||||
- View most recent samples, similar to the Apple Health app
|
||||
- Support viewing special sample types, like ECGs
|
||||
- Show details for samples, and allow adding them to Apple Health
|
||||
- Support more filtering options to find samples
|
||||
BIN
screens.png
Normal file
BIN
screens.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 441 KiB |
Reference in New Issue
Block a user