Skip to content
This repository was archived by the owner on Jul 2, 2025. It is now read-only.

Commit ec63756

Browse files
authored
Merge pull request #464 from googlesamples/yang
2 parents 6434e6d + 0bfd15c commit ec63756

21 files changed

+612
-25
lines changed

android/canonical/app/build.gradle

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
apply plugin: 'com.android.application'
22
apply plugin: 'kotlin-android'
33
apply plugin: 'kotlin-android-extensions'
4+
apply plugin: 'kotlin-kapt'
45

56
android {
67
compileSdkVersion 29
78
buildToolsVersion "29.0.3"
89

10+
buildFeatures {
11+
dataBinding true
12+
}
13+
914
defaultConfig {
1015
applicationId "com.google.samples.quickstart.canonical"
1116
minSdkVersion 16
@@ -27,9 +32,16 @@ android {
2732
dependencies {
2833
implementation fileTree(dir: "libs", include: ["*.jar"])
2934
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
30-
implementation 'androidx.core:core-ktx:1.1.0'
35+
implementation 'androidx.core:core-ktx:1.3.0'
3136
implementation 'androidx.appcompat:appcompat:1.1.0'
3237
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
38+
implementation 'com.google.android.gms:play-services-auth:18.0.0'
39+
implementation 'com.google.android.material:material:1.1.0'
40+
implementation 'com.google.android.gms:play-services-maps:17.0.0'
41+
implementation 'com.google.android.gms:play-services-location:17.0.0'
42+
implementation "android.arch.lifecycle:extensions:1.1.1"
43+
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
44+
kapt 'com.android.databinding:compiler:3.1.4'
3345
testImplementation 'junit:junit:4.12'
3446
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
3547
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<resources>
2+
<!--
3+
TODO: Before you run your application, you need a Google Maps API key.
4+
5+
To get one, follow this link, follow the directions and press "Create" at the end:
6+
7+
https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=CF:9E:07:3A:08:E9:41:50:B3:2D:4C:6E:50:04:A5:E2:6A:64:72:87%3Bcom.google.samples.quickstart.canonical
8+
9+
You can also add your credentials to an existing key, using these values:
10+
11+
Package name:
12+
com.google.samples.quickstart.canonical
13+
14+
SHA-1 certificate fingerprint:
15+
CF:9E:07:3A:08:E9:41:50:B3:2D:4C:6E:50:04:A5:E2:6A:64:72:87
16+
17+
Alternatively, follow the directions here:
18+
https://developers.google.com/maps/documentation/android/start#get-key
19+
20+
Once you have your key (it starts with "AIza"), replace the "google_maps_key"
21+
string in this file.
22+
-->
23+
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">AIzaSyDz7brZFFw7tIg8bQLCALELeHp4JNkZmJo</string>
24+
25+
</resources>

android/canonical/app/src/main/AndroidManifest.xml

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,40 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="com.google.samples.quickstart.canonical">
44

5-
<application
6-
android:allowBackup="true"
7-
android:icon="@mipmap/ic_launcher"
8-
android:label="@string/app_name"
9-
android:roundIcon="@mipmap/ic_launcher_round"
10-
android:supportsRtl="true"
11-
android:theme="@style/AppTheme">
12-
<activity android:name=".MainActivity">
13-
<intent-filter>
14-
<action android:name="android.intent.action.MAIN" />
5+
<!--
6+
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
7+
Google Maps Android API v2, but you must specify either coarse or fine
8+
location permissions for the "MyLocation" functionality.
9+
-->
10+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
1511

16-
<category android:name="android.intent.category.LAUNCHER" />
17-
</intent-filter>
18-
</activity>
19-
</application>
12+
<application
13+
android:allowBackup="true"
14+
android:icon="@mipmap/ic_launcher"
15+
android:label="@string/app_name"
16+
android:roundIcon="@mipmap/ic_launcher_round"
17+
android:supportsRtl="true"
18+
android:theme="@style/AppTheme">
19+
20+
<!--
21+
The API key for Google Maps-based APIs is defined as a string resource.
22+
(See the file "res/values/google_maps_api.xml").
23+
Note that the API key is linked to the encryption key used to sign the APK.
24+
You need a different API key for each encryption key, including the release key that is used to
25+
sign the APK for publishing.
26+
You can define the keys for the debug and release targets in src/debug/ and src/release/.
27+
-->
28+
<meta-data
29+
android:name="com.google.android.geo.API_KEY"
30+
android:value="@string/google_maps_key" />
31+
32+
<activity android:name=".MainActivity">
33+
<intent-filter>
34+
<action android:name="android.intent.action.MAIN" />
35+
36+
<category android:name="android.intent.category.LAUNCHER" />
37+
</intent-filter>
38+
</activity>
39+
</application>
2040

2141
</manifest>

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/MainActivity.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,61 @@ package com.google.samples.quickstart.canonical
22

33
import androidx.appcompat.app.AppCompatActivity
44
import android.os.Bundle
5+
import androidx.fragment.app.FragmentTransaction
6+
import com.google.android.material.bottomnavigation.BottomNavigationView
57

68
class MainActivity : AppCompatActivity() {
9+
710
override fun onCreate(savedInstanceState: Bundle?) {
811
super.onCreate(savedInstanceState)
912
setContentView(R.layout.activity_main)
13+
14+
val runFragment = RunFragment()
15+
supportFragmentManager
16+
.beginTransaction()
17+
.replace(R.id.fragment_container, runFragment)
18+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
19+
.commit()
20+
21+
val bottomNavigation : BottomNavigationView = findViewById(R.id.bottom_navigation_view)
22+
bottomNavigation.setOnNavigationItemSelectedListener { item ->
23+
when (item.itemId) {
24+
25+
R.id.bottom_navigation_item_run -> {
26+
val runFragment = RunFragment()
27+
supportFragmentManager
28+
.beginTransaction()
29+
.replace(R.id.fragment_container, runFragment)
30+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
31+
.commit()
32+
true
33+
}
34+
35+
R.id.bottom_navigation_item_map -> {
36+
val mapsFragment = MapsFragment()
37+
supportFragmentManager
38+
.beginTransaction()
39+
.replace(R.id.fragment_container, mapsFragment)
40+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
41+
.commit()
42+
true
43+
}
44+
45+
R.id.bottom_navigation_item_profile -> {
46+
val meFragment = MeFragment()
47+
supportFragmentManager
48+
.beginTransaction()
49+
.replace(R.id.fragment_container, meFragment)
50+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
51+
.commit()
52+
true
53+
}
54+
55+
else -> false
56+
}
57+
}
1058
}
59+
60+
61+
1162
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.google.samples.quickstart.canonical
2+
3+
import android.Manifest
4+
import android.app.Activity
5+
import android.content.pm.PackageManager
6+
import android.location.Location
7+
import androidx.fragment.app.Fragment
8+
9+
import android.os.Bundle
10+
import android.view.LayoutInflater
11+
import android.view.View
12+
import android.view.ViewGroup
13+
import androidx.core.content.ContextCompat.checkSelfPermission
14+
import com.google.android.gms.location.FusedLocationProviderClient
15+
import com.google.android.gms.location.LocationServices
16+
17+
import com.google.android.gms.maps.CameraUpdateFactory
18+
import com.google.android.gms.maps.GoogleMap
19+
import com.google.android.gms.maps.OnMapReadyCallback
20+
import com.google.android.gms.maps.SupportMapFragment
21+
import com.google.android.gms.maps.model.LatLng
22+
import com.google.android.gms.maps.model.MarkerOptions
23+
24+
class MapsFragment : Fragment() {
25+
26+
private lateinit var map: GoogleMap
27+
private lateinit var fusedLocationClient: FusedLocationProviderClient
28+
private lateinit var lastLocation: Location
29+
30+
companion object {
31+
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
32+
}
33+
34+
override fun onRequestPermissionsResult(requestCode: Int,
35+
permissions: Array<String>, grantResults: IntArray) {
36+
when (requestCode) {
37+
LOCATION_PERMISSION_REQUEST_CODE -> {
38+
// If request is cancelled, the result arrays are empty.
39+
if ((grantResults.isNotEmpty() &&
40+
grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
41+
setUpMap()
42+
} else {
43+
// Explain to the user that the feature is unavailable because
44+
// the features requires a permission that the user has denied.
45+
}
46+
return
47+
}
48+
else -> {
49+
// Ignore all other requests.
50+
}
51+
}
52+
}
53+
54+
private fun setUpMap() {
55+
if (checkSelfPermission(context as Activity,
56+
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
57+
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
58+
return
59+
}
60+
61+
map.isMyLocationEnabled = true
62+
63+
fusedLocationClient.lastLocation.addOnSuccessListener(this.activity as Activity) { location ->
64+
// Got last known location. In some rare situations this can be null.
65+
if (location != null) {
66+
lastLocation = location
67+
val currentLatLng = LatLng(location.latitude, location.longitude)
68+
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
69+
map.addMarker(MarkerOptions().position(currentLatLng).title("My location"))
70+
map.moveCamera(CameraUpdateFactory.newLatLng(currentLatLng))
71+
}
72+
}
73+
}
74+
75+
76+
private val mapReadyCallback = OnMapReadyCallback { googleMap ->
77+
/**
78+
* Manipulates the map once available.
79+
* This callback is triggered when the map is ready to be used.
80+
* This is where we can add markers or lines, add listeners or move the camera.
81+
* In this case, we just add a marker near Sydney, Australia.
82+
* If Google Play services is not installed on the device, the user will be prompted to
83+
* install it inside the SupportMapFragment. This method will only be triggered once the
84+
* user has installed Google Play services and returned to the app.
85+
*/
86+
map = googleMap
87+
map.uiSettings.isZoomControlsEnabled = true
88+
setUpMap()
89+
}
90+
91+
override fun onCreateView(
92+
inflater: LayoutInflater,
93+
container: ViewGroup?,
94+
savedInstanceState: Bundle?
95+
): View? {
96+
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this.activity as Activity)
97+
return inflater.inflate(R.layout.fragment_maps, container, false)
98+
}
99+
100+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
101+
super.onViewCreated(view, savedInstanceState)
102+
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
103+
mapFragment?.getMapAsync(mapReadyCallback)
104+
}
105+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.google.samples.quickstart.canonical
2+
3+
import android.os.Bundle
4+
import androidx.fragment.app.Fragment
5+
import android.view.LayoutInflater
6+
import android.view.View
7+
import android.view.ViewGroup
8+
9+
// TODO: Rename parameter arguments, choose names that match
10+
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
11+
private const val ARG_PARAM1 = "param1"
12+
private const val ARG_PARAM2 = "param2"
13+
14+
/**
15+
* A simple [Fragment] subclass.
16+
* Use the [MeFragment.newInstance] factory method to
17+
* create an instance of this fragment.
18+
*/
19+
class MeFragment : Fragment() {
20+
// TODO: Rename and change types of parameters
21+
private var param1: String? = null
22+
private var param2: String? = null
23+
24+
override fun onCreate(savedInstanceState: Bundle?) {
25+
super.onCreate(savedInstanceState)
26+
arguments?.let {
27+
param1 = it.getString(ARG_PARAM1)
28+
param2 = it.getString(ARG_PARAM2)
29+
}
30+
}
31+
32+
override fun onCreateView(
33+
inflater: LayoutInflater, container: ViewGroup?,
34+
savedInstanceState: Bundle?
35+
): View? {
36+
// Inflate the layout for this fragment
37+
return inflater.inflate(R.layout.fragment_me, container, false)
38+
}
39+
40+
companion object {
41+
/**
42+
* Use this factory method to create a new instance of
43+
* this fragment using the provided parameters.
44+
*
45+
* @param param1 Parameter 1.
46+
* @param param2 Parameter 2.
47+
* @return A new instance of fragment MeFragment.
48+
*/
49+
// TODO: Rename and change types and number of parameters
50+
@JvmStatic
51+
fun newInstance(param1: String, param2: String) =
52+
MeFragment().apply {
53+
arguments = Bundle().apply {
54+
putString(ARG_PARAM1, param1)
55+
putString(ARG_PARAM2, param2)
56+
}
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)