信鸽推送笔记
记录一下这周使用腾讯信鸽推送的吐血过程。总结一下,没事不要用腾讯的产品,按照开发文档一顿操作猛如虎,运行一下各种报错兼容问题,实在是无力吐槽。奈何我司大佬有腾讯血统,使用的都是腾讯系列的产品。
开发步骤
- 1:资源导入以及配置
- 2:账号绑定
- 3:接收状态栏消息
- 4:接收应用内消息
- 5:账号解绑
- 6:集成华为、小米、魅族厂商通道(周末在写)
1.资源导入以及配置
起初我也是按照官方文档,号称10分钟快速集成推送功能,然后各种出错,搞了我一下午一脸懵逼。直接贴出最终正确的配置过程如下:
先去官网申请一个测试应用如下
image.png
把申请的测试应用ACCESS ID和ACCESS KEY填入如下:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.***.***"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
abiFilters 'armeabi', 'armeabi-v7a'
}
manifestPlaceholders = [
XG_ACCESS_ID : "21*******",
XG_ACCESS_KEY: "AX1********",
]
}
dependencies {
//信鸽jar
implementation 'com.tencent.xinge:xinge:3.2.7-Release'
//jg包
implementation 'com.tencent.jg:jg:1.1'
//wup包
implementation 'com.tencent.wup:wup:1.0.0.E-Release'
//mid包
implementation 'com.tencent.mid:mid:4.0.6-release'
}
manifest配置如下
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/logo"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/logo"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:name">
......
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.fsxq.createcamp"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/photo_path" />
</provider>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<receiver
android:name="com.***.***.xgpush.MessageReceiver"
android:exported="true">
<intent-filter>
<!-- 接收消息透传 -->
<action android:name="com.tencent.android.tpush.action.PUSH_MESSAGE" />
<!-- 监听注册、反注册、设置/删除标签、通知被点击等处理结果 -->
<action android:name="com.tencent.android.tpush.action.FEEDBACK" />
</intent-filter>
</receiver>
</application>
<!-- 【必须】 信鸽SDK所需权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 【常用】 信鸽SDK所需权限 -->
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 【可选】 信鸽SDK所需权限 -->
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
其中的MessageReceiver是继承自XGPushBaseReceiver的一个消息处理类,后续的状态栏信息和应用内消息通过此类处理,MessageReceiver类如下
import android.app.NotificationManager;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.fsxq.createcamp.bean.MessageEvent;
import com.fsxq.createcamp.bean.XGMessageBean;
import com.fsxq.createcamp.utils.MyUtils;
import com.google.gson.Gson;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
import com.tencent.android.tpush.XGPushRegisterResult;
import com.tencent.android.tpush.XGPushShowedResult;
import com.tencent.android.tpush.XGPushTextMessage;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Create by 陈扬齐
* Create on 2019-06-26
* description:
*/
public class MessageReceiver extends XGPushBaseReceiver {
// 通知展示
@Override
public void onNotifactionShowedResult(Context context, XGPushShowedResult notifiShowedRlt) {
Log.i("push", "收到状态栏消息:" + notifiShowedRlt.getTitle() + "---" + notifiShowedRlt.getContent());
MyUtils.showToast(context,
"收到消息:" + notifiShowedRlt.getTitle() + "---" + notifiShowedRlt.getContent());
}
//反注册的回调
@Override
public void onUnregisterResult(Context context, int errorCode) {
Log.i("push", "解绑账号的回调");
}
//设置tag的回调
@Override
public void onSetTagResult(Context context, int errorCode, String tagName) {
Log.i("push", "设置tag的回调");
}
//删除tag的回调
@Override
public void onDeleteTagResult(Context context, int errorCode, String tagName) {
Log.i("push", "删除tag的回调");
}
// 通知点击回调 actionType=1为该消息被清除,actionType=0为该消息被点击。此处不能做点击消息跳转,详细方法请参照官网的Android常见问题文档
@Override
public void onNotifactionClickedResult(Context context, XGPushClickedResult message) {
Log.i("push", "+++++++++++++++ 通知被点击 跳转到指定页面。");
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
if (context == null || message == null) {
return;
}
String text = "";
if (message.getActionType() == XGPushClickedResult.NOTIFACTION_CLICKED_TYPE) {
// 通知在通知栏被点击啦。。。。。
// APP自己处理点击的相关动作
// 这个动作可以在activity的onResume也能监听,请看第3点相关内容
text = "通知被打开 :" + message;
} else if (message.getActionType() == XGPushClickedResult.NOTIFACTION_DELETED_TYPE) {
// 通知被清除啦。。。。
// APP自己处理通知被清除后的相关动作
text = "通知被清除 :" + message;
}
Toast.makeText(context, "广播接收到通知被点击:" + message.toString(), Toast.LENGTH_SHORT).show();
// 获取自定义key-value
String customContent = message.getCustomContent();
if (customContent != null && customContent.length() != 0) {
try {
JSONObject obj = new JSONObject(customContent);
// key1为前台配置的key
if (!obj.isNull("key")) {
String value = obj.getString("key");
Log.i("push", "键值对消息:" + value);
}
// ...
} catch (JSONException e) {
e.printStackTrace();
}
}
}
//注册的回调
@Override
public void onRegisterResult(Context context, int errorCode,
XGPushRegisterResult message) {
if (context == null || message == null) {
return;
}
String text = "";
if (errorCode == XGPushBaseReceiver.SUCCESS) {
text = "注册成功" + message;
// 在这里拿token
String token = message.getToken();
} else {
text = message + "注册失败错误码:" + errorCode;
}
Log.i("push", text);
}
// 消息透传的回调
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
Log.i("push", "应用内消息:" + new Gson().toJson(message));
String customContent = message.getCustomContent();
if (customContent != null && customContent.length() != 0) {
try {
XGMessageBean bean = new Gson().fromJson(customContent, XGMessageBean.class);
EventBus.getDefault().post(new MessageEvent(bean.getType()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过如上操作就已经完成信鸽推送的配置了。
2.绑定账号
信鸽提供了三种方式绑定推送终端,设备Token,Tag(标签),账号。通过这三种方式可以实现一对一,一对多等推送目的,我使用的是通过绑定用户账号确定推送目标,简单的用一个单例TPushManager封装一下信鸽绑定找那个号和解绑账号的功能如下
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.fsxq.createcamp.bean.Constant;
import com.fsxq.createcamp.retrofit.RetrofitFactory;
import com.fsxq.createcamp.utils.SPUtils;
import com.tencent.android.tpush.XGIOperateCallback;
import com.tencent.android.tpush.XGPushConfig;
import com.tencent.android.tpush.XGPushManager;
/**
* Create by 陈扬齐
* Create on 2019-06-26
* description:
*/
public class TPushManager {
private TPushManager() {
}
private static class TPushManagerHolder {
private static final TPushManager INSTANCE = new TPushManager();
}
public static TPushManager getInstance() {
return TPushManager.TPushManagerHolder.INSTANCE;
}
/**
* 初始化绑定
*
* @param context
*/
public void config(Context context) {
//线上环境不开启debug
if (!RetrofitFactory.IS_ONLINE) {
XGPushConfig.enableDebug(context, true);
}
String userId = SPUtils.getInstance().getString(Constant.SP.USER_ID);
String pushPrefix = SPUtils.getInstance().getString(Constant.SP.PUSH_PREFIX);
if (TextUtils.isEmpty(userId) || TextUtils.isEmpty(pushPrefix))
return;
String account = pushPrefix + userId;
Log.i("push", "account:" + account);
XGPushManager.registerPush(context, account,
new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.i("push", "注册成功:" + data);
}
@Override
public void onFail(Object data, int errorCode, String msg) {
Log.i("push", "注册失败,错误码:" + errorCode + "错误信息:" + msg);
}
});
// // 新建自定义样式
// XGBasicPushNotificationBuilder build = new XGBasicPushNotificationBuilder();
// // 设置自定义样式属性,该属性对对应的编号生效,指定后不能修改。
// build.setIcon(R.mipmap.logo)
// .setSound(RingtoneManager.getActualDefaultRingtoneUri(context,
// RingtoneManager.TYPE_ALARM)) // 设置声音
// .setDefaults(Notification.DEFAULT_VIBRATE) // 振动
// .setFlags(Notification.FLAG_NO_CLEAR); // 是否可清除
// // 设置通知样式,样式编号为1,即build_id为1,可通过后台脚本指定
// XGPushManager.setPushNotificationBuilder(context, 1, build);
}
/**
* 解除账号绑定
*
* @param context
*/
public void unRegister(Context context) {
String userId = SPUtils.getInstance().getString(Constant.SP.USER_ID);
String pushPrefix = SPUtils.getInstance().getString(Constant.SP.PUSH_PREFIX);
if (TextUtils.isEmpty(userId) || TextUtils.isEmpty(pushPrefix))
return;
String account = pushPrefix + userId;
XGPushManager.delAccount(context, account);
XGPushManager.unregisterPush(context);
}
}
然后根据你的需求在Application或者Mainactivity进行账号绑定
TPushManager.getInstance().config(this);
3:接收状态栏消息
如信鸽后台发送一条状态栏消息,在MessageReceiver的onNotifactionShowedResult回调中就能接收到状态栏消息了。在这之前先确定一下APP是否有获取通知权限,没有则提示用户齐设置页面开启,获取通知权限实现如下
/**
* 通知用户开启推送
*/
private void initNotificationRight() {
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
Log.i("push", "已有通知权限");
} else {
Log.i("push", "没有通知权限");
new QMUIDialog.MessageDialogBuilder(this)
.setTitle("开启推送通知")
.setMessage("打开通知,不错过每一个精彩时刻~")
.addAction("以后再说", (dialog, index) -> dialog.dismiss())
.addAction("确定", (dialog, index) -> {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings" +
".APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package",
MainActivity.this.getPackageName(),
null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings",
"com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName",
MainActivity.this.getPackageName());
}
startActivity(localIntent);
dialog.dismiss();
})
.show();
}
}
image.png
4.应用内通知
应用内通知不在状态栏展示,这个功能就比较有用了,比如通知用户有未读消息,有新的版本发布,有新的广告图去下载,而且不受限是否有通知权限,且可以携带键值对参数方便客户端进行不同的处理。在MessageReceiver的onTextMessage回调中接收到消息,通过回调过来的结果message.getCustomContent
可以获得json字符串格式的键值对参数,具体格式可以通过Gson转对象为json字符串查看。解析到键值对的值再通过广播或者EventBus等进行所需操作。
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
Log.i("push", "应用内消息:" + new Gson().toJson(message));
String customContent = message.getCustomContent();
if (customContent != null && customContent.length() != 0) {
try {
XGMessageBean bean = new Gson().fromJson(customContent, XGMessageBean.class);
EventBus.getDefault().post(new MessageEvent(bean.getType()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.解绑账号
账户退出登录的时候解除bangd
TPushManager.getInstance().unRegister(this);
致此信鸽使用基本完成了,下一篇写信鸽集成第三方厂商推送通道华为、小米、魅族