1、集成sdk
project
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.0'
app
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
}
implementation platform('com.google.firebase:firebase-bom:29.0.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-messaging'
在android{}里面配置,防止编译不过
gradle.taskGraph.whenReady {
tasks.each { task ->
if (task.name.contains("uploadCrashlyticsMappingFile")) {
task.enabled = false
}
}
}
把xxx.json放到app目录下面,至此配置结束
2.在manifest.xml中配置,
MyFirebaseMessagingService用来获取推送过来的消息,以及token变化时,把token传给自家的后端
<service
android:name=".base.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/bc_app_logo" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/font_green" />
**
3.MyFirebaseMessagingService:
**
/**
* @des
* @date 2022/3/7
* @author sam
*/
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val PUSH_CHANNEL_ID = "ID"
private val PUSH_CHANNEL_NAME = "peacock"
private val mNotificationId = 1000
private var mNotificationManager: NotificationManager? = null
override fun onCreate() {
super.onCreate()
mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
PUSH_CHANNEL_ID,
PUSH_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
)
if (mNotificationManager != null) {
mNotificationManager!!.createNotificationChannel(channel)
}
}
}
override fun onMessageReceived(p0: RemoteMessage) {
super.onMessageReceived(p0)
p0.notification?.body?.apply {
if (!isRunBackground(applicationContext)) {
sendNotification(p0.notification!!.body!!, p0)
}
}
}
override fun onNewToken(p0: String) {
super.onNewToken(p0)
Log.e("token changed--->",p0)
subToken(p0)
}
/**
* 在前台时,点击时的跳转逻辑,及推送通知
*/
private fun sendNotification(messageBody: String, remoteMessage: RemoteMessage) {
val intent: Intent
if (remoteMessage.data.isNotEmpty() && remoteMessage.data["type"] != null && remoteMessage.data["orderId"] != null) {
//提现
if (remoteMessage.data["type"] == "1") {
intent = Intent(this, OrderDetailActivity::class.java)
intent.putExtra("isShowOnly", false)
intent.putExtra("orderId", remoteMessage.data["orderId"]!!.toInt())
}
//还款
else if (remoteMessage.data["type"] == "2") {
intent = Intent(this, RepaymentDetailActivity::class.java)
intent.putExtra("orderId", remoteMessage.data["orderId"]!!.toInt())
} else {
Log.w("-->", "nothing")
intent = Intent(this, SplashActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
} else {
intent = Intent(this, SplashActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
val pendingIntent = PendingIntent.getActivity(
this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT
)
val defaultSoundUri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder: NotificationCompat.Builder =
NotificationCompat.Builder(this, PUSH_CHANNEL_ID)
.setSmallIcon(R.drawable.bc_app_logo)
.setContentTitle(remoteMessage.notification?.title ?: "")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
mNotificationManager?.notify(mNotificationId, notificationBuilder.build())
}
/**
* 判断是在前台还是后台
*/
private fun isRunBackground(context: Context): Boolean {
val activityManager = context.applicationContext
.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val packageName = context.applicationContext.packageName
val appProcesses = activityManager
.runningAppProcesses ?: return true
for (appProcess in appProcesses) {
if (appProcess.processName == packageName && appProcess.importance ==
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
) {
return false
}
}
return true
}
/**
* 发送token到服务器
*/
private fun subToken(token: String) {
OkGo.post<String>(Constant.URL_FIRE_BASE_TOKEN)
.headers(getHeaders(applicationContext))
.params("token", token)
.execute(object : GsonCallBack<BaseResponse<Any>>() {
override fun onSuccess(response: BaseResponse<Any>) {
if (response.isSuccess()) {
}
}
override fun onFail(response: Response<String>?, e: JsonParseException?) {
}
})
}
}
**
4.token删除及重新获取,这个地方是我自己的理解
** 我在退出登录的时候调用了deleteToken 在MainActivity里面调用了getToken,这样可以保证,MyFirebaseMessagingService 里面的onNewToken,当重新登录时候获取到
详细是这样的:
MainActivity的onCreate里面:
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.e("TAG", "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
// Get new FCM registration token
val token = task.result
// Log and toast
})
退出的时候:
R.id.tv_mine_exit -> {
SPUtils.getInstance().clear()
SPUtils.getInstance().putBooleanValue(SPUtils.IS_FIRST_RUN, false)
FirebaseMessaging.getInstance().deleteToken()
//清空后再存储
activity?.finish()
//false
LoginActivity.start(activity as AppCompatActivity, false)
}
**
5.踩坑,重要
** firebase当app前台的时候并不会显示通知,划线:不显示通知,这个害我郁闷好几天,咋收不到消息哩,,,有个逻辑需要自己处理: 1.当app在后台时,firebase消息展示通知栏,点击默认进Splash,这个没问题 2.当app在前台显示时,firebase不展示通知,需要自己处理逻辑
**
6.权限
** 目前至少国内手机默认不会给通知权限,需要自己写代码引导用户操作 具体代码如下:
调用方式:(dialog自己整)
if (!isNotifyEnabled(applicationContext)) {
StarDialog(this).setTitle("notice").setContent("开通知").setConfirmText("确定")
.setOnStarDialogClickListener(object : StarDialogClickListener {
override fun onCancel() {
}
override fun onConfirm() {
startSetting(this@MainActivity)
}
}).show()
}
import android.app.AppOpsManager
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.annotation.RequiresApi
/**
* @des 通知工具
* @date 2022/3/8
* @author sam
*/
private const val CHECK_OP_NO_THROW = "checkOpNoThrow"
private const val OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"
//调用该方法获取是否开启通知栏权限
fun isNotifyEnabled(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isEnableV26(context)
} else {
isEnabledV19(context)
}
}
/**
* 8.0以下判断
*
* @param context api19 4.4及以上判断
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private fun isEnabledV19(context: Context): Boolean {
val mAppOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val appInfo = context.applicationInfo
val pkg = context.applicationContext.packageName
val uid = appInfo.uid
var appOpsClass: Class<*>? = null
try {
appOpsClass = Class.forName(AppOpsManager::class.java.name)
val checkOpNoThrowMethod = appOpsClass.getMethod(
CHECK_OP_NO_THROW,
Integer.TYPE, Integer.TYPE, String::class.java
)
val opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION)
val value = opPostNotificationValue[Int::class.java] as Int
return checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) as Int ==
AppOpsManager.MODE_ALLOWED
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 8.0及以上通知权限判断
*
* @param context
* @return
*/
private fun isEnableV26(context: Context): Boolean {
val appInfo = context.applicationInfo
val pkg = context.applicationContext.packageName
val uid = appInfo.uid
return try {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val sServiceField = notificationManager.javaClass.getDeclaredMethod("getService")
sServiceField.isAccessible = true
val sService = sServiceField.invoke(notificationManager)
val method = sService.javaClass.getDeclaredMethod(
"areNotificationsEnabledForPackage",
String::class.java,
Integer.TYPE
)
method.isAccessible = true
method.invoke(sService, pkg, uid) as Boolean
} catch (e: Exception) {
true
}
}
fun startSetting(context: Context) {
val localIntent = Intent()
//直接跳转到应用通知设置的代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //8.0及以上
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
localIntent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
localIntent.data = Uri.fromParts("package", context.packageName, null)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0以上到8.0以下
localIntent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
localIntent.putExtra("app_package", context.packageName)
localIntent.putExtra("app_uid", context.applicationInfo.uid)
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { //4.4
localIntent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
localIntent.addCategory(Intent.CATEGORY_DEFAULT)
localIntent.data = Uri.parse("package:" + context.packageName)
} else {
//4.4以下没有从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (Build.VERSION.SDK_INT >= 9) {
localIntent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
localIntent.data = Uri.fromParts("package", context.packageName, null)
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.action = Intent.ACTION_VIEW
localIntent.setClassName(
"com.android.settings",
"com.android.setting.InstalledAppDetails"
)
localIntent.putExtra("com.android.settings.ApplicationPkgName", context.packageName)
}
}
context.startActivity(localIntent)
}
**
补充:
** 我这边推送的后端格式大概是这样的:这里的token是我传给后端的
String registrationToken = "d1OjZra6RSqJcIhsu7bpA9:APA91bHb2oety9CW3R5kYDQjOfkd3HiOhYiW5tdoQrw2jxgMIrw6wGvD9utHbypGWi1uIpy9qTxc55KlI5acZTtoOs6a_mYUapOiLGSoiB8";
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("xxxxx")
.setBody("xxxxxxxx")
.build())
//携带数据
.putData("type", "1")
.putData("orderId", "285")
.setToken(registrationToken)
.build();
String response = FirebaseMessaging.getInstance().send(message);
不用谢……
|