Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate with Firebase In-App Messaging & Notifications #85

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,35 @@ dependencies {

implementation("com.google.android.play:app-update-ktx:2.0.1")

implementation(platform("com.google.firebase:firebase-bom:32.4.1"))
implementation(platform("com.google.firebase:firebase-bom:32.5.0"))
implementation("com.google.firebase:firebase-config")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-inappmessaging-display")
implementation("com.google.firebase:firebase-config-ktx")
implementation("com.google.firebase:firebase-messaging-ktx")
implementation("com.google.android.gms:play-services-tagmanager:18.0.4")
implementation("com.google.android.gms:play-services-measurement-api:21.4.0")

implementation("com.github.ianatha.termux:termux-shared:feat-non-proc-terms-SNAPSHOT")
implementation("com.github.ianatha.termux:terminal-view:feat-non-proc-terms-SNAPSHOT")

implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
implementation(platform("io.github.Rosemoe.sora-editor:bom:0.22.1"))
implementation("io.github.Rosemoe.sora-editor:editor")
implementation("io.github.Rosemoe.sora-editor:language-java")
implementation("io.github.Rosemoe.sora-editor:language-textmate")

implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation("androidx.activity:activity-compose:1.8.0")

implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("com.google.android.gms:play-services-measurement-api:21.4.0")
implementation("com.google.android.material:material:1.10.0")

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
Expand Down
27 changes: 20 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="com.google.android.gms.permission.AD_ID"
tools:node="remove" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

<uses-sdk tools:overrideLibrary="io.github.rosemoe.sora.lsp" />
<!-- <meta-data-->
<!-- android:name="com.google.firebase.messaging.default_notification_icon"-->
<!-- android:resource="@drawable/ic_stat_ic_notification" />-->
<!-- <meta-data-->
<!-- android:name="com.google.firebase.messaging.default_notification_color"-->
<!-- android:resource="@color/colorAccent" />-->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />

<application
android:icon="@mipmap/ic_launcher"
Expand All @@ -19,6 +25,14 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">

<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

<profileable
android:shell="true"
tools:targetApi="q" />
Expand Down Expand Up @@ -61,5 +75,4 @@
</intent-filter>
</activity>
</application>

</manifest>
4 changes: 3 additions & 1 deletion app/src/main/java/io/atha/bababasic/ActivityAbout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import io.atha.bababasic.databinding.ActivityAboutBinding

class ActivityAbout : AppCompatActivity() {
class ActivityAbout : BabaActivity() {
private lateinit var binding: ActivityAboutBinding

override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -27,5 +27,7 @@ class ActivityAbout : AppCompatActivity() {
intent.data = Uri.parse("https://github.com/ianatha/bababasic")
startActivity(intent)
}

initFirebase()
}
}
49 changes: 3 additions & 46 deletions app/src/main/java/io/atha/bababasic/ActivityMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.content.res.Configuration
import android.graphics.Typeface
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
Expand All @@ -17,13 +16,6 @@ import android.view.MenuItem
import android.view.View
import android.widget.PopupMenu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import io.atha.bababasic.databinding.ActivityMainBinding
import io.atha.bababasic.editor.switchThemeIfRequired
import io.atha.libbababasic.Interpreter.checkSyntax
Expand Down Expand Up @@ -51,9 +43,6 @@ import io.github.rosemoe.sora.widget.component.EditorAutoCompletion
import io.github.rosemoe.sora.widget.component.Magnifier
import io.github.rosemoe.sora.widget.getComponent
import io.github.rosemoe.sora.widget.subscribeEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.eclipse.tm4e.core.registry.IThemeSource
import java.io.BufferedReader
import java.io.IOException
Expand All @@ -62,49 +51,17 @@ import java.io.OutputStream
import java.util.regex.PatternSyntaxException
import java.util.stream.Collectors


class ActivityMain : AppCompatActivity() {
lateinit var firebaseAnalytics: FirebaseAnalytics
class ActivityMain : BabaActivity() {
lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
firebaseAnalytics = Firebase.analytics
CrashHandler.INSTANCE.init(this)

binding = ActivityMainBinding.inflate(layoutInflater)
prepareView()
setContentView(binding.root)

val testLabSetting = Settings.System.getString(contentResolver, "firebase.test.lab")
if ("true" == testLabSetting) {
val bundle = Bundle().apply {
putString("traffic_type", "testlab")
}
Firebase.analytics.setDefaultEventParameters(bundle)
}

checkForUpdates()
}

private fun checkForUpdates() {
val context = this
CoroutineScope(Dispatchers.Main).launch {
val appUpdateManager = AppUpdateManagerFactory.create(context)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo

appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
context,
1011
)
}
}
}
initFirebase()
}

private var searchOptions = SearchOptions(false, false)
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/io/atha/bababasic/ActivityRun.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ data class RunDatum(
val src: String,
) : Serializable

class ActivityRun : AppCompatActivity() {
class ActivityRun : BabaActivity() {
private lateinit var viewClient: TermuxTerminalViewClient
private lateinit var mPreferences: AppSharedPreferences
lateinit var binding: ActivityRunBinding
Expand Down Expand Up @@ -144,6 +144,7 @@ class ActivityRun : AppCompatActivity() {
session.initializeEmulator(1, 1)
setContentView(binding.root)
viewClient.onCreate()
initFirebase()
}

fun getTerminalView(): TerminalView = binding.terminal
Expand Down
145 changes: 145 additions & 0 deletions app/src/main/java/io/atha/bababasic/BabaActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package io.atha.bababasic

import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.inappmessaging.ktx.inAppMessaging
import com.google.firebase.ktx.Firebase
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

abstract class BabaActivity : AppCompatActivity() {
lateinit var firebaseAnalytics: FirebaseAnalytics

protected fun initFirebase() {
firebaseAnalytics = Firebase.analytics
CrashHandler.INSTANCE.init(this)
val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 3600
}
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.setDefaultsAsync(mapOf(
"feature_docs" to "0"
))

Firebase.inAppMessaging.addClickListener { inAppMessage, action ->
Log.i("inapp", "clicked ${inAppMessage} ${action}")
}

val testLabSetting = Settings.System.getString(contentResolver, "firebase.test.lab")
if ("true" == testLabSetting) {
val bundle = Bundle().apply {
putString("traffic_type", "testlab")
}
Firebase.analytics.setDefaultEventParameters(bundle)
}

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w("fcm", "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}

// Get new FCM registration token
val token = task.result

// Log and toast
Log.d("fcm", token)
})

if (Build.VERSION.SDK_INT >= 33) {
// notificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
} else {
hasNotificationPermissionGranted = true
}
}

private fun showSettingDialog() {
MaterialAlertDialogBuilder(this, com.google.android.material.R.style.MaterialAlertDialog_Material3)
.setTitle("Notification Permission")
.setMessage("Notification permission is required, Please allow notification permission from setting")
.setPositiveButton("Ok") { _, _ ->
val intent = Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
}
.setNegativeButton("Cancel", null)
.show()
}

private fun showNotificationPermissionRationale() {
MaterialAlertDialogBuilder(this, com.google.android.material.R.style.MaterialAlertDialog_Material3)
.setTitle("Alert")
.setMessage("Notification permission is required, to show notification")
.setPositiveButton("Ok") { _, _ ->
if (Build.VERSION.SDK_INT >= 33) {
notificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
}
}
.setNegativeButton("Cancel", null)
.show()
}

var hasNotificationPermissionGranted = false

private val notificationPermissionLauncher =
this.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
hasNotificationPermissionGranted = isGranted
if (!isGranted) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= 33) {
if (shouldShowRequestPermissionRationale(android.Manifest.permission.POST_NOTIFICATIONS)) {
showNotificationPermissionRationale()
} else {
showSettingDialog()
}
}
}
} else {
Toast.makeText(applicationContext, "notification permission granted", Toast.LENGTH_SHORT)
.show()
}
}


private fun checkForUpdates() {
val context = this
CoroutineScope(Dispatchers.Main).launch {
val appUpdateManager = AppUpdateManagerFactory.create(context)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo

appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
context,
1011
)
}
}
}
}
}
Loading
Loading