【问题标题】:Can’t find how to edit push notifications title and content within code - Android Studio找不到如何在代码中编辑推送通知标题和内容 - Android Studio
【发布时间】:2020-02-16 15:53:59
【问题描述】:

我购买了应用程序模板,但我无法在代码中找出更改推送通知标题和内容的位置(Firebase 作为消息提供者平台)。开发人员无法访问,我无法进一步处理项目。

例如,改为推送“您有新消息”我想要“您有一条新消息”;我搜索了整个代码但没有成功。

另外 - 有什么方法可以将推送通知翻译成多种语言?

编辑

源文件中没有与消息相关的 Firebase 扩展服务,仅与电话身份验证相关。

代码示例:

package com.innomalist.taxi.driver.activities.splash

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.Window
import android.view.WindowManager
import androidx.databinding.DataBindingUtil
import com.crashlytics.android.Crashlytics
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.AuthUI.IdpConfig.PhoneBuilder
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.iid.FirebaseInstanceId
import com.gun0912.tedpermission.PermissionListener
import com.gun0912.tedpermission.TedPermission
import com.innomalist.taxi.common.components.BaseActivity
import com.innomalist.taxi.common.interfaces.AlertDialogEvent
import com.innomalist.taxi.common.networking.socket.interfaces.ConnectionError
import com.innomalist.taxi.common.networking.socket.interfaces.Namespace
import com.innomalist.taxi.common.networking.socket.interfaces.RemoteResponse
import com.innomalist.taxi.common.networking.socket.interfaces.SocketNetworkDispatcher
import com.innomalist.taxi.common.utils.AlertDialogBuilder
import com.innomalist.taxi.common.utils.AlertDialogBuilder.DialogResult
import com.innomalist.taxi.common.utils.AlertDialogBuilder.show
import com.innomalist.taxi.common.utils.AlerterHelper.showError
import com.innomalist.taxi.common.utils.CommonUtils.isGPSEnabled
import com.innomalist.taxi.common.utils.CommonUtils.isInternetDisabled
import com.innomalist.taxi.common.utils.MyPreferenceManager.Companion.getInstance
import com.innomalist.taxi.driver.R
import com.innomalist.taxi.driver.activities.main.MainActivity
import com.innomalist.taxi.driver.activities.profile.ProfileActivity
import com.innomalist.taxi.driver.databinding.ActivitySplashBinding
import com.innomalist.taxi.driver.networking.http.GetRegisterInfo
import com.innomalist.taxi.driver.networking.http.Login
import com.innomalist.taxi.driver.networking.http.LoginResult
import com.innomalist.taxi.driver.networking.http.RegistrationInfo
import io.fabric.sdk.android.Fabric
import java.lang.Exception

class SplashActivity : BaseActivity() {
    private lateinit var binding: ActivitySplashBinding
    private var SIGN_IN_ACTIVITY = 123
    private var startRequested = false
    private val permissionListener: PermissionListener = object : PermissionListener {
        override fun onPermissionDenied(deniedPermissions: List<String>) {
            show(this@SplashActivity,"It is not possible to run the app as driver without location permission. Given that you have already didn't approved location access you can now go to settings and enabled it. Then you can close app and open it again to access.", AlertDialogBuilder.DialogButton.OK, AlertDialogEvent {
                checkPermissions()
            })
        }
        override fun onPermissionGranted() {
            if(getInstance(applicationContext).token != null) {
                tryConnect(getInstance(applicationContext).token!!)
            } else {
                goToLoginMode()
            }
        }
    }
    private val onLoginClicked = View.OnClickListener {
        startActivityForResult(
                AuthUI.getInstance()
                        .createSignInIntentBuilder()
                        .setAvailableProviders(listOf(PhoneBuilder().build()))
                        .setLogo(R.drawable.logo)
                        .setTheme(currentTheme)
                        .build(),
                SIGN_IN_ACTIVITY)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        isImmersive = true
        super.onCreate(savedInstanceState)
        if (getString(R.string.fabric_key) != "") {
            Fabric.with(this, Crashlytics())
        }
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_splash)
        binding.loginButton.setOnClickListener(onLoginClicked)
        checkPermissions()
    }

    private fun checkPermissions() {
        if (!isGPSEnabled(this)) {
            show(this, getString(R.string.message_enable_gps), AlertDialogBuilder.DialogButton.CANCEL_RETRY, AlertDialogEvent { result: DialogResult ->
                if (result === DialogResult.RETRY) {
                    checkPermissions()
                } else {
                    finishAffinity()
                }
            })
            return
        }
        if (isInternetDisabled(this)) {
            show(this, getString(R.string.message_internet_connection), AlertDialogBuilder.DialogButton.CANCEL_RETRY, AlertDialogEvent { result: DialogResult ->
                if (result === DialogResult.RETRY) {
                    checkPermissions()
                } else {
                    finishAffinity()
                }
            })
            return
        }
        TedPermission.with(this)
                .setPermissionListener(permissionListener)
                .setDeniedMessage(getString(R.string.message_permission_denied))
                .setPermissions(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION)
                .check()
    }

    fun tryConnect(jwtToken: String) {
        FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener {fb ->
            SocketNetworkDispatcher.instance.connect(Namespace.Driver, jwtToken, fb.result?.token ?: "") {
                when (it) {
                    is RemoteResponse.Success -> {
                        startMainActivity()
                    }

                    is RemoteResponse.Error -> {
                        when (it.error) {
                            ConnectionError.RegistrationIncomplete -> {
                                runOnUiThread {
                                    showRegisterForm(jwtToken)
                                }
                            }

                            else -> {
                                runOnUiThread {
                                    goToLoginMode()
                                    try {
                                        it.error.showAlert(this)
                                    } catch (exception: Exception) {

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private fun showRegisterForm(jwtToken: String) {
        GetRegisterInfo(jwtToken).execute<RegistrationInfo> {
            when(it) {
                is RemoteResponse.Success -> {
                    runOnUiThread {
                        preferences.driver = it.body.driver
                        preferences.services = ArrayList(it.body.services)
                        val intent = Intent(this@SplashActivity, ProfileActivity::class.java)
                        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                        startActivity(intent)
                    }
                }

                is RemoteResponse.Error -> {
                    //it.error.showAlert(this)
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()
        if(preferences.token != null) {
            tryConnect(preferences.token!!)
        }
    }

    private fun startMainActivity() {
        if (startRequested) return
        startRequested = true
        val intent = Intent(this@SplashActivity, MainActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        startActivity(intent)
    }

    private fun tryLogin(firebaseToken: String) {
        goToLoadingMode()
        Login(firebaseToken).execute<LoginResult> {
            when(it) {
                is RemoteResponse.Success -> {
                    getInstance(applicationContext).driver = it.body.user
                    getInstance(applicationContext).token = it.body.token
                    tryConnect(it.body.token)
                }
                is RemoteResponse.Error -> {
                    showError(this, it.error.localizedDescription)
                }
            }
        }
    }

    private fun goToLoadingMode() {
        binding.loginButton.visibility = View.GONE
        binding.progressBar.visibility = View.VISIBLE
    }

    private fun goToLoginMode() {
        binding.loginButton.visibility = View.VISIBLE
        binding.progressBar.visibility = View.GONE
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == SIGN_IN_ACTIVITY) {
            if (resultCode == Activity.RESULT_OK) {
                FirebaseAuth.getInstance().currentUser!!.getIdToken(false).addOnCompleteListener {
                    tryLogin(it.result!!.token!!)
                }
                return
            }
            showError(this@SplashActivity, getString(R.string.login_failed))
            goToLoginMode()
        }
    }
}

附加信息

让我解释一下消息的性质:有两个应用程序 - 司机和乘客:当乘客做某事时,例如 - 要求附近的司机,附近的所有司机都会收到推送消息 - 你有一个新的请求。此外,例如 - 付款时 - 乘客收到消息 - 付款已结算。看在上帝的份上,这个存储在哪里:)

GRADLE 文件

应用程序内部有三个模块 - 通用、驱动程序和骑手,以及四个 gradle.build 文件。

通用模块 Gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'


android {
    compileSdkVersion 29
    buildToolsVersion '29.0.2'
    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 29
        multiDexEnabled true
        versionCode 1
        versionName '1.0.0'
        vectorDrawables.useSupportLibrary = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled true
    }
}

dependencies {
    api 'androidx.multidex:multidex:2.0.1'
    api 'androidx.recyclerview:recyclerview-selection:1.1.0-beta01'
    api 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
    api 'com.google.android.material:material:1.2.0-alpha03'
    api 'com.google.android.gms:play-services-maps:17.0.0'
    api 'com.google.android.gms:play-services-location:17.0.0'
    api 'com.google.firebase:firebase-messaging:20.1.0'
    api 'com.firebaseui:firebase-ui:6.2.0'
    api('io.socket:socket.io-client:1.0.0') {
        exclude group: 'org.json', module: 'json'
    }
    api('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
        transitive = true
    }
    api 'com.google.maps.android:android-maps-utils:0.6.2'
    api 'com.github.medyo:android-about-page:1.2.4'
    api 'com.squareup.moshi:moshi:1.9.2'
    api 'com.squareup.moshi:moshi-kotlin:1.9.2'
    kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.9.2'
    api 'de.psdev.licensesdialog:licensesdialog:2.1.0'
    api 'com.github.tylersuehr7:empty-state-recyclerview:1.0.4'
    api 'com.github.yalantis:ucrop:2.2.4'
    api 'com.github.esafirm.android-image-picker:imagepicker:2.2.0'
    api 'com.github.bumptech.glide:glide:4.10.0'
    api 'com.tapadoo.android:alerter:5.0.0'
    api 'gun0912.ted:tedpermission:2.2.2'
    api 'com.github.stfalcon:chatkit:0.3.3'
    api('com.stripe:stripe-android:12.8.2@aar') {
        transitive = true
    }
    api 'com.github.MAXDeliveryNG:slideview:1.1.0'
    api 'com.braintreepayments.api:drop-in:3.7.1'
    api 'com.airbnb.android:lottie:3.3.1'

    //noinspection LifecycleAnnotationProcessorWithJava8
    kapt 'androidx.lifecycle:lifecycle-compiler:2.2.0'
    api 'androidx.preference:preference-ktx:1.1.0'
    api 'androidx.core:core-ktx:1.1.0'
    api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    api "org.jetbrains.kotlin:kotlin-script-runtime:1.3.61"
    api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
    api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
}

驱动模块 Gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'

android {
    compileSdkVersion 29
    buildToolsVersion '29.0.2'
    defaultConfig {
        applicationId 'com.ldrive.taxi.driver'
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 35
        versionName '3.0.9'
        multiDexEnabled true
        vectorDrawables.useSupportLibrary = true
    }
    signingConfigs {
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    api project(':common')
    api 'com.diogobernardino:williamchart:3.3.0'
}
apply plugin: 'com.google.gms.google-services'
repositories {
    mavenCentral()
}

乘客/乘客模块 Gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'

android {
    compileSdkVersion 29
    buildToolsVersion '29.0.2'
    defaultConfig {
        applicationId "com.ldrive.taxi.rider"
        minSdkVersion 19
        targetSdkVersion 29
        multiDexEnabled true
        versionCode 35
        versionName "3.0.9"
        vectorDrawables.useSupportLibrary = true
        dexOptions {
            jumboMode true
        }
    }
    if (project.hasProperty("RELEASE_KEY_ALIAS")) {
        signingConfigs {
            release {
                storeFile file(RELEASE_STORE_FILE)
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    api project(':common')
    implementation 'com.github.Innomalist:floatingsearchview:0.3'
    implementation ('com.google.android.libraries.places:places:2.1.0')
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
    testImplementation 'junit:junit:4.12'
}
configurations {
    all*.exclude group: 'com.google.guava', module: 'listenablefuture'
}
apply plugin: 'com.google.gms.google-services'

项目等级

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.3.61'
    repositories {
        maven { url "https://maven.google.com" }
        jcenter()
        maven { url 'https://maven.fabric.io/public' }
        google()
        maven { url 'https://plugins.gradle.org/m2/'}
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'io.fabric.tools:gradle:1.29.0'
        classpath 'com.google.gms:google-services:4.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

    }
}

allprojects {
    repositories {
        maven { url "https://maven.google.com" }
        jcenter()
        mavenCentral()
        google()
        maven { url "https://jitpack.io" }
        maven { url 'https://maven.fabric.io/public' }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

【问题讨论】:

    标签: android firebase push-notification


    【解决方案1】:

    尝试搜索扩展 FirebaseMessagingService 的类。这是所有 FCM 服务设置的地方。

    编辑

    这就是我在自己的应用中自定义通知的方式:

    Intent intent = new Intent(this, BOBusinessHomePage.class);           
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    
    Notification notification =
        new NotificationCompat.Builder(getApplicationContext(), "0")
        .setSmallIcon(R.drawable.business_icon)
        .setContentTitle("A client has posted a new review in your business page!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)
        .build();
    mNotificationManager.notify(0, notification);
    

    尝试在您的项目中搜索“通知”或任何与上述类似的模板。

    或者,尝试搜索名为onMessageReceived()的回调方法。

    说明

    默认情况下,您的应用在前台时不会显示它收到的任何 FCM 消息,因此当您发送消息时,无法保证您的用户会真正看到该消息。

    要处理您的应用在前台收到的消息,您需要扩展 FirebaseMessagingService,覆盖 onMessageReceived 方法,然后使用 getNotification 或 getData 检索消息的内容,具体取决于您是否在工作带有数据或通知消息,或两者兼有。

    【讨论】:

    • 这里我会尝试将所有与FMS相关的代码分享出来,但都是普通的(暂时不在PC,稍后会分享),但根本没有定义通知消息。是否有可能有通知。数据存储在应用程序源代码之外的其他地方?
    • 源文件中没有与消息相关的Firebase扩展服务,仅与电话认证服务有关。
    • 您好,很抱歉回复晚了,这里是晚上。因此,要使用 firebase 自定义推送通知,您必须覆盖名为:“onMessageReceived”的回调方法。如果您在应用程序中没有找到此方法,则表示尚未设置 FCM。让我知道它是否对你有帮助:)
    • 你好。也许我在这里搜索了错误的项目,只是大声思考——这不是 Firebase(没有 onMessageReceived() 方法)。让我解释一下消息的性质:有两个应用程序 - 司机和乘客:当乘客做某事时,例如 - 要求附近的司机,附近的所有司机都会收到推送消息 - 你有一个新的请求。此外,例如 - 付款时 - 乘客收到消息 - 付款已结算。看在上帝的份上,这个存储在哪里:)
    • 我假设驱动程序在后台应用程序时收到新请求的推送通知。你可以在你的问题中分享你的“build.gradle”文件吗?我正在尝试找出谁是您的推送通知服务第三方提供商。如果您已经解决了,请告诉我如何:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多