F-Droid flavor without Firebase; works
This commit is contained in:
parent
a6ae5c11da
commit
cdf7a7c685
11 changed files with 72 additions and 30 deletions
|
@ -34,20 +34,16 @@ android {
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
debuggable true
|
debuggable true
|
||||||
applicationIdSuffix ".debug"
|
|
||||||
versionNameSuffix "-debug"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "store"
|
flavorDimensions "store"
|
||||||
productFlavors {
|
productFlavors {
|
||||||
forPlay {
|
play {
|
||||||
dimension "store"
|
buildConfigField 'boolean', 'FIREBASE_AVAILABLE', 'true'
|
||||||
buildConfigField 'String', 'STORE', '"play"'
|
|
||||||
}
|
}
|
||||||
forFDroid {
|
fdroid {
|
||||||
dimension "store"
|
buildConfigField 'boolean', 'FIREBASE_AVAILABLE', 'false'
|
||||||
buildConfigField 'String', 'STORE', '"fdroid"'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +77,7 @@ dependencies {
|
||||||
implementation "com.squareup.okhttp3:okhttp:4.9.2"
|
implementation "com.squareup.okhttp3:okhttp:4.9.2"
|
||||||
|
|
||||||
// Firebase, sigh ... (only Google Play)
|
// Firebase, sigh ... (only Google Play)
|
||||||
forPlayImplementation 'com.google.firebase:firebase-messaging:22.0.0'
|
playImplementation 'com.google.firebase:firebase-messaging:22.0.0'
|
||||||
|
|
||||||
// RecyclerView
|
// RecyclerView
|
||||||
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerViewVersion"
|
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerViewVersion"
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.heckel.ntfy.firebase
|
||||||
|
|
||||||
|
class FirebaseMessenger {
|
||||||
|
fun subscribe(topic: String) {
|
||||||
|
// Dummy to keep F-Droid flavor happy
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unsubscribe(topic: String) {
|
||||||
|
// Dummy to keep F-Droid flavor happy
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package io.heckel.ntfy.firebase
|
||||||
|
|
||||||
|
class FirebaseService {
|
||||||
|
// Dummy to keep F-Droid flavor happy
|
||||||
|
}
|
|
@ -53,9 +53,9 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<!-- Firebase messaging -->
|
<!-- Firebase messaging (note that this is empty in the F-Droid flavor) -->
|
||||||
<service
|
<service
|
||||||
android:name=".msg.FirebaseService"
|
android:name=".firebase.FirebaseService"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
||||||
|
|
|
@ -2,10 +2,8 @@ package io.heckel.ntfy.app
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
|
||||||
import io.heckel.ntfy.data.Database
|
import io.heckel.ntfy.data.Database
|
||||||
import io.heckel.ntfy.data.Repository
|
import io.heckel.ntfy.data.Repository
|
||||||
import io.heckel.ntfy.msg.ApiService
|
|
||||||
|
|
||||||
class Application : Application() {
|
class Application : Application() {
|
||||||
private val database by lazy { Database.getInstance(this) }
|
private val database by lazy { Database.getInstance(this) }
|
||||||
|
|
|
@ -15,6 +15,7 @@ import com.google.android.material.textfield.TextInputEditText
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.data.Database
|
import io.heckel.ntfy.data.Database
|
||||||
import io.heckel.ntfy.data.Repository
|
import io.heckel.ntfy.data.Repository
|
||||||
|
import io.heckel.ntfy.BuildConfig
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@ -60,13 +61,20 @@ class AddFragment : DialogFragment() {
|
||||||
useAnotherServerCheckbox = view.findViewById(R.id.add_dialog_use_another_server_checkbox) as CheckBox
|
useAnotherServerCheckbox = view.findViewById(R.id.add_dialog_use_another_server_checkbox) as CheckBox
|
||||||
useAnotherServerDescription = view.findViewById(R.id.add_dialog_use_another_server_description)
|
useAnotherServerDescription = view.findViewById(R.id.add_dialog_use_another_server_description)
|
||||||
|
|
||||||
|
// Show/hide based on flavor
|
||||||
|
instantDeliveryBox.visibility = if (BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
// Build dialog
|
// Build dialog
|
||||||
val alert = AlertDialog.Builder(activity)
|
val alert = AlertDialog.Builder(activity)
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setPositiveButton(R.string.add_dialog_button_subscribe) { _, _ ->
|
.setPositiveButton(R.string.add_dialog_button_subscribe) { _, _ ->
|
||||||
val topic = topicNameText.text.toString()
|
val topic = topicNameText.text.toString()
|
||||||
val baseUrl = getBaseUrl()
|
val baseUrl = getBaseUrl()
|
||||||
val instant = if (useAnotherServerCheckbox.isChecked) true else instantDeliveryCheckbox.isChecked
|
val instant = if (!BuildConfig.FIREBASE_AVAILABLE || useAnotherServerCheckbox.isChecked) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
instantDeliveryCheckbox.isChecked
|
||||||
|
}
|
||||||
subscribeListener.onSubscribe(topic, baseUrl, instant)
|
subscribeListener.onSubscribe(topic, baseUrl, instant)
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.add_dialog_button_cancel) { _, _ ->
|
.setNegativeButton(R.string.add_dialog_button_cancel) { _, _ ->
|
||||||
|
@ -107,7 +115,7 @@ class AddFragment : DialogFragment() {
|
||||||
} else {
|
} else {
|
||||||
useAnotherServerDescription.visibility = View.GONE
|
useAnotherServerDescription.visibility = View.GONE
|
||||||
baseUrlText.visibility = View.GONE
|
baseUrlText.visibility = View.GONE
|
||||||
instantDeliveryBox.visibility = View.VISIBLE
|
instantDeliveryBox.visibility = if (BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
|
||||||
if (instantDeliveryCheckbox.isChecked) instantDeliveryDescription.visibility = View.VISIBLE
|
if (instantDeliveryCheckbox.isChecked) instantDeliveryDescription.visibility = View.VISIBLE
|
||||||
else instantDeliveryDescription.visibility = View.GONE
|
else instantDeliveryDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
@ -149,6 +157,6 @@ class AddFragment : DialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "NtfyAffFragment"
|
const val TAG = "NtfyAddFragment"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
import io.heckel.ntfy.BuildConfig
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.app.Application
|
import io.heckel.ntfy.app.Application
|
||||||
import io.heckel.ntfy.data.Notification
|
import io.heckel.ntfy.data.Notification
|
||||||
|
@ -372,7 +373,8 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
||||||
val enableInstantItem = menu.findItem(R.id.detail_menu_enable_instant)
|
val enableInstantItem = menu.findItem(R.id.detail_menu_enable_instant)
|
||||||
val disableInstantItem = menu.findItem(R.id.detail_menu_disable_instant)
|
val disableInstantItem = menu.findItem(R.id.detail_menu_disable_instant)
|
||||||
val instantInfoItem = menu.findItem(R.id.detail_menu_instant_info)
|
val instantInfoItem = menu.findItem(R.id.detail_menu_instant_info)
|
||||||
if (subscriptionBaseUrl == appBaseUrl) {
|
val allowToggleInstant = BuildConfig.FIREBASE_AVAILABLE && subscriptionBaseUrl == appBaseUrl
|
||||||
|
if (allowToggleInstant) {
|
||||||
enableInstantItem?.isVisible = !subscriptionInstant
|
enableInstantItem?.isVisible = !subscriptionInstant
|
||||||
disableInstantItem?.isVisible = subscriptionInstant
|
disableInstantItem?.isVisible = subscriptionInstant
|
||||||
instantInfoItem?.isVisible = false
|
instantInfoItem?.isVisible = false
|
||||||
|
|
|
@ -19,7 +19,6 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.google.firebase.messaging.FirebaseMessaging
|
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.app.Application
|
import io.heckel.ntfy.app.Application
|
||||||
import io.heckel.ntfy.data.Subscription
|
import io.heckel.ntfy.data.Subscription
|
||||||
|
@ -27,6 +26,7 @@ import io.heckel.ntfy.data.topicShortUrl
|
||||||
import io.heckel.ntfy.msg.ApiService
|
import io.heckel.ntfy.msg.ApiService
|
||||||
import io.heckel.ntfy.msg.NotificationService
|
import io.heckel.ntfy.msg.NotificationService
|
||||||
import io.heckel.ntfy.work.PollWorker
|
import io.heckel.ntfy.work.PollWorker
|
||||||
|
import io.heckel.ntfy.firebase.FirebaseMessenger
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
@ -41,6 +41,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
||||||
}
|
}
|
||||||
private val repository by lazy { (application as Application).repository }
|
private val repository by lazy { (application as Application).repository }
|
||||||
private val api = ApiService()
|
private val api = ApiService()
|
||||||
|
private val messenger = FirebaseMessenger()
|
||||||
|
|
||||||
// UI elements
|
// UI elements
|
||||||
private lateinit var menu: Menu
|
private lateinit var menu: Menu
|
||||||
|
@ -267,15 +268,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
||||||
// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
|
// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
|
||||||
if (baseUrl == appBaseUrl) {
|
if (baseUrl == appBaseUrl) {
|
||||||
Log.d(TAG, "Subscribing to Firebase")
|
Log.d(TAG, "Subscribing to Firebase")
|
||||||
FirebaseMessaging
|
messenger.subscribe(topic)
|
||||||
.getInstance()
|
|
||||||
.subscribeToTopic(topic)
|
|
||||||
.addOnCompleteListener {
|
|
||||||
Log.d(TAG, "Subscribing to topic complete: result=${it.result}, exception=${it.exception}, successful=${it.isSuccessful}")
|
|
||||||
}
|
|
||||||
.addOnFailureListener {
|
|
||||||
Log.e(TAG, "Subscribing to topic failed: $it")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch cached messages
|
// Fetch cached messages
|
||||||
|
@ -366,7 +359,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
||||||
subscriptionBaseUrl?.let { baseUrl ->
|
subscriptionBaseUrl?.let { baseUrl ->
|
||||||
if (baseUrl == appBaseUrl) {
|
if (baseUrl == appBaseUrl) {
|
||||||
Log.d(TAG, "Unsubscribing from Firebase")
|
Log.d(TAG, "Unsubscribing from Firebase")
|
||||||
subscriptionTopic?.let { topic -> FirebaseMessaging.getInstance().unsubscribeFromTopic(topic) }
|
subscriptionTopic?.let { topic -> messenger.unsubscribe(topic) }
|
||||||
}
|
}
|
||||||
// Subscriber service changes are triggered in the observe() call above
|
// Subscriber service changes are triggered in the observe() call above
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
|
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
|
||||||
<string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
|
<string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
|
||||||
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
|
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
|
||||||
<string name="detail_instant_info">Instant delivery cannot be disabled for subscriptions from other servers</string>
|
<string name="detail_instant_info">Instant delivery is enabled</string>
|
||||||
|
|
||||||
<!-- Detail activity: Action bar -->
|
<!-- Detail activity: Action bar -->
|
||||||
<string name="detail_menu_notifications_enabled">Notifications enabled</string>
|
<string name="detail_menu_notifications_enabled">Notifications enabled</string>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.heckel.ntfy.firebase
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
|
|
||||||
|
class FirebaseMessenger {
|
||||||
|
fun subscribe(topic: String) {
|
||||||
|
FirebaseMessaging
|
||||||
|
.getInstance()
|
||||||
|
.subscribeToTopic(topic)
|
||||||
|
.addOnCompleteListener {
|
||||||
|
Log.d(TAG, "Subscribing to topic complete: result=${it.result}, exception=${it.exception}, successful=${it.isSuccessful}")
|
||||||
|
}
|
||||||
|
.addOnFailureListener {
|
||||||
|
Log.e(TAG, "Subscribing to topic failed: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unsubscribe(topic: String) {
|
||||||
|
FirebaseMessaging
|
||||||
|
.getInstance()
|
||||||
|
.unsubscribeFromTopic(topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "NtfyFirebase"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.heckel.ntfy.msg
|
package io.heckel.ntfy.firebase
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
|
@ -6,6 +6,7 @@ import com.google.firebase.messaging.RemoteMessage
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.app.Application
|
import io.heckel.ntfy.app.Application
|
||||||
import io.heckel.ntfy.data.Notification
|
import io.heckel.ntfy.data.Notification
|
||||||
|
import io.heckel.ntfy.msg.NotificationService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
Loading…
Reference in a new issue