diff --git a/.dependabot/config.yml b/.dependabot/config.yml index 1c70e7ae..1c2ab467 100644 --- a/.dependabot/config.yml +++ b/.dependabot/config.yml @@ -24,12 +24,24 @@ update_configs: commit_message: prefix: "chore(deps)" + - package_manager: "java:gradle" + directory: "./tutorials/kotlin/CurrentPlaceDetailsOnMap/" + update_schedule: "daily" + commit_message: + prefix: "chore(deps)" + - package_manager: "java:gradle" directory: "./tutorials/java/MapWithMarker/" update_schedule: "daily" commit_message: prefix: "chore(deps)" + - package_manager: "java:gradle" + directory: "./tutorials/kotlin/MapWithMarker/" + update_schedule: "daily" + commit_message: + prefix: "chore(deps)" + - package_manager: "java:gradle" directory: "./tutorials/java/Polygons/" update_schedule: "daily" @@ -37,13 +49,13 @@ update_configs: prefix: "chore(deps)" - package_manager: "java:gradle" - directory: "./tutorials/java/StyledMap/" + directory: "./tutorials/kotlin/Polygons/" update_schedule: "daily" commit_message: prefix: "chore(deps)" - package_manager: "java:gradle" - directory: "./tutorials/kotlin/MapWithMarker/" + directory: "./tutorials/java/StyledMap/" update_schedule: "daily" commit_message: prefix: "chore(deps)" diff --git a/tutorials/java/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java b/tutorials/java/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java index 5dd30794..f3a6d027 100644 --- a/tutorials/java/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java +++ b/tutorials/java/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java @@ -62,75 +62,88 @@ public class MapsActivityCurrentPlace extends AppCompatActivity implements OnMapReadyCallback { private static final String TAG = MapsActivityCurrentPlace.class.getSimpleName(); - private GoogleMap mMap; - private CameraPosition mCameraPosition; + private GoogleMap map; + private CameraPosition cameraPosition; // The entry point to the Places API. - private PlacesClient mPlacesClient; + private PlacesClient placesClient; // The entry point to the Fused Location Provider. - private FusedLocationProviderClient mFusedLocationProviderClient; + private FusedLocationProviderClient fusedLocationProviderClient; // A default location (Sydney, Australia) and default zoom to use when location permission is // not granted. - private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085); + private final LatLng defaultLocation = new LatLng(-33.8523341, 151.2106085); private static final int DEFAULT_ZOOM = 15; private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1; - private boolean mLocationPermissionGranted; + private boolean locationPermissionGranted; // The geographical location where the device is currently located. That is, the last-known // location retrieved by the Fused Location Provider. - private Location mLastKnownLocation; + private Location lastKnownLocation; // Keys for storing activity state. + // [START maps_current_place_state_keys] private static final String KEY_CAMERA_POSITION = "camera_position"; private static final String KEY_LOCATION = "location"; + // [END maps_current_place_state_keys] // Used for selecting the current place. private static final int M_MAX_ENTRIES = 5; - private String[] mLikelyPlaceNames; - private String[] mLikelyPlaceAddresses; - private List[] mLikelyPlaceAttributions; - private LatLng[] mLikelyPlaceLatLngs; + private String[] likelyPlaceNames; + private String[] likelyPlaceAddresses; + private List[] likelyPlaceAttributions; + private LatLng[] likelyPlaceLatLngs; + // [START maps_current_place_on_create] @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // [START_EXCLUDE silent] + // [START maps_current_place_on_create_save_instance_state] // Retrieve location and camera position from saved instance state. if (savedInstanceState != null) { - mLastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION); - mCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION); + lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION); + cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION); } + // [END maps_current_place_on_create_save_instance_state] + // [END_EXCLUDE] // Retrieve the content view that renders the map. setContentView(R.layout.activity_maps); + // [START_EXCLUDE silent] // Construct a PlacesClient Places.initialize(getApplicationContext(), getString(R.string.google_maps_key)); - mPlacesClient = Places.createClient(this); + placesClient = Places.createClient(this); // Construct a FusedLocationProviderClient. - mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); // Build the map. + // [START maps_current_place_map_fragment] SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); - + // [END maps_current_place_map_fragment] + // [END_EXCLUDE] } + // [END maps_current_place_on_create] /** * Saves the state of the map when the activity is paused. */ + // [START maps_current_place_on_save_instance_state] @Override protected void onSaveInstanceState(Bundle outState) { - if (mMap != null) { - outState.putParcelable(KEY_CAMERA_POSITION, mMap.getCameraPosition()); - outState.putParcelable(KEY_LOCATION, mLastKnownLocation); - super.onSaveInstanceState(outState); + if (map != null) { + outState.putParcelable(KEY_CAMERA_POSITION, map.getCameraPosition()); + outState.putParcelable(KEY_LOCATION, lastKnownLocation); } + super.onSaveInstanceState(outState); } + // [END maps_current_place_on_save_instance_state] /** * Sets up the options menu. @@ -148,6 +161,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity * @param item The menu item to handle. * @return Boolean. */ + // [START maps_current_place_on_options_item_selected] @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.option_get_place) { @@ -155,18 +169,22 @@ public class MapsActivityCurrentPlace extends AppCompatActivity } return true; } + // [END maps_current_place_on_options_item_selected] /** * Manipulates the map when it's available. * This callback is triggered when the map is ready to be used. */ + // [START maps_current_place_on_map_ready] @Override public void onMapReady(GoogleMap map) { - mMap = map; + this.map = map; + // [START_EXCLUDE] + // [START map_current_place_set_info_window_adapter] // Use a custom info window adapter to handle multiple lines of text in the // info window contents. - mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { + this.map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { @Override // Return null here, so that getInfoContents() is called next. @@ -189,9 +207,11 @@ public class MapsActivityCurrentPlace extends AppCompatActivity return infoWindow; } }); + // [END map_current_place_set_info_window_adapter] // Prompt the user for permission. getLocationPermission(); + // [END_EXCLUDE] // Turn on the My Location layer and the related control on the map. updateLocationUI(); @@ -199,48 +219,51 @@ public class MapsActivityCurrentPlace extends AppCompatActivity // Get the current location of the device and set the position of the map. getDeviceLocation(); } + // [END maps_current_place_on_map_ready] /** * Gets the current location of the device, and positions the map's camera. */ + // [START maps_current_place_get_device_location] private void getDeviceLocation() { /* * Get the best and most recent location of the device, which may be null in rare * cases when a location is not available. */ try { - if (mLocationPermissionGranted) { - Task locationResult = mFusedLocationProviderClient.getLastLocation(); + if (locationPermissionGranted) { + Task locationResult = fusedLocationProviderClient.getLastLocation(); locationResult.addOnCompleteListener(this, new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { // Set the map's camera position to the current location of the device. - mLastKnownLocation = task.getResult(); - if (mLastKnownLocation != null) { - mMap.moveCamera(CameraUpdateFactory.newLatLngZoom( - new LatLng(mLastKnownLocation.getLatitude(), - mLastKnownLocation.getLongitude()), DEFAULT_ZOOM)); + lastKnownLocation = task.getResult(); + if (lastKnownLocation != null) { + map.moveCamera(CameraUpdateFactory.newLatLngZoom( + new LatLng(lastKnownLocation.getLatitude(), + lastKnownLocation.getLongitude()), DEFAULT_ZOOM)); } } else { Log.d(TAG, "Current location is null. Using defaults."); Log.e(TAG, "Exception: %s", task.getException()); - mMap.moveCamera(CameraUpdateFactory - .newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM)); - mMap.getUiSettings().setMyLocationButtonEnabled(false); + map.moveCamera(CameraUpdateFactory + .newLatLngZoom(defaultLocation, DEFAULT_ZOOM)); + map.getUiSettings().setMyLocationButtonEnabled(false); } } }); } } catch (SecurityException e) { - Log.e("Exception: %s", e.getMessage()); + Log.e("Exception: %s", e.getMessage(), e); } } - + // [END maps_current_place_get_device_location] /** * Prompts the user for permission to use the device location. */ + // [START maps_current_place_location_permission] private void getLocationPermission() { /* * Request location permission, so that we can get the location of the @@ -250,44 +273,48 @@ public class MapsActivityCurrentPlace extends AppCompatActivity if (ContextCompat.checkSelfPermission(this.getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { - mLocationPermissionGranted = true; + locationPermissionGranted = true; } else { ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); } } + // [END maps_current_place_location_permission] /** * Handles the result of the request for location permissions. */ + // [START maps_current_place_on_request_permissions_result] @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - mLocationPermissionGranted = false; + locationPermissionGranted = false; switch (requestCode) { case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - mLocationPermissionGranted = true; + locationPermissionGranted = true; } } } updateLocationUI(); } + // [END maps_current_place_on_request_permissions_result] /** * Prompts the user to select the current place from a list of likely places, and shows the * current place on the map - provided the user has granted location permission. */ + // [START maps_current_place_show_current_place] private void showCurrentPlace() { - if (mMap == null) { + if (map == null) { return; } - if (mLocationPermissionGranted) { + if (locationPermissionGranted) { // Use fields to define the data types to return. List placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG); @@ -300,7 +327,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity // are the best match for the device's current location. @SuppressWarnings("MissingPermission") final Task placeResult = - mPlacesClient.findCurrentPlace(request); + placesClient.findCurrentPlace(request); placeResult.addOnCompleteListener (new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { @@ -316,18 +343,18 @@ public class MapsActivityCurrentPlace extends AppCompatActivity } int i = 0; - mLikelyPlaceNames = new String[count]; - mLikelyPlaceAddresses = new String[count]; - mLikelyPlaceAttributions = new List[count]; - mLikelyPlaceLatLngs = new LatLng[count]; + likelyPlaceNames = new String[count]; + likelyPlaceAddresses = new String[count]; + likelyPlaceAttributions = new List[count]; + likelyPlaceLatLngs = new LatLng[count]; for (PlaceLikelihood placeLikelihood : likelyPlaces.getPlaceLikelihoods()) { // Build a list of likely places to show the user. - mLikelyPlaceNames[i] = placeLikelihood.getPlace().getName(); - mLikelyPlaceAddresses[i] = placeLikelihood.getPlace().getAddress(); - mLikelyPlaceAttributions[i] = placeLikelihood.getPlace() + likelyPlaceNames[i] = placeLikelihood.getPlace().getName(); + likelyPlaceAddresses[i] = placeLikelihood.getPlace().getAddress(); + likelyPlaceAttributions[i] = placeLikelihood.getPlace() .getAttributions(); - mLikelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng(); + likelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng(); i++; if (i > (count - 1)) { @@ -349,40 +376,42 @@ public class MapsActivityCurrentPlace extends AppCompatActivity Log.i(TAG, "The user did not grant location permission."); // Add a default marker, because the user hasn't selected a place. - mMap.addMarker(new MarkerOptions() + map.addMarker(new MarkerOptions() .title(getString(R.string.default_info_title)) - .position(mDefaultLocation) + .position(defaultLocation) .snippet(getString(R.string.default_info_snippet))); // Prompt the user for permission. getLocationPermission(); } } + // [END maps_current_place_show_current_place] /** * Displays a form allowing the user to select a place from a list of likely places. */ + // [START maps_current_place_open_places_dialog] private void openPlacesDialog() { // Ask the user to choose the place where they are now. DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // The "which" argument contains the position of the selected item. - LatLng markerLatLng = mLikelyPlaceLatLngs[which]; - String markerSnippet = mLikelyPlaceAddresses[which]; - if (mLikelyPlaceAttributions[which] != null) { - markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[which]; + LatLng markerLatLng = likelyPlaceLatLngs[which]; + String markerSnippet = likelyPlaceAddresses[which]; + if (likelyPlaceAttributions[which] != null) { + markerSnippet = markerSnippet + "\n" + likelyPlaceAttributions[which]; } // Add a marker for the selected place, with an info window // showing information about that place. - mMap.addMarker(new MarkerOptions() - .title(mLikelyPlaceNames[which]) + map.addMarker(new MarkerOptions() + .title(likelyPlaceNames[which]) .position(markerLatLng) .snippet(markerSnippet)); // Position the map's camera at the location of the marker. - mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng, + map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng, DEFAULT_ZOOM)); } }; @@ -390,29 +419,32 @@ public class MapsActivityCurrentPlace extends AppCompatActivity // Display the dialog. AlertDialog dialog = new AlertDialog.Builder(this) .setTitle(R.string.pick_place) - .setItems(mLikelyPlaceNames, listener) + .setItems(likelyPlaceNames, listener) .show(); } + // [END maps_current_place_open_places_dialog] /** * Updates the map's UI settings based on whether the user has granted location permission. */ + // [START maps_current_place_update_location_ui] private void updateLocationUI() { - if (mMap == null) { + if (map == null) { return; } try { - if (mLocationPermissionGranted) { - mMap.setMyLocationEnabled(true); - mMap.getUiSettings().setMyLocationButtonEnabled(true); + if (locationPermissionGranted) { + map.setMyLocationEnabled(true); + map.getUiSettings().setMyLocationButtonEnabled(true); } else { - mMap.setMyLocationEnabled(false); - mMap.getUiSettings().setMyLocationButtonEnabled(false); - mLastKnownLocation = null; + map.setMyLocationEnabled(false); + map.getUiSettings().setMyLocationButtonEnabled(false); + lastKnownLocation = null; getLocationPermission(); } } catch (SecurityException e) { Log.e("Exception: %s", e.getMessage()); } } + // [END maps_current_place_update_location_ui] } diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/.gitignore b/tutorials/kotlin/CurrentPlaceDetailsOnMap/.gitignore new file mode 100644 index 00000000..39fb081a --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/README.md b/tutorials/kotlin/CurrentPlaceDetailsOnMap/README.md new file mode 100644 index 00000000..1c98a921 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/README.md @@ -0,0 +1,46 @@ +Google Maps Android API Sample: Current Place Details +===================================================== + +This sample goes hand in hand with a tutorial for the Google Maps Android API: +[Select Current Place and Show Details on a Map](https://developers.google.com/maps/documentation/android-api/current-place-tutorial). + +Prerequisites +-------------- + +- Android SDK v24 +- Latest Android Build Tools +- Android Support Repository + +Getting started +--------------- + +This sample uses the Gradle build system. + +1. Download the samples by cloning this repository or downloading an archived + snapshot. (See the options at the top of the page.) +1. In Android Studio, create a new project and choose the "Import non-Android Studio project" or + "Import Project" option. +1. Select the `CurrentPlaceDetailsOnMap` directory that you downloaded with this repository. +1. If prompted for a gradle configuration, accept the default settings. + Alternatively use the "gradlew build" command to build the project directly. +1. Add your API key to your app's `gradle.properties` file. + (For information on getting an API key, see the + [documentation](https://developers.google.com/maps/documentation/android-api/signup).) + +Support +------- + +- Stack Overflow: https://stackoverflow.com/questions/tagged/android+google-maps + +If you have discovered an issue with the Google Maps Android API v2, please see +the resources here: https://developers.google.com/maps/documentation/android-api/support + +If you've found an error in these samples, please file an issue: +https://github.com/googlemaps/android-samples/issues + +![Analytics](https://ga-beacon.appspot.com/UA-12846745-20/android-samples-apidemos/readme?pixel) + +License +------- + +Please refer to the [LICENSE](https://github.com/googlemaps/android-samples/blob/master/LICENSE) at the root of this repo. diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/.gitignore b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle new file mode 100644 index 00000000..0bd44dc2 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 29 + buildToolsVersion '28.0.3' + defaultConfig { + applicationId "com.example.currentplacedetailsonmap" + minSdkVersion 17 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "") + } + buildTypes { + debug { + debuggable true + } + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.gms:play-services-maps:17.0.0' + implementation 'com.google.android.libraries.places:places:2.2.0' + testImplementation'junit:junit:4.13' + implementation "androidx.core:core-ktx:1.2.0" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/proguard-rules.pro b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/proguard-rules.pro new file mode 100644 index 00000000..240615e3 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/proguard-rules.pro @@ -0,0 +1,28 @@ +# +# Proguard config for a Google Maps Android API sample project. +# +# This file only contains the proguard options required by the Google Maps +# Android API v2. You should use these settings in addition to those provided by the +# Android SDK (/tools/proguard/proguard-android-optimize.txt). +# +# For more details on the use of proguard in Android, please read: +# http://proguard.sourceforge.net/manual/examples.html#androidapplication +-optimizations !code/simplification/variable +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Fragment +-keep public class * extends android.support.v4.app.Fragment +# The Maps Android API uses custom parcelables. +# Use this rule (which is slightly broader than the standard recommended one) +# to avoid obfuscating them. +-keepclassmembers class * implements android.os.Parcelable { + static *** CREATOR; +} +# The Maps Android API uses serialization. +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + static final java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/AndroidManifest.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..4e780eb1 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.kt b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.kt new file mode 100644 index 00000000..0beab5e0 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.kt @@ -0,0 +1,411 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.example.currentplacedetailsonmap + +import android.Manifest +import android.content.DialogInterface +import android.content.pm.PackageManager +import android.location.Location +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.FrameLayout +import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter +import com.google.android.gms.maps.OnMapReadyCallback +import com.google.android.gms.maps.SupportMapFragment +import com.google.android.gms.maps.model.CameraPosition +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.Marker +import com.google.android.gms.maps.model.MarkerOptions +import com.google.android.libraries.places.api.Places +import com.google.android.libraries.places.api.model.Place +import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest +import com.google.android.libraries.places.api.net.PlacesClient +import java.util.* + +/** + * An activity that displays a map showing the place at the device's current location. + */ +class MapsActivityCurrentPlace : AppCompatActivity(), OnMapReadyCallback { + private var map: GoogleMap? = null + private var cameraPosition: CameraPosition? = null + + // The entry point to the Places API. + private lateinit var placesClient: PlacesClient + + // The entry point to the Fused Location Provider. + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient + + // A default location (Sydney, Australia) and default zoom to use when location permission is + // not granted. + private val defaultLocation = LatLng(-33.8523341, 151.2106085) + private var locationPermissionGranted = false + + // The geographical location where the device is currently located. That is, the last-known + // location retrieved by the Fused Location Provider. + private var lastKnownLocation: Location? = null + private var likelyPlaceNames: Array = arrayOfNulls(0) + private var likelyPlaceAddresses: Array = arrayOfNulls(0) + private var likelyPlaceAttributions: Array?> = arrayOfNulls(0) + private var likelyPlaceLatLngs: Array = arrayOfNulls(0) + + // [START maps_current_place_on_create] + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // [START_EXCLUDE silent] + // Retrieve location and camera position from saved instance state. + // [START maps_current_place_on_create_save_instance_state] + if (savedInstanceState != null) { + lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION) + cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION) + } + // [END maps_current_place_on_create_save_instance_state] + // [END_EXCLUDE] + + // Retrieve the content view that renders the map. + setContentView(R.layout.activity_maps) + + // [START_EXCLUDE silent] + // Construct a PlacesClient + Places.initialize(applicationContext, getString(R.string.google_maps_key)) + placesClient = Places.createClient(this) + + // Construct a FusedLocationProviderClient. + fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) + + // Build the map. + // [START maps_current_place_map_fragment] + val mapFragment = supportFragmentManager + .findFragmentById(R.id.map) as SupportMapFragment? + mapFragment?.getMapAsync(this) + // [END maps_current_place_map_fragment] + // [END_EXCLUDE] + } + // [END maps_current_place_on_create] + + /** + * Saves the state of the map when the activity is paused. + */ + // [START maps_current_place_on_save_instance_state] + override fun onSaveInstanceState(outState: Bundle) { + if (map != null) { + outState.putParcelable(KEY_CAMERA_POSITION, map!!.cameraPosition) + outState.putParcelable(KEY_LOCATION, lastKnownLocation) + } + super.onSaveInstanceState(outState) + } + // [END maps_current_place_on_save_instance_state] + + /** + * Sets up the options menu. + * @param menu The options menu. + * @return Boolean. + */ + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.current_place_menu, menu) + return true + } + + /** + * Handles a click on the menu option to get a place. + * @param item The menu item to handle. + * @return Boolean. + */ + // [START maps_current_place_on_options_item_selected] + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == R.id.option_get_place) { + showCurrentPlace() + } + return true + } + // [END maps_current_place_on_options_item_selected] + + /** + * Manipulates the map when it's available. + * This callback is triggered when the map is ready to be used. + */ + // [START maps_current_place_on_map_ready] + override fun onMapReady(map: GoogleMap) { + this.map = map + + // [START_EXCLUDE] + // [START map_current_place_set_info_window_adapter] + // Use a custom info window adapter to handle multiple lines of text in the + // info window contents. + this.map?.setInfoWindowAdapter(object : InfoWindowAdapter { + // Return null here, so that getInfoContents() is called next. + override fun getInfoWindow(arg0: Marker): View? { + return null + } + + override fun getInfoContents(marker: Marker): View { + // Inflate the layouts for the info window, title and snippet. + val infoWindow = layoutInflater.inflate(R.layout.custom_info_contents, + findViewById(R.id.map), false) + val title = infoWindow.findViewById(R.id.title) + title.text = marker.title + val snippet = infoWindow.findViewById(R.id.snippet) + snippet.text = marker.snippet + return infoWindow + } + }) + // [END map_current_place_set_info_window_adapter] + + // Prompt the user for permission. + getLocationPermission() + // [END_EXCLUDE] + + // Turn on the My Location layer and the related control on the map. + updateLocationUI() + + // Get the current location of the device and set the position of the map. + getDeviceLocation() + } + // [END maps_current_place_on_map_ready] + + /** + * Gets the current location of the device, and positions the map's camera. + */ + // [START maps_current_place_get_device_location] + private fun getDeviceLocation() { + /* + * Get the best and most recent location of the device, which may be null in rare + * cases when a location is not available. + */ + try { + if (locationPermissionGranted) { + val locationResult = fusedLocationProviderClient.lastLocation + locationResult.addOnCompleteListener(this) { task -> + if (task.isSuccessful) { + // Set the map's camera position to the current location of the device. + lastKnownLocation = task.result + if (lastKnownLocation != null) { + map!!.moveCamera(CameraUpdateFactory.newLatLngZoom( + LatLng(lastKnownLocation!!.latitude, + lastKnownLocation!!.longitude), DEFAULT_ZOOM.toFloat())) + } + } else { + Log.d(TAG, "Current location is null. Using defaults.") + Log.e(TAG, "Exception: %s", task.exception) + map?.moveCamera(CameraUpdateFactory + .newLatLngZoom(defaultLocation, DEFAULT_ZOOM.toFloat())) + map?.uiSettings?.isMyLocationButtonEnabled = false + } + } + } + } catch (e: SecurityException) { + Log.e("Exception: %s", e.message, e) + } + } + // [END maps_current_place_get_device_location] + + /** + * Prompts the user for permission to use the device location. + */ + // [START maps_current_place_location_permission] + private fun getLocationPermission() { + /* + * Request location permission, so that we can get the location of the + * device. The result of the permission request is handled by a callback, + * onRequestPermissionsResult. + */ + if (ContextCompat.checkSelfPermission(this.applicationContext, + Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + locationPermissionGranted = true + } else { + ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), + PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) + } + } + // [END maps_current_place_location_permission] + + /** + * Handles the result of the request for location permissions. + */ + // [START maps_current_place_on_request_permissions_result] + override fun onRequestPermissionsResult(requestCode: Int, + permissions: Array, + grantResults: IntArray) { + locationPermissionGranted = false + when (requestCode) { + PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> { + + // If request is cancelled, the result arrays are empty. + if (grantResults.isNotEmpty() && + grantResults[0] == PackageManager.PERMISSION_GRANTED) { + locationPermissionGranted = true + } + } + } + updateLocationUI() + } + // [END maps_current_place_on_request_permissions_result] + + /** + * Prompts the user to select the current place from a list of likely places, and shows the + * current place on the map - provided the user has granted location permission. + */ + // [START maps_current_place_show_current_place] + private fun showCurrentPlace() { + if (map == null) { + return + } + if (locationPermissionGranted) { + // Use fields to define the data types to return. + val placeFields = listOf(Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG) + + // Use the builder to create a FindCurrentPlaceRequest. + val request = FindCurrentPlaceRequest.newInstance(placeFields) + + // Get the likely places - that is, the businesses and other points of interest that + // are the best match for the device's current location. + val placeResult = placesClient.findCurrentPlace(request) + placeResult.addOnCompleteListener { task -> + if (task.isSuccessful && task.result != null) { + val likelyPlaces = task.result + + // Set the count, handling cases where less than 5 entries are returned. + val count = if (likelyPlaces != null && likelyPlaces.placeLikelihoods.size < M_MAX_ENTRIES) { + likelyPlaces.placeLikelihoods.size + } else { + M_MAX_ENTRIES + } + var i = 0 + likelyPlaceNames = arrayOfNulls(count) + likelyPlaceAddresses = arrayOfNulls(count) + likelyPlaceAttributions = arrayOfNulls?>(count) + likelyPlaceLatLngs = arrayOfNulls(count) + for (placeLikelihood in likelyPlaces?.placeLikelihoods ?: emptyList()) { + // Build a list of likely places to show the user. + likelyPlaceNames[i] = placeLikelihood.place.name + likelyPlaceAddresses[i] = placeLikelihood.place.address + likelyPlaceAttributions[i] = placeLikelihood.place.attributions + likelyPlaceLatLngs[i] = placeLikelihood.place.latLng + i++ + if (i > count - 1) { + break + } + } + + // Show a dialog offering the user the list of likely places, and add a + // marker at the selected place. + openPlacesDialog() + } else { + Log.e(TAG, "Exception: %s", task.exception) + } + } + } else { + // The user has not granted permission. + Log.i(TAG, "The user did not grant location permission.") + + // Add a default marker, because the user hasn't selected a place. + map!!.addMarker(MarkerOptions() + .title(getString(R.string.default_info_title)) + .position(defaultLocation) + .snippet(getString(R.string.default_info_snippet))) + + // Prompt the user for permission. + getLocationPermission() + } + } + // [END maps_current_place_show_current_place] + + /** + * Displays a form allowing the user to select a place from a list of likely places. + */ + // [START maps_current_place_open_places_dialog] + private fun openPlacesDialog() { + // Ask the user to choose the place where they are now. + val listener = DialogInterface.OnClickListener { dialog, which -> // The "which" argument contains the position of the selected item. + val markerLatLng = likelyPlaceLatLngs[which] + var markerSnippet = likelyPlaceAddresses[which] + if (likelyPlaceAttributions[which] != null) { + markerSnippet = """ + $markerSnippet + ${likelyPlaceAttributions[which]} + """.trimIndent() + } + + // Add a marker for the selected place, with an info window + // showing information about that place. + map!!.addMarker(MarkerOptions() + .title(likelyPlaceNames[which]) + .position(markerLatLng!!) + .snippet(markerSnippet)) + + // Position the map's camera at the location of the marker. + map!!.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng, + DEFAULT_ZOOM.toFloat())) + } + + // Display the dialog. + AlertDialog.Builder(this) + .setTitle(R.string.pick_place) + .setItems(likelyPlaceNames, listener) + .show() + } + // [END maps_current_place_open_places_dialog] + + /** + * Updates the map's UI settings based on whether the user has granted location permission. + */ + // [START maps_current_place_update_location_ui] + private fun updateLocationUI() { + if (map == null) { + return + } + try { + if (locationPermissionGranted) { + map!!.isMyLocationEnabled = true + map!!.uiSettings.isMyLocationButtonEnabled = true + } else { + map!!.isMyLocationEnabled = false + map!!.uiSettings.isMyLocationButtonEnabled = false + lastKnownLocation = null + getLocationPermission() + } + } catch (e: SecurityException) { + Log.e("Exception: %s", e.message, e) + } + } + // [END maps_current_place_update_location_ui] + + companion object { + private val TAG = MapsActivityCurrentPlace::class.java.simpleName + private const val DEFAULT_ZOOM = 15 + private const val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1 + + // Keys for storing activity state. + // [START maps_current_place_state_keys] + private const val KEY_CAMERA_POSITION = "camera_position" + private const val KEY_LOCATION = "location" + // [END maps_current_place_state_keys] + + // Used for selecting the current place. + private const val M_MAX_ENTRIES = 5 + } +} \ No newline at end of file diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/activity_maps.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/activity_maps.xml new file mode 100644 index 00000000..5cd0884b --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/activity_maps.xml @@ -0,0 +1,7 @@ + diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/custom_info_contents.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/custom_info_contents.xml new file mode 100644 index 00000000..68f82fc7 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/layout/custom_info_contents.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/menu/current_place_menu.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/menu/current_place_menu.xml new file mode 100644 index 00000000..792716a2 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/menu/current_place_menu.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-hdpi/ic_launcher.png b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..cde69bcc Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-mdpi/ic_launcher.png b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..c133a0cb Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..bfa42f0e Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..324e72cd Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..aee44e13 Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/colors.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..3ab3e9cb --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/strings.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..e90fc36b --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + Current Place Details + Current Place Details + Default Location + No places found, because location permission is disabled. + Get place + Choose a place + diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/styles.xml b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..5885930d --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/build.gradle b/tutorials/kotlin/CurrentPlaceDetailsOnMap/build.gradle new file mode 100644 index 00000000..e70ae793 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.kotlin_version = '1.3.72' + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { + url 'https://maven.google.com' + } + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle.properties b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle.properties new file mode 100644 index 00000000..d85870af --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle.properties @@ -0,0 +1,24 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +android.useAndroidX=true +android.enableJetifier=true + +# Replace the value below with your own Google API key for Android app. +# To learn how to get a Google Maps Platform API key, visit: +# https://developers.google.com/maps/gmp-get-started +GOOGLE_MAPS_API_KEY=YOUR_API_KEY diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.jar b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..13372aef Binary files /dev/null and b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.properties b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..0633a9fc --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 15 11:26:52 PDT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew.bat b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/settings.gradle b/tutorials/kotlin/CurrentPlaceDetailsOnMap/settings.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/settings.gradle @@ -0,0 +1 @@ +include ':app'