@capawesome/capacitor-maps-launcher 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapawesomeCapacitorMapsLauncher.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +292 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +10 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/MapsLauncher.java +200 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/MapsLauncherPlugin.java +117 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/CustomException.java +20 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/CustomExceptions.java +15 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/options/Destination.java +57 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/options/NavigateOptions.java +54 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/results/GetAvailableAppsResult.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/classes/results/GetDefaultAppResult.java +25 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/interfaces/Callback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/interfaces/EmptyCallback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/interfaces/NonEmptyResultCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/interfaces/Result.java +7 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +329 -0
- package/dist/esm/definitions.d.ts +195 -0
- package/dist/esm/definitions.js +47 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +7 -0
- package/dist/esm/web.js +13 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +74 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +77 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Classes/Options/Destination.swift +36 -0
- package/ios/Plugin/Classes/Options/NavigateOptions.swift +23 -0
- package/ios/Plugin/Classes/Results/GetAvailableAppsResult.swift +16 -0
- package/ios/Plugin/Enums/CustomError.swift +36 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/MapsLauncher.swift +182 -0
- package/ios/Plugin/MapsLauncherPlugin.swift +71 -0
- package/ios/Plugin/Protocols/Result.swift +5 -0
- package/package.json +94 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapawesomeCapacitorMapsLauncher'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '15.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robin Genz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CapawesomeCapacitorMapsLauncher",
|
|
6
|
+
platforms: [.iOS(.v15)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CapawesomeCapacitorMapsLauncher",
|
|
10
|
+
targets: ["MapsLauncherPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "MapsLauncherPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Plugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "MapsLauncherPluginTests",
|
|
25
|
+
dependencies: ["MapsLauncherPlugin"],
|
|
26
|
+
path: "ios/PluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# @capawesome/capacitor-maps-launcher
|
|
2
|
+
|
|
3
|
+
Capacitor plugin to launch navigation apps with turn-by-turn directions.
|
|
4
|
+
|
|
5
|
+
<div class="capawesome-z29o10a">
|
|
6
|
+
<a href="https://cloud.capawesome.io/" target="_blank">
|
|
7
|
+
<img alt="Deliver Live Updates to your Capacitor app with Capawesome Cloud" src="https://cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
|
|
8
|
+
</a>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- 🧭 **Navigate**: Launch a navigation app with turn-by-turn directions to a destination.
|
|
14
|
+
- 🗺️ **Curated apps**: Support for Google Maps, Apple Maps (iOS) and Waze.
|
|
15
|
+
- 📍 **Coordinates & addresses**: Navigate to coordinates or a plain address.
|
|
16
|
+
- 🚗 **Travel modes**: Choose between driving, walking, bicycling and transit (best-effort per app).
|
|
17
|
+
- ✅ **Availability**: Check which navigation apps are installed and can be launched.
|
|
18
|
+
- 📦 **CocoaPods & SPM**: Supports CocoaPods and Swift Package Manager for iOS.
|
|
19
|
+
- 🔁 **Up-to-date**: Always supports the latest Capacitor version.
|
|
20
|
+
|
|
21
|
+
Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!
|
|
22
|
+
|
|
23
|
+
## Newsletter
|
|
24
|
+
|
|
25
|
+
Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).
|
|
26
|
+
|
|
27
|
+
## Compatibility
|
|
28
|
+
|
|
29
|
+
| Plugin Version | Capacitor Version | Status |
|
|
30
|
+
| -------------- | ----------------- | -------------- |
|
|
31
|
+
| 0.x.x | >=8.x.x | Active support |
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
You can use our **AI-Assisted Setup** to install the plugin.
|
|
36
|
+
Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx skills add capawesome-team/skills --skill capacitor-plugins
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then use the following prompt:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-maps-launcher` plugin in my project.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install @capawesome/capacitor-maps-launcher
|
|
52
|
+
npx cap sync
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Android
|
|
56
|
+
|
|
57
|
+
The plugin declares the required [package visibility](https://developer.android.com/training/package-visibility) `<queries>` for Google Maps and Waze in its own `AndroidManifest.xml`. No additional configuration is required.
|
|
58
|
+
|
|
59
|
+
### iOS
|
|
60
|
+
|
|
61
|
+
#### Application Queries Schemes
|
|
62
|
+
|
|
63
|
+
To detect and launch Google Maps and Waze, the following URL schemes must be added to the `LSApplicationQueriesSchemes` array in the `Info.plist` file of your app. Without them, `getAvailableApps(...)` reports those apps as unavailable and `navigate(...)` rejects with the `APP_NOT_AVAILABLE` error code.
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<key>LSApplicationQueriesSchemes</key>
|
|
67
|
+
<array>
|
|
68
|
+
<string>comgooglemaps</string>
|
|
69
|
+
<string>waze</string>
|
|
70
|
+
</array>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Apple Maps is always available and does not require any configuration.
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
No configuration required for this plugin.
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { MapsLauncher, NavigationApp } from '@capawesome/capacitor-maps-launcher';
|
|
83
|
+
|
|
84
|
+
const getAvailableApps = async () => {
|
|
85
|
+
const { apps } = await MapsLauncher.getAvailableApps();
|
|
86
|
+
return apps;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const getDefaultApp = async () => {
|
|
90
|
+
const { app } = await MapsLauncher.getDefaultApp();
|
|
91
|
+
return app;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const navigate = async () => {
|
|
95
|
+
await MapsLauncher.navigate({
|
|
96
|
+
destination: {
|
|
97
|
+
latitude: 37.3349,
|
|
98
|
+
longitude: -122.009,
|
|
99
|
+
},
|
|
100
|
+
app: NavigationApp.GoogleMaps,
|
|
101
|
+
travelMode: 'driving',
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const navigateToAddress = async () => {
|
|
106
|
+
await MapsLauncher.navigate({
|
|
107
|
+
destination: {
|
|
108
|
+
address: 'Apple Park, Cupertino, CA',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## API
|
|
115
|
+
|
|
116
|
+
<docgen-index>
|
|
117
|
+
|
|
118
|
+
* [`getAvailableApps()`](#getavailableapps)
|
|
119
|
+
* [`getDefaultApp()`](#getdefaultapp)
|
|
120
|
+
* [`navigate(...)`](#navigate)
|
|
121
|
+
* [Interfaces](#interfaces)
|
|
122
|
+
* [Type Aliases](#type-aliases)
|
|
123
|
+
* [Enums](#enums)
|
|
124
|
+
|
|
125
|
+
</docgen-index>
|
|
126
|
+
|
|
127
|
+
<docgen-api>
|
|
128
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
129
|
+
|
|
130
|
+
### getAvailableApps()
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
getAvailableApps() => Promise<GetAvailableAppsResult>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Get the navigation apps that are installed and can be launched.
|
|
137
|
+
|
|
138
|
+
On iOS, Apple Maps is always included. Google Maps and Waze are only
|
|
139
|
+
included if the corresponding `LSApplicationQueriesSchemes` entries are
|
|
140
|
+
added to the `Info.plist` file of your app.
|
|
141
|
+
|
|
142
|
+
Only available on Android and iOS.
|
|
143
|
+
|
|
144
|
+
**Returns:** <code>Promise<<a href="#getavailableappsresult">GetAvailableAppsResult</a>></code>
|
|
145
|
+
|
|
146
|
+
**Since:** 0.1.0
|
|
147
|
+
|
|
148
|
+
--------------------
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
### getDefaultApp()
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
getDefaultApp() => Promise<GetDefaultAppResult>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Get the navigation app that is configured as the default handler for
|
|
158
|
+
navigation intents.
|
|
159
|
+
|
|
160
|
+
Returns `null` if the default app is not part of the curated list of
|
|
161
|
+
supported apps or if no default app is set (i.e. the system shows a
|
|
162
|
+
chooser).
|
|
163
|
+
|
|
164
|
+
Only available on Android.
|
|
165
|
+
|
|
166
|
+
**Returns:** <code>Promise<<a href="#getdefaultappresult">GetDefaultAppResult</a>></code>
|
|
167
|
+
|
|
168
|
+
**Since:** 0.1.0
|
|
169
|
+
|
|
170
|
+
--------------------
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
### navigate(...)
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
navigate(options: NavigateOptions) => Promise<void>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Launch a navigation app with turn-by-turn directions to a destination.
|
|
180
|
+
|
|
181
|
+
If no `app` is provided, the system default behavior is used (a chooser on
|
|
182
|
+
Android, Apple Maps on iOS).
|
|
183
|
+
|
|
184
|
+
Only available on Android and iOS.
|
|
185
|
+
|
|
186
|
+
| Param | Type |
|
|
187
|
+
| ------------- | ----------------------------------------------------------- |
|
|
188
|
+
| **`options`** | <code><a href="#navigateoptions">NavigateOptions</a></code> |
|
|
189
|
+
|
|
190
|
+
**Since:** 0.1.0
|
|
191
|
+
|
|
192
|
+
--------------------
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
### Interfaces
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
#### GetAvailableAppsResult
|
|
199
|
+
|
|
200
|
+
| Prop | Type | Description | Since |
|
|
201
|
+
| ---------- | ---------------------------- | ----------------------------------------------------------- | ----- |
|
|
202
|
+
| **`apps`** | <code>NavigationApp[]</code> | The navigation apps that are installed and can be launched. | 0.1.0 |
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
#### GetDefaultAppResult
|
|
206
|
+
|
|
207
|
+
| Prop | Type | Description | Since |
|
|
208
|
+
| --------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
|
|
209
|
+
| **`app`** | <code><a href="#navigationapp">NavigationApp</a> \| null</code> | The navigation app that is configured as the default handler. Returns `null` if the default app is not part of the curated list of supported apps or if no default app is set. | 0.1.0 |
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
#### NavigateOptions
|
|
213
|
+
|
|
214
|
+
| Prop | Type | Description | Default | Since |
|
|
215
|
+
| ----------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ----- |
|
|
216
|
+
| **`app`** | <code><a href="#navigationapp">NavigationApp</a></code> | The navigation app to launch. If not provided, the system default behavior is used (a chooser on Android, Apple Maps on iOS). | | 0.1.0 |
|
|
217
|
+
| **`destination`** | <code><a href="#destination">Destination</a></code> | The destination to navigate to. | | 0.1.0 |
|
|
218
|
+
| **`start`** | <code><a href="#destination">Destination</a></code> | The start location of the route. If not provided, the current location of the device is used. **Note**: The support depends on the selected app. Apple Maps supports it fully, Google Maps opens the directions preview instead of starting turn-by-turn navigation, and Waze ignores it. | | 0.1.0 |
|
|
219
|
+
| **`travelMode`** | <code><a href="#travelmode">TravelMode</a></code> | The travel mode to use for the directions. **Note**: The support depends on the selected app and is best-effort. Waze only supports driving and ignores this option. | <code>'driving'</code> | 0.1.0 |
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
#### Destination
|
|
223
|
+
|
|
224
|
+
A destination is either defined by its coordinates or by its address, but
|
|
225
|
+
not both.
|
|
226
|
+
|
|
227
|
+
| Prop | Type | Description | Since |
|
|
228
|
+
| --------------- | ------------------- | -------------------------------------------------------------------------------------------------- | ----- |
|
|
229
|
+
| **`address`** | <code>string</code> | The address of the destination. Must be provided without `latitude` and `longitude`. | 0.1.0 |
|
|
230
|
+
| **`latitude`** | <code>number</code> | The latitude of the destination. Must be provided together with `longitude` and without `address`. | 0.1.0 |
|
|
231
|
+
| **`longitude`** | <code>number</code> | The longitude of the destination. Must be provided together with `latitude` and without `address`. | 0.1.0 |
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
### Type Aliases
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
#### TravelMode
|
|
238
|
+
|
|
239
|
+
The travel mode to use for the directions.
|
|
240
|
+
|
|
241
|
+
- `driving`: Driving directions.
|
|
242
|
+
- `walking`: Walking directions.
|
|
243
|
+
- `bicycling`: Bicycling directions.
|
|
244
|
+
- `transit`: Public transit directions.
|
|
245
|
+
|
|
246
|
+
<code>'driving' | 'walking' | 'bicycling' | 'transit'</code>
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
### Enums
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
#### NavigationApp
|
|
253
|
+
|
|
254
|
+
| Members | Value | Description | Since |
|
|
255
|
+
| ---------------- | ------------------------- | ---------------------------------- | ----- |
|
|
256
|
+
| **`AppleMaps`** | <code>'appleMaps'</code> | Apple Maps. Only available on iOS. | 0.1.0 |
|
|
257
|
+
| **`GoogleMaps`** | <code>'googleMaps'</code> | Google Maps. | 0.1.0 |
|
|
258
|
+
| **`Waze`** | <code>'waze'</code> | Waze. | 0.1.0 |
|
|
259
|
+
|
|
260
|
+
</docgen-api>
|
|
261
|
+
|
|
262
|
+
## Platform Support
|
|
263
|
+
|
|
264
|
+
The behavior of the `navigate(...)` method depends on the selected app and platform. Keep the following in mind:
|
|
265
|
+
|
|
266
|
+
### Start location
|
|
267
|
+
|
|
268
|
+
| App | `start` support |
|
|
269
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
270
|
+
| Apple Maps | Full support. |
|
|
271
|
+
| Google Maps | Supported, but opens the directions preview instead of starting turn-by-turn navigation directly. |
|
|
272
|
+
| Waze | Not supported. The option is ignored. |
|
|
273
|
+
|
|
274
|
+
If `start` is not provided, the current location of the device is used.
|
|
275
|
+
|
|
276
|
+
### Travel mode
|
|
277
|
+
|
|
278
|
+
| App | `driving` | `walking` | `bicycling` | `transit` |
|
|
279
|
+
| ----------- | --------- | --------- | ----------- | --------- |
|
|
280
|
+
| Apple Maps | ✅ | ✅ | ❌ | ✅ |
|
|
281
|
+
| Google Maps | ✅ | ✅ | ✅ | ✅ |
|
|
282
|
+
| Waze | ✅ | ❌ | ❌ | ❌ |
|
|
283
|
+
|
|
284
|
+
Unsupported travel modes fall back to the default behavior of the respective app. Waze only supports driving and ignores the `travelMode` option.
|
|
285
|
+
|
|
286
|
+
## Changelog
|
|
287
|
+
|
|
288
|
+
See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/maps-launcher/CHANGELOG.md).
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
See [LICENSE](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/maps-launcher/LICENSE).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.13.0'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace = "io.capawesome.capacitorjs.plugins.mapslauncher"
|
|
22
|
+
compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError = false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
mavenCentral()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
53
|
+
implementation project(':capacitor-android')
|
|
54
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
55
|
+
testImplementation "junit:junit:$junitVersion"
|
|
56
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
57
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
58
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<queries>
|
|
3
|
+
<package android:name="com.google.android.apps.maps" />
|
|
4
|
+
<package android:name="com.waze" />
|
|
5
|
+
<intent>
|
|
6
|
+
<action android:name="android.intent.action.VIEW" />
|
|
7
|
+
<data android:scheme="geo" />
|
|
8
|
+
</intent>
|
|
9
|
+
</queries>
|
|
10
|
+
</manifest>
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/mapslauncher/MapsLauncher.java
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.mapslauncher;
|
|
2
|
+
|
|
3
|
+
import android.content.ActivityNotFoundException;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.content.Intent;
|
|
6
|
+
import android.content.pm.PackageManager;
|
|
7
|
+
import android.content.pm.ResolveInfo;
|
|
8
|
+
import android.net.Uri;
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.classes.CustomExceptions;
|
|
12
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.classes.options.Destination;
|
|
13
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.classes.options.NavigateOptions;
|
|
14
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.classes.results.GetAvailableAppsResult;
|
|
15
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.classes.results.GetDefaultAppResult;
|
|
16
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.interfaces.EmptyCallback;
|
|
17
|
+
import io.capawesome.capacitorjs.plugins.mapslauncher.interfaces.NonEmptyResultCallback;
|
|
18
|
+
import java.util.ArrayList;
|
|
19
|
+
import java.util.List;
|
|
20
|
+
|
|
21
|
+
public class MapsLauncher {
|
|
22
|
+
|
|
23
|
+
public static final String APP_GOOGLE_MAPS = "googleMaps";
|
|
24
|
+
public static final String APP_WAZE = "waze";
|
|
25
|
+
public static final String PACKAGE_GOOGLE_MAPS = "com.google.android.apps.maps";
|
|
26
|
+
public static final String PACKAGE_WAZE = "com.waze";
|
|
27
|
+
|
|
28
|
+
@NonNull
|
|
29
|
+
private final MapsLauncherPlugin plugin;
|
|
30
|
+
|
|
31
|
+
public MapsLauncher(@NonNull MapsLauncherPlugin plugin) {
|
|
32
|
+
this.plugin = plugin;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void getAvailableApps(@NonNull NonEmptyResultCallback<GetAvailableAppsResult> callback) {
|
|
36
|
+
List<String> apps = new ArrayList<>();
|
|
37
|
+
if (isPackageInstalled(PACKAGE_GOOGLE_MAPS)) {
|
|
38
|
+
apps.add(APP_GOOGLE_MAPS);
|
|
39
|
+
}
|
|
40
|
+
if (isPackageInstalled(PACKAGE_WAZE)) {
|
|
41
|
+
apps.add(APP_WAZE);
|
|
42
|
+
}
|
|
43
|
+
callback.success(new GetAvailableAppsResult(apps));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public void getDefaultApp(@NonNull NonEmptyResultCallback<GetDefaultAppResult> callback) {
|
|
47
|
+
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=0,0"));
|
|
48
|
+
ResolveInfo resolveInfo = getContext().getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
|
49
|
+
String app = null;
|
|
50
|
+
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
|
51
|
+
app = mapPackageToApp(resolveInfo.activityInfo.packageName);
|
|
52
|
+
}
|
|
53
|
+
callback.success(new GetDefaultAppResult(app));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public void navigate(@NonNull NavigateOptions options, @NonNull EmptyCallback callback) throws Exception {
|
|
57
|
+
String app = options.getApp();
|
|
58
|
+
if (app != null) {
|
|
59
|
+
String packageName = getPackageForApp(app);
|
|
60
|
+
if (packageName == null || !isPackageInstalled(packageName)) {
|
|
61
|
+
throw CustomExceptions.APP_NOT_AVAILABLE;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
Intent intent = createIntent(options);
|
|
65
|
+
try {
|
|
66
|
+
plugin.getActivity().startActivity(intent);
|
|
67
|
+
} catch (ActivityNotFoundException exception) {
|
|
68
|
+
throw CustomExceptions.LAUNCH_FAILED;
|
|
69
|
+
}
|
|
70
|
+
callback.success();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@NonNull
|
|
74
|
+
private Intent createDefaultIntent(@NonNull Destination destination) {
|
|
75
|
+
return new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + Uri.encode(formatDestination(destination))));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@NonNull
|
|
79
|
+
private Intent createGoogleMapsIntent(@NonNull Destination destination, @Nullable Destination start, @Nullable String travelMode) {
|
|
80
|
+
Uri uri;
|
|
81
|
+
if (start == null) {
|
|
82
|
+
String value =
|
|
83
|
+
"google.navigation:q=" + Uri.encode(formatDestination(destination)) + "&mode=" + mapTravelModeToGoogleMode(travelMode);
|
|
84
|
+
uri = Uri.parse(value);
|
|
85
|
+
} else {
|
|
86
|
+
String value =
|
|
87
|
+
"https://www.google.com/maps/dir/?api=1" +
|
|
88
|
+
"&origin=" +
|
|
89
|
+
Uri.encode(formatDestination(start)) +
|
|
90
|
+
"&destination=" +
|
|
91
|
+
Uri.encode(formatDestination(destination)) +
|
|
92
|
+
"&travelmode=" +
|
|
93
|
+
mapTravelModeToGoogleUrlMode(travelMode);
|
|
94
|
+
uri = Uri.parse(value);
|
|
95
|
+
}
|
|
96
|
+
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
|
97
|
+
intent.setPackage(PACKAGE_GOOGLE_MAPS);
|
|
98
|
+
return intent;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@NonNull
|
|
102
|
+
private Intent createIntent(@NonNull NavigateOptions options) {
|
|
103
|
+
String app = options.getApp();
|
|
104
|
+
if (APP_GOOGLE_MAPS.equals(app)) {
|
|
105
|
+
return createGoogleMapsIntent(options.getDestination(), options.getStart(), options.getTravelMode());
|
|
106
|
+
} else if (APP_WAZE.equals(app)) {
|
|
107
|
+
return createWazeIntent(options.getDestination());
|
|
108
|
+
} else {
|
|
109
|
+
return createDefaultIntent(options.getDestination());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@NonNull
|
|
114
|
+
private Intent createWazeIntent(@NonNull Destination destination) {
|
|
115
|
+
String query = destination.hasCoordinates() ? "ll=" : "q=";
|
|
116
|
+
String value = "https://waze.com/ul?" + query + Uri.encode(formatDestination(destination)) + "&navigate=yes";
|
|
117
|
+
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(value));
|
|
118
|
+
intent.setPackage(PACKAGE_WAZE);
|
|
119
|
+
return intent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@NonNull
|
|
123
|
+
private String formatDestination(@NonNull Destination destination) {
|
|
124
|
+
if (destination.hasCoordinates()) {
|
|
125
|
+
return destination.getLatitude() + "," + destination.getLongitude();
|
|
126
|
+
}
|
|
127
|
+
String address = destination.getAddress();
|
|
128
|
+
return address == null ? "" : address;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@NonNull
|
|
132
|
+
private Context getContext() {
|
|
133
|
+
return plugin.getContext();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@Nullable
|
|
137
|
+
private String getPackageForApp(@NonNull String app) {
|
|
138
|
+
switch (app) {
|
|
139
|
+
case APP_GOOGLE_MAPS:
|
|
140
|
+
return PACKAGE_GOOGLE_MAPS;
|
|
141
|
+
case APP_WAZE:
|
|
142
|
+
return PACKAGE_WAZE;
|
|
143
|
+
default:
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private boolean isPackageInstalled(@NonNull String packageName) {
|
|
149
|
+
try {
|
|
150
|
+
getContext().getPackageManager().getPackageInfo(packageName, 0);
|
|
151
|
+
return true;
|
|
152
|
+
} catch (PackageManager.NameNotFoundException exception) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@Nullable
|
|
158
|
+
private String mapPackageToApp(@NonNull String packageName) {
|
|
159
|
+
switch (packageName) {
|
|
160
|
+
case PACKAGE_GOOGLE_MAPS:
|
|
161
|
+
return APP_GOOGLE_MAPS;
|
|
162
|
+
case PACKAGE_WAZE:
|
|
163
|
+
return APP_WAZE;
|
|
164
|
+
default:
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@NonNull
|
|
170
|
+
private String mapTravelModeToGoogleMode(@Nullable String travelMode) {
|
|
171
|
+
if (travelMode == null) {
|
|
172
|
+
return "d";
|
|
173
|
+
}
|
|
174
|
+
switch (travelMode) {
|
|
175
|
+
case "walking":
|
|
176
|
+
return "w";
|
|
177
|
+
case "bicycling":
|
|
178
|
+
return "b";
|
|
179
|
+
case "transit":
|
|
180
|
+
return "l";
|
|
181
|
+
default:
|
|
182
|
+
return "d";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@NonNull
|
|
187
|
+
private String mapTravelModeToGoogleUrlMode(@Nullable String travelMode) {
|
|
188
|
+
if (travelMode == null) {
|
|
189
|
+
return "driving";
|
|
190
|
+
}
|
|
191
|
+
switch (travelMode) {
|
|
192
|
+
case "walking":
|
|
193
|
+
case "bicycling":
|
|
194
|
+
case "transit":
|
|
195
|
+
return travelMode;
|
|
196
|
+
default:
|
|
197
|
+
return "driving";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|