@capgo/nativegeocoder 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapgoNativegeocoder'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '12.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+ end
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # @capgo/nativegeocoder
2
+
3
+ Capacitor plugin for native forward and reverse geocoding
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @capgo/nativegeocoder
9
+ npx cap sync
10
+ ```
11
+
12
+ ## API
13
+
14
+ <docgen-index>
15
+
16
+ * [`reverseGeocode(...)`](#reversegeocode)
17
+ * [`forwardGeocode(...)`](#forwardgeocode)
18
+ * [Interfaces](#interfaces)
19
+
20
+ </docgen-index>
21
+
22
+ <docgen-api>
23
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
24
+
25
+ ### reverseGeocode(...)
26
+
27
+ ```typescript
28
+ reverseGeocode(options: reverseOptions) => Promise<{ addresses: Adress[]; }>
29
+ ```
30
+
31
+ | Param | Type |
32
+ | ------------- | --------------------------------------------------------- |
33
+ | **`options`** | <code><a href="#reverseoptions">reverseOptions</a></code> |
34
+
35
+ **Returns:** <code>Promise&lt;{ addresses: Adress[]; }&gt;</code>
36
+
37
+ --------------------
38
+
39
+
40
+ ### forwardGeocode(...)
41
+
42
+ ```typescript
43
+ forwardGeocode(options: ForwardOptions) => Promise<{ addresses: Adress[]; }>
44
+ ```
45
+
46
+ | Param | Type |
47
+ | ------------- | --------------------------------------------------------- |
48
+ | **`options`** | <code><a href="#forwardoptions">ForwardOptions</a></code> |
49
+
50
+ **Returns:** <code>Promise&lt;{ addresses: Adress[]; }&gt;</code>
51
+
52
+ --------------------
53
+
54
+
55
+ ### Interfaces
56
+
57
+
58
+ #### Adress
59
+
60
+ | Prop | Type |
61
+ | --------------------------- | --------------------- |
62
+ | **`latitude`** | <code>string</code> |
63
+ | **`longitude`** | <code>string</code> |
64
+ | **`countryCode`** | <code>string</code> |
65
+ | **`postalCode`** | <code>string</code> |
66
+ | **`administrativeArea`** | <code>string</code> |
67
+ | **`subAdministrativeArea`** | <code>string</code> |
68
+ | **`locality`** | <code>string</code> |
69
+ | **`subLocality`** | <code>string</code> |
70
+ | **`thoroughfare`** | <code>string</code> |
71
+ | **`subThoroughfare`** | <code>string</code> |
72
+ | **`areasOfInterest`** | <code>string[]</code> |
73
+ | **`formatted_address`** | <code>string</code> |
74
+
75
+
76
+ #### reverseOptions
77
+
78
+ | Prop | Type |
79
+ | ------------------- | -------------------- |
80
+ | **`latitude`** | <code>number</code> |
81
+ | **`longitude`** | <code>number</code> |
82
+ | **`useLocale`** | <code>boolean</code> |
83
+ | **`defaultLocale`** | <code>string</code> |
84
+ | **`maxResults`** | <code>number</code> |
85
+ | **`apiKey`** | <code>string</code> |
86
+
87
+
88
+ #### ForwardOptions
89
+
90
+ | Prop | Type |
91
+ | ------------------- | -------------------- |
92
+ | **`addressString`** | <code>string</code> |
93
+ | **`useLocale`** | <code>boolean</code> |
94
+ | **`defaultLocale`** | <code>string</code> |
95
+ | **`maxResults`** | <code>number</code> |
96
+ | **`apiKey`** | <code>string</code> |
97
+
98
+ </docgen-api>
@@ -0,0 +1,58 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.1'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.2.0'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.2'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.3.0'
6
+ }
7
+
8
+ buildscript {
9
+ repositories {
10
+ google()
11
+ jcenter()
12
+ }
13
+ dependencies {
14
+ classpath 'com.android.tools.build:gradle:4.2.1'
15
+ }
16
+ }
17
+
18
+ apply plugin: 'com.android.library'
19
+
20
+ android {
21
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 30
22
+ defaultConfig {
23
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 21
24
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 30
25
+ versionCode 1
26
+ versionName "1.0"
27
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
28
+ }
29
+ buildTypes {
30
+ release {
31
+ minifyEnabled false
32
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
33
+ }
34
+ }
35
+ lintOptions {
36
+ abortOnError false
37
+ }
38
+ compileOptions {
39
+ sourceCompatibility JavaVersion.VERSION_1_8
40
+ targetCompatibility JavaVersion.VERSION_1_8
41
+ }
42
+ }
43
+
44
+ repositories {
45
+ google()
46
+ mavenCentral()
47
+ jcenter()
48
+ }
49
+
50
+
51
+ dependencies {
52
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
53
+ implementation project(':capacitor-android')
54
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
55
+ testImplementation "junit:junit:$junitVersion"
56
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
57
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
58
+ }
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="ee.forgr.capacitor_nativegeocoder">
3
+ </manifest>
@@ -0,0 +1,239 @@
1
+ package ee.forgr.capacitor_nativegeocoder;
2
+
3
+ import android.util.Log;
4
+
5
+ public class NativeGeocoder {
6
+
7
+ public Context context;
8
+ /**
9
+ * Reverse geocode a given latitude and longitude to find location address
10
+ * @param latitude double
11
+ * @param longitude double
12
+ * @param call PluginCall
13
+ */
14
+ private void reverseGeocode(double latitude, double longitude, PluginCall call) {
15
+
16
+ if (latitude == 0 || longitude == 0) {
17
+ call.reject("Expected two non-empty double arguments.");
18
+ return;
19
+ }
20
+
21
+ if (!Geocoder.isPresent()) {
22
+ call.reject("Geocoder is not present on this device/emulator.");
23
+ return;
24
+ }
25
+
26
+ NativeGeocoderOptions geocoderOptions = getNativeGeocoderOptions(options);
27
+ geocoder = createGeocoderWithOptions(geocoderOptions);
28
+
29
+ try {
30
+ List<Address> geoResults = geocoder.getFromLocation(latitude, longitude, geocoderOptions.maxResults);
31
+ if (geoResults.size() > 0) {
32
+ int maxResultObjects = geoResults.size() >= geocoderOptions.maxResults ? geoResults.size() : geoResults.size();
33
+ JSONArray resultObj = new JSONArray();
34
+
35
+ for (int i = 0; i < maxResultObjects; i++) {
36
+ Address address = geoResults.get(i);
37
+
38
+ // https://developer.android.com/reference/android/location/Address.html
39
+ JSONObject placemark = new JSONObject();
40
+ placemark.put("latitude", !String.valueOf(address.getLatitude()).isEmpty() ? address.getLatitude() : "");
41
+ placemark.put("longitude", !String.valueOf(address.getLongitude()).isEmpty() ? address.getLongitude() : "");
42
+ placemark.put("countryCode", address.getCountryCode() != null ? address.getCountryCode() : "");
43
+ placemark.put("countryName", address.getCountryName() != null ? address.getCountryName() : "");
44
+ placemark.put("postalCode", address.getPostalCode() != null ? address.getPostalCode() : "");
45
+ placemark.put("administrativeArea", address.getAdminArea() != null ? address.getAdminArea() : "");
46
+ placemark.put("subAdministrativeArea", address.getSubAdminArea() != null ? address.getSubAdminArea() : "");
47
+ placemark.put("locality", address.getLocality() != null ? address.getLocality() : "");
48
+ placemark.put("subLocality", address.getSubLocality() != null ? address.getSubLocality() : "");
49
+ placemark.put("thoroughfare", address.getThoroughfare() != null ? address.getThoroughfare() : "");
50
+ placemark.put("subThoroughfare", address.getSubThoroughfare() != null ? address.getSubThoroughfare() : "");
51
+ placemark.put("areasOfInterest", address.getFeatureName() != null ? new JSONArray(new String[]{ address.getFeatureName()} ) : new JSONArray());
52
+
53
+ resultObj.put(placemark);
54
+ }
55
+ call.resolve(resultObj);
56
+ } else {
57
+ call.reject("Cannot get an address.");
58
+ }
59
+ }
60
+ catch (Exception e) {
61
+ String errorMsg = e.getMessage();
62
+ if (e.getMessage().equals("grpc failed") && !isNetworkAvailable()) {
63
+ errorMsg = "No Internet Access";
64
+ }
65
+ call.reject("Geocoder:getFromLocationName Error: " + errorMsg);
66
+ }
67
+ }
68
+
69
+
70
+ /**
71
+ * Forward geocode a given address to find coordinates
72
+ * @param addressString String
73
+ * @param options JSONObject
74
+ * @param call PluginCall
75
+ */
76
+ private void forwardGeocode(String addressString, PluginCall call) {
77
+ if (addressString == null || addressString.length() == 0) {
78
+ call.reject("Expected a non-empty string argument.");
79
+ return;
80
+ }
81
+
82
+ if (!Geocoder.isPresent()) {
83
+ call.reject("Geocoder is not present on this device/emulator.");
84
+ return;
85
+ }
86
+
87
+ NativeGeocoderOptions geocoderOptions = getNativeGeocoderOptions(call);
88
+ geocoder = createGeocoderWithOptions(geocoderOptions);
89
+
90
+ try {
91
+ List<Address> geoResults = geocoder.getFromLocationName(addressString, geocoderOptions.maxResults);
92
+
93
+ if (geoResults.size() > 0) {
94
+ int maxResultObjects = geoResults.size() >= geocoderOptions.maxResults ? geoResults.size() : geoResults.size();
95
+ JSONArray resultObj = new JSONArray();
96
+
97
+ for (int i = 0; i < maxResultObjects; i++) {
98
+ Address address = geoResults.get(i);
99
+
100
+ try {
101
+ String latitude = String.valueOf(address.getLatitude());
102
+ String longitude = String.valueOf(address.getLongitude());
103
+
104
+ if (!latitude.isEmpty() && !longitude.isEmpty()) {
105
+ // https://developer.android.com/reference/android/location/Address.html
106
+ JSONObject placemark = new JSONObject();
107
+ placemark.put("latitude", latitude);
108
+ placemark.put("longitude", longitude);
109
+ placemark.put("countryCode", address.getCountryCode() != null ? address.getCountryCode() : "");
110
+ placemark.put("countryName", address.getCountryName() != null ? address.getCountryName() : "");
111
+ placemark.put("postalCode", address.getPostalCode() != null ? address.getPostalCode() : "");
112
+ placemark.put("administrativeArea", address.getAdminArea() != null ? address.getAdminArea() : "");
113
+ placemark.put("subAdministrativeArea", address.getSubAdminArea() != null ? address.getSubAdminArea() : "");
114
+ placemark.put("locality", address.getLocality() != null ? address.getLocality() : "");
115
+ placemark.put("subLocality", address.getSubLocality() != null ? address.getSubLocality() : "");
116
+ placemark.put("thoroughfare", address.getThoroughfare() != null ? address.getThoroughfare() : "");
117
+ placemark.put("subThoroughfare", address.getSubThoroughfare() != null ? address.getSubThoroughfare() : "");
118
+ placemark.put("areasOfInterest", address.getFeatureName() != null ? new JSONArray(new String[]{ address.getFeatureName() }) : new JSONArray());
119
+
120
+ resultObj.put(placemark);
121
+ }
122
+ }
123
+ catch (RuntimeException e) {
124
+ e.printStackTrace();
125
+ }
126
+ }
127
+
128
+ if (resultObj.length() == 0) {
129
+ call.reject("Cannot get latitude and/or longitude.");
130
+ } else {
131
+ call.resolve(resultObj);
132
+ }
133
+
134
+ } else {
135
+ call.reject("Cannot find a location.");
136
+ }
137
+ }
138
+ catch (Exception e) {
139
+ String errorMsg = e.getMessage();
140
+ if (e.getMessage().equals("grpc failed") && !isNetworkAvailable()) {
141
+ errorMsg = "No Internet Access";
142
+ }
143
+ call.reject("Geocoder:getFromLocationName Error: " + errorMsg);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Get network connection
149
+ * @return boolean
150
+ */
151
+ private boolean isNetworkAvailable() {
152
+ ConnectivityManager connectivityManager
153
+ = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
154
+ NetworkInfo activeNetworkInfo = null;
155
+ if (connectivityManager != null) {
156
+ activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
157
+ }
158
+ return activeNetworkInfo != null && activeNetworkInfo.isConnected();
159
+ }
160
+
161
+ /**
162
+ * Get a valid NativeGeocoderOptions object
163
+ * @param options JSONObject
164
+ * @return NativeGeocoderOptions
165
+ */
166
+ private NativeGeocoderOptions getNativeGeocoderOptions(JSONObject options) {
167
+ NativeGeocoderOptions geocoderOptions = new NativeGeocoderOptions();
168
+
169
+ if (options != null) {
170
+ try {
171
+ geocoderOptions.useLocale = !options.has("useLocale") || options.getBoolean("useLocale");
172
+ } catch (JSONException e) {
173
+ geocoderOptions.useLocale = true;
174
+ }
175
+
176
+ if (options.has("defaultLocale")) {
177
+ try {
178
+ geocoderOptions.defaultLocale = options.getString("defaultLocale");
179
+ } catch (JSONException e) {
180
+ geocoderOptions.defaultLocale = null;
181
+ }
182
+ } else {
183
+ geocoderOptions.defaultLocale = null;
184
+ }
185
+ if (options.has("maxResults")) {
186
+ try {
187
+ geocoderOptions.maxResults = options.getInt("maxResults");
188
+ } catch (JSONException e) {
189
+ geocoderOptions.maxResults = 1;
190
+ }
191
+
192
+ if (geocoderOptions.maxResults > 0) {
193
+ int MAX_RESULTS_COUNT = 5;
194
+ geocoderOptions.maxResults = Math.min(geocoderOptions.maxResults, MAX_RESULTS_COUNT);
195
+ } else {
196
+ geocoderOptions.maxResults = 1;
197
+ }
198
+ } else {
199
+ geocoderOptions.maxResults = 1;
200
+ }
201
+ } else {
202
+ geocoderOptions.useLocale = true;
203
+ geocoderOptions.defaultLocale = null;
204
+ geocoderOptions.maxResults = 1;
205
+ }
206
+
207
+ return geocoderOptions;
208
+ }
209
+
210
+ /**
211
+ * Create a Geocoder with NativeGeocoderOptions
212
+ * @param geocoderOptions NativeGeocoderOptions
213
+ * @return Geocoder
214
+ */
215
+ private Geocoder createGeocoderWithOptions(NativeGeocoderOptions geocoderOptions) {
216
+ if (geocoderOptions.defaultLocale != null && !geocoderOptions.defaultLocale.isEmpty()) {
217
+ Locale locale;
218
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
219
+ locale = Locale.forLanguageTag(geocoderOptions.defaultLocale);
220
+ } else {
221
+ String[] parts = geocoderOptions.defaultLocale.split("[-_]", -1);
222
+ if (parts.length == 1)
223
+ locale = new Locale(parts[0]);
224
+ else if (parts.length == 2 || (parts.length == 3 && parts[2].startsWith("#")))
225
+ locale = new Locale(parts[0], parts[1]);
226
+ else
227
+ locale = new Locale(parts[0], parts[1], parts[2]);
228
+ }
229
+ geocoder = new Geocoder(context.getApplicationContext(), locale);
230
+ } else {
231
+ if (geocoderOptions.useLocale) {
232
+ geocoder = new Geocoder(context.getApplicationContext(), Locale.getDefault());
233
+ } else {
234
+ geocoder = new Geocoder(context.getApplicationContext(), Locale.ENGLISH);
235
+ }
236
+ }
237
+ return geocoder;
238
+ }
239
+ }
@@ -0,0 +1,39 @@
1
+ package ee.forgr.capacitor_nativegeocoder;
2
+
3
+ import com.getcapacitor.JSObject;
4
+ import com.getcapacitor.Plugin;
5
+ import com.getcapacitor.PluginCall;
6
+ import com.getcapacitor.PluginMethod;
7
+ import com.getcapacitor.annotation.CapacitorPlugin;
8
+
9
+ @CapacitorPlugin(name = "NativeGeocoder")
10
+ public class NativeGeocoderPlugin extends Plugin {
11
+
12
+ private NativeGeocoder implementation = new NativeGeocoder();
13
+
14
+ @Override
15
+ public void load() {
16
+ super.load();
17
+ implementation.context = this.getContext()
18
+ }
19
+
20
+ @PluginMethod
21
+ public void reverseGeocode(PluginCall call) {
22
+ String addressString = call.getString("addressString");
23
+ if (addressString == null) {
24
+ call.reject("Missing addressString");
25
+ return;
26
+ }
27
+ implementation.reverseGeocode(addressString, call)
28
+ }
29
+ @PluginMethod
30
+ public void forwardGeocode(PluginCall call) {
31
+ Number latitude = call.getNumber("latitude");
32
+ Number longitude = call.getNumber("longitude");
33
+ if (latitude == null || longitude == null) {
34
+ call.reject("Missing latitude or longitude");
35
+ return;
36
+ }
37
+ implementation.forwardGeocode(latitude, longitude, call)
38
+ }
39
+ }
File without changes