aboutsummaryrefslogtreecommitdiff
path: root/androidApp
diff options
context:
space:
mode:
Diffstat (limited to 'androidApp')
-rw-r--r--androidApp/build.gradle.kts27
-rw-r--r--androidApp/src/google/AndroidManifest.xml28
-rw-r--r--androidApp/src/google/java/GoogleMainApplication.kt62
-rw-r--r--androidApp/src/google/java/ManagerMessagingService.kt54
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt2
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt38
-rw-r--r--androidApp/src/main/res/drawable/icon_notify.xml28
-rw-r--r--androidApp/src/main/res/values/strings.xml3
8 files changed, 238 insertions, 4 deletions
diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts
index 22d894a..eecf55b 100644
--- a/androidApp/build.gradle.kts
+++ b/androidApp/build.gradle.kts
@@ -7,7 +7,7 @@ plugins {
android {
compileSdk = 31
defaultConfig {
- applicationId = "mx.trackermap.TrackerMap.android"
+ applicationId = "mx.trackermap.TrackerMap"
minSdk = 21
targetSdk = 31
versionCode = 1
@@ -21,8 +21,22 @@ android {
buildFeatures {
viewBinding = true
}
+
+ flavorDimensionList.add("regular")
+ productFlavors {
+ create("regular") {
+ dimension = "regular"
+ isDefault = true
+ }
+ create("google") {
+ dimension = "regular"
+ isDefault = true
+ }
+ }
}
+val googleImplementation by configurations
+
dependencies {
implementation(project(":shared"))
implementation("com.google.android.material:material:1.4.0")
@@ -32,12 +46,21 @@ dependencies {
implementation("com.github.Zhuinden:live-event:1.2.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0")
+ implementation("androidx.preference:preference-ktx:1.1.1")
implementation("io.insert-koin:koin-android:3.1.4")
implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.fragment:fragment-ktx:1.4.0")
implementation("io.ktor:ktor-client-serialization:1.6.6")
+ implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.1")
implementation("com.github.zerobranch:SwipeLayout:1.3.1")
implementation("com.github.addisonElliott:SegmentedButton:3.1.9")
implementation("mil.nga.sf:sf-wkt:1.0.1")
implementation(group = "", name = "WhirlyGlobeMaply", ext = "aar")
-} \ No newline at end of file
+
+ googleImplementation(platform("com.google.firebase:firebase-bom:29.0.3"))
+ googleImplementation("com.google.firebase:firebase-messaging")
+}
+
+if (gradle.startParameter.taskRequests.toString().contains("Google")) {
+ apply(plugin = "com.google.gms.google-services")
+}
diff --git a/androidApp/src/google/AndroidManifest.xml b/androidApp/src/google/AndroidManifest.xml
new file mode 100644
index 0000000..f7aea6c
--- /dev/null
+++ b/androidApp/src/google/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="mx.trackermap.TrackerMap.android">
+
+ <application
+ android:name=".GoogleMainApplication"
+ tools:replace="android:name"
+ tools:ignore="GoogleAppIndexingWarning">
+
+ <meta-data
+ android:name="com.google.firebase.messaging.default_notification_channel_id"
+ android:value="@string/notification_channel_id" />
+
+ <meta-data
+ android:name="com.google.firebase.messaging.default_notification_icon"
+ android:resource="@drawable/icon_notify" />
+
+ <service android:exported="false" android:name=".ManagerMessagingService">
+ <intent-filter>
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
+ </intent-filter>
+ </service>
+
+ </application>
+
+</manifest>
diff --git a/androidApp/src/google/java/GoogleMainApplication.kt b/androidApp/src/google/java/GoogleMainApplication.kt
new file mode 100644
index 0000000..96062e1
--- /dev/null
+++ b/androidApp/src/google/java/GoogleMainApplication.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 - 2021 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * 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 mx.trackermap.TrackerMap.android
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Build
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import com.google.firebase.messaging.FirebaseMessaging
+import kotlinx.coroutines.DelicateCoroutinesApi
+import mx.trackermap.TrackerMap.android.session.LoginFragment
+
+@DelicateCoroutinesApi
+class GoogleMainApplication : TrackerApp() {
+
+ override fun onCreate() {
+ super.onCreate()
+ val intentFilter = IntentFilter(LoginFragment.EVENT_LOGIN)
+ LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val channel = NotificationChannel(
+ getString(R.string.notification_channel_id),
+ getString(R.string.notification_channel),
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+ (getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(channel)
+ }
+ }
+
+ private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ FirebaseMessaging.getInstance().token.addOnCompleteListener {
+ if (it.isSuccessful) {
+ broadcastToken(it.result)
+ }
+ }
+ }
+ }
+
+ fun broadcastToken(token: String?) {
+ val intent = Intent(LoginFragment.EVENT_TOKEN)
+ intent.putExtra(LoginFragment.KEY_TOKEN, token)
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
+ }
+}
diff --git a/androidApp/src/google/java/ManagerMessagingService.kt b/androidApp/src/google/java/ManagerMessagingService.kt
new file mode 100644
index 0000000..b10475f
--- /dev/null
+++ b/androidApp/src/google/java/ManagerMessagingService.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 - 2021 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * 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 mx.trackermap.TrackerMap.android
+
+import android.annotation.SuppressLint
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import com.google.firebase.messaging.FirebaseMessagingService
+import com.google.firebase.messaging.RemoteMessage
+import kotlinx.coroutines.DelicateCoroutinesApi
+import mx.trackermap.TrackerMap.android.units.UnitsActivity
+
+@DelicateCoroutinesApi
+class ManagerMessagingService : FirebaseMessagingService() {
+
+ @SuppressLint("UnspecifiedImmutableFlag")
+ override fun onMessageReceived(remoteMessage: RemoteMessage) {
+ super.onMessageReceived(remoteMessage)
+ val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
+ } else {
+ PendingIntent.FLAG_ONE_SHOT
+ }
+ val pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, UnitsActivity::class.java), flags)
+ val builder = NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
+ .setSmallIcon(R.drawable.icon_notify)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(remoteMessage.notification?.body)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ (getSystemService(NOTIFICATION_SERVICE) as NotificationManager).notify(remoteMessage.hashCode(), builder.build())
+ }
+
+ override fun onNewToken(token: String) {
+ super.onNewToken(token)
+ (application as GoogleMainApplication).broadcastToken(token)
+ }
+}
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
index cdb7102..4cbf8e5 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
@@ -19,7 +19,7 @@ import org.koin.core.logger.Level
import org.koin.dsl.module
@DelicateCoroutinesApi
-class TrackerApp : Application() {
+open class TrackerApp : Application() {
override fun onCreate() {
super.onCreate()
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt
index 674c2d3..185a444 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt
@@ -1,6 +1,6 @@
package mx.trackermap.TrackerMap.android.session
-import android.content.Intent
+import android.content.*
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
@@ -9,6 +9,8 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.Fragment
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import androidx.preference.PreferenceManager
import com.zhuinden.liveevent.observe
import kotlinx.coroutines.DelicateCoroutinesApi
import mx.trackermap.TrackerMap.android.databinding.LoginBinding
@@ -20,6 +22,7 @@ class LoginFragment : Fragment() {
private var _binding: LoginBinding? = null
private val binding get() = _binding!!
private val loginViewModel: LoginViewModel by viewModel()
+ private lateinit var broadcastManager: LocalBroadcastManager
override fun onCreateView(
inflater: LayoutInflater,
@@ -35,9 +38,21 @@ class LoginFragment : Fragment() {
setupEvents()
setupObservers()
+ broadcastManager = LocalBroadcastManager.getInstance(activity!!)
loginViewModel.restoreSession()
}
+ override fun onStart() {
+ super.onStart()
+ val intentFilter = IntentFilter(EVENT_TOKEN)
+ broadcastManager.registerReceiver(broadcastReceiver, intentFilter)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ broadcastManager.unregisterReceiver(broadcastReceiver)
+ }
+
override fun onDestroyView() {
super.onDestroyView()
_binding = null
@@ -72,6 +87,7 @@ class LoginFragment : Fragment() {
Toast.makeText(context, "Failed login", Toast.LENGTH_SHORT).show()
}
LoginViewModel.LoginState.Success -> {
+ broadcastManager.sendBroadcast(Intent(EVENT_LOGIN))
val activity = requireActivity()
val intent = Intent(activity.applicationContext, UnitsActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
@@ -81,4 +97,24 @@ class LoginFragment : Fragment() {
}
}
}
+
+ private val broadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(p0: Context?, p1: Intent?) {
+ p1?.getStringExtra(KEY_TOKEN)?.let { token ->
+ PreferenceManager
+ .getDefaultSharedPreferences(activity)
+ .edit()
+ .putString(PREFERENCE_TOKEN, token)
+ .apply()
+ }
+ }
+ }
+
+ companion object {
+ const val EVENT_LOGIN = "eventLogin"
+ const val EVENT_TOKEN = "eventToken"
+ const val KEY_TOKEN = "keyToken"
+
+ const val PREFERENCE_TOKEN = "token"
+ }
} \ No newline at end of file
diff --git a/androidApp/src/main/res/drawable/icon_notify.xml b/androidApp/src/main/res/drawable/icon_notify.xml
new file mode 100644
index 0000000..c92915e
--- /dev/null
+++ b/androidApp/src/main/res/drawable/icon_notify.xml
@@ -0,0 +1,28 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="31.75"
+ android:viewportHeight="31.75">
+ <path
+ android:pathData="m16.7714,15.5323c5.3724,1.0493 7.469,14.6249 7.469,14.6249 0,0 -0.3949,-10.5539 -8.531,-11.6354 -6.4938,-0.8632 -11.1417,7.5606 -11.1417,7.5606 0,0 6.9261,-11.581 12.2037,-10.5502z"
+ android:strokeLineJoin="bevel"
+ android:strokeWidth="1.8058915"
+ android:fillColor="#ff3232"
+ android:strokeColor="#ff3232"
+ android:strokeLineCap="butt"/>
+ <path
+ android:pathData="m18.261,8.9784c5.3724,1.0493 7.469,14.6249 7.469,14.6249 0,0 -0.3949,-10.5539 -8.531,-11.6354 -6.4938,-0.8632 -11.1417,7.5606 -11.1417,7.5606 0,0 6.9261,-11.581 12.2037,-10.5502z"
+ android:strokeLineJoin="bevel"
+ android:strokeWidth="1.8058915"
+ android:fillColor="#ff3232"
+ android:strokeColor="#ff3232"
+ android:strokeLineCap="butt"/>
+ <path
+ android:pathData="m19.6015,2.4245c5.3724,1.0493 7.469,14.6249 7.469,14.6249 0,0 -0.3949,-10.5539 -8.531,-11.6354 -6.4938,-0.8632 -11.1417,7.5606 -11.1417,7.5606 0,0 6.9261,-11.581 12.2037,-10.5502z"
+ android:strokeLineJoin="bevel"
+ android:strokeWidth="1.8058915"
+ android:fillColor="#ff3232"
+ android:strokeColor="#ff3232"
+ android:strokeLineCap="butt"/>
+</vector>
diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml
index b8080f5..5f39ce1 100644
--- a/androidApp/src/main/res/values/strings.xml
+++ b/androidApp/src/main/res/values/strings.xml
@@ -20,6 +20,9 @@
https://mt0.google.com/vt/lyrs=y&amp;hl=en&amp;x={x}&amp;y={y}&amp;z={z}&amp;s=Ga
</string>
+ <string name="notification_channel_id" translatable="false">default</string>
+ <string name="notification_channel" translatable="false">Default</string>
+
<!-- LoginActivity -->
<string name="login_username">Username</string>
<string name="login_password">Password</string>