├── .editorconfig
├── .gitattributes
├── .github
├── actions
│ └── setup
│ │ └── action.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .nvmrc
├── .prettierignore
├── .watchmanconfig
├── .yarnrc
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── android
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── osmdroid
│ ├── OsmMapCallout.java
│ ├── OsmMapCalloutManager.java
│ ├── OsmMapCircle.java
│ ├── OsmMapCircleManager.java
│ ├── OsmMapFeature.java
│ ├── OsmMapFileTile.java
│ ├── OsmMapFileTileManager.java
│ ├── OsmMapManager.java
│ ├── OsmMapMarker.java
│ ├── OsmMapMarkerManager.java
│ ├── OsmMapModule.java
│ ├── OsmMapPolygon.java
│ ├── OsmMapPolygonManager.java
│ ├── OsmMapPolyline.java
│ ├── OsmMapPolylineManager.java
│ ├── OsmMapUrlTile.java
│ ├── OsmMapUrlTileManager.java
│ ├── OsmMapView.java
│ ├── OsmRegionChangeEvent.java
│ ├── OsmdroidPackage.java
│ ├── overlays
│ ├── InterceptDoubleTapOverlay.java
│ └── InterceptScrollOverlay.java
│ └── utils
│ ├── FileUtil.java
│ ├── ImageReadable.java
│ ├── ImageReader.java
│ ├── ImageUtil.java
│ ├── LatLngBoundsUtils.java
│ └── SizeReportingShadowNode.java
├── babel.config.js
├── docs
├── callout.md
├── circle.md
├── geojson.md
├── mapview.md
├── marker.md
├── polygon.md
├── polyline.md
└── tiles.md
├── example
├── .bundle
│ └── config
├── .node-version
├── .ruby-version
├── .watchmanconfig
├── Gemfile
├── android
│ ├── app
│ │ ├── _BUCK
│ │ ├── build.gradle
│ │ ├── build_defs.bzl
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── osmdroidexample
│ │ │ │ └── ReactNativeFlipper.java
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── osmdroidexample
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── MainApplication.java
│ │ │ │ └── newarchitecture
│ │ │ │ ├── MainApplicationReactNativeHost.java
│ │ │ │ ├── components
│ │ │ │ └── MainComponentsRegistry.java
│ │ │ │ └── modules
│ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java
│ │ │ ├── jni
│ │ │ ├── CMakeLists.txt
│ │ │ ├── MainApplicationModuleProvider.cpp
│ │ │ ├── MainApplicationModuleProvider.h
│ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp
│ │ │ ├── MainApplicationTurboModuleManagerDelegate.h
│ │ │ ├── MainComponentsRegistry.cpp
│ │ │ ├── MainComponentsRegistry.h
│ │ │ └── OnLoad.cpp
│ │ │ └── res
│ │ │ ├── drawable
│ │ │ └── rn_edit_text_material.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── app.json
├── babel.config.js
├── index.js
├── ios
│ ├── .xcode.env
│ ├── File.swift
│ ├── OsmdroidExample-Bridging-Header.h
│ ├── OsmdroidExample.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── OsmdroidExample.xcscheme
│ ├── OsmdroidExample.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── OsmdroidExample
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── LaunchScreen.storyboard
│ │ └── main.m
│ ├── OsmdroidExampleTests
│ │ ├── Info.plist
│ │ └── OsmdroidExampleTests.m
│ ├── Podfile
│ └── Podfile.lock
├── metro.config.js
├── package.json
├── react-native.config.js
├── src
│ └── App.tsx
└── yarn.lock
├── images
├── circle.png
├── mapView.png
├── marker.png
├── polygon.png
├── polyline.png
└── urlTile.png
├── lefthook.yml
├── package.json
├── scripts
└── bootstrap.js
├── src
├── AnimatedRegion.ts
├── Geojson.tsx
├── MapCallout.tsx
├── MapCircle.tsx
├── MapMarker.tsx
├── MapMarkerNativeComponent.ts
├── MapPolygon.tsx
├── MapPolyline.tsx
├── MapUrlTile.tsx
├── MapView.tsx
├── MapView.types.ts
├── MapViewNativeComponent.ts
├── __tests__
│ └── index.test.tsx
├── decorateMapComponent.ts
├── index.ts
├── sharedTypes.ts
└── sharedTypesInternal.ts
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | indent_style = space
10 | indent_size = 2
11 |
12 | end_of_line = lf
13 | charset = utf-8
14 | trim_trailing_whitespace = true
15 | insert_final_newline = true
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 | # specific for windows script files
3 | *.bat text eol=crlf
--------------------------------------------------------------------------------
/.github/actions/setup/action.yml:
--------------------------------------------------------------------------------
1 | name: Setup
2 | description: Setup Node.js and install dependencies
3 |
4 | runs:
5 | using: composite
6 | steps:
7 | - name: Setup Node.js
8 | uses: actions/setup-node@v3
9 | with:
10 | node-version-file: .nvmrc
11 |
12 | - name: Cache dependencies
13 | id: yarn-cache
14 | uses: actions/cache@v3
15 | with:
16 | path: |
17 | **/node_modules
18 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
19 | restore-keys: |
20 | ${{ runner.os }}-yarn-
21 |
22 | - name: Install dependencies
23 | if: steps.yarn-cache.outputs.cache-hit != 'true'
24 | run: |
25 | yarn install --cwd example --frozen-lockfile
26 | yarn install --frozen-lockfile
27 | shell: bash
28 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 | branches:
8 | - main
9 |
10 | jobs:
11 | lint:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v3
16 |
17 | - name: Setup
18 | uses: ./.github/actions/setup
19 |
20 | - name: Lint files
21 | run: yarn lint
22 |
23 | - name: Typecheck files
24 | run: yarn typecheck
25 |
26 | test:
27 | runs-on: ubuntu-latest
28 | steps:
29 | - name: Checkout
30 | uses: actions/checkout@v3
31 |
32 | - name: Setup
33 | uses: ./.github/actions/setup
34 |
35 | - name: Run unit tests
36 | run: yarn test --maxWorkers=2 --coverage
37 |
38 | build:
39 | runs-on: ubuntu-latest
40 | steps:
41 | - name: Checkout
42 | uses: actions/checkout@v3
43 |
44 | - name: Setup
45 | uses: ./.github/actions/setup
46 |
47 | - name: Build package
48 | run: yarn prepack
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # XDE
6 | .expo/
7 |
8 | # VSCode
9 | .vscode/
10 | jsconfig.json
11 |
12 | # Xcode
13 | #
14 | build/
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 | *.xccheckout
25 | *.moved-aside
26 | DerivedData
27 | *.hmap
28 | *.ipa
29 | *.xcuserstate
30 | project.xcworkspace
31 |
32 | # Android/IJ
33 | #
34 | .classpath
35 | .cxx
36 | .gradle
37 | .idea
38 | .project
39 | .settings
40 | local.properties
41 | android.iml
42 |
43 | # Cocoapods
44 | #
45 | example/ios/Pods
46 |
47 | # Ruby
48 | example/vendor/
49 |
50 | # node.js
51 | #
52 | node_modules/
53 | npm-debug.log
54 | yarn-debug.log
55 | yarn-error.log
56 |
57 | # BUCK
58 | buck-out/
59 | \.buckd/
60 | android/app/libs
61 | android/keystores/debug.keystore
62 |
63 | # Expo
64 | .expo/
65 |
66 | # Turborepo
67 | .turbo/
68 |
69 | # generated by bob
70 | lib/
71 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 16.18.1
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | *.md
2 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | # Override Yarn command so we can automatically setup the repo on running `yarn`
2 |
3 | yarn-path "scripts/bootstrap.js"
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributor Covenant Code of Conduct
3 |
4 | ## Our Pledge
5 |
6 | We as members, contributors, and leaders pledge to make participation in our
7 | community a harassment-free experience for everyone, regardless of age, body
8 | size, visible or invisible disability, ethnicity, sex characteristics, gender
9 | identity and expression, level of experience, education, socio-economic status,
10 | nationality, personal appearance, race, caste, color, religion, or sexual
11 | identity and orientation.
12 |
13 | We pledge to act and interact in ways that contribute to an open, welcoming,
14 | diverse, inclusive, and healthy community.
15 |
16 | ## Our Standards
17 |
18 | Examples of behavior that contributes to a positive environment for our
19 | community include:
20 |
21 | * Demonstrating empathy and kindness toward other people
22 | * Being respectful of differing opinions, viewpoints, and experiences
23 | * Giving and gracefully accepting constructive feedback
24 | * Accepting responsibility and apologizing to those affected by our mistakes,
25 | and learning from the experience
26 | * Focusing on what is best not just for us as individuals, but for the overall
27 | community
28 |
29 | Examples of unacceptable behavior include:
30 |
31 | * The use of sexualized language or imagery, and sexual attention or advances of
32 | any kind
33 | * Trolling, insulting or derogatory comments, and personal or political attacks
34 | * Public or private harassment
35 | * Publishing others' private information, such as a physical or email address,
36 | without their explicit permission
37 | * Other conduct which could reasonably be considered inappropriate in a
38 | professional setting
39 |
40 | ## Enforcement Responsibilities
41 |
42 | Community leaders are responsible for clarifying and enforcing our standards of
43 | acceptable behavior and will take appropriate and fair corrective action in
44 | response to any behavior that they deem inappropriate, threatening, offensive,
45 | or harmful.
46 |
47 | Community leaders have the right and responsibility to remove, edit, or reject
48 | comments, commits, code, wiki edits, issues, and other contributions that are
49 | not aligned to this Code of Conduct, and will communicate reasons for moderation
50 | decisions when appropriate.
51 |
52 | ## Scope
53 |
54 | This Code of Conduct applies within all community spaces, and also applies when
55 | an individual is officially representing the community in public spaces.
56 | Examples of representing our community include using an official e-mail address,
57 | posting via an official social media account, or acting as an appointed
58 | representative at an online or offline event.
59 |
60 | ## Enforcement
61 |
62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
63 | reported to the community leaders responsible for enforcement at
64 | [INSERT CONTACT METHOD].
65 | All complaints will be reviewed and investigated promptly and fairly.
66 |
67 | All community leaders are obligated to respect the privacy and security of the
68 | reporter of any incident.
69 |
70 | ## Enforcement Guidelines
71 |
72 | Community leaders will follow these Community Impact Guidelines in determining
73 | the consequences for any action they deem in violation of this Code of Conduct:
74 |
75 | ### 1. Correction
76 |
77 | **Community Impact**: Use of inappropriate language or other behavior deemed
78 | unprofessional or unwelcome in the community.
79 |
80 | **Consequence**: A private, written warning from community leaders, providing
81 | clarity around the nature of the violation and an explanation of why the
82 | behavior was inappropriate. A public apology may be requested.
83 |
84 | ### 2. Warning
85 |
86 | **Community Impact**: A violation through a single incident or series of
87 | actions.
88 |
89 | **Consequence**: A warning with consequences for continued behavior. No
90 | interaction with the people involved, including unsolicited interaction with
91 | those enforcing the Code of Conduct, for a specified period of time. This
92 | includes avoiding interactions in community spaces as well as external channels
93 | like social media. Violating these terms may lead to a temporary or permanent
94 | ban.
95 |
96 | ### 3. Temporary Ban
97 |
98 | **Community Impact**: A serious violation of community standards, including
99 | sustained inappropriate behavior.
100 |
101 | **Consequence**: A temporary ban from any sort of interaction or public
102 | communication with the community for a specified period of time. No public or
103 | private interaction with the people involved, including unsolicited interaction
104 | with those enforcing the Code of Conduct, is allowed during this period.
105 | Violating these terms may lead to a permanent ban.
106 |
107 | ### 4. Permanent Ban
108 |
109 | **Community Impact**: Demonstrating a pattern of violation of community
110 | standards, including sustained inappropriate behavior, harassment of an
111 | individual, or aggression toward or disparagement of classes of individuals.
112 |
113 | **Consequence**: A permanent ban from any sort of public interaction within the
114 | community.
115 |
116 | ## Attribution
117 |
118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119 | version 2.1, available at
120 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
121 |
122 | Community Impact Guidelines were inspired by
123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124 |
125 | For answers to common questions about this code of conduct, see the FAQ at
126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
127 | [https://www.contributor-covenant.org/translations][translations].
128 |
129 | [homepage]: https://www.contributor-covenant.org
130 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
131 | [Mozilla CoC]: https://github.com/mozilla/diversity
132 | [FAQ]: https://www.contributor-covenant.org/faq
133 | [translations]: https://www.contributor-covenant.org/translations
134 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are always welcome, no matter how large or small!
4 |
5 | We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).
6 |
7 | ## Development workflow
8 |
9 | To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
10 |
11 | ```sh
12 | yarn
13 | ```
14 |
15 | > While it's possible to use [`npm`](https://github.com/npm/cli), the tooling is built around [`yarn`](https://classic.yarnpkg.com/), so you'll have an easier time if you use `yarn` for development.
16 |
17 | While developing, you can run the [example app](/example/) to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app.
18 |
19 | To start the packager:
20 |
21 | ```sh
22 | yarn example start
23 | ```
24 |
25 | To run the example app on Android:
26 |
27 | ```sh
28 | yarn example android
29 | ```
30 |
31 | To run the example app on iOS:
32 |
33 | ```sh
34 | yarn example ios
35 | ```
36 |
37 | Make sure your code passes TypeScript and ESLint. Run the following to verify:
38 |
39 | ```sh
40 | yarn typecheck
41 | yarn lint
42 | ```
43 |
44 | To fix formatting errors, run the following:
45 |
46 | ```sh
47 | yarn lint --fix
48 | ```
49 |
50 | Remember to add tests for your change if possible. Run the unit tests by:
51 |
52 | ```sh
53 | yarn test
54 | ```
55 |
56 | To edit the Objective-C or Swift files, open `example/ios/OsmdroidExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-osmdroid`.
57 |
58 | To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-osmdroid` under `Android`.
59 |
60 |
61 | ### Commit message convention
62 |
63 | We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
64 |
65 | - `fix`: bug fixes, e.g. fix crash due to deprecated method.
66 | - `feat`: new features, e.g. add new method to the module.
67 | - `refactor`: code refactor, e.g. migrate from class components to hooks.
68 | - `docs`: changes into documentation, e.g. add usage example for the module..
69 | - `test`: adding or updating tests, e.g. add integration tests using detox.
70 | - `chore`: tooling changes, e.g. change CI config.
71 |
72 | Our pre-commit hooks verify that your commit message matches this format when committing.
73 |
74 | ### Linting and tests
75 |
76 | [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)
77 |
78 | We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
79 |
80 | Our pre-commit hooks verify that the linter and tests pass when committing.
81 |
82 | ### Publishing to npm
83 |
84 | We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.
85 |
86 | To publish new versions, run the following:
87 |
88 | ```sh
89 | yarn release
90 | ```
91 |
92 | ### Scripts
93 |
94 | The `package.json` file contains various scripts for common tasks:
95 |
96 | - `yarn bootstrap`: setup project by installing all dependencies and pods.
97 | - `yarn typecheck`: type-check files with TypeScript.
98 | - `yarn lint`: lint files with ESLint.
99 | - `yarn test`: run unit tests with Jest.
100 | - `yarn example start`: start the Metro server for the example app.
101 | - `yarn example android`: run the example app on Android.
102 | - `yarn example ios`: run the example app on iOS.
103 |
104 | ### Sending a pull request
105 |
106 | > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
107 |
108 | When you're sending a pull request:
109 |
110 | - Prefer small pull requests focused on one change.
111 | - Verify that linters and tests are passing.
112 | - Review the documentation to make sure it looks good.
113 | - Follow the pull request template when opening a pull request.
114 | - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
115 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Nikita_Kovantsov
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-osmdroid [](https://www.npmjs.com/package/@splicer97/react-native-osmdroid) [](http://www.npmtrends.com/@splicer97/react-native-osmdroid)
2 |
3 | React Native Open Street Maps components for Android.
4 | This is unofficial React Native wrapper for Osmdroid SDK.
5 | Many thanks to [fqborges](https://github.com/fqborges) for his [library](https://github.com/fqborges/react-native-maps-osmdroid), which is the basis of this library!
6 | ## Installation
7 |
8 | ```sh
9 | npm install @splicer97/react-native-osmdroid
10 | ```
11 |
12 | or
13 |
14 | ```sh
15 | yarn add @splicer97/react-native-osmdroid
16 | ```
17 |
18 | ## Manifest
19 |
20 | In most cases, you will have to set the following authorizations in your AndroidManifest.xml:
21 |
22 | ```sh
23 |
24 |
25 |
26 |
27 | ```
28 |
29 | If you are only using parts of the library, you can adjust the permissions accordingly.
30 |
31 | Online tile provider
32 |
33 | ```sh
34 |
35 |
36 | ```
37 |
38 | Offline tile provider and storing tiles
39 |
40 | ```sh
41 |
42 | ```
43 |
44 | Location provider
45 |
46 | ```sh
47 |
48 | ```
49 |
50 | Android 6.0+ devices require you have to check for "dangerous" permissions at runtime.
51 | osmdroid requires the following dangerous permissions:
52 | WRITE_EXTERNAL_STORAGE and ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATION.
53 | See [OpenStreetMapViewer's implementation](https://github.com/osmdroid/osmdroid/blob/master/OpenStreetMapViewer/src/main/java/org/osmdroid/MainActivity.java#L83) or [Google Documentation on Permissions](https://developer.android.com/training/permissions/requesting)
54 |
55 | ## Component API
56 |
57 | [`` Component API](docs/mapview.md)
58 |
59 | [`` Component API](docs/marker.md)
60 |
61 | [`` Component API](docs/callout.md)
62 |
63 | [`` Component API](docs/polygon.md)
64 |
65 | [`` Component API](docs/polyline.md)
66 |
67 | [`` Component API](docs/circle.md)
68 |
69 | [`` Component API](docs/overlay.md)
70 |
71 | [`` Component API](docs/heatmap.md)
72 |
73 | [`` Component API](docs/geojson.md)
74 |
75 | [`` and `` Component API](docs/tiles.md)
76 |
77 | ## Usage
78 |
79 | ```js
80 | import MapView from '@splicer97/react-native-osmdroid';
81 |
82 | // ...
83 | ;
91 | ```
92 |
93 | ## Examples
94 | ### MapView
95 |
96 |
97 | ### Polyline
98 |
99 |
100 | ### Marker
101 |
102 |
103 | ### Polygon
104 |
105 |
106 | ### Circle
107 |
108 |
109 | ### UrlTile
110 |
111 |
112 | ## Contributing
113 |
114 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
115 |
116 | ## License
117 |
118 | MIT
119 |
120 | ---
121 |
122 | Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
123 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:7.2.1"
9 | }
10 | }
11 |
12 | def isNewArchitectureEnabled() {
13 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
14 | }
15 |
16 | apply plugin: "com.android.library"
17 |
18 | if (isNewArchitectureEnabled()) {
19 | apply plugin: "com.facebook.react"
20 | }
21 |
22 | def getExtOrDefault(name) {
23 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Osmdroid_" + name]
24 | }
25 |
26 | def getExtOrIntegerDefault(name) {
27 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Osmdroid_" + name]).toInteger()
28 | }
29 |
30 | android {
31 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
32 |
33 | defaultConfig {
34 | minSdkVersion getExtOrIntegerDefault("minSdkVersion")
35 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
36 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
37 | }
38 | buildTypes {
39 | release {
40 | minifyEnabled false
41 | }
42 | }
43 |
44 | lintOptions {
45 | disable "GradleCompatible"
46 | }
47 |
48 | compileOptions {
49 | sourceCompatibility JavaVersion.VERSION_1_8
50 | targetCompatibility JavaVersion.VERSION_1_8
51 | }
52 |
53 | }
54 |
55 | repositories {
56 | repositories {
57 | maven {
58 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
59 | url("$rootDir/../node_modules/react-native/android")
60 | }
61 | maven {
62 | // Android JSC is installed from npm
63 | url("$rootDir/../node_modules/jsc-android/dist")
64 | }
65 | mavenCentral {
66 | // We don't want to fetch react-native from Maven Central as there are
67 | // older versions over there.
68 | content {
69 | excludeGroup "com.facebook.react"
70 | }
71 | }
72 |
73 | google()
74 | maven { url "https://maven.google.com" }
75 | maven { url 'https://www.jitpack.io' }
76 | }
77 | }
78 |
79 |
80 | dependencies {
81 | implementation "com.facebook.react:react-native:+"
82 | implementation "org.osmdroid:osmdroid-android:6.1.17"
83 | }
84 |
85 | if (isNewArchitectureEnabled()) {
86 | react {
87 | jsRootDir = file("../src/")
88 | libraryName = "OsmdroidView"
89 | codegenJavaPackageName = "com.osmdroid"
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | Osmdroid_kotlinVersion=1.7.0
2 | Osmdroid_minSdkVersion=21
3 | Osmdroid_targetSdkVersion=31
4 | Osmdroid_compileSdkVersion=31
5 | Osmdroid_ndkversion=21.4.7075529
6 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapCallout.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import com.facebook.react.views.view.ReactViewGroup;
5 |
6 | public class OsmMapCallout extends ReactViewGroup {
7 | private boolean tooltip = false;
8 | public int width;
9 | public int height;
10 |
11 | public OsmMapCallout(Context context) {
12 | super(context);
13 | }
14 |
15 | public void setTooltip(boolean tooltip) {
16 | this.tooltip = tooltip;
17 | }
18 |
19 | public boolean getTooltip() {
20 | return this.tooltip;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapCalloutManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import com.osmdroid.utils.SizeReportingShadowNode;
6 | import com.facebook.react.common.MapBuilder;
7 | import com.facebook.react.uimanager.LayoutShadowNode;
8 | import com.facebook.react.uimanager.ThemedReactContext;
9 | import com.facebook.react.uimanager.ViewGroupManager;
10 | import com.facebook.react.uimanager.annotations.ReactProp;
11 |
12 | import java.util.Map;
13 |
14 | import javax.annotation.Nullable;
15 |
16 | public class OsmMapCalloutManager extends ViewGroupManager {
17 |
18 | @Override
19 | public String getName() {
20 | return "OsmMapCallout";
21 | }
22 |
23 | @Override
24 | public OsmMapCallout createViewInstance(@NonNull ThemedReactContext context) {
25 | return new OsmMapCallout(context);
26 | }
27 |
28 | @ReactProp(name = "tooltip", defaultBoolean = false)
29 | public void setTooltip(OsmMapCallout view, boolean tooltip) {
30 | view.setTooltip(tooltip);
31 | }
32 |
33 | @Override
34 | @Nullable
35 | public Map getExportedCustomDirectEventTypeConstants() {
36 | return MapBuilder.of("onPress", MapBuilder.of("registrationName", "onPress"));
37 | }
38 |
39 | @Override
40 | public LayoutShadowNode createShadowNodeInstance() {
41 | // we use a custom shadow node that emits the width/height of the view
42 | // after layout with the updateExtraData method. Without this, we can't generate
43 | // a bitmap of the appropriate width/height of the rendered view.
44 | return new SizeReportingShadowNode();
45 | }
46 |
47 | @Override
48 | public void updateExtraData(OsmMapCallout view, Object extraData) {
49 | // This method is called from the shadow node with the width/height of the rendered
50 | // marker view.
51 | //noinspection unchecked
52 | Map data = (Map) extraData;
53 | float width = data.get("width");
54 | float height = data.get("height");
55 | view.width = (int) width;
56 | view.height = (int) height;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapCircle.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 |
5 | import org.osmdroid.util.GeoPoint;
6 | import org.osmdroid.views.MapView;
7 | import org.osmdroid.views.overlay.Polygon;
8 |
9 | public class OsmMapCircle extends OsmMapFeature {
10 |
11 | private Polygon polygon;
12 |
13 | private GeoPoint center;
14 | private double radius;
15 | private int strokeColor;
16 | private int fillColor;
17 | private float strokeWidth;
18 | private MapView mapView;
19 |
20 | public OsmMapCircle(Context context) {
21 | super(context);
22 | }
23 |
24 | public void setCenter(GeoPoint center) {
25 | this.center = center;
26 | if (polygon != null) {
27 | polygon.setPoints(Polygon.pointsAsCircle(center, radius));
28 | }
29 | }
30 |
31 | public void setRadius(double radius) {
32 | this.radius = radius;
33 | if (polygon != null) {
34 | polygon.setPoints(Polygon.pointsAsCircle(center, radius));
35 | }
36 | }
37 |
38 | public void setFillColor(int color) {
39 | this.fillColor = color;
40 | if (polygon != null) {
41 | polygon.getFillPaint().setColor(color);
42 | mapView.invalidate();
43 | }
44 | }
45 |
46 | public void setStrokeColor(int color) {
47 | this.strokeColor = color;
48 | if (polygon != null) {
49 | polygon.getOutlinePaint().setColor(color);
50 | mapView.invalidate();
51 | }
52 | }
53 |
54 | public void setStrokeWidth(float width) {
55 | this.strokeWidth = width;
56 | if (polygon != null) {
57 | polygon.getOutlinePaint().setStrokeWidth(width);
58 | mapView.invalidate();
59 | }
60 | }
61 |
62 | @Override
63 | public Object getFeature() {
64 | return polygon;
65 | }
66 |
67 | @Override
68 | public void addToMap(MapView map) {
69 | polygon = new Polygon();
70 | mapView = map;
71 | polygon.setPoints(Polygon.pointsAsCircle(center, radius));
72 | polygon.getFillPaint().setColor(fillColor);
73 | polygon.getOutlinePaint().setColor(strokeColor);
74 | polygon.getOutlinePaint().setStrokeWidth(strokeWidth);
75 | map.getOverlays().add(polygon);
76 | mapView.invalidate();
77 | }
78 |
79 | @Override
80 | public void removeFromMap(MapView map) {
81 | map.getOverlays().remove(polygon);
82 | polygon = null;
83 | mapView = null;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapCircleManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Build;
6 | import android.util.DisplayMetrics;
7 | import android.view.WindowManager;
8 |
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.bridge.ReadableMap;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.uimanager.ViewGroupManager;
13 | import com.facebook.react.uimanager.annotations.ReactProp;
14 |
15 | import org.osmdroid.util.GeoPoint;
16 |
17 | public class OsmMapCircleManager extends ViewGroupManager {
18 | private final DisplayMetrics metrics;
19 |
20 | public OsmMapCircleManager(ReactApplicationContext reactContext) {
21 | super();
22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
23 | metrics = new DisplayMetrics();
24 | ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE))
25 | .getDefaultDisplay()
26 | .getRealMetrics(metrics);
27 | } else {
28 | metrics = reactContext.getResources().getDisplayMetrics();
29 | }
30 | }
31 |
32 | @Override
33 | public String getName() {
34 | return "OsmMapCircle";
35 | }
36 |
37 | @Override
38 | public OsmMapCircle createViewInstance(ThemedReactContext context) {
39 | return new OsmMapCircle(context);
40 | }
41 |
42 | @ReactProp(name = "center")
43 | public void setCenter(OsmMapCircle view, ReadableMap center) {
44 | view.setCenter(new GeoPoint(center.getDouble("latitude"), center.getDouble("longitude")));
45 | }
46 |
47 | @ReactProp(name = "radius", defaultDouble = 0)
48 | public void setRadius(OsmMapCircle view, double radius) {
49 | view.setRadius(radius);
50 | }
51 |
52 | @ReactProp(name = "strokeWidth", defaultFloat = 1f)
53 | public void setStrokeWidth(OsmMapCircle view, float widthInPoints) {
54 | float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS
55 | view.setStrokeWidth(widthInScreenPx);
56 | }
57 |
58 | @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color")
59 | public void setFillColor(OsmMapCircle view, int color) {
60 | view.setFillColor(color);
61 | }
62 |
63 | @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color")
64 | public void setStrokeColor(OsmMapCircle view, int color) {
65 | view.setStrokeColor(color);
66 | }
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapFeature.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 |
5 | import com.facebook.react.views.view.ReactViewGroup;
6 |
7 | import org.osmdroid.views.MapView;
8 |
9 | public abstract class OsmMapFeature extends ReactViewGroup {
10 | public OsmMapFeature(Context context) {
11 | super(context);
12 | }
13 |
14 | public abstract void addToMap(MapView map);
15 |
16 | public abstract void removeFromMap(MapView map);
17 |
18 | public abstract Object getFeature();
19 | }
20 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapFileTile.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import androidx.annotation.NonNull;
5 | import android.util.Log;
6 |
7 | import org.osmdroid.tileprovider.modules.ArchiveFileFactory;
8 | import org.osmdroid.tileprovider.modules.IArchiveFile;
9 | import org.osmdroid.tileprovider.modules.OfflineTileProvider;
10 | import org.osmdroid.tileprovider.tilesource.FileBasedTileSource;
11 | import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
12 | import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
13 | import org.osmdroid.views.MapView;
14 |
15 | import java.io.File;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.Set;
19 |
20 | public class OsmMapFileTile extends OsmMapFeature {
21 |
22 | private final static String TAG = "OsmMapFileTile";
23 |
24 | private float maximumZ = 100.f;
25 | private float minimumZ = 0;
26 | private String fileDirPath = "/offline_tiles/";
27 |
28 | public OsmMapFileTile(Context context) {
29 | super(context);
30 | }
31 |
32 | @Override public void addToMap(MapView map) {
33 | setupMapProvider(map);
34 | map.setUseDataConnection(false);
35 | }
36 |
37 | @Override public void removeFromMap(MapView map) {
38 | map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
39 | }
40 |
41 | @Override public Object getFeature() {
42 | return null;
43 | }
44 |
45 | public void setMaximumZ(float maximumZ) {
46 | this.maximumZ = maximumZ;
47 | }
48 |
49 | public void setMinimumZ(float minimumZ) {
50 | this.minimumZ = minimumZ;
51 | }
52 |
53 | public void setFileDirPath(String filePath) {
54 | this.fileDirPath = filePath;
55 | }
56 |
57 | @NonNull
58 | private File[] findAllSupportedFilesInDirectory(File directory) {
59 | List candidates = new ArrayList<>();
60 | File[] list = directory.listFiles();
61 | for (int i = 0; i < list.length; i++) {
62 | if (list[i].isDirectory()) {
63 | continue;
64 | }
65 | String name = list[i].getName().toLowerCase();
66 | if (!name.contains(".")) {
67 | continue; //skip files without an extension
68 | }
69 | name = name.substring(name.lastIndexOf(".") + 1);
70 | if (name.length() == 0) {
71 | continue;
72 | }
73 | if (ArchiveFileFactory.isFileExtensionRegistered(name)) {
74 | candidates.add(list[i]);
75 | }
76 | }
77 | return candidates.toArray(new File[0]);
78 | }
79 |
80 | private void setupMapProvider(@NonNull MapView map) {
81 | //first we'll look at the default location for tiles that we support
82 | Context context = map.getContext();
83 | File f = new File(context.getFilesDir() + fileDirPath);
84 | if (f.exists() && f.isDirectory()) {
85 |
86 | File[] list = findAllSupportedFilesInDirectory(f);
87 | if (list.length > 0) {
88 | try {
89 | OfflineTileProvider tileProvider =
90 | new OfflineTileProvider(new SimpleRegisterReceiver(map.getContext()), list);
91 | map.setTileProvider(tileProvider);
92 | // setup tile source
93 | String source = "";
94 | IArchiveFile[] archives = tileProvider.getArchives();
95 | if (archives.length > 0) {
96 | //cheating a bit here, get the first archive file and ask for the tile sources
97 | // names it contains
98 | Set tileSources = archives[0].getTileSources();
99 | //presumably, this would be a great place to tell your users which tiles sources
100 | // are available
101 | if (!tileSources.isEmpty()) {
102 | //ok good, we found at least one tile source, create a basic file based tile
103 | // source using that name
104 | //and set it. If we don't set it, osmdroid will attempt to use the default
105 | // source, which is "MAPNIK",
106 | //which probably won't match your offline tile source, unless it's MAPNIK
107 | source = tileSources.iterator().next();
108 | map.setTileSource(FileBasedTileSource.getSource(source));
109 | } else {
110 | map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
111 | }
112 |
113 | } else {
114 | map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
115 | }
116 | Log.d(TAG, "Using " + source);
117 | map.invalidate();
118 | return;
119 | } catch (Exception ex) {
120 | ex.printStackTrace();
121 | }
122 | } else {
123 | Log.d(TAG, f.getAbsolutePath() + " dir not found!");
124 | }
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapFileTileManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import com.facebook.react.uimanager.ThemedReactContext;
4 | import com.facebook.react.uimanager.ViewGroupManager;
5 | import com.facebook.react.uimanager.annotations.ReactProp;
6 |
7 | public class OsmMapFileTileManager extends ViewGroupManager {
8 |
9 | public OsmMapFileTileManager() {
10 | super();
11 | }
12 |
13 | @Override
14 | public String getName() {
15 | return "OsmMapFileTile";
16 | }
17 |
18 | @Override
19 | public OsmMapFileTile createViewInstance(ThemedReactContext context) {
20 | return new OsmMapFileTile(context);
21 | }
22 |
23 | @ReactProp(name = "minimumZ", defaultFloat = 0.0f)
24 | public void setMinimumZ(OsmMapFileTile view, float minimumZ) {
25 | view.setMinimumZ(minimumZ);
26 | }
27 |
28 | @ReactProp(name = "maximumZ", defaultFloat = 100.0f)
29 | public void setMaximumZ(OsmMapFileTile view, float maximumZ) {
30 | view.setMaximumZ(maximumZ);
31 | }
32 |
33 | @ReactProp(name="fileDirPath")
34 | public void setFilePath(OsmMapFileTile view, String fileDirPath) {
35 | view.setFileDirPath(fileDirPath);
36 | }
37 |
38 | // todo create offline placeholder binding\
39 | // //https://github.com/osmdroid/osmdroid/issues/330
40 | // //custom image placeholder for files that aren't available
41 | // mMapView.getTileProvider().setTileLoadFailureImage(getResources().getDrawable(R
42 | // .drawable.notfound));
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapMarkerManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.graphics.Color;
4 | import android.view.View;
5 |
6 | import com.osmdroid.utils.SizeReportingShadowNode;
7 | import com.facebook.react.bridge.ReadableArray;
8 | import com.facebook.react.bridge.ReadableMap;
9 | import com.facebook.react.common.MapBuilder;
10 | import com.facebook.react.uimanager.LayoutShadowNode;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.uimanager.ViewGroupManager;
13 | import com.facebook.react.uimanager.annotations.ReactProp;
14 |
15 | import org.osmdroid.views.overlay.Marker;
16 |
17 | import java.util.HashMap;
18 | import java.util.Map;
19 |
20 | import javax.annotation.Nullable;
21 |
22 | public class OsmMapMarkerManager extends ViewGroupManager {
23 |
24 | private static final int SHOW_INFO_WINDOW = 1;
25 | private static final int HIDE_INFO_WINDOW = 2;
26 |
27 | public OsmMapMarkerManager() {
28 | }
29 |
30 | @Override
31 | public String getName() {
32 | return "OsmMapMarker";
33 | }
34 |
35 | @Override
36 | public OsmMapMarker createViewInstance(ThemedReactContext context) {
37 | return new OsmMapMarker(context);
38 | }
39 |
40 | @Override
41 | public void onDropViewInstance(OsmMapMarker view) {
42 | view.cleanup();
43 | super.onDropViewInstance(view);
44 | }
45 |
46 | @ReactProp(name = "coordinate")
47 | public void setCoordinate(OsmMapMarker view, ReadableMap map) {
48 | view.setCoordinate(map);
49 | }
50 |
51 | @ReactProp(name = "title")
52 | public void setTitle(OsmMapMarker view, String title) {
53 | view.setTitle(title);
54 | }
55 |
56 | @ReactProp(name = "identifier")
57 | public void setIdentifier(OsmMapMarker view, String identifier) {
58 | view.setIdentifier(identifier);
59 | }
60 |
61 | @ReactProp(name = "description")
62 | public void setDescription(OsmMapMarker view, String description) {
63 | view.setSnippet(description);
64 | }
65 |
66 | // NOTE(lmr):
67 | // android uses normalized coordinate systems for this, and is provided through the
68 | // `anchor` property and `calloutAnchor` instead. Perhaps some work could be done
69 | // to normalize iOS and android to use just one of the systems.
70 | // @ReactProp(name = "centerOffset")
71 | // public void setCenterOffset(AirMapMarker view, ReadableMap map) {
72 | //
73 | // }
74 | //
75 | // @ReactProp(name = "calloutOffset")
76 | // public void setCalloutOffset(AirMapMarker view, ReadableMap map) {
77 | //
78 | // }
79 |
80 | @ReactProp(name = "anchor")
81 | public void setAnchor(OsmMapMarker view, ReadableMap map) {
82 | // should default to (0.5, 1) (bottom middle)
83 | double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5;
84 | double y = map != null && map.hasKey("y") ? map.getDouble("y") : 1.0;
85 | view.setAnchor(x, y);
86 | }
87 |
88 | @ReactProp(name = "calloutAnchor")
89 | public void setCalloutAnchor(OsmMapMarker view, ReadableMap map) {
90 | // should default to (0.5, 0) (top middle)
91 | double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5;
92 | double y = map != null && map.hasKey("y") ? map.getDouble("y") : 0.0;
93 | view.setCalloutAnchor(x, y);
94 | }
95 |
96 | @ReactProp(name = "image")
97 | public void setImage(OsmMapMarker view, @Nullable String source) {
98 | view.setImage(source);
99 | }
100 | // public void setImage(AirMapMarker view, ReadableMap image) {
101 | // view.setImage(image);
102 | // }
103 |
104 | @ReactProp(name = "pinColor", defaultInt = Color.RED, customType = "Color")
105 | public void setPinColor(OsmMapMarker view, int pinColor) {
106 | float[] hsv = new float[3];
107 | Color.colorToHSV(pinColor, hsv);
108 | // NOTE: android only supports a hue
109 | view.setMarkerHue(hsv[0]);
110 | }
111 |
112 | @ReactProp(name = "rotation", defaultFloat = 0.0f)
113 | public void setMarkerRotation(OsmMapMarker view, float rotation) {
114 | view.setRotation(rotation);
115 | }
116 |
117 | @ReactProp(name = "flat", defaultBoolean = false)
118 | public void setFlat(OsmMapMarker view, boolean flat) {
119 | view.setFlat(flat);
120 | }
121 |
122 | @ReactProp(name = "draggable", defaultBoolean = false)
123 | public void setDraggable(OsmMapMarker view, boolean draggable) {
124 | view.setDraggable(draggable);
125 | }
126 |
127 | // @Override
128 | // @ReactProp(name = "zIndex", defaultFloat = 0.0f)
129 | // public void setZIndex(AirMapMarker view, float zIndex) {
130 | // super.setZIndex(view, zIndex);
131 | // int integerZIndex = Math.round(zIndex);
132 | // view.setZIndex(integerZIndex);
133 | // }
134 |
135 | @Override
136 | @ReactProp(name = "opacity", defaultFloat = 1.0f)
137 | public void setOpacity(OsmMapMarker view, float opacity) {
138 | super.setOpacity(view, opacity);
139 | view.setOpacity(opacity);
140 | }
141 |
142 | @Override
143 | public void addView(OsmMapMarker parent, View child, int index) {
144 | // if an component is a child, then it is a callout view, NOT part of the
145 | // marker.
146 | if (child instanceof OsmMapCallout) {
147 | parent.setCalloutView((OsmMapCallout) child);
148 | } else {
149 | super.addView(parent, child, index);
150 | parent.update();
151 | }
152 | }
153 |
154 | @Override
155 | public void removeViewAt(OsmMapMarker parent, int index) {
156 | super.removeViewAt(parent, index);
157 | parent.update();
158 | }
159 |
160 | @Override
161 | @Nullable
162 | public Map getCommandsMap() {
163 | return MapBuilder.of(
164 | "showCallout", SHOW_INFO_WINDOW,
165 | "hideCallout", HIDE_INFO_WINDOW
166 | );
167 | }
168 |
169 | @Override
170 | public void receiveCommand(OsmMapMarker view, int commandId, @Nullable ReadableArray args) {
171 | switch (commandId) {
172 | case SHOW_INFO_WINDOW:
173 | ((Marker) view.getFeature()).showInfoWindow();
174 | break;
175 |
176 | case HIDE_INFO_WINDOW:
177 | ((Marker) view.getFeature()).closeInfoWindow();
178 | break;
179 | }
180 | }
181 |
182 | @Override
183 | @Nullable
184 | public Map getExportedCustomDirectEventTypeConstants() {
185 | Map> map = MapBuilder.of(
186 | "onPress", MapBuilder.of("registrationName", "onPress"),
187 | "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"),
188 | "onDragStart", MapBuilder.of("registrationName", "onDragStart"),
189 | "onDrag", MapBuilder.of("registrationName", "onDrag"),
190 | "onDragEnd", MapBuilder.of("registrationName", "onDragEnd")
191 | );
192 |
193 | map.putAll(MapBuilder.of(
194 | "onDragStart", MapBuilder.of("registrationName", "onDragStart"),
195 | "onDrag", MapBuilder.of("registrationName", "onDrag"),
196 | "onDragEnd", MapBuilder.of("registrationName", "onDragEnd")
197 | ));
198 |
199 | return map;
200 | }
201 |
202 | @Override
203 | public LayoutShadowNode createShadowNodeInstance() {
204 | // we use a custom shadow node that emits the width/height of the view
205 | // after layout with the updateExtraData method. Without this, we can't generate
206 | // a bitmap of the appropriate width/height of the rendered view.
207 | return new SizeReportingShadowNode();
208 | }
209 |
210 | @Override
211 | public void updateExtraData(OsmMapMarker view, Object extraData) {
212 | // This method is called from the shadow node with the width/height of the rendered
213 | // marker view.
214 | HashMap data = (HashMap) extraData;
215 | float width = data.get("width");
216 | float height = data.get("height");
217 | view.update((int) width, (int) height);
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapPolygon.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 |
5 | import com.facebook.react.bridge.ReadableArray;
6 | import com.facebook.react.bridge.ReadableMap;
7 |
8 | import org.osmdroid.util.GeoPoint;
9 | import org.osmdroid.views.MapView;
10 | import org.osmdroid.views.overlay.Polygon;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class OsmMapPolygon extends OsmMapFeature {
16 |
17 | private Polygon polygon;
18 |
19 | private List coordinates;
20 | private int strokeColor;
21 | private int fillColor;
22 | private float strokeWidth;
23 | private MapView mapView;
24 |
25 | public OsmMapPolygon(Context context) {
26 | super(context);
27 | }
28 |
29 | public void setCoordinates(ReadableArray coordinates) {
30 | // it's kind of a bummer that we can't run map() or anything on the ReadableArray
31 | this.coordinates = new ArrayList<>(coordinates.size()+1);
32 | for (int i = 0; i < coordinates.size(); i++) {
33 | ReadableMap coordinate = coordinates.getMap(i);
34 | this.coordinates.add(i,
35 | new GeoPoint(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")));
36 | }
37 | this.coordinates.add(this.coordinates.get(0));
38 | if (polygon != null) {
39 | polygon.setPoints(this.coordinates);
40 | mapView.invalidate();
41 | }
42 | }
43 |
44 | public void setFillColor(int color) {
45 | this.fillColor = color;
46 | if (polygon != null) {
47 | polygon.getFillPaint().setColor(color);
48 | mapView.invalidate();
49 | }
50 | }
51 |
52 | public void setStrokeColor(int color) {
53 | this.strokeColor = color;
54 | if (polygon != null) {
55 | polygon.getOutlinePaint().setColor(color);
56 | mapView.invalidate();
57 | }
58 | }
59 |
60 | public void setStrokeWidth(float width) {
61 | this.strokeWidth = width;
62 | if (polygon != null) {
63 | polygon.getOutlinePaint().setStrokeWidth(width);
64 | mapView.invalidate();
65 | }
66 | }
67 |
68 |
69 | @Override
70 | public Object getFeature() {
71 | return polygon;
72 | }
73 |
74 | @Override
75 | public void addToMap(MapView map) {
76 | polygon = new Polygon();
77 | mapView = map;
78 | polygon.setPoints(coordinates);
79 | polygon.getFillPaint().setColor(fillColor);
80 | polygon.getOutlinePaint().setColor(strokeColor);
81 | polygon.getOutlinePaint().setStrokeWidth(strokeWidth);
82 | map.getOverlays().add(polygon);
83 | mapView.invalidate();
84 | }
85 |
86 | @Override
87 | public void removeFromMap(MapView map) {
88 | map.getOverlays().remove(polygon);
89 | polygon = null;
90 | mapView = null;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapPolygonManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Build;
6 | import android.util.DisplayMetrics;
7 | import android.view.WindowManager;
8 |
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.bridge.ReadableArray;
11 | import com.facebook.react.common.MapBuilder;
12 | import com.facebook.react.uimanager.ThemedReactContext;
13 | import com.facebook.react.uimanager.ViewGroupManager;
14 | import com.facebook.react.uimanager.annotations.ReactProp;
15 |
16 | import java.util.Map;
17 |
18 | import javax.annotation.Nullable;
19 |
20 | public class OsmMapPolygonManager extends ViewGroupManager {
21 | private final DisplayMetrics metrics;
22 |
23 | public OsmMapPolygonManager(ReactApplicationContext reactContext) {
24 | super();
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
26 | metrics = new DisplayMetrics();
27 | ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE))
28 | .getDefaultDisplay()
29 | .getRealMetrics(metrics);
30 | } else {
31 | metrics = reactContext.getResources().getDisplayMetrics();
32 | }
33 | }
34 |
35 | @Override
36 | public String getName() {
37 | return "OsmMapPolygon";
38 | }
39 |
40 | @Override
41 | public OsmMapPolygon createViewInstance(ThemedReactContext context) {
42 | return new OsmMapPolygon(context);
43 | }
44 |
45 | @ReactProp(name = "coordinates")
46 | public void setCoordinate(OsmMapPolygon view, ReadableArray coordinates) {
47 | view.setCoordinates(coordinates);
48 | }
49 |
50 | @ReactProp(name = "strokeWidth", defaultFloat = 1f)
51 | public void setStrokeWidth(OsmMapPolygon view, float widthInPoints) {
52 | float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS
53 | view.setStrokeWidth(widthInScreenPx);
54 | }
55 |
56 | @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color")
57 | public void setFillColor(OsmMapPolygon view, int color) {
58 | view.setFillColor(color);
59 | }
60 |
61 | @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color")
62 | public void setStrokeColor(OsmMapPolygon view, int color) {
63 | view.setStrokeColor(color);
64 | }
65 |
66 |
67 | @Override
68 | @Nullable
69 | public Map getExportedCustomDirectEventTypeConstants() {
70 | return MapBuilder.of(
71 | "onPress", MapBuilder.of("registrationName", "onPress")
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapPolyline.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 |
5 | import com.facebook.react.bridge.ReadableArray;
6 | import com.facebook.react.bridge.ReadableMap;
7 |
8 | import org.osmdroid.util.GeoPoint;
9 | import org.osmdroid.views.MapView;
10 | import org.osmdroid.views.overlay.Polyline;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class OsmMapPolyline extends OsmMapFeature {
16 |
17 | private Polyline polyline;
18 |
19 | private List coordinates;
20 | private int color;
21 | private float width;
22 | private boolean geodesic;
23 | // private float zIndex;
24 | private MapView mapView;
25 |
26 | public OsmMapPolyline(Context context) {
27 | super(context);
28 | }
29 |
30 | public void setCoordinates(ReadableArray coordinates) {
31 | this.coordinates = new ArrayList<>(coordinates.size());
32 | for (int i = 0; i < coordinates.size(); i++) {
33 | ReadableMap coordinate = coordinates.getMap(i);
34 | this.coordinates.add(i,
35 | new GeoPoint(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")));
36 | }
37 | if (polyline != null) {
38 | polyline.setPoints(this.coordinates);
39 | mapView.invalidate();
40 | }
41 | }
42 |
43 | public void setColor(int color) {
44 | this.color = color;
45 | if (polyline != null) {
46 | polyline.getOutlinePaint().setColor(color);
47 | mapView.invalidate();
48 | }
49 | }
50 |
51 | public void setWidth(float width) {
52 | this.width = width;
53 | if (polyline != null) {
54 | polyline.getOutlinePaint().setStrokeWidth(width);
55 | mapView.invalidate();
56 | }
57 | }
58 |
59 | public void setGeodesic(boolean geodesic) {
60 | this.geodesic = geodesic;
61 | if (polyline != null) {
62 | polyline.setGeodesic(geodesic);
63 | mapView.invalidate();
64 | }
65 | }
66 |
67 | @Override
68 | public Object getFeature() {
69 | return polyline;
70 | }
71 |
72 | @Override
73 | public void addToMap(MapView map) {
74 | polyline = new Polyline();
75 | mapView = map;
76 | polyline.setPoints(coordinates);
77 | polyline.getOutlinePaint().setColor(color);
78 | polyline.getOutlinePaint().setStrokeWidth(width);
79 | polyline.setGeodesic(geodesic);
80 | mapView.getOverlayManager().add(polyline);
81 | mapView.invalidate();
82 | }
83 |
84 | @Override
85 | public void removeFromMap(MapView map) {
86 | map.getOverlays().remove(polyline);
87 | polyline = null;
88 | mapView = null;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapPolylineManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Build;
6 | import android.util.DisplayMetrics;
7 | import android.view.WindowManager;
8 |
9 | import com.facebook.react.bridge.ReactApplicationContext;
10 | import com.facebook.react.bridge.ReadableArray;
11 | import com.facebook.react.common.MapBuilder;
12 | import com.facebook.react.uimanager.ThemedReactContext;
13 | import com.facebook.react.uimanager.ViewGroupManager;
14 | import com.facebook.react.uimanager.annotations.ReactProp;
15 |
16 | import java.util.Map;
17 |
18 | import javax.annotation.Nullable;
19 |
20 | public class OsmMapPolylineManager extends ViewGroupManager {
21 | private final DisplayMetrics metrics;
22 |
23 | public OsmMapPolylineManager(ReactApplicationContext reactContext) {
24 | super();
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
26 | metrics = new DisplayMetrics();
27 | ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE))
28 | .getDefaultDisplay()
29 | .getRealMetrics(metrics);
30 | } else {
31 | metrics = reactContext.getResources().getDisplayMetrics();
32 | }
33 | }
34 |
35 | @Override
36 | public String getName() {
37 | return "OsmMapPolyline";
38 | }
39 |
40 | @Override
41 | public OsmMapPolyline createViewInstance(ThemedReactContext context) {
42 | return new OsmMapPolyline(context);
43 | }
44 |
45 | @ReactProp(name = "coordinates")
46 | public void setCoordinate(OsmMapPolyline view, ReadableArray coordinates) {
47 | view.setCoordinates(coordinates);
48 | }
49 |
50 | @ReactProp(name = "strokeWidth", defaultFloat = 1f)
51 | public void setStrokeWidth(OsmMapPolyline view, float widthInPoints) {
52 | float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS
53 | view.setWidth(widthInScreenPx);
54 | }
55 |
56 | @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color")
57 | public void setStrokeColor(OsmMapPolyline view, int color) {
58 | view.setColor(color);
59 | }
60 |
61 | @ReactProp(name = "geodesic", defaultBoolean = false)
62 | public void setGeodesic(OsmMapPolyline view, boolean geodesic) {
63 | view.setGeodesic(geodesic);
64 | }
65 |
66 |
67 | @Override
68 | @Nullable
69 | public Map getExportedCustomDirectEventTypeConstants() {
70 | return MapBuilder.of(
71 | "onPress", MapBuilder.of("registrationName", "onPress")
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapUrlTile.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 |
7 | import org.osmdroid.tileprovider.tilesource.ITileSource;
8 | import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
9 | import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
10 | import org.osmdroid.util.MapTileIndex;
11 | import org.osmdroid.views.MapView;
12 |
13 |
14 | public class OsmMapUrlTile extends OsmMapFeature {
15 |
16 |
17 | private String urlTemplate;
18 | private float maximumZ = 100.f;
19 | private float minimumZ = 0;
20 |
21 | public class OsmMapTileSource extends OnlineTileSourceBase {
22 |
23 | public OsmMapTileSource(final String aName, final int aZoomMinLevel,
24 | final int aZoomMaxLevel, final int aTileSizePixels,
25 | final String urlTemplate) {
26 | super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels,
27 | null, new String[]{urlTemplate}, null);
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return name();
33 | }
34 |
35 | @Override
36 | public String getTileURLString(final long pMapTileIndex) {
37 | String url = getBaseUrl()
38 | .replace("{x}", Integer.toString(MapTileIndex.getX(pMapTileIndex)))
39 | .replace("{y}", Integer.toString(MapTileIndex.getY(pMapTileIndex)))
40 | .replace("{z}", Integer.toString(MapTileIndex.getZoom(pMapTileIndex)));
41 |
42 | Log.e("OsmMapTileSource", url);
43 | return url;
44 | }
45 |
46 | @Override
47 | public String getTileRelativeFilenameString(long pMapTileIndex) {
48 | return pathBase()
49 | .replace("{x}", Integer.toString(MapTileIndex.getX(pMapTileIndex)))
50 | .replace("{y}", Integer.toString(MapTileIndex.getY(pMapTileIndex)))
51 | .replace("{z}", Integer.toString(MapTileIndex.getZoom(pMapTileIndex)));
52 | }
53 | }
54 |
55 | public OsmMapUrlTile(Context context) {
56 | super(context);
57 | }
58 |
59 | public void setUrlTemplate(String urlTemplate) {
60 | this.urlTemplate = urlTemplate;
61 | }
62 |
63 | public void setMaximumZ(float maximumZ) {
64 | this.maximumZ = maximumZ;
65 | }
66 |
67 | public void setMinimumZ(float minimumZ) {
68 | this.minimumZ = minimumZ;
69 | }
70 |
71 | @Override
72 | public Object getFeature() {
73 | return this;
74 | }
75 |
76 | @Override
77 | public void addToMap(MapView map) {
78 | final ITileSource tileSource = new OsmMapTileSource("OsmMapTileSource", (int) minimumZ, (int) maximumZ, 256, urlTemplate);
79 | map.setTileSource(tileSource);
80 | }
81 |
82 | @Override
83 | public void removeFromMap(MapView map) {
84 | map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmMapUrlTileManager.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.util.DisplayMetrics;
6 | import android.view.WindowManager;
7 |
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.uimanager.ThemedReactContext;
10 | import com.facebook.react.uimanager.ViewGroupManager;
11 | import com.facebook.react.uimanager.annotations.ReactProp;
12 |
13 | public class OsmMapUrlTileManager extends ViewGroupManager {
14 |
15 | public OsmMapUrlTileManager() {
16 | super();
17 | }
18 |
19 | @Override
20 | public String getName() {
21 | return "OsmMapUrlTile";
22 | }
23 |
24 | @Override
25 | public OsmMapUrlTile createViewInstance(ThemedReactContext context) {
26 | return new OsmMapUrlTile(context);
27 | }
28 |
29 | @ReactProp(name = "urlTemplate")
30 | public void setUrlTemplate(OsmMapUrlTile view, String urlTemplate) {
31 | view.setUrlTemplate(urlTemplate);
32 | }
33 |
34 | @ReactProp(name = "minimumZ", defaultFloat = 0.0f)
35 | public void setMinimumZ(OsmMapUrlTile view, float minimumZ) {
36 | view.setMinimumZ(minimumZ);
37 | }
38 |
39 | @ReactProp(name = "maximumZ", defaultFloat = 100.0f)
40 | public void setMaximumZ(OsmMapUrlTile view, float maximumZ) {
41 | view.setMaximumZ(maximumZ);
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmRegionChangeEvent.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import com.facebook.react.bridge.WritableMap;
4 | import com.facebook.react.bridge.WritableNativeMap;
5 | import com.facebook.react.uimanager.events.Event;
6 | import com.facebook.react.uimanager.events.RCTEventEmitter;
7 | import org.osmdroid.api.IGeoPoint;
8 | import org.osmdroid.util.BoundingBox;
9 |
10 | public class OsmRegionChangeEvent extends Event {
11 | private final BoundingBox bounds;
12 | private final IGeoPoint center;
13 | private final boolean continuous;
14 |
15 | public OsmRegionChangeEvent(int id, BoundingBox bounds, IGeoPoint center, boolean continuous) {
16 | super(id);
17 | this.bounds = bounds;
18 | this.center = center;
19 | this.continuous = continuous;
20 | }
21 |
22 | @Override
23 | public String getEventName() {
24 | return "topChange";
25 | }
26 |
27 | @Override
28 | public boolean canCoalesce() {
29 | return false;
30 | }
31 |
32 | @Override
33 | public void dispatch(RCTEventEmitter rctEventEmitter) {
34 |
35 | WritableMap event = new WritableNativeMap();
36 | event.putBoolean("continuous", continuous);
37 |
38 | WritableMap region = new WritableNativeMap();
39 | region.putDouble("latitude", center.getLatitude());
40 | region.putDouble("longitude", center.getLongitude());
41 | region.putDouble("latitudeDelta", bounds.getLatitudeSpan());
42 | region.putDouble("longitudeDelta", bounds.getLongitudeSpanWithDateLine());
43 | event.putMap("region", region);
44 |
45 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/OsmdroidPackage.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.NativeModule;
5 | import com.facebook.react.bridge.ReactApplicationContext;
6 | import com.facebook.react.uimanager.ViewManager;
7 |
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | public class OsmdroidPackage implements ReactPackage {
12 | @Override
13 | public List createNativeModules(ReactApplicationContext reactContext) {
14 | return Arrays.asList(new OsmMapModule(reactContext));
15 | }
16 |
17 | @Override
18 | public List createViewManagers(ReactApplicationContext reactContext) {
19 | OsmMapCalloutManager osmCalloutManager = new OsmMapCalloutManager();
20 | OsmMapMarkerManager osmMarkerManager = new OsmMapMarkerManager();
21 | OsmMapPolylineManager osmPolylineManager = new OsmMapPolylineManager(reactContext);
22 | OsmMapPolygonManager osmPolygonManager = new OsmMapPolygonManager(reactContext);
23 | OsmMapCircleManager osmMapCircleManager = new OsmMapCircleManager(reactContext);
24 | OsmMapManager osmMapManager = new OsmMapManager(reactContext);
25 | OsmMapUrlTileManager osmUrlTileManager = new OsmMapUrlTileManager();
26 | OsmMapFileTileManager osmMapFileTileManager = new OsmMapFileTileManager();
27 | return Arrays.asList(
28 | osmCalloutManager,
29 | osmMarkerManager,
30 | osmPolylineManager,
31 | osmPolygonManager,
32 | osmMapCircleManager,
33 | osmMapManager,
34 | osmUrlTileManager,
35 | osmMapFileTileManager);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/overlays/InterceptDoubleTapOverlay.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.overlays;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.MotionEvent;
5 |
6 | import org.osmdroid.views.MapView;
7 | import org.osmdroid.views.overlay.Overlay;
8 |
9 | public class InterceptDoubleTapOverlay extends Overlay {
10 |
11 | public InterceptDoubleTapOverlay() {
12 | }
13 |
14 | @Override public void draw(Canvas canvas, MapView mapView, boolean b) {
15 | }
16 |
17 | @Override
18 | public boolean onDoubleTap(MotionEvent e, MapView mapView) {
19 | return isEnabled();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/overlays/InterceptScrollOverlay.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.overlays;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.MotionEvent;
5 |
6 | import org.osmdroid.views.MapView;
7 | import org.osmdroid.views.overlay.Overlay;
8 |
9 | public class InterceptScrollOverlay extends Overlay {
10 |
11 | public InterceptScrollOverlay() {
12 | }
13 |
14 | @Override public void draw(Canvas canvas, MapView mapView, boolean b) {
15 | }
16 |
17 | @Override public boolean onScroll(MotionEvent pEvent1, MotionEvent pEvent2, float pDistanceX,
18 | float pDistanceY, MapView pMapView) {
19 | return isEnabled();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.utils;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.os.AsyncTask;
6 |
7 | import com.facebook.common.logging.FLog;
8 | import com.facebook.react.common.ReactConstants;
9 |
10 | import java.io.File;
11 | import java.io.FileInputStream;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.net.URL;
16 | import java.nio.channels.Channels;
17 | import java.nio.channels.ReadableByteChannel;
18 |
19 | public class FileUtil extends AsyncTask {
20 |
21 | private final String NAME = "FileUtil";
22 | private final String TEMP_FILE_SUFFIX = "temp";
23 |
24 | private Exception exception;
25 | private Context context;
26 |
27 | public FileUtil(Context context) {
28 | super();
29 |
30 | this.context = context;
31 | }
32 |
33 | protected InputStream doInBackground(String... urls) {
34 | try {
35 | Uri fileContentUri = Uri.parse(urls[0]);
36 |
37 | if (fileContentUri.getScheme().startsWith("http")) {
38 | return getDownloadFileInputStream(context, fileContentUri);
39 | }
40 | return context.getContentResolver().openInputStream(fileContentUri);
41 | } catch (Exception e) {
42 | this.exception = e;
43 | FLog.e(
44 | ReactConstants.TAG,
45 | "Could not retrieve file for contentUri " + urls[0],
46 | e);
47 | return null;
48 | }
49 | }
50 |
51 | private InputStream getDownloadFileInputStream(Context context, Uri uri)
52 | throws IOException {
53 | final File outputDir = context.getApplicationContext().getCacheDir();
54 | final File file = File.createTempFile(NAME, TEMP_FILE_SUFFIX, outputDir);
55 | file.deleteOnExit();
56 |
57 | final URL url = new URL(uri.toString());
58 | final InputStream is = url.openStream();
59 | try {
60 | final ReadableByteChannel channel = Channels.newChannel(is);
61 | try {
62 | final FileOutputStream stream = new FileOutputStream(file);
63 | try {
64 | stream.getChannel().transferFrom(channel, 0, Long.MAX_VALUE);
65 | return new FileInputStream(file);
66 | } finally {
67 | stream.close();
68 | }
69 | } finally {
70 | channel.close();
71 | }
72 | } finally {
73 | is.close();
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/ImageReadable.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.utils;
2 |
3 |
4 | import android.graphics.Bitmap;
5 |
6 | public interface ImageReadable {
7 |
8 | public void setIconBitmap(Bitmap bitmap);
9 |
10 | public void update();
11 | }
12 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/ImageReader.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.utils;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.Bitmap;
6 | import android.graphics.drawable.Animatable;
7 | import android.net.Uri;
8 |
9 | import com.facebook.common.references.CloseableReference;
10 | import com.facebook.datasource.DataSource;
11 | import com.facebook.drawee.backends.pipeline.Fresco;
12 | import com.facebook.drawee.controller.BaseControllerListener;
13 | import com.facebook.drawee.controller.ControllerListener;
14 | import com.facebook.drawee.drawable.ScalingUtils;
15 | import com.facebook.drawee.generic.GenericDraweeHierarchy;
16 | import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
17 | import com.facebook.drawee.interfaces.DraweeController;
18 | import com.facebook.drawee.view.DraweeHolder;
19 | import com.facebook.imagepipeline.core.ImagePipeline;
20 | import com.facebook.imagepipeline.image.CloseableImage;
21 | import com.facebook.imagepipeline.image.CloseableStaticBitmap;
22 | import com.facebook.imagepipeline.image.ImageInfo;
23 | import com.facebook.imagepipeline.request.ImageRequest;
24 | import com.facebook.imagepipeline.request.ImageRequestBuilder;
25 |
26 | import javax.annotation.Nullable;
27 |
28 | public class ImageReader {
29 |
30 | private final ImageReadable imp;
31 | private final Context context;
32 | private final Resources resources;
33 |
34 | private final DraweeHolder> logoHolder;
35 | private DataSource> dataSource;
36 |
37 | private final ControllerListener mLogoControllerListener =
38 | new BaseControllerListener() {
39 | @Override
40 | public void onFinalImageSet(
41 | String id,
42 | @Nullable final ImageInfo imageInfo,
43 | @Nullable Animatable animatable) {
44 | CloseableReference imageReference = null;
45 | try {
46 | imageReference = dataSource.getResult();
47 | if (imageReference != null) {
48 | CloseableImage image = imageReference.get();
49 | if (image != null && image instanceof CloseableStaticBitmap) {
50 | CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image;
51 | Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap();
52 | if (bitmap != null) {
53 | bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
54 | imp.setIconBitmap(bitmap);
55 | }
56 | }
57 | }
58 | } finally {
59 | dataSource.close();
60 | if (imageReference != null) {
61 | CloseableReference.closeSafely(imageReference);
62 | }
63 | }
64 | imp.update();
65 | }
66 | };
67 |
68 | public ImageReader(Context context, Resources resources, ImageReadable imp) {
69 | this.context = context;
70 | this.resources = resources;
71 | this.imp = imp;
72 | logoHolder = DraweeHolder.create(createDraweeHeirarchy(resources), context);
73 | logoHolder.onAttach();
74 | }
75 |
76 | private GenericDraweeHierarchy createDraweeHeirarchy(Resources resources){
77 | return new GenericDraweeHierarchyBuilder(resources)
78 | .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
79 | .setFadeDuration(0)
80 | .build();
81 | }
82 |
83 | public void setImage(String uri) {
84 | if (uri == null) {
85 | imp.update();
86 | } else if (uri.startsWith("http://") || uri.startsWith("https://") ||
87 | uri.startsWith("file://") || uri.startsWith("asset://")) {
88 | ImageRequest imageRequest = ImageRequestBuilder
89 | .newBuilderWithSource(Uri.parse(uri))
90 | .build();
91 | ImagePipeline imagePipeline = Fresco.getImagePipeline();
92 | dataSource = imagePipeline.fetchDecodedImage(imageRequest, this);
93 |
94 | DraweeController controller = Fresco.newDraweeControllerBuilder()
95 | .setImageRequest(imageRequest)
96 | .setControllerListener(mLogoControllerListener)
97 | .setOldController(logoHolder.getController())
98 | .build();
99 | logoHolder.setController(controller);
100 | } else {
101 | imp.update();
102 | }
103 |
104 |
105 | }
106 |
107 | private int getDrawableResourceByName(String name) {
108 | return this.resources.getIdentifier(
109 | name,
110 | "drawable",
111 | this.context.getPackageName());
112 | }
113 |
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/ImageUtil.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.utils;
2 |
3 |
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.util.Base64;
7 |
8 | import java.io.ByteArrayOutputStream;
9 |
10 | public class ImageUtil {
11 | public static Bitmap convert(String base64Str) throws IllegalArgumentException {
12 | byte[] decodedBytes = Base64.decode(
13 | base64Str.substring(base64Str.indexOf(",") + 1),
14 | Base64.DEFAULT
15 | );
16 |
17 | return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
18 | }
19 |
20 | public static String convert(Bitmap bitmap) {
21 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
22 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
23 |
24 | return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/LatLngBoundsUtils.java:
--------------------------------------------------------------------------------
1 | package com.osmdroid.utils;
2 |
3 | import org.osmdroid.util.BoundingBox;
4 | import org.osmdroid.util.GeoPoint;
5 |
6 | public class LatLngBoundsUtils {
7 | public static boolean BoundsAreDifferent(BoundingBox a, BoundingBox b) {
8 | GeoPoint centerA = a.getCenterWithDateLine();
9 | double latA = centerA.getLatitude();
10 | double lngA = centerA.getLongitude();
11 | double latDeltaA = a.getLatitudeSpan();
12 | double lngDeltaA = a.getLongitudeSpanWithDateLine();
13 |
14 | GeoPoint centerB = b.getCenterWithDateLine();
15 | double latB = centerB.getLatitude();
16 | double lngB = centerB.getLongitude();
17 | double latDeltaB = b.getLatitudeSpan();
18 | double lngDeltaB = b.getLongitudeSpanWithDateLine();
19 |
20 | double latEps = LatitudeEpsilon(a, b);
21 | double lngEps = LongitudeEpsilon(a, b);
22 |
23 | return
24 | different(latA, latB, latEps) ||
25 | different(lngA, lngB, lngEps) ||
26 | different(latDeltaA, latDeltaB, latEps) ||
27 | different(lngDeltaA, lngDeltaB, lngEps);
28 | }
29 |
30 | private static boolean different(double a, double b, double epsilon) {
31 | return Math.abs(a - b) > epsilon;
32 | }
33 |
34 | private static double LatitudeEpsilon(BoundingBox a, BoundingBox b) {
35 | double sizeA = a.getLatitudeSpan(); // something mod 180?
36 | double sizeB = b.getLatitudeSpan(); // something mod 180?
37 | double size = Math.min(Math.abs(sizeA), Math.abs(sizeB));
38 | return size / 2560;
39 | }
40 |
41 | private static double LongitudeEpsilon(BoundingBox a, BoundingBox b) {
42 | double sizeA = a.getLongitudeSpanWithDateLine();
43 | double sizeB = b.getLongitudeSpanWithDateLine();
44 | double size = Math.min(Math.abs(sizeA), Math.abs(sizeB));
45 | return size / 2560;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/android/src/main/java/com/osmdroid/utils/SizeReportingShadowNode.java:
--------------------------------------------------------------------------------
1 |
2 | package com.osmdroid.utils;
3 |
4 | import com.facebook.react.uimanager.LayoutShadowNode;
5 | import com.facebook.react.uimanager.UIViewOperationQueue;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | // Custom LayoutShadowNode implementation used in conjunction with the AirMapManager
11 | // which sends the width/height of the view after layout occurs.
12 | public class SizeReportingShadowNode extends LayoutShadowNode {
13 |
14 | @Override
15 | public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
16 | super.onCollectExtraUpdates(uiViewOperationQueue);
17 |
18 | Map data = new HashMap<>();
19 | data.put("width", getLayoutWidth());
20 | data.put("height", getLayoutHeight());
21 |
22 | uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/docs/callout.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | |---|---|---|---|
7 | | `tooltip` | `Boolean` | `false` | If `false`, a default "tooltip" bubble window will be drawn around this callouts children. If `true`, the child views can fully customize their appearance, including any "bubble" like styles.
8 |
9 |
10 | ## Events
11 |
12 | | Event Name | Returns | Notes
13 | |---|---|---|
14 | | `onPress` | | Callback that is called when the user presses on the callout
15 |
16 |
17 |
18 | ---
19 |
20 |
--------------------------------------------------------------------------------
/docs/circle.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | |---|---|---|---|
7 | | `center` | `LatLng` | (Required) | The coordinate of the center of the circle
8 | | `radius` | `Number` | (Required) | The radius of the circle to be drawn (in meters)
9 | | `strokeWidth` | `Number` | `1` | The stroke width to use for the path.
10 | | `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path.
11 | | `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path.
12 |
13 |
14 | ## Types
15 |
16 | ```
17 | type LatLng {
18 | latitude: Number,
19 | longitude: Number,
20 | }
21 | ```
22 |
--------------------------------------------------------------------------------
/docs/geojson.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | | --------- | ---- | ------------------------------------------------------ | ---- |
7 | | `geojson` | `GeoJSON` | | [Geojson](https://geojson.org/) description of object. |
8 | | `strokeColor` | `String` | `stroke` property in GeoJson if present else `#000` | The stroke color to use for polygons and polylines. |
9 | | `fillColor` | `String` | `fill` property in GeoJson | The fill color to use for polygons. |
10 | | `strokeWidth` | `Number` | `stroke-width` property in Geojson if present else `1` | The stroke width to use for polygons and polylines. |
11 | | `color` | `String` | `marker-color` property in GeoJson | The color to use for points. |
12 | | `lineDashPhase` | `Number` | | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. |
13 | | `lineDashPattern` | `Array` | | An array of numbers specifying the dash pattern to use for the path. The array contains one or more numbers that indicate the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on. |
14 | | `lineCap` | `'butt' | 'round' | 'square'` | | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. Note: lineCap is not yet supported for GoogleMaps provider on iOS. |
15 | | `lineJoin` | `'miter'| 'round' | 'bevel'` | | The line join style to apply to corners of the path. Possible values are `miter`, `round` or `bevel`. |
16 | | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. |
17 | | `zIndex` | `Number` | | Layer level of the z-index value |
18 | | `onPress` | `Function` | | returns the selected overlay value with the onPress functionality |
19 | | `markerComponent` | `React Node` | | Component to render in place of the default marker when the overlay type is a `point`
20 | | `title` | `string` | | The title of the marker. This is only used if the component has no children that are a ``
21 | | `tracksViewChanges` | `Boolean` | true | Sets whether this marker should track view changes. It's recommended to turn it off whenever it's possible to improve custom marker performance. This is the default value for all point markers in your geojson data. It can be overriden on a per point basis by adding a `trackViewChanges` property to the `properties` object on the point.
22 |
23 | ## Example
24 |
25 | ```
26 | import React from 'react';
27 | import MapView, {Geojson} from 'react-native-maps';
28 |
29 | const myPlace = {
30 | type: 'FeatureCollection',
31 | features: [
32 | {
33 | type: 'Feature',
34 | properties: {},
35 | geometry: {
36 | type: 'Point',
37 | coordinates: [64.165329, 48.844287],
38 | }
39 | }
40 | ]
41 | };
42 |
43 | const Map = props => (
44 |
45 |
51 |
52 | );
53 | ```
54 |
--------------------------------------------------------------------------------
/docs/marker.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | |---|---|---|---|
7 | | `title` | `String` | | The title of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided.
8 | | `description` | `String` | | The description of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided.
9 | | `image` | `ImageSource`* | | A custom image to be used as the marker's icon. Only local image resources are allowed to be used.
10 | | `icon` | `ImageSource`* | | Marker icon to render. Only local image resources are allowed to be used.
11 | | `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used.
For Android, the set of available colors is limited. Unsupported colors will fall back to red.
12 | | `coordinate` | `LatLng` | | The coordinate for the marker.
13 | | `calloutOffset` | `Point` | (0, 0) | The offset (in points) at which to place the callout bubble.
This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.
For Google Maps, see the `calloutAnchor` prop.
14 | | `anchor` | `Point` | (0.5, 1) | Sets the anchor point for the marker.
The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.
The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).
For MapKit on iOS, see the `centerOffset` prop.
15 | | `calloutAnchor` | `Point` | (0.5, 0) | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.
The default is the top middle of the image.
16 | | `flat` | `Boolean` | false | Sets whether this marker should be flat against the map true or a billboard facing the camera.
17 | | `identifier` | `String` | | An identifier used to reference this marker at a later date.
18 | | `rotation` | `Float` | 0 | A float number indicating marker's rotation angle, in degrees.
19 | | `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned).
20 | | `tracksViewChanges` | `Boolean` | true | Sets whether this marker should track view changes. It's recommended to turn it off whenever it's possible to improve custom marker performance.
21 | | `tracksInfoWindowChanges` | `Boolean` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only.
22 | | `opacity` | `Float` | 1.0 | The marker's opacity between 0.0 and 1.0.
23 |
24 | \* `ImageSource` [docs](https://reactnative.dev/docs/image#imagesource)
25 |
26 | ## Events
27 |
28 | To access event data, you will need to use `e.nativeEvent`. For example, `onPress={e => console.log(e.nativeEvent)}` will log the entire event object to your console.
29 |
30 | | Event Name | Returns | Notes
31 | |---|---|---|
32 | | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the user presses on the marker
33 | | `onSelect` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the user selects the marker, before the callout is shown. **Note**: iOS only.
34 | | `onDeselect` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the marker is deselected, before the callout is hidden. **Note**: iOS only.
35 | | `onCalloutPress` | | Callback that is called when the user taps the callout view.
36 | | `onDragStart` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the user initiates a drag on this marker (if it is draggable)
37 | | `onDrag` | `{ coordinate: LatLng, position: Point }` | Callback called continuously as the marker is dragged
38 | | `onDragEnd` | `{ coordinate: LatLng, position: Point }` | Callback that is called when a drag on this marker finishes. This is usually the point you will want to setState on the marker's coordinate again
39 |
40 |
41 | ## Methods
42 |
43 | | Method Name | Arguments | Notes
44 | |---|---|---|
45 | | `showCallout` | | Shows the callout for this marker
46 | | `hideCallout` | | Hides the callout for this marker
47 | | `animateMarkerToCoordinate` | `coordinate: LatLng, duration: number` | Animates marker movement.
48 | | `redraw` | | Causes a redraw of the marker. Useful when there are updates to the marker and `tracksViewChanges` comes with a cost that is too high.
49 |
50 |
51 |
52 | ## Types
53 |
54 | ```
55 | type LatLng {
56 | latitude: Number,
57 | longitude: Number,
58 | }
59 | ```
60 |
61 | ```
62 | type Point {
63 | x: Number,
64 | y: Number,
65 | }
66 | ```
67 |
68 | ## Children Components
69 |
70 | Children components can be added within a Marker and rendered content will replace the marker symbol. This is a way of creating custom markers and allowing use of native SVGs.
71 |
72 | Example:
73 | ```
74 |
75 |
76 | SF
77 |
78 |
79 | ```
80 |
--------------------------------------------------------------------------------
/docs/polygon.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | |---|---|---|---|
7 | | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polygon
8 | | `holes` | `Array>` | | A 2d array of coordinates to describe holes of the polygon where each hole has at least 3 points.
9 | | `strokeWidth` | `Number` | `1` | The stroke width to use for the path.
10 | | `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path.
11 | | `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path.
12 | | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere.
13 | | `tappable` | `Bool` | `false` | Boolean to allow a polygon to be tappable and use the onPress function.
14 |
15 | ## Events
16 |
17 | | Event Name | Returns | Notes
18 | |---|---|---|
19 | | `onPress` | | Callback that is called when the user presses on the polygon
20 |
21 | ## Types
22 |
23 | ```
24 | type LatLng {
25 | latitude: Number,
26 | longitude: Number,
27 | }
28 | ```
29 |
--------------------------------------------------------------------------------
/docs/polyline.md:
--------------------------------------------------------------------------------
1 | # `` Component API
2 |
3 | ## Props
4 |
5 | | Prop | Type | Default | Note |
6 | |---|---|---|---|
7 | | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polyline
8 | | `strokeWidth` | `Number` | `1` | The stroke width to use for the path.
9 | | `strokeColor` | `String` | `#000, rgba(r,g,b,0.5)` | The stroke color to use for the path.
10 | | `strokeColors` | `Array` | `null` | The stroke colors to use for the path (iOS only). Must be the same length as `coordinates`.
11 | | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. Note: lineCap is not yet supported for GoogleMaps provider on iOS.
12 | | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere.
13 | | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap.
14 | | `lineDashPattern` | `Array` | `null` | An array of numbers specifying the dash pattern to use for the path. The array contains one or more numbers that indicate the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on.
15 | | `tappable` | `Bool` | false | Boolean to allow a polyline to be tappable and use the onPress function.
16 |
17 | ## Events
18 |
19 | | Event Name | Returns | Notes
20 | |---|---|---|
21 | | `onPress` | | Callback that is called when the user presses on the polyline
22 |
23 | ## Types
24 |
25 | ```
26 | type LatLng {
27 | latitude: Number,
28 | longitude: Number,
29 | }
30 | ```
31 |
32 | ## Gradient Polylines (iOS MapKit only)
33 |
34 | Gradient polylines can be created by using the `strokeColors` prop. `strokeColors` must be an array with the same number of elements as `coordinates`.
35 |
36 | Example:
37 |
38 | ```js
39 | import MapView, { Polyline } from 'react-native-maps';
40 |
41 |
42 |
62 |
63 | ```
64 |
--------------------------------------------------------------------------------
/example/.bundle/config:
--------------------------------------------------------------------------------
1 | BUNDLE_PATH: "vendor/bundle"
2 | BUNDLE_FORCE_RUBY_PLATFORM: 1
3 |
--------------------------------------------------------------------------------
/example/.node-version:
--------------------------------------------------------------------------------
1 | 16
2 |
--------------------------------------------------------------------------------
/example/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.5
2 |
--------------------------------------------------------------------------------
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
4 | ruby '2.7.5'
5 |
6 | gem 'cocoapods', '~> 1.11', '>= 1.11.2'
7 |
--------------------------------------------------------------------------------
/example/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.osmdroidexample",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.osmdroidexample",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/example/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/osmdroidexample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | *
This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.osmdroidexample;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceEventListener;
23 | import com.facebook.react.ReactInstanceManager;
24 | import com.facebook.react.bridge.ReactContext;
25 | import com.facebook.react.modules.network.NetworkingModule;
26 | import okhttp3.OkHttpClient;
27 |
28 | public class ReactNativeFlipper {
29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
30 | if (FlipperUtils.shouldEnableFlipper(context)) {
31 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
32 |
33 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
34 | client.addPlugin(new ReactFlipperPlugin());
35 | client.addPlugin(new DatabasesFlipperPlugin(context));
36 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
37 | client.addPlugin(CrashReporterPlugin.getInstance());
38 |
39 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
40 | NetworkingModule.setCustomClientBuilder(
41 | new NetworkingModule.CustomClientBuilder() {
42 | @Override
43 | public void apply(OkHttpClient.Builder builder) {
44 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
45 | }
46 | });
47 | client.addPlugin(networkFlipperPlugin);
48 | client.start();
49 |
50 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
51 | // Hence we run if after all native modules have been initialized
52 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
53 | if (reactContext == null) {
54 | reactInstanceManager.addReactInstanceEventListener(
55 | new ReactInstanceEventListener() {
56 | @Override
57 | public void onReactContextInitialized(ReactContext reactContext) {
58 | reactInstanceManager.removeReactInstanceEventListener(this);
59 | reactContext.runOnNativeModulesQueueThread(
60 | new Runnable() {
61 | @Override
62 | public void run() {
63 | client.addPlugin(new FrescoFlipperPlugin());
64 | }
65 | });
66 | }
67 | });
68 | } else {
69 | client.addPlugin(new FrescoFlipperPlugin());
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/osmdroidexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.osmdroidexample;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 |
7 | public class MainActivity extends ReactActivity {
8 |
9 | /**
10 | * Returns the name of the main component registered from JavaScript. This is used to schedule
11 | * rendering of the component.
12 | */
13 | @Override
14 | protected String getMainComponentName() {
15 | return "OsmdroidExample";
16 | }
17 |
18 | /**
19 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
20 | * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
21 | * (Paper).
22 | */
23 | @Override
24 | protected ReactActivityDelegate createReactActivityDelegate() {
25 | return new MainActivityDelegate(this, getMainComponentName());
26 | }
27 |
28 | public static class MainActivityDelegate extends ReactActivityDelegate {
29 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
30 | super(activity, mainComponentName);
31 | }
32 |
33 | @Override
34 | protected ReactRootView createRootView() {
35 | ReactRootView reactRootView = new ReactRootView(getContext());
36 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
37 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
38 | return reactRootView;
39 | }
40 |
41 | @Override
42 | protected boolean isConcurrentRootEnabled() {
43 | // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
44 | // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
45 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/osmdroidexample/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.osmdroidexample;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.config.ReactFeatureFlags;
11 | import com.facebook.soloader.SoLoader;
12 | import com.osmdroidexample.newarchitecture.MainApplicationReactNativeHost;
13 | import java.lang.reflect.InvocationTargetException;
14 | import java.util.List;
15 |
16 | public class MainApplication extends Application implements ReactApplication {
17 |
18 | private final ReactNativeHost mReactNativeHost =
19 | new ReactNativeHost(this) {
20 | @Override
21 | public boolean getUseDeveloperSupport() {
22 | return BuildConfig.DEBUG;
23 | }
24 |
25 | @Override
26 | protected List getPackages() {
27 | @SuppressWarnings("UnnecessaryLocalVariable")
28 | List packages = new PackageList(this).getPackages();
29 | // Packages that cannot be autolinked yet can be added manually here, for example:
30 | // packages.add(new MyReactNativePackage());
31 | return packages;
32 | }
33 |
34 | @Override
35 | protected String getJSMainModuleName() {
36 | return "index";
37 | }
38 | };
39 |
40 | private final ReactNativeHost mNewArchitectureNativeHost =
41 | new MainApplicationReactNativeHost(this);
42 |
43 | @Override
44 | public ReactNativeHost getReactNativeHost() {
45 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
46 | return mNewArchitectureNativeHost;
47 | } else {
48 | return mReactNativeHost;
49 | }
50 | }
51 |
52 | @Override
53 | public void onCreate() {
54 | super.onCreate();
55 | // If you opted-in for the New Architecture, we enable the TurboModule system
56 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
57 | SoLoader.init(this, /* native exopackage */ false);
58 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
59 | }
60 |
61 | /**
62 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
63 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
64 | *
65 | * @param context
66 | * @param reactInstanceManager
67 | */
68 | private static void initializeFlipper(
69 | Context context, ReactInstanceManager reactInstanceManager) {
70 | if (BuildConfig.DEBUG) {
71 | try {
72 | /*
73 | We use reflection here to pick up the class that initializes Flipper,
74 | since Flipper library is not available in release mode
75 | */
76 | Class> aClass = Class.forName("com.osmdroidexample.ReactNativeFlipper");
77 | aClass
78 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
79 | .invoke(null, context, reactInstanceManager);
80 | } catch (ClassNotFoundException e) {
81 | e.printStackTrace();
82 | } catch (NoSuchMethodException e) {
83 | e.printStackTrace();
84 | } catch (IllegalAccessException e) {
85 | e.printStackTrace();
86 | } catch (InvocationTargetException e) {
87 | e.printStackTrace();
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/osmdroidexample/newarchitecture/MainApplicationReactNativeHost.java:
--------------------------------------------------------------------------------
1 | package com.osmdroidexample.newarchitecture;
2 |
3 | import android.app.Application;
4 | import androidx.annotation.NonNull;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactInstanceManager;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
10 | import com.facebook.react.bridge.JSIModulePackage;
11 | import com.facebook.react.bridge.JSIModuleProvider;
12 | import com.facebook.react.bridge.JSIModuleSpec;
13 | import com.facebook.react.bridge.JSIModuleType;
14 | import com.facebook.react.bridge.JavaScriptContextHolder;
15 | import com.facebook.react.bridge.ReactApplicationContext;
16 | import com.facebook.react.bridge.UIManager;
17 | import com.facebook.react.fabric.ComponentFactory;
18 | import com.facebook.react.fabric.CoreComponentsRegistry;
19 | import com.facebook.react.fabric.FabricJSIModuleProvider;
20 | import com.facebook.react.fabric.ReactNativeConfig;
21 | import com.facebook.react.uimanager.ViewManagerRegistry;
22 | import com.osmdroidexample.BuildConfig;
23 | import com.osmdroidexample.newarchitecture.components.MainComponentsRegistry;
24 | import com.osmdroidexample.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | /**
29 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
30 | * TurboModule delegates and the Fabric Renderer.
31 | *
32 | *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
33 | * `newArchEnabled` property). Is ignored otherwise.
34 | */
35 | public class MainApplicationReactNativeHost extends ReactNativeHost {
36 | public MainApplicationReactNativeHost(Application application) {
37 | super(application);
38 | }
39 |
40 | @Override
41 | public boolean getUseDeveloperSupport() {
42 | return BuildConfig.DEBUG;
43 | }
44 |
45 | @Override
46 | protected List getPackages() {
47 | List packages = new PackageList(this).getPackages();
48 | // Packages that cannot be autolinked yet can be added manually here, for example:
49 | // packages.add(new MyReactNativePackage());
50 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
51 | // packages.add(new TurboReactPackage() { ... });
52 | // If you have custom Fabric Components, their ViewManagers should also be loaded here
53 | // inside a ReactPackage.
54 | return packages;
55 | }
56 |
57 | @Override
58 | protected String getJSMainModuleName() {
59 | return "index";
60 | }
61 |
62 | @NonNull
63 | @Override
64 | protected ReactPackageTurboModuleManagerDelegate.Builder
65 | getReactPackageTurboModuleManagerDelegateBuilder() {
66 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
67 | // for the new architecture and to use TurboModules correctly.
68 | return new MainApplicationTurboModuleManagerDelegate.Builder();
69 | }
70 |
71 | @Override
72 | protected JSIModulePackage getJSIModulePackage() {
73 | return new JSIModulePackage() {
74 | @Override
75 | public List getJSIModules(
76 | final ReactApplicationContext reactApplicationContext,
77 | final JavaScriptContextHolder jsContext) {
78 | final List specs = new ArrayList<>();
79 |
80 | // Here we provide a new JSIModuleSpec that will be responsible of providing the
81 | // custom Fabric Components.
82 | specs.add(
83 | new JSIModuleSpec() {
84 | @Override
85 | public JSIModuleType getJSIModuleType() {
86 | return JSIModuleType.UIManager;
87 | }
88 |
89 | @Override
90 | public JSIModuleProvider getJSIModuleProvider() {
91 | final ComponentFactory componentFactory = new ComponentFactory();
92 | CoreComponentsRegistry.register(componentFactory);
93 |
94 | // Here we register a Components Registry.
95 | // The one that is generated with the template contains no components
96 | // and just provides you the one from React Native core.
97 | MainComponentsRegistry.register(componentFactory);
98 |
99 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
100 |
101 | ViewManagerRegistry viewManagerRegistry =
102 | new ViewManagerRegistry(
103 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
104 |
105 | return new FabricJSIModuleProvider(
106 | reactApplicationContext,
107 | componentFactory,
108 | ReactNativeConfig.DEFAULT_CONFIG,
109 | viewManagerRegistry);
110 | }
111 | });
112 | return specs;
113 | }
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/osmdroidexample/newarchitecture/components/MainComponentsRegistry.java:
--------------------------------------------------------------------------------
1 | package com.osmdroidexample.newarchitecture.components;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.proguard.annotations.DoNotStrip;
5 | import com.facebook.react.fabric.ComponentFactory;
6 | import com.facebook.soloader.SoLoader;
7 |
8 | /**
9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a
10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
11 | * folder for you).
12 | *
13 | *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
14 | * `newArchEnabled` property). Is ignored otherwise.
15 | */
16 | @DoNotStrip
17 | public class MainComponentsRegistry {
18 | static {
19 | SoLoader.loadLibrary("fabricjni");
20 | }
21 |
22 | @DoNotStrip private final HybridData mHybridData;
23 |
24 | @DoNotStrip
25 | private native HybridData initHybrid(ComponentFactory componentFactory);
26 |
27 | @DoNotStrip
28 | private MainComponentsRegistry(ComponentFactory componentFactory) {
29 | mHybridData = initHybrid(componentFactory);
30 | }
31 |
32 | @DoNotStrip
33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) {
34 | return new MainComponentsRegistry(componentFactory);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/osmdroidexample/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java:
--------------------------------------------------------------------------------
1 | package com.osmdroidexample.newarchitecture.modules;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.soloader.SoLoader;
8 | import java.util.List;
9 |
10 | /**
11 | * Class responsible to load the TurboModules. This class has native methods and needs a
12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
13 | * folder for you).
14 | *
15 | *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
16 | * `newArchEnabled` property). Is ignored otherwise.
17 | */
18 | public class MainApplicationTurboModuleManagerDelegate
19 | extends ReactPackageTurboModuleManagerDelegate {
20 |
21 | private static volatile boolean sIsSoLibraryLoaded;
22 |
23 | protected MainApplicationTurboModuleManagerDelegate(
24 | ReactApplicationContext reactApplicationContext, List packages) {
25 | super(reactApplicationContext, packages);
26 | }
27 |
28 | protected native HybridData initHybrid();
29 |
30 | native boolean canCreateTurboModule(String moduleName);
31 |
32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
33 | protected MainApplicationTurboModuleManagerDelegate build(
34 | ReactApplicationContext context, List packages) {
35 | return new MainApplicationTurboModuleManagerDelegate(context, packages);
36 | }
37 | }
38 |
39 | @Override
40 | protected synchronized void maybeLoadOtherSoLibraries() {
41 | if (!sIsSoLibraryLoaded) {
42 | // If you change the name of your application .so file in the Android.mk file,
43 | // make sure you update the name here as well.
44 | SoLoader.loadLibrary("osmdroidexample_appmodules");
45 | sIsSoLibraryLoaded = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 |
3 | # Define the library name here.
4 | project(osmdroidexample_appmodules)
5 |
6 | # This file includes all the necessary to let you build your application with the New Architecture.
7 | include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainApplicationModuleProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "MainApplicationModuleProvider.h"
2 |
3 | #include
4 | #include
5 |
6 | namespace facebook {
7 | namespace react {
8 |
9 | std::shared_ptr MainApplicationModuleProvider(
10 | const std::string &moduleName,
11 | const JavaTurboModule::InitParams ¶ms) {
12 | // Here you can provide your own module provider for TurboModules coming from
13 | // either your application or from external libraries. The approach to follow
14 | // is similar to the following (for a library called `samplelibrary`:
15 | //
16 | // auto module = samplelibrary_ModuleProvider(moduleName, params);
17 | // if (module != nullptr) {
18 | // return module;
19 | // }
20 | // return rncore_ModuleProvider(moduleName, params);
21 |
22 | // Module providers autolinked by RN CLI
23 | auto rncli_module = rncli_ModuleProvider(moduleName, params);
24 | if (rncli_module != nullptr) {
25 | return rncli_module;
26 | }
27 |
28 | return rncore_ModuleProvider(moduleName, params);
29 | }
30 |
31 | } // namespace react
32 | } // namespace facebook
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainApplicationModuleProvider.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | namespace facebook {
9 | namespace react {
10 |
11 | std::shared_ptr MainApplicationModuleProvider(
12 | const std::string &moduleName,
13 | const JavaTurboModule::InitParams ¶ms);
14 |
15 | } // namespace react
16 | } // namespace facebook
17 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp:
--------------------------------------------------------------------------------
1 | #include "MainApplicationTurboModuleManagerDelegate.h"
2 | #include "MainApplicationModuleProvider.h"
3 |
4 | namespace facebook {
5 | namespace react {
6 |
7 | jni::local_ref
8 | MainApplicationTurboModuleManagerDelegate::initHybrid(
9 | jni::alias_ref) {
10 | return makeCxxInstance();
11 | }
12 |
13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() {
14 | registerHybrid({
15 | makeNativeMethod(
16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
17 | makeNativeMethod(
18 | "canCreateTurboModule",
19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
20 | });
21 | }
22 |
23 | std::shared_ptr
24 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
25 | const std::string &name,
26 | const std::shared_ptr &jsInvoker) {
27 | // Not implemented yet: provide pure-C++ NativeModules here.
28 | return nullptr;
29 | }
30 |
31 | std::shared_ptr
32 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
33 | const std::string &name,
34 | const JavaTurboModule::InitParams ¶ms) {
35 | return MainApplicationModuleProvider(name, params);
36 | }
37 |
38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
39 | const std::string &name) {
40 | return getTurboModule(name, nullptr) != nullptr ||
41 | getTurboModule(name, {.moduleName = name}) != nullptr;
42 | }
43 |
44 | } // namespace react
45 | } // namespace facebook
46 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 | #include
6 |
7 | namespace facebook {
8 | namespace react {
9 |
10 | class MainApplicationTurboModuleManagerDelegate
11 | : public jni::HybridClass<
12 | MainApplicationTurboModuleManagerDelegate,
13 | TurboModuleManagerDelegate> {
14 | public:
15 | // Adapt it to the package you used for your Java class.
16 | static constexpr auto kJavaDescriptor =
17 | "Lcom/osmdroidexample/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
18 |
19 | static jni::local_ref initHybrid(jni::alias_ref);
20 |
21 | static void registerNatives();
22 |
23 | std::shared_ptr getTurboModule(
24 | const std::string &name,
25 | const std::shared_ptr &jsInvoker) override;
26 | std::shared_ptr getTurboModule(
27 | const std::string &name,
28 | const JavaTurboModule::InitParams ¶ms) override;
29 |
30 | /**
31 | * Test-only method. Allows user to verify whether a TurboModule can be
32 | * created by instances of this class.
33 | */
34 | bool canCreateTurboModule(const std::string &name);
35 | };
36 |
37 | } // namespace react
38 | } // namespace facebook
39 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainComponentsRegistry.cpp:
--------------------------------------------------------------------------------
1 | #include "MainComponentsRegistry.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace facebook {
10 | namespace react {
11 |
12 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
13 |
14 | std::shared_ptr
15 | MainComponentsRegistry::sharedProviderRegistry() {
16 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
17 |
18 | // Autolinked providers registered by RN CLI
19 | rncli_registerProviders(providerRegistry);
20 |
21 | // Custom Fabric Components go here. You can register custom
22 | // components coming from your App or from 3rd party libraries here.
23 | //
24 | // providerRegistry->add(concreteComponentDescriptorProvider<
25 | // AocViewerComponentDescriptor>());
26 | return providerRegistry;
27 | }
28 |
29 | jni::local_ref
30 | MainComponentsRegistry::initHybrid(
31 | jni::alias_ref,
32 | ComponentFactory *delegate) {
33 | auto instance = makeCxxInstance(delegate);
34 |
35 | auto buildRegistryFunction =
36 | [](EventDispatcher::Weak const &eventDispatcher,
37 | ContextContainer::Shared const &contextContainer)
38 | -> ComponentDescriptorRegistry::Shared {
39 | auto registry = MainComponentsRegistry::sharedProviderRegistry()
40 | ->createComponentDescriptorRegistry(
41 | {eventDispatcher, contextContainer});
42 |
43 | auto mutableRegistry =
44 | std::const_pointer_cast(registry);
45 |
46 | mutableRegistry->setFallbackComponentDescriptor(
47 | std::make_shared(
48 | ComponentDescriptorParameters{
49 | eventDispatcher, contextContainer, nullptr}));
50 |
51 | return registry;
52 | };
53 |
54 | delegate->buildRegistryFunction = buildRegistryFunction;
55 | return instance;
56 | }
57 |
58 | void MainComponentsRegistry::registerNatives() {
59 | registerHybrid({
60 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
61 | });
62 | }
63 |
64 | } // namespace react
65 | } // namespace facebook
66 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/MainComponentsRegistry.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace facebook {
9 | namespace react {
10 |
11 | class MainComponentsRegistry
12 | : public facebook::jni::HybridClass {
13 | public:
14 | // Adapt it to the package you used for your Java class.
15 | constexpr static auto kJavaDescriptor =
16 | "Lcom/osmdroidexample/newarchitecture/components/MainComponentsRegistry;";
17 |
18 | static void registerNatives();
19 |
20 | MainComponentsRegistry(ComponentFactory *delegate);
21 |
22 | private:
23 | static std::shared_ptr
24 | sharedProviderRegistry();
25 |
26 | static jni::local_ref initHybrid(
27 | jni::alias_ref,
28 | ComponentFactory *delegate);
29 | };
30 |
31 | } // namespace react
32 | } // namespace facebook
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/jni/OnLoad.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "MainApplicationTurboModuleManagerDelegate.h"
3 | #include "MainComponentsRegistry.h"
4 |
5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
6 | return facebook::jni::initialize(vm, [] {
7 | facebook::react::MainApplicationTurboModuleManagerDelegate::
8 | registerNatives();
9 | facebook::react::MainComponentsRegistry::registerNatives();
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | OsmdroidExample
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "31.0.0"
6 | minSdkVersion = 21
7 | compileSdkVersion = 31
8 | targetSdkVersion = 31
9 |
10 | if (System.properties['os.arch'] == "aarch64") {
11 | // For M1 Users we need to use the NDK 24 which added support for aarch64
12 | ndkVersion = "24.0.8215888"
13 | } else {
14 | // Otherwise we default to the side-by-side NDK version from AGP.
15 | ndkVersion = "21.4.7075529"
16 | }
17 | }
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | dependencies {
23 | classpath("com.android.tools.build:gradle:7.2.1")
24 | classpath("com.facebook.react:react-native-gradle-plugin")
25 | classpath("de.undercouch:gradle-download-task:5.0.1")
26 | // NOTE: Do not place your application dependencies here; they belong
27 | // in the individual module build.gradle files
28 | }
29 | }
30 |
31 | allprojects {
32 | repositories {
33 | maven {
34 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
35 | url("$rootDir/../node_modules/react-native/android")
36 | }
37 | maven {
38 | // Android JSC is installed from npm
39 | url("$rootDir/../node_modules/jsc-android/dist")
40 | }
41 | mavenCentral {
42 | // We don't want to fetch react-native from Maven Central as there are
43 | // older versions over there.
44 | content {
45 | excludeGroup "com.facebook.react"
46 | }
47 | }
48 | google()
49 | maven { url 'https://www.jitpack.io' }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.174.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'OsmdroidExample'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 | includeBuild('../node_modules/react-native-gradle-plugin')
5 |
6 | if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
7 | include(":ReactAndroid")
8 | project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
9 | include(":ReactAndroid:hermes-engine")
10 | project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine')
11 | }
12 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OsmdroidExample",
3 | "displayName": "OsmdroidExample"
4 | }
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const pak = require('../package.json');
3 |
4 | module.exports = {
5 | presets: ['module:metro-react-native-babel-preset'],
6 | plugins: [
7 | [
8 | 'module-resolver',
9 | {
10 | extensions: ['.tsx', '.ts', '.js', '.json'],
11 | alias: {
12 | [pak.name]: path.join(__dirname, '..', pak.source),
13 | },
14 | },
15 | ],
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native';
2 | import App from './src/App';
3 | import { name as appName } from './app.json';
4 |
5 | AppRegistry.registerComponent(appName, () => App);
6 |
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/example/ios/File.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // OsmdroidExample
4 | //
5 |
6 | import Foundation
7 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample.xcodeproj/xcshareddata/xcschemes/OsmdroidExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #import
8 |
9 | #if RCT_NEW_ARCH_ENABLED
10 | #import
11 | #import
12 | #import
13 | #import
14 | #import
15 | #import
16 |
17 | #import
18 |
19 | static NSString *const kRNConcurrentRoot = @"concurrentRoot";
20 |
21 | @interface AppDelegate () {
22 | RCTTurboModuleManager *_turboModuleManager;
23 | RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
24 | std::shared_ptr _reactNativeConfig;
25 | facebook::react::ContextContainer::Shared _contextContainer;
26 | }
27 | @end
28 | #endif
29 |
30 | @implementation AppDelegate
31 |
32 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
33 | {
34 | RCTAppSetupPrepareApp(application);
35 |
36 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
37 |
38 | #if RCT_NEW_ARCH_ENABLED
39 | _contextContainer = std::make_shared();
40 | _reactNativeConfig = std::make_shared();
41 | _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
42 | _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
43 | bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
44 | #endif
45 |
46 | NSDictionary *initProps = [self prepareInitialProps];
47 | UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"OsmdroidExample", initProps);
48 |
49 | if (@available(iOS 13.0, *)) {
50 | rootView.backgroundColor = [UIColor systemBackgroundColor];
51 | } else {
52 | rootView.backgroundColor = [UIColor whiteColor];
53 | }
54 |
55 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
56 | UIViewController *rootViewController = [UIViewController new];
57 | rootViewController.view = rootView;
58 | self.window.rootViewController = rootViewController;
59 | [self.window makeKeyAndVisible];
60 | return YES;
61 | }
62 |
63 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
64 | ///
65 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
66 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
67 | /// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`.
68 | - (BOOL)concurrentRootEnabled
69 | {
70 | // Switch this bool to turn on and off the concurrent root
71 | return true;
72 | }
73 |
74 | - (NSDictionary *)prepareInitialProps
75 | {
76 | NSMutableDictionary *initProps = [NSMutableDictionary new];
77 |
78 | #ifdef RCT_NEW_ARCH_ENABLED
79 | initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
80 | #endif
81 |
82 | return initProps;
83 | }
84 |
85 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
86 | {
87 | #if DEBUG
88 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
89 | #else
90 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
91 | #endif
92 | }
93 |
94 | #if RCT_NEW_ARCH_ENABLED
95 |
96 | #pragma mark - RCTCxxBridgeDelegate
97 |
98 | - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge
99 | {
100 | _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
101 | delegate:self
102 | jsInvoker:bridge.jsCallInvoker];
103 | return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
104 | }
105 |
106 | #pragma mark RCTTurboModuleManagerDelegate
107 |
108 | - (Class)getModuleClassFromName:(const char *)name
109 | {
110 | return RCTCoreModulesClassProvider(name);
111 | }
112 |
113 | - (std::shared_ptr)getTurboModule:(const std::string &)name
114 | jsInvoker:(std::shared_ptr)jsInvoker
115 | {
116 | return nullptr;
117 | }
118 |
119 | - (std::shared_ptr)getTurboModule:(const std::string &)name
120 | initParams:
121 | (const facebook::react::ObjCTurboModule::InitParams &)params
122 | {
123 | return nullptr;
124 | }
125 |
126 | - (id)getModuleInstanceFromClass:(Class)moduleClass
127 | {
128 | return RCTAppSetupDefaultModuleFromClass(moduleClass);
129 | }
130 |
131 | #endif
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | OsmdroidExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UIViewControllerBasedStatusBarAppearance
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExample/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | @autoreleasepool {
8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/OsmdroidExampleTests/OsmdroidExampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface OsmdroidExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation OsmdroidExampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '12.4'
5 | install! 'cocoapods', :deterministic_uuids => false
6 |
7 | target 'OsmdroidExample' do
8 | config = use_native_modules!
9 |
10 | # Flags change depending on the env values.
11 | flags = get_default_flags()
12 |
13 | use_react_native!(
14 | :path => config[:reactNativePath],
15 | # Hermes is now enabled by default. Disable by setting this flag to false.
16 | # Upcoming versions of React Native may rely on get_default_flags(), but
17 | # we make it explicit here to aid in the React Native upgrade process.
18 | :hermes_enabled => true,
19 | :fabric_enabled => flags[:fabric_enabled],
20 | # Enables Flipper.
21 | #
22 | # Note that if you have use_frameworks! enabled, Flipper will not work and
23 | # you should disable the next line.
24 | :flipper_configuration => FlipperConfiguration.enabled,
25 | # An absolute path to your application root.
26 | :app_path => "#{Pod::Config.instance.installation_root}/.."
27 | )
28 |
29 | target 'OsmdroidExampleTests' do
30 | inherit! :complete
31 | # Pods for testing
32 | end
33 |
34 | post_install do |installer|
35 | react_native_post_install(
36 | installer,
37 | # Set `mac_catalyst_enabled` to `true` in order to apply patches
38 | # necessary for Mac Catalyst builds
39 | :mac_catalyst_enabled => false
40 | )
41 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const escape = require('escape-string-regexp');
3 | const exclusionList = require('metro-config/src/defaults/exclusionList');
4 | const pak = require('../package.json');
5 |
6 | const root = path.resolve(__dirname, '..');
7 |
8 | const modules = Object.keys({
9 | ...pak.peerDependencies,
10 | });
11 |
12 | module.exports = {
13 | projectRoot: __dirname,
14 | watchFolders: [root],
15 |
16 | // We need to make sure that only one version is loaded for peerDependencies
17 | // So we block them at the root, and alias them to the versions in example's node_modules
18 | resolver: {
19 | blacklistRE: exclusionList(
20 | modules.map(
21 | (m) =>
22 | new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
23 | )
24 | ),
25 |
26 | extraNodeModules: modules.reduce((acc, name) => {
27 | acc[name] = path.join(__dirname, 'node_modules', name);
28 | return acc;
29 | }, {}),
30 | },
31 |
32 | transformer: {
33 | getTransformOptions: async () => ({
34 | transform: {
35 | experimentalImportSupport: false,
36 | inlineRequires: true,
37 | },
38 | }),
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OsmdroidExample",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "pods": "pod-install --quiet"
10 | },
11 | "dependencies": {
12 | "react": "18.1.0",
13 | "react-native": "0.70.6"
14 | },
15 | "devDependencies": {
16 | "@babel/core": "^7.12.9",
17 | "@babel/runtime": "^7.12.5",
18 | "metro-react-native-babel-preset": "0.72.3",
19 | "babel-plugin-module-resolver": "^4.1.0"
20 | }
21 | }
--------------------------------------------------------------------------------
/example/react-native.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const pak = require('../package.json');
3 |
4 | module.exports = {
5 | dependencies: {
6 | [pak.name]: {
7 | root: path.join(__dirname, '..'),
8 | },
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
4 | import MapView, {
5 | Circle,
6 | Marker,
7 | Polygon,
8 | Polyline,
9 | Region,
10 | UrlTile,
11 | } from '@splicer97/react-native-osmdroid';
12 |
13 | export default function App() {
14 | const initialRegion: Region = {
15 | latitude: 55.75222,
16 | longitude: 37.61556,
17 | latitudeDelta: 0.5,
18 | longitudeDelta: 0.5,
19 | };
20 | const toner =
21 | 'https://api.maptiler.com/maps/toner-v2/{z}/{x}/{y}.png?key=j46yoHMlBMQRgTY3lCMk';
22 | const mapRef = React.useRef();
23 | const zelenograd: Region = {
24 | latitude: 55.9825,
25 | longitude: 37.18139,
26 | latitudeDelta: 0.5,
27 | longitudeDelta: 0.5,
28 | };
29 | const goHome = () => {
30 | mapRef.current?.animateToRegion(zelenograd);
31 | };
32 | return (
33 |
34 | {
39 | console.log('🚀 ~ file: App.tsx:117 ~ App ~ onRegionChange:', event);
40 | }}
41 | onRegionChangeComplete={(event) => {
42 | console.log('🚀 ~ file: App.tsx:117 ~ App ~ onRegionChange:', event);
43 | }}
44 | >
45 |
51 |
52 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem
53 | blanditiis nobis, assumenda ipsam ex cupiditate delectus inventore
54 | labore autem optio eum illo adipisci exercitationem quas incidunt
55 | distinctio! Iure, ex quisquam!
56 |
57 |
58 |
80 |
98 |
107 |
108 |
109 |
121 |
122 | );
123 | }
124 |
125 | const styles = StyleSheet.create({
126 | container: {
127 | ...StyleSheet.absoluteFillObject,
128 | },
129 | });
130 |
--------------------------------------------------------------------------------
/images/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/circle.png
--------------------------------------------------------------------------------
/images/mapView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/mapView.png
--------------------------------------------------------------------------------
/images/marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/marker.png
--------------------------------------------------------------------------------
/images/polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/polygon.png
--------------------------------------------------------------------------------
/images/polyline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/polyline.png
--------------------------------------------------------------------------------
/images/urlTile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Splicer97/react-native-osmdroid/5eceda08c0cbd2b5e14f8f55150274e38500949f/images/urlTile.png
--------------------------------------------------------------------------------
/lefthook.yml:
--------------------------------------------------------------------------------
1 | pre-commit:
2 | parallel: true
3 | commands:
4 | lint:
5 | files: git diff --name-only @{push}
6 | glob: "*.{js,ts,jsx,tsx}"
7 | run: npx eslint {files}
8 | types:
9 | files: git diff --name-only @{push}
10 | glob: "*.{js,ts, jsx, tsx}"
11 | run: npx tsc --noEmit
12 | commit-msg:
13 | parallel: true
14 | commands:
15 | commitlint:
16 | run: npx commitlint --edit
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@splicer97/react-native-osmdroid",
3 | "version": "0.14.1",
4 | "description": "This is unofficial React Native wrapper for osmdroid maps",
5 | "main": "lib/commonjs/index",
6 | "module": "lib/module/index",
7 | "types": "lib/typescript/index.d.ts",
8 | "react-native": "src/index",
9 | "source": "src/index",
10 | "files": [
11 | "src",
12 | "lib",
13 | "android",
14 | "ios",
15 | "cpp",
16 | "*.podspec",
17 | "!lib/typescript/example",
18 | "!ios/build",
19 | "!android/build",
20 | "!android/gradle",
21 | "!android/gradlew",
22 | "!android/gradlew.bat",
23 | "!android/local.properties",
24 | "!**/__tests__",
25 | "!**/__fixtures__",
26 | "!**/__mocks__",
27 | "!**/.*"
28 | ],
29 | "scripts": {
30 | "test": "jest",
31 | "typecheck": "tsc --noEmit",
32 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
33 | "prepack": "bob build",
34 | "release": "release-it",
35 | "example": "yarn --cwd example",
36 | "bootstrap": "yarn example && yarn install && yarn example pods",
37 | "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build"
38 | },
39 | "keywords": [
40 | "react-native",
41 | "react",
42 | "maps",
43 | "osmdroid",
44 | "open-street-maps",
45 | "osm",
46 | "android"
47 | ],
48 | "repository": "https://github.com/Splicer97/react-native-osmdroid",
49 | "author": "Nikita_Kovantsov (https://github.com/Splicer97)",
50 | "license": "MIT",
51 | "bugs": {
52 | "url": "https://github.com/Splicer97/react-native-osmdroid/issues"
53 | },
54 | "homepage": "https://github.com/Splicer97/react-native-osmdroid#readme",
55 | "publishConfig": {
56 | "registry": "https://registry.npmjs.org/"
57 | },
58 | "dependencies": {
59 | "@types/geojson": "^7946.0.10"
60 | },
61 | "devDependencies": {
62 | "@evilmartians/lefthook": "^1.2.2",
63 | "@commitlint/config-conventional": "^17.0.2",
64 | "@react-native-community/eslint-config": "^3.0.2",
65 | "@release-it/conventional-changelog": "^5.0.0",
66 | "@types/jest": "^28.1.2",
67 | "@types/react": "~17.0.21",
68 | "@types/react-native": "0.70.0",
69 | "commitlint": "^17.0.2",
70 | "del-cli": "^5.0.0",
71 | "eslint": "^8.4.1",
72 | "eslint-config-prettier": "^8.5.0",
73 | "eslint-plugin-prettier": "^4.0.0",
74 | "jest": "^28.1.1",
75 | "pod-install": "^0.1.0",
76 | "prettier": "^2.0.5",
77 | "react": "18.1.0",
78 | "react-native": "0.70.6",
79 | "react-native-builder-bob": "^0.20.0",
80 | "release-it": "^15.0.0",
81 | "typescript": "^4.5.2"
82 | },
83 | "resolutions": {
84 | "@types/react": "17.0.21"
85 | },
86 | "peerDependencies": {
87 | "react": "*",
88 | "react-native": "*"
89 | },
90 | "engines": {
91 | "node": ">= 16.0.0"
92 | },
93 | "packageManager": "^yarn@1.22.15",
94 | "jest": {
95 | "preset": "react-native",
96 | "modulePathIgnorePatterns": [
97 | "/example/node_modules",
98 | "/lib/"
99 | ]
100 | },
101 | "commitlint": {
102 | "extends": [
103 | "@commitlint/config-conventional"
104 | ]
105 | },
106 | "release-it": {
107 | "git": {
108 | "commitMessage": "chore: release ${version}",
109 | "tagName": "v${version}"
110 | },
111 | "npm": {
112 | "publish": true
113 | },
114 | "github": {
115 | "release": true
116 | },
117 | "plugins": {
118 | "@release-it/conventional-changelog": {
119 | "preset": "angular"
120 | }
121 | }
122 | },
123 | "eslintConfig": {
124 | "root": true,
125 | "extends": [
126 | "@react-native-community",
127 | "prettier"
128 | ],
129 | "rules": {
130 | "prettier/prettier": [
131 | "error",
132 | {
133 | "quoteProps": "consistent",
134 | "singleQuote": true,
135 | "tabWidth": 2,
136 | "trailingComma": "es5",
137 | "useTabs": false
138 | }
139 | ]
140 | }
141 | },
142 | "eslintIgnore": [
143 | "node_modules/",
144 | "lib/"
145 | ],
146 | "prettier": {
147 | "quoteProps": "consistent",
148 | "singleQuote": true,
149 | "tabWidth": 2,
150 | "trailingComma": "es5",
151 | "useTabs": false
152 | },
153 | "react-native-builder-bob": {
154 | "source": "src",
155 | "output": "lib",
156 | "targets": [
157 | "commonjs",
158 | "module",
159 | [
160 | "typescript",
161 | {
162 | "project": "tsconfig.build.json"
163 | }
164 | ]
165 | ]
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/scripts/bootstrap.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 | const path = require('path');
3 | const child_process = require('child_process');
4 |
5 | const root = path.resolve(__dirname, '..');
6 | const args = process.argv.slice(2);
7 | const options = {
8 | cwd: process.cwd(),
9 | env: process.env,
10 | stdio: 'inherit',
11 | encoding: 'utf-8',
12 | };
13 |
14 | if (os.type() === 'Windows_NT') {
15 | options.shell = true;
16 | }
17 |
18 | let result;
19 |
20 | if (process.cwd() !== root || args.length) {
21 | // We're not in the root of the project, or additional arguments were passed
22 | // In this case, forward the command to `yarn`
23 | result = child_process.spawnSync('yarn', args, options);
24 | } else {
25 | // If `yarn` is run without arguments, perform bootstrap
26 | result = child_process.spawnSync('yarn', ['bootstrap'], options);
27 | }
28 |
29 | process.exitCode = result.status;
30 |
--------------------------------------------------------------------------------
/src/AnimatedRegion.ts:
--------------------------------------------------------------------------------
1 | import { Animated } from 'react-native';
2 | import type { Region } from './sharedTypes';
3 |
4 | const AnimatedWithChildren = Object.getPrototypeOf(Animated.ValueXY);
5 | if (__DEV__) {
6 | if (AnimatedWithChildren.name !== 'AnimatedWithChildren') {
7 | console.error(
8 | 'AnimatedRegion could not obtain AnimatedWithChildren base class'
9 | );
10 | }
11 | }
12 |
13 | const configTypes: (keyof Region)[] = [
14 | 'latitude',
15 | 'longitude',
16 | 'latitudeDelta',
17 | 'longitudeDelta',
18 | ];
19 |
20 | const defaultValues = {
21 | // probably want to come up with better defaults
22 | latitude: 0,
23 | longitude: 0,
24 | latitudeDelta: 0,
25 | longitudeDelta: 0,
26 | };
27 |
28 | let _uniqueId = 1;
29 |
30 | type TValueIn = number | Animated.Value | undefined;
31 |
32 | type Props = Partial | undefined;
33 |
34 | const getAnimatedValue = (valueIn: TValueIn, fallback: number) => {
35 | if (valueIn instanceof Animated.Value) {
36 | return valueIn;
37 | } else if (typeof valueIn === 'number') {
38 | return new Animated.Value(valueIn);
39 | }
40 | return new Animated.Value(fallback);
41 | };
42 |
43 | export default class AnimatedMapRegion extends AnimatedWithChildren {
44 | constructor(valueIn: Props = {}) {
45 | super();
46 | this.latitude = getAnimatedValue(valueIn.latitude, defaultValues.latitude);
47 | this.longitude = getAnimatedValue(
48 | valueIn.longitude,
49 | defaultValues.longitude
50 | );
51 | this.latitudeDelta = getAnimatedValue(
52 | valueIn.latitudeDelta,
53 | defaultValues.latitudeDelta
54 | );
55 | this.longitudeDelta = getAnimatedValue(
56 | valueIn.longitudeDelta,
57 | defaultValues.longitudeDelta
58 | );
59 | this._regionListeners = {};
60 | }
61 |
62 | setValue(value: Region) {
63 | this.latitude._value = value.latitude;
64 | this.longitude._value = value.longitude;
65 | this.latitudeDelta._value = value.latitudeDelta;
66 | this.longitudeDelta._value = value.longitudeDelta;
67 | }
68 |
69 | setOffset(offset: Region) {
70 | this.latitude.setOffset(offset.latitude);
71 | this.longitude.setOffset(offset.longitude);
72 | this.latitudeDelta.setOffset(offset.latitudeDelta);
73 | this.longitudeDelta.setOffset(offset.longitudeDelta);
74 | }
75 |
76 | flattenOffset() {
77 | this.latitude.flattenOffset();
78 | this.longitude.flattenOffset();
79 | this.latitudeDelta.flattenOffset();
80 | this.longitudeDelta.flattenOffset();
81 | }
82 |
83 | private __getValue() {
84 | return {
85 | latitude: this.latitude.__getValue(),
86 | longitude: this.longitude.__getValue(),
87 | latitudeDelta: this.latitudeDelta.__getValue(),
88 | longitudeDelta: this.longitudeDelta.__getValue(),
89 | };
90 | }
91 |
92 | // private __attach() {
93 | // this.latitude.__addChild(this);
94 | // this.longitude.__addChild(this);
95 | // this.latitudeDelta.__addChild(this);
96 | // this.longitudeDelta.__addChild(this);
97 | // }
98 |
99 | // private __detach() {
100 | // this.latitude.__removeChild(this);
101 | // this.longitude.__removeChild(this);
102 | // this.latitudeDelta.__removeChild(this);
103 | // this.longitudeDelta.__removeChild(this);
104 | // }
105 |
106 | stopAnimation(callback: (region: Region) => void) {
107 | this.latitude.stopAnimation();
108 | this.longitude.stopAnimation();
109 | this.latitudeDelta.stopAnimation();
110 | this.longitudeDelta.stopAnimation();
111 | callback && callback(this.__getValue());
112 | }
113 |
114 | addListener(callback: (region: Region) => void) {
115 | const id = String(_uniqueId++);
116 | const jointCallback = () => /*{value}*/ callback(this.__getValue());
117 | this._regionListeners[id] = {
118 | latitude: this.latitude.addListener(jointCallback),
119 | longitude: this.longitude.addListener(jointCallback),
120 | latitudeDelta: this.latitudeDelta.addListener(jointCallback),
121 | longitudeDelta: this.longitudeDelta.addListener(jointCallback),
122 | };
123 | return id;
124 | }
125 |
126 | removeListener(id: string) {
127 | this.latitude.removeListener(this._regionListeners[id].latitude);
128 | this.longitude.removeListener(this._regionListeners[id].longitude);
129 | this.latitudeDelta.removeListener(this._regionListeners[id].latitudeDelta);
130 | this.longitudeDelta.removeListener(
131 | this._regionListeners[id].longitudeDelta
132 | );
133 | delete this._regionListeners[id];
134 | }
135 |
136 | spring(config: Animated.SpringAnimationConfig & Region) {
137 | const animations = [];
138 | for (const type of configTypes) {
139 | if (config.hasOwnProperty(type)) {
140 | animations.push(
141 | Animated.spring(this[type], {
142 | ...config,
143 | toValue: config[type],
144 | // may help to eliminate some dev warnings and perf issues
145 | useNativeDriver: !!config?.useNativeDriver,
146 | })
147 | );
148 | }
149 | }
150 | return Animated.parallel(animations);
151 | }
152 |
153 | timing(config: Animated.TimingAnimationConfig & Region) {
154 | const animations = [];
155 | for (const type of configTypes) {
156 | if (config.hasOwnProperty(type)) {
157 | animations.push(
158 | Animated.timing(this[type], {
159 | ...config,
160 | toValue: config[type],
161 | // may help to eliminate some dev warnings and perf issues
162 | useNativeDriver: !!config?.useNativeDriver,
163 | })
164 | );
165 | }
166 | }
167 | return Animated.parallel(animations);
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/MapCallout.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { requireNativeComponent, StyleSheet, ViewProps } from 'react-native';
3 | import type { CalloutPressEvent } from './sharedTypes';
4 |
5 | export type MapCalloutProps = ViewProps & {
6 | /**
7 | * Callback that is called when the user presses on the callout
8 | *
9 | */
10 | onPress?: (event: CalloutPressEvent) => void;
11 |
12 | /**
13 | * If `false`, a default "tooltip" bubble window will be drawn around this callouts children.
14 | * If `true`, the child views can fully customize their appearance, including any "bubble" like styles.
15 | *
16 | * @default false
17 | */
18 | tooltip?: boolean;
19 | };
20 |
21 | type NativeProps = MapCalloutProps;
22 |
23 | class MapCallout extends React.Component {
24 | render() {
25 | const { tooltip = false } = this.props;
26 | return (
27 |
32 | );
33 | }
34 | }
35 |
36 | const styles = StyleSheet.create({
37 | callout: {
38 | position: 'absolute',
39 | },
40 | });
41 |
42 | const OsmMapCallout = requireNativeComponent('OsmMapCallout');
43 |
44 | export default MapCallout;
45 |
--------------------------------------------------------------------------------
/src/MapCircle.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { requireNativeComponent, View, ViewProps } from 'react-native';
3 | import type { NativeComponent } from './decorateMapComponent';
4 | import type { LatLng } from './sharedTypes';
5 |
6 | export type MapCircleProps = ViewProps & {
7 | /**
8 | * The coordinates of the center of the circle.
9 | *
10 | */
11 | center: LatLng;
12 |
13 | /**
14 | * The fill color to use for the path.
15 | *
16 | * @default `#000`, `rgba(r,g,b,0.5)`
17 | */
18 | fillColor?: string;
19 |
20 | /**
21 | * The radius of the circle to be drawn (in meters)
22 | *
23 | */
24 | radius: number;
25 |
26 | /**
27 | * The stroke color to use for the path.
28 | *
29 | * @default `#000`, `rgba(r,g,b,0.5)`
30 | */
31 | strokeColor?: string;
32 |
33 | /**
34 | * The stroke width to use for the path.
35 | *
36 | * @default 1
37 | */
38 | strokeWidth?: number;
39 | };
40 |
41 | type NativeProps = MapCircleProps & { ref: React.RefObject };
42 |
43 | class MapCircle extends React.Component {
44 | private circle: NativeProps['ref'];
45 |
46 | constructor(props: MapCircleProps) {
47 | super(props);
48 | this.circle = React.createRef();
49 | }
50 |
51 | setNativeProps(props: Partial) {
52 | this.circle.current?.setNativeProps(props);
53 | }
54 |
55 | render() {
56 | const { strokeColor = '#000', strokeWidth = 1 } = this.props;
57 |
58 | return (
59 |
65 | );
66 | }
67 | }
68 |
69 | const OsmMapCircle: NativeComponent =
70 | requireNativeComponent('OsmMapCircle');
71 |
72 | export default MapCircle;
73 |
--------------------------------------------------------------------------------
/src/MapMarkerNativeComponent.ts:
--------------------------------------------------------------------------------
1 | import type { HostComponent } from 'react-native';
2 | import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
3 | import type { NativeProps } from './MapMarker';
4 | import type { LatLng } from './sharedTypes';
5 |
6 | export type MapMarkerNativeComponentType = HostComponent;
7 |
8 | interface NativeCommands {
9 | showCallout: (
10 | viewRef: NonNullable<
11 | React.RefObject['current']
12 | >
13 | ) => void;
14 | hideCallout: (
15 | viewRef: NonNullable<
16 | React.RefObject['current']
17 | >
18 | ) => void;
19 | redrawCallout: (
20 | viewRef: NonNullable<
21 | React.RefObject['current']
22 | >
23 | ) => void;
24 | animateMarkerToCoordinate: (
25 | viewRef: NonNullable<
26 | React.RefObject['current']
27 | >,
28 | coordinate: LatLng,
29 | duration: number
30 | ) => void;
31 | redraw: (
32 | viewRef: NonNullable<
33 | React.RefObject['current']
34 | >
35 | ) => void;
36 | }
37 |
38 | export const Commands: NativeCommands = codegenNativeCommands({
39 | supportedCommands: [
40 | 'showCallout',
41 | 'hideCallout',
42 | 'redrawCallout',
43 | 'animateMarkerToCoordinate',
44 | 'redraw',
45 | ],
46 | });
47 |
--------------------------------------------------------------------------------
/src/MapPolygon.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | NativeSyntheticEvent,
4 | requireNativeComponent,
5 | View,
6 | ViewProps,
7 | } from 'react-native';
8 | import type { NativeComponent } from './decorateMapComponent';
9 | import type { LatLng, Point } from './sharedTypes';
10 |
11 | export type MapPolygonProps = ViewProps & {
12 | /**
13 | * An array of coordinates to describe the polygon
14 | *
15 | */
16 | coordinates: LatLng[];
17 |
18 | /**
19 | * The fill color to use for the path.
20 | *
21 | * @default `#000`, `rgba(r,g,b,0.5)`
22 | */
23 | fillColor?: string;
24 |
25 | /**
26 | * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection.
27 | * A geodesic is the shortest path between two points on the Earth's surface.
28 | * The geodesic curve is constructed assuming the Earth is a sphere.
29 | *
30 | */
31 | geodesic?: boolean;
32 |
33 | /**
34 | * A 2d array of coordinates to describe holes of the polygon where each hole has at least 3 points.
35 | *
36 | */
37 | holes?: LatLng[][];
38 |
39 | /**
40 | * Callback that is called when the user presses on the polygon
41 | *
42 | */
43 | onPress?: (event: PolygonPressEvent) => void;
44 |
45 | /**
46 | * The stroke color to use for the path.
47 | *
48 | * @default `#000`, `rgba(r,g,b,0.5)`
49 | */
50 | strokeColor?: string;
51 |
52 | /**
53 | * The stroke width to use for the path.
54 | *
55 | * @default 1
56 | */
57 | strokeWidth?: number;
58 |
59 | /**
60 | * Boolean to allow a polygon to be tappable and use the onPress function.
61 | *
62 | */
63 | tappable?: boolean;
64 | };
65 |
66 | type PolygonPressEvent = NativeSyntheticEvent<{
67 | action: 'polygon-press';
68 | id?: string;
69 | coordinate?: LatLng;
70 | position?: Point;
71 | }>;
72 |
73 | type NativeProps = MapPolygonProps & { ref: React.RefObject };
74 |
75 | class MapPolygon extends React.Component {
76 | private polygon: NativeProps['ref'];
77 |
78 | constructor(props: MapPolygonProps) {
79 | super(props);
80 | this.polygon = React.createRef();
81 | }
82 |
83 | setNativeProps(props: Partial) {
84 | this.polygon.current?.setNativeProps(props);
85 | }
86 |
87 | render() {
88 | const { strokeColor = '#000', strokeWidth = 1 } = this.props;
89 | return (
90 |
96 | );
97 | }
98 | }
99 |
100 | const OsmMapPolygon: NativeComponent =
101 | requireNativeComponent('OsmMapPolygon');
102 |
103 | export default MapPolygon;
104 |
--------------------------------------------------------------------------------
/src/MapPolyline.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | NativeSyntheticEvent,
4 | requireNativeComponent,
5 | View,
6 | ViewProps,
7 | } from 'react-native';
8 | import type { NativeComponent } from './decorateMapComponent';
9 | import type { LatLng, LineCapType, Point } from './sharedTypes';
10 |
11 | export type MapPolylineProps = ViewProps & {
12 | /**
13 | * An array of coordinates to describe the polyline
14 | */
15 | coordinates: LatLng[];
16 |
17 | /**
18 | * The fill color to use for the path.
19 | *
20 | * @default `#000`, `rgba(r,g,b,0.5)`
21 | */
22 | fillColor?: string;
23 |
24 | /**
25 | * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection.
26 | * A geodesic is the shortest path between two points on the Earth's surface.
27 | * The geodesic curve is constructed assuming the Earth is a sphere.
28 | */
29 | geodesic?: boolean;
30 |
31 | /**
32 | * The line cap style to apply to the open ends of the path
33 | *
34 | * @default `round`
35 | */
36 | lineCap?: LineCapType;
37 |
38 | /**
39 | * An array of numbers specifying the dash pattern to use for the path.
40 | * The array contains one or more numbers that indicate the lengths (measured in points)
41 | * of the line segments and gaps in the pattern.
42 | * The values in the array alternate, starting with the first line segment length,
43 | * followed by the first gap length, followed by the second line segment length, and so on.
44 | */
45 | lineDashPattern?: number[];
46 |
47 | /**
48 | * Callback that is called when the user presses on the polyline
49 | */
50 | onPress?: (event: PolylinePressEvent) => void;
51 |
52 | /**
53 | * The stroke color to use for the path.
54 | *
55 | * @default `#000`, `rgba(r,g,b,0.5)`
56 | */
57 | strokeColor?: string;
58 |
59 | /**
60 | * The stroke colors to use for the path.
61 | *
62 | * Must be the same length as `coordinates`
63 | */
64 | strokeColors?: string[];
65 |
66 | /**
67 | * The stroke width to use for the path.
68 | *
69 | * @default 1
70 | */
71 | strokeWidth?: number;
72 |
73 | /**
74 | * Boolean to allow the polyline to be tappable and use the onPress function.
75 | */
76 | tappable?: boolean;
77 | };
78 |
79 | export type PolylinePressEvent = NativeSyntheticEvent<{
80 | action: 'polyline-press';
81 | id?: string;
82 | coordinate?: LatLng;
83 | position?: Point;
84 | }>;
85 |
86 | type NativeProps = MapPolylineProps & { ref: React.RefObject };
87 |
88 | class MapPolyline extends React.Component {
89 | private polyline: NativeProps['ref'];
90 |
91 | constructor(props: MapPolylineProps) {
92 | super(props);
93 | this.polyline = React.createRef();
94 | }
95 |
96 | setNativeProps(props: Partial) {
97 | this.polyline.current?.setNativeProps(props);
98 | }
99 |
100 | render() {
101 | const {
102 | strokeColor = '#000',
103 | strokeWidth = 1,
104 | lineCap = 'round',
105 | } = this.props;
106 |
107 | return (
108 |
115 | );
116 | }
117 | }
118 |
119 | const OsmMapPolyline: NativeComponent =
120 | requireNativeComponent('OsmMapPolyline');
121 |
122 | export default MapPolyline;
123 |
--------------------------------------------------------------------------------
/src/MapUrlTile.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import { requireNativeComponent, ViewProps } from 'react-native';
4 |
5 | export type MapUrlTileProps = ViewProps & {
6 | /**
7 | * Doubles tile size from 256 to 512 utilising higher zoom levels
8 | * i.e loading 4 higher zoom level tiles and combining them for one high-resolution tile.
9 | * NB! using this makes text labels smaller than in the original map style.
10 | *
11 | */
12 | doubleTileSize?: boolean;
13 |
14 | /**
15 | * Allow tiles using the TMS coordinate system (origin bottom left) to be used,
16 | * and displayed at their correct coordinates.
17 | */
18 | flipY?: boolean;
19 |
20 | /**
21 | * The maximum native zoom level for this tile overlay i.e. the highest zoom level that the tile server provides.
22 | * Tiles are auto-scaled for higher zoom levels.
23 | */
24 | maximumNativeZ?: number;
25 |
26 | /**
27 | * The maximum zoom level for this tile overlay.
28 | */
29 | maximumZ?: number;
30 |
31 | /**
32 | * The minimum zoom level for this tile overlay.
33 | */
34 | minimumZ?: number;
35 |
36 | /**
37 | * In offline-mode tiles are not fetched from the tile servers, rather only tiles stored in the cache directory are used.
38 | * Furthermore automated tile scaling is activated: if tile at a desired zoom level is not found from the cache directory,
39 | * then lower zoom level tile is used (up to 4 levels lower) and scaled.
40 | *
41 | * @default false
42 | */
43 | offlineMode?: boolean;
44 |
45 | /**
46 | * Map layer opacity. Value between 0 - 1, with 0 meaning fully transparent.
47 | */
48 | opacity?: number;
49 |
50 | /**
51 | * Defines maximum age in seconds for a cached tile before it's refreshed.
52 | *
53 | * NB! Refresh logic is "serve-stale-while-refresh"
54 | * i.e. to ensure map availability a stale (over max age) tile is served
55 | * while a tile refresh process is started in the background.
56 | */
57 | tileCacheMaxAge?: number;
58 |
59 | /**
60 | * Enable caching of tiles in the specified directory.
61 | * Directory can be specified either as a normal path or in URL format (`file://`).
62 | *
63 | * Tiles are stored in tileCachePath directory as `/{z}/{x}/{y}` i.e. in sub-directories 2-levels deep,
64 | * filename is tile y-coordinate without any filetype-extension.
65 | *
66 | * NB! All cache management needs to be implemented by client e.g. deleting tiles to manage use of storage space etc.
67 | */
68 | tileCachePath?: string;
69 |
70 | /**
71 | * Tile size, default size is 256 (for tiles of 256 _ 256 pixels).
72 | * High-res (aka 'retina') tiles are 512 (tiles of 512 _ 512 pixels)
73 | */
74 | tileSize?: number;
75 |
76 | /**
77 | * The url template of the map tileserver.
78 | * (URLTile) The patterns {x} {y} {z} will be replaced at runtime.
79 | * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png.
80 | *
81 | * It is also possible to refer to tiles in local filesystem with file:///top-level-directory/sub-directory/{z}/{x}/{y}.png URL-format.
82 | * (WMSTile) The patterns {minX} {maxX} {minY} {maxY} {width} {height} will be replaced at runtime according to EPSG:900913 specification bounding box.
83 | * For example, https://demo.geo-solutions.it/geoserver/tiger/wms?service=WMS&version=1.1.0&request=GetMap&layers=tiger:poi&styles=&bbox={minX},{minY},{maxX},{maxY}&width={width}&height={height}&srs=EPSG:900913&format=image/png&transparent=true&format_options=dpi:213.
84 | */
85 |
86 | urlTemplate: string;
87 | };
88 |
89 | type NativeProps = MapUrlTileProps;
90 |
91 | class MapUrlTile extends React.Component {
92 | render() {
93 | return ;
94 | }
95 | }
96 |
97 | const OsmMapUrlTile = requireNativeComponent('OsmMapUrlTile');
98 |
99 | export default MapUrlTile;
100 |
--------------------------------------------------------------------------------
/src/MapView.types.ts:
--------------------------------------------------------------------------------
1 | import type { ClickEvent, LatLng, Point, Region } from './sharedTypes';
2 | import type { NativeSyntheticEvent } from 'react-native';
3 |
4 | // All types in this file are directly exported with the package for external
5 | // use.
6 |
7 | export type Camera = {
8 | center: LatLng;
9 | };
10 |
11 | export type MapStyleElement = {
12 | featureType?: string;
13 | elementType?: string;
14 | stylers: object[];
15 | };
16 |
17 | export type EdgePadding = {
18 | top: Number;
19 | right: Number;
20 | bottom: Number;
21 | left: Number;
22 | };
23 |
24 | export type MapType =
25 | | 'hybrid'
26 | | 'mutedStandard'
27 | | 'none'
28 | | 'satellite'
29 | | 'standard'
30 | | 'terrain';
31 |
32 | export type MapTypes = {
33 | STANDARD: 'standard';
34 | SATELLITE: 'satellite';
35 | HYBRID: 'hybrid';
36 | TERRAIN: 'terrain';
37 | NONE: 'none';
38 | MUTEDSTANDARD: 'mutedStandard';
39 | };
40 |
41 | export type IndoorLevel = {
42 | index: number;
43 | name: string;
44 | shortName: string;
45 | };
46 |
47 | export type ActiveIndoorLevel = {
48 | activeLevelIndex: number;
49 | name: string;
50 | shortName: string;
51 | };
52 |
53 | export type IndoorLevelActivatedEvent = NativeSyntheticEvent<{
54 | IndoorLevel: ActiveIndoorLevel;
55 | }>;
56 |
57 | export type IndoorBuilding = {
58 | underground: boolean;
59 | activeLevelIndex: number;
60 | levels: IndoorLevel[];
61 | };
62 |
63 | export type IndoorBuildingEvent = NativeSyntheticEvent<{
64 | IndoorBuilding: IndoorBuilding;
65 | }>;
66 |
67 | export type KmlMarker = {
68 | id: string;
69 | title: string;
70 | description: string;
71 | coordinate: LatLng;
72 | position: Point;
73 | };
74 |
75 | export type KmlMapEvent = NativeSyntheticEvent<{ markers: KmlMarker[] }>;
76 |
77 | export type LongPressEvent = ClickEvent<{
78 | /**
79 | * @platform Android
80 | */
81 | action?: 'long-press';
82 | }>;
83 |
84 | export type PanDragEvent = ClickEvent;
85 |
86 | export type PoiClickEvent = NativeSyntheticEvent<{
87 | placeId: string;
88 | name: string;
89 | coordinate: LatLng;
90 |
91 | /**
92 | * @platform Android
93 | */
94 | position?: Point;
95 | }>;
96 |
97 | export type MapPressEvent = ClickEvent<{
98 | /**
99 | * @platform Android
100 | */
101 | action?: 'press' | 'marker-press';
102 | }>;
103 |
104 | export type Details = {
105 | isGesture?: boolean;
106 | };
107 |
108 | export type UserLocationChangeEvent = NativeSyntheticEvent<{
109 | coordinate?: LatLng & {
110 | altitude: number;
111 | timestamp: number;
112 | accuracy: number;
113 | speed: number;
114 | heading: number;
115 |
116 | /**
117 | * @platform iOS
118 | */
119 | altitudeAccuracy?: number;
120 |
121 | /**
122 | * @platform Android
123 | */
124 | isFromMockProvider?: boolean;
125 | };
126 |
127 | /**
128 | * @platform iOS
129 | */
130 | error?: {
131 | message: string;
132 | };
133 | }>;
134 |
135 | export type ChangeEvent = NativeSyntheticEvent<{
136 | continuous: boolean;
137 | region: Region;
138 | }>;
139 |
140 | export type FitToOptions = {
141 | edgePadding?: EdgePadding;
142 | animated?: boolean;
143 | };
144 |
145 | export type BoundingBox = { northEast: LatLng; southWest: LatLng };
146 |
147 | export type SnapshotOptions = {
148 | /** optional, when omitted the view-width is used */
149 | width?: number;
150 | /** optional, when omitted the view-height is used */
151 | height?: number;
152 | /** __iOS only__, optional region to render */
153 | region?: Region;
154 | /** image formats, defaults to 'png' */
155 | format?: 'png' | 'jpg';
156 | /** image quality: 0..1 (only relevant for jpg, default: 1) */
157 | quality?: number;
158 | /** result types, defaults to 'file' */
159 | result?: 'file' | 'base64';
160 | };
161 |
162 | export type Address = {
163 | administrativeArea: string;
164 | country: string;
165 | countryCode: string;
166 | locality: string;
167 | name: string;
168 | postalCode: string;
169 | subAdministrativeArea: string;
170 | subLocality: string;
171 | thoroughfare: string;
172 | };
173 |
174 | export type NativeCommandName =
175 | | 'animateCamera'
176 | | 'animateToRegion'
177 | | 'coordinateForPoint'
178 | | 'fitToCoordinates'
179 | | 'fitToElements'
180 | | 'fitToSuppliedMarkers'
181 | | 'getAddressFromCoordinates'
182 | | 'getCamera'
183 | | 'getMapBoundaries'
184 | | 'getMarkersFrames'
185 | | 'pointForCoordinate'
186 | | 'setCamera'
187 | | 'setIndoorActiveLevelIndex'
188 | | 'setMapBoundaries'
189 | | 'takeSnapshot';
190 |
--------------------------------------------------------------------------------
/src/MapViewNativeComponent.ts:
--------------------------------------------------------------------------------
1 | import type { HostComponent } from 'react-native';
2 | import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
3 | import type { NativeProps } from './MapView';
4 | import type { Camera, EdgePadding } from './MapView.types';
5 | import type { LatLng, Region } from './sharedTypes';
6 |
7 | export type MapViewNativeComponentType = HostComponent;
8 |
9 | interface NativeCommands {
10 | animateToRegion: (
11 | viewRef: NonNullable<
12 | React.RefObject['current']
13 | >,
14 | region: Region,
15 | duration: number
16 | ) => void;
17 |
18 | setCamera: (
19 | viewRef: NonNullable<
20 | React.RefObject['current']
21 | >,
22 | camera: Partial
23 | ) => void;
24 |
25 | animateCamera: (
26 | viewRef: NonNullable<
27 | React.RefObject['current']
28 | >,
29 | camera: Partial,
30 | duration: number
31 | ) => void;
32 |
33 | fitToElements: (
34 | viewRef: NonNullable<
35 | React.RefObject['current']
36 | >,
37 | edgePadding: EdgePadding,
38 | animated: boolean
39 | ) => void;
40 |
41 | fitToSuppliedMarkers: (
42 | viewRef: NonNullable<
43 | React.RefObject['current']
44 | >,
45 | markers: string[],
46 | edgePadding: EdgePadding,
47 | animated: boolean
48 | ) => void;
49 |
50 | fitToCoordinates: (
51 | viewRef: NonNullable<
52 | React.RefObject['current']
53 | >,
54 | coordinates: LatLng[],
55 | edgePadding: EdgePadding,
56 | animated: boolean
57 | ) => void;
58 |
59 | setMapBoundaries: (
60 | viewRef: NonNullable<
61 | React.RefObject['current']
62 | >,
63 | northEast: LatLng,
64 | southWest: LatLng
65 | ) => void;
66 |
67 | setIndoorActiveLevelIndex: (
68 | viewRef: NonNullable<
69 | React.RefObject['current']
70 | >,
71 | activeLevelIndex: number
72 | ) => void;
73 | }
74 |
75 | export const Commands: NativeCommands = codegenNativeCommands({
76 | supportedCommands: [
77 | 'animateToRegion',
78 | 'setCamera',
79 | 'animateCamera',
80 | 'fitToElements',
81 | 'fitToSuppliedMarkers',
82 | 'fitToCoordinates',
83 | 'setMapBoundaries',
84 | 'setIndoorActiveLevelIndex',
85 | ],
86 | });
87 |
--------------------------------------------------------------------------------
/src/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | it.todo('write a test');
2 |
--------------------------------------------------------------------------------
/src/decorateMapComponent.ts:
--------------------------------------------------------------------------------
1 | import type { HostComponent } from 'react-native';
2 |
3 | export const createNotSupportedComponent = (message: string) => () => {
4 | console.error(message);
5 | return null;
6 | };
7 |
8 | export type NativeComponent =
9 | | HostComponent
10 | | ReturnType;
11 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import MapView, { MapViewProps } from './MapView';
2 | export type { MapViewProps };
3 | import Marker from './MapMarker';
4 | import Polyline from './MapPolyline';
5 | import Polygon from './MapPolygon';
6 | export type { MapPolylineProps, PolylinePressEvent } from './MapPolyline';
7 | export type { MapPolygonProps } from './MapPolygon';
8 | export { default as Callout } from './MapCallout';
9 | export type { MapCalloutProps } from './MapCallout';
10 | export { default as Circle } from './MapCircle';
11 | export type { MapCircleProps } from './MapCircle';
12 | export { default as UrlTile } from './MapUrlTile';
13 | export type { MapUrlTileProps } from './MapUrlTile';
14 | export * from './MapView.types';
15 | export * from './sharedTypes';
16 | export default MapView;
17 | export { Marker, Polyline, Polygon };
18 | export { default as AnimatedRegion } from './AnimatedRegion';
19 |
--------------------------------------------------------------------------------
/src/sharedTypes.ts:
--------------------------------------------------------------------------------
1 | import type { NativeSyntheticEvent } from 'react-native';
2 |
3 | export type Provider = 'google' | undefined;
4 |
5 | export type LatLng = {
6 | latitude: number;
7 | longitude: number;
8 | };
9 |
10 | export type Point = {
11 | x: number;
12 | y: number;
13 | };
14 |
15 | export type Region = LatLng & {
16 | latitudeDelta: number;
17 | longitudeDelta: number;
18 | };
19 |
20 | export type Frame = Point & { height: number; width: number };
21 |
22 | export type CalloutPressEvent = NativeSyntheticEvent<{
23 | action: 'callout-press';
24 |
25 | /**
26 | * @platform iOS
27 | */
28 | frame?: Frame;
29 |
30 | /**
31 | * @platform iOS
32 | */
33 | id?: string;
34 |
35 | /**
36 | * @platform iOS
37 | */
38 | point?: Point;
39 |
40 | /**
41 | * @platform Android
42 | */
43 | coordinate?: LatLng;
44 |
45 | /**
46 | * @platform Android
47 | */
48 | position?: Point;
49 | }>;
50 |
51 | export type LineCapType = 'butt' | 'round' | 'square';
52 | export type LineJoinType = 'miter' | 'round' | 'bevel';
53 |
54 | export type ClickEvent = NativeSyntheticEvent<
55 | { coordinate: LatLng; position: Point } & T
56 | >;
57 |
58 | export type MarkerDeselectEvent = Omit<
59 | ClickEvent<{
60 | action: 'marker-deselect';
61 | id: string;
62 | }>,
63 | 'position'
64 | >;
65 |
66 | export type MarkerSelectEvent = Omit<
67 | ClickEvent<{ id: string; action: 'marker-select' }>,
68 | 'position'
69 | >;
70 |
71 | export type MarkerDragEvent = ClickEvent<{
72 | /**
73 | * @platform iOS
74 | */
75 | id?: string;
76 | }>;
77 |
78 | export type MarkerDragStartEndEvent = NativeSyntheticEvent<{
79 | coordinate: LatLng;
80 |
81 | /**
82 | * @platform iOS
83 | */
84 | id?: string;
85 |
86 | /**
87 | * @platform Android
88 | */
89 | position?: Point;
90 | }>;
91 |
92 | export type MarkerPressEvent = NativeSyntheticEvent<{
93 | id: string;
94 | action: 'marker-press';
95 | coordinate: LatLng;
96 |
97 | /**
98 | * @platform Android
99 | */
100 | position?: Point;
101 | }>;
102 |
--------------------------------------------------------------------------------
/src/sharedTypesInternal.ts:
--------------------------------------------------------------------------------
1 | export type Modify = Omit & R;
2 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "extends": "./tsconfig",
4 | "exclude": ["example"]
5 | }
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "@splicer97/react-native-osmdroid": ["./src/index"]
6 | },
7 | "allowUnreachableCode": false,
8 | "allowUnusedLabels": false,
9 | "esModuleInterop": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "jsx": "react",
12 | "lib": ["esnext"],
13 | "module": "esnext",
14 | "moduleResolution": "node",
15 | "noFallthroughCasesInSwitch": true,
16 | "noImplicitReturns": true,
17 | "noImplicitUseStrict": false,
18 | "noStrictGenericChecks": false,
19 | "noUncheckedIndexedAccess": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "resolveJsonModule": true,
23 | "skipLibCheck": true,
24 | "strict": true,
25 | "target": "esnext"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------