集成百度云推送,Android8.0系统推送收不到问题解决方案

因为之前没有集成过百度云推送,接手新项目之后项目需求是接入百度云推送,没办法因为项目是海外项目所以只能硬着头皮来接入了,话不多说开始你的表演:

首先就是去百度云推送的官网去创建应用并启用:

.在配置详情页中,扫描二维码或者点击下载SDK,可以下载对应包名的demo,个人建议直接点击右上角的下载SDK来下载demo,因为我刚开始使用二维码下载下来的demo并不是最新的版本,也没有百度云产品的简介。

.运行demo没问题也可以推送,感觉百度云推送还是很nice的,so那就去集成到咱们自己的项目中吧

.将自己需要的文件提取出来,尽可能的去掉无用的东西。**demo中包好了许多功能是你用不到的,因此需要将自己需要功能的相关文件摘出来。结果测试没问题。需要的东西如下:
pushservice-5.2.0.12.jar包,所有的.so文件,notification_custom_builder.xml(这是通知栏的布局),  

注意:如果您的 Android 工程使用的是 Android API level 21 及以上的版本,您的通知图标背景 必须是透明的,否则在 Android5.0 及以上的机器上通知图标可能会变成白色的方块。

  1. 在该工程下创建一个 libs 文件夹

  2. 将 pushservice-VERSION.jar 拷贝到 libs 文件夹中,把 SDK 压缩包中的 libs/armeabi 目录下的

    libbdpush_V2_9.so 拷贝到工程对应的 libs/armeabi 文件夹下。

    1. a)  如果你的工程中没有使用其他的.so,建议只复制 armeabi 文件夹。

    2. b)  如果你的工程中还使用了其他的.so 文件,只需要拷贝云推送对应目录下的.so 文件。

    3. c)  如果你使用的 Android 开发环境是 Android Stutio,在工程中“src/main”目录中新建名为

      jniLibs 的目录,将 libs 文件夹中文件拷贝到“jniLibs”目录内。

.AndroidManifest.xm中的权限:

<!-- Push service 运行需要的权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" /> 
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 富媒体需要声明的权限 -->
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/> 
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> 
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<!-- 适配 Android N 系统必需的 ContentProvider 写权限声明-->
<uses-permission android:name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.你的包名" /> 
<permission
android:name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.你的包名 " android:protectionLevel="normal">
 
 

.AndroidManifest.xml 注册消息接收 Receiver

客户端需实现自己的 MyPushMessageReceiver,接收 Push 服务的消息,并实现对消息的处理。以

下是 AndroidManifest.xml 中的配置代码。

<!-- push 应用定义消息 receiver 声明 -->
<receiver android:name="YourPackageName.MyPushMessageReceiver">
<intent-filter>
<!-- 接收 push 消息 -->
<action android:name="com.baidu.android.pushservice.action.MESSAGE" />
<!-- 接收 bind、setTags 等 method 的返回结果 -->
<action android:name="com.baidu.android.pushservice.action.RECEIVE" />
<!-- 可选,接受通知点击事件,和通知自定义内容 -->
<action android:name="com.baidu.android.pushservice.action.notification.CLICK" />
</intent-filter> 
</receiver>

7. AndroidManifest.xml 增加 pushservice 配置

<!-- push service start -->
<!-- 用于接收系统消息以保证 PushService 正常运行 -->
<receiver android:name="com.baidu.android.pushservice.PushServiceReceiver" android:process=": bdservice_v1" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="com.baidu.android.pushservice.action.notification.SHOW" /> 
<action android:name="com.baidu.android.pushservice.action.media.CLICK" />
<!-- 以下四项为可选的 action 声明,可大大提高 service 存活率和消息到达速度 --> 
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" /> 
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter> 
</receiver>

<!-- Push 服务接收客户端发送的各种请求-->
<receiver android:name="com.baidu.android.pushservice.RegistrationReceiver"
android:process=": bdservice_v1" > 
<intent-filter>
<action android:name="com.baidu.android.pushservice.action.METHOD " />
<action android:name="com.baidu.android.pushservice.action.BIND_SYNC " /> 
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package" /> 
</intent-filter>
</receiver>
<!-- Push 服务 -->
<!-- 注意:在 4.0 及以后的版本需加上如下所示的 intent-filter action -->
<service android:name="com.baidu.android.pushservice.PushService" 
android:exported="true"
android:process=":bdservice_v1" >
<intent-filter >
<action android:name="com.baidu.android.pushservice.action.PUSH_SERVICE" />
</intent-filter>
</service>
<!-- 注意:在 4.4 及以后的版本需加上如下所示的 service -->
<service android:name="com.baidu.android.pushservice.CommandService"
android:exported="true" >
</service>
<!-- 适配 Android N 系统所必需的 ContentProvider, 写权限中包含应用包名--> 
</provider
android:name="com.baidu.android.pushservice.PushInfoProvider" android:authorities="YourPackageName.bdpush" android:writePermission="baidu.push.permission.WRITE_PUSHINFOPROVIDER.YourPackageName"android:protectionLevel = "signature" android:exported="true" /> 
<!-- push service end -->

8. 富媒体功能(可选)

富媒体是相对于一般消息而言,一种高级的通知,提供文本、视频、音乐等形式的消息。您需要 把富媒体相关的资源文件(包括 layout 文件、图片和字符资源分别添加到相应的资源目录),同时在 AndroidManifest.xml 文件里声明富媒体 Activity。如果应用不支持富媒体推送功能,可以不添加相关的 资源和声明。在 targetSdkVersion>=23 时,需要应用具有 sd 卡读写权限,否则富媒体不能正常展示。

◆ 资源

- Layout:
◼ bpush_download_progress.xml ◼ bpush_media_list_item.xml
◼ bpush_media_list.xml

- drawable:
◼ bpush_list_item_bg.9.png ◼ bpush_return_btn.png
◼ bpush_top_bg.9.png

.AndroidManifest.xml声明权限

<!--富媒体需要声明的权限 --/> 
<uses-permission
android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> 
<uses-permission
android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> 
<uses-permission
android:name="android.permission.EXPAND_STATUS_BAR" />

.AndroidManifest.xml声明Activity

<!-- push 富媒体,不使用富媒体推送不需要添加 --> 
<activity
android:name="com.baidu.android.pushservice.richmedia.MediaViewActivity" android:configChanges="orientation|keyboardHidden" android:label="MediaViewActivity" >
</activity> 
<activity
android:name="com.baidu.android.pushservice.richmedia.MediaListActivity" android:configChanges="orientation|keyboardHidden" android:label="MediaListActivity"
android:launchMode="singleTask" >
</activity>

9. 请确保 AndroidManifest.xml 中声明了必须的组件以及组件的属性,否则 Push 服务部分功能 可能无法正常工作。

.客户端程序需要自己实现一个 Receiver 来接收 Push 消息、接口调用回调以及通知点击事件,也 就是上文提到的 AndrodManifest.xml 中注册的 receiver ,该 Receiver 需要继承 PushMessageReceiver,示例如下:

/*
 * Push消息处理receiver。请编写您需要的回调函数, 一般来说: onBind是必须的,用来处理startWork返回值;
 *onMessage用来接收透传消息; onSetTags、onDelTags、onListTags是tag相关操作的回调;
 *onNotificationClicked在通知被点击时回调; onUnbind是stopWork接口的返回值回调

 * 返回值中的errorCode,解释如下:
 *0 - Success
 *10001 - Network Problem
 *10101  Integrate Check Error
 *30600 - Internal Server Error
 *30601 - Method Not Allowed
 *30602 - Request Params Not Valid
 *30603 - Authentication Failed
 *30604 - Quota Use Up Payment Required
 *30605 -Data Required Not Found
 *30606 - Request Time Expires Timeout
 *30607 - Channel Token Timeout
 *30608 - Bind Relation Not Found
 *30609 - Bind Number Too Many

 * 当您遇到以上返回错误时,如果解释不了您的问题,请用同一请求的返回值requestId和errorCode联系我们追查问题。
 *
 */

public class MyPushMessageReceiver extends PushMessageReceiver {
    /** TAG to Log */
    public static final String TAG = MyPushMessageReceiver.class
            .getSimpleName();

    /**
     * 调用PushManager.startWork后,sdk将对push
     * server发起绑定请求,这个过程是异步的。绑定请求的结果通过onBind返回。 如果您需要用单播推送,需要把这里获取的channel
     * id和user id上传到应用server中,再调用server接口用channel id和user id给单个手机或者用户推送。
     *
     * @param context
     *            BroadcastReceiver的执行Context
     * @param errorCode
     *            绑定接口返回值,0 - 成功
     * @param appid
     *            应用id。errorCode非0时为null
     * @param userId
     *            应用user id。errorCode非0时为null
     * @param channelId
     *            应用channel id。errorCode非0时为null
     * @param requestId
     *            向服务端发起的请求id。在追查问题时有用;
     * @return none
     */
    @Override
    public void onBind(Context context, int errorCode, String appid,
            String userId, String channelId, String requestId) {
        String responseString = "onBind errorCode=" + errorCode + " appid="
                + appid + " userId=" + userId + " channelId=" + channelId
                + " requestId=" + requestId;
        Log.d(TAG, responseString);

        if (errorCode == 0) {
            // 绑定成功
        }
        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, responseString);
    }

    /**
     * 接收透传消息的函数。
     *
     * @param context
     *            上下文
     * @param message
     *            推送的消息
     * @param customContentString
     *            自定义内容,为空或者json字符串
     */
    @Override
    public void onMessage(Context context, String message,
            String customContentString) {
        String messageString = "透传消息 message=\"" + message
                + "\" customContentString=" + customContentString;
        Log.d(TAG, messageString);

        // 自定义内容获取方式,mykey和myvalue对应透传消息推送时自定义内容中设置的键和值
        if (!TextUtils.isEmpty(customContentString)) {
            JSONObject customJson = null;
            try {
                customJson = new JSONObject(customContentString);
                String myvalue = null;
                if (!customJson.isNull("mykey")) {
                    myvalue = customJson.getString("mykey");
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, messageString);
    }

    /**
     * 接收通知点击的函数。
     *
     * @param context
     *            上下文
     * @param title
     *            推送的通知的标题
     * @param description
     *            推送的通知的描述
     * @param customContentString
     *            自定义内容,为空或者json字符串
     */
    @Override
    public void onNotificationClicked(Context context, String title,
            String description, String customContentString) {
        String notifyString = "通知点击 title=\"" + title + "\" description=\""
                + description + "\" customContent=" + customContentString;
        Log.d(TAG, notifyString);

        // 自定义内容获取方式,mykey和myvalue对应通知推送时自定义内容中设置的键和值
        if (!TextUtils.isEmpty(customContentString)) {
            JSONObject customJson = null;
            try {
                customJson = new JSONObject(customContentString);
                String myvalue = null;
                if (!customJson.isNull("mykey")) {
                    myvalue = customJson.getString("mykey");
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, notifyString);
    }

    /**
     * 接收通知到达的函数。
     *
     * @param context
     *            上下文
     * @param title
     *            推送的通知的标题
     * @param description
     *            推送的通知的描述
     * @param customContentString
     *            自定义内容,为空或者json字符串
     */

    @Override
    public void onNotificationArrived(Context context, String title,
            String description, String customContentString) {

        String notifyString = "onNotificationArrived  title=\"" + title
                + "\" description=\"" + description + "\" customContent="
                + customContentString;
        Log.d(TAG, notifyString);

        // 自定义内容获取方式,mykey和myvalue对应通知推送时自定义内容中设置的键和值
        if (!TextUtils.isEmpty(customContentString)) {
            JSONObject customJson = null;
            try {
                customJson = new JSONObject(customContentString);
                String myvalue = null;
                if (!customJson.isNull("mykey")) {
                    myvalue = customJson.getString("mykey");
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        // 你可以參考 onNotificationClicked中的提示从自定义内容获取具体值
        updateContent(context, notifyString);
    }

//    /**
//     * setTags() 的回调函数。
//     *
//     * @param context
//     *            上下文
//     * @param errorCode
//     *            错误码。0表示某些tag已经设置成功;非0表示所有tag的设置均失败。
//     * @param successTags
//     *            设置成功的tag
//     * @param failTags
//     *            设置失败的tag
//     * @param requestId
//     *            分配给对云推送的请求的id
//     */
    @Override
    public void onSetTags(Context context, int errorCode,
            List<String> sucessTags, List<String> failTags, String requestId) {
        String responseString = "onSetTags errorCode=" + errorCode
                + " sucessTags=" + sucessTags + " failTags=" + failTags
                + " requestId=" + requestId;
        Log.d(TAG, responseString);

        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, responseString);
    }

//    /**
//     * delTags() 的回调函数。
//     *
//     * @param context
//     *            上下文
//     * @param errorCode
//     *            错误码。0表示某些tag已经删除成功;非0表示所有tag均删除失败。
//     * @param successTags
//     *            成功删除的tag
//     * @param failTags
//     *            删除失败的tag
//     * @param requestId
//     *            分配给对云推送的请求的id
//     */
    @Override
    public void onDelTags(Context context, int errorCode,
            List<String> sucessTags, List<String> failTags, String requestId) {
        String responseString = "onDelTags errorCode=" + errorCode
                + " sucessTags=" + sucessTags + " failTags=" + failTags
                + " requestId=" + requestId;
        Log.d(TAG, responseString);

        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, responseString);
    }

    /**
     * listTags() 的回调函数。
     *
     * @param context
     *            上下文
     * @param errorCode
     *            错误码。0表示列举tag成功;非0表示失败。
     * @param tags
     *            当前应用设置的所有tag。
     * @param requestId
     *            分配给对云推送的请求的id
     */
    @Override
    public void onListTags(Context context, int errorCode, List<String> tags,
            String requestId) {
        String responseString = "onListTags errorCode=" + errorCode + " tags="
                + tags;
        Log.d(TAG, responseString);

        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, responseString);
    }

    /**
     * PushManager.stopWork() 的回调函数。
     *
     * @param context
     *            上下文
     * @param errorCode
     *            错误码。0表示从云推送解绑定成功;非0表示失败。
     * @param requestId
     *            分配给对云推送的请求的id
     */
    @Override
    public void onUnbind(Context context, int errorCode, String requestId) {
        String responseString = "onUnbind errorCode=" + errorCode
                + " requestId = " + requestId;
        Log.d(TAG, responseString);

        if (errorCode == 0) {
            // 解绑定成功
        }
        // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑
        updateContent(context, responseString);
    }

    private void updateContent(Context context, String content) {
        Log.d(TAG, "updateContent");
        String logText = "" + Utils.logStringCache;

        if (!logText.equals("")) {
            logText += "\n";
        }

        SimpleDateFormat sDateFormat = new SimpleDateFormat("HH-mm-ss");
        logText += sDateFormat.format(new Date()) + ": ";
        logText += content;

        Utils.logStringCache = logText;

        Intent intent = new Intent();
        intent.setClass(context.getApplicationContext(), MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.getApplicationContext().startActivity(intent);
    }

}

.到这里就已经差不多了,其实百度云推送的集成并没有和其他推送有什么区别很难

.然后就是百度云推送的初始化,官方文档建议初始化放在主Activity不要放在Application里面进行初始化

PushManager.startWork(this, PushConstants.LOGIN_TYPE_API_KEY,"你的api_key");

.ok运行走一波,so easy,当你以为已经结束的时候其实只是刚开始,经过测试,不行!!!!!,接收不到消息。
有的测试机可以收到有的测试机收不到,想啊想,不知道错在哪,然后开始怀疑是不是包冲突了?然后各种方法排除测试等等,没得到任何结论!!

.然后各种百度,但是关于百度云推送的文章实在太少了,偶然间看到大神们的文章:

https://blog.csdn.net/kinglong68/article/details/53507086

https://blog.csdn.net/cdkd123/article/details/50521924

.在build.gradle里要配置下,位置在build.gradle -> android下和compileSdkVersion平级目录:

sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }

.而不是

sourceSets {  
        main {   
            jniLibs.srcDirs = ['libs']  
        }  
}  

我试了试,去掉这句话也可以。
注意,项目中本来配置着
在官网,建议使用Android Studio工具开发者,将.so文件放入jniLibs目录下,奶奶的,为啥不说清楚,gradle中也需要配置!!!

就这样,问题解决了。

.如果想设置响应铃声的问题,这个我没有试,具体可以参考大佬的文章(文末):

https://blog.csdn.net/kinglong68/article/details/53507086

.至此测试,不仅仅是OK,简直nice,都可以推送,内心还有一点小开心外带一点小兴奋

如果这样的话你就等着吃苦瓜吧,因为问题并没有完全解决,你再试试Android 8.0简直是灾难,因为Android在Android O之后取消了设置channelid你发的推送在Android 8.0上根本就没有任何消息可以收到,没办法问度娘吧,然后陷入了死循环,日后的两天在百度 + 百度中度过,找了无数种方法还是不行,看看官方的公众号和QQ群看下吧,发现竟然被注销了,没错你找不到百度云推送的官方客服人员了,没办法,再去官网看看吧,抱着试一试的心态,选择右上角的SDK下载试试吧(因为之前是二维码下载的)

.我去发现压缩包里多出了好多东西,什么文档了,最新的百度云更新状态说明了等等,这官网也是够无聊的,没办法谁让人牛呢,忍了

.在文档里终于找到了Android 8.0的推送解决办法,这里记给大家

.从 SDK 5.8.0 版本开始,提供关于 Android O(8.x)新特性---通知渠道的设置接口。 若您的应用需要适配 Android O(8.x)系统,且将目标版本 targetSdkVersion 设置为 26 及以上

时,可自定义系统所必需的 channelId 和 channelName 字段,若不指定,SDK 将使用渠道名默 认值"Push"。对于 BasicPushNotificationBuilder,所有的通知消息均使用同一个 channel;对 于 CustomPushNotificationBuilder,可根据自定义的 notification_builder_id 编号,来指定 不同 channel。调用方法示例如下:

设置过的 channel 都会显示在系统的应用通知列表中,您可以根据需要调用 Android O 系统 API 删除 SDK 默认的 channelId(“com.baidu.android.pushservice.push”)或自定义的 channelId。 调用方法示例如下:

这里就不说没用的了,直接把解决问题的所有代码贴出来(我是写在了初始化的后面):

        //初始化百度云推送,第三个参数为自己百度推送申请的appkey
        PushManager.startWork(this,PushConstants.LOGIN_TYPE_API_KEY,"你的api_key");

        //与下方代码中 PushManager.setNotificationBuilder(this, 1, cBuilder)中的第二个参数对应
        CustomPushNotificationBuilder cBuilder = new CustomPushNotificationBuilder( R.layout.notification_custom_builder, R.id.notification_icon, R.id.notification_title, R.id.notification_text);
        cBuilder.setNotificationFlags(Notification.FLAG_AUTO_CANCEL);
        cBuilder.setNotificationDefaults(Notification.DEFAULT_VIBRATE);
        cBuilder.setStatusbarIcon(this.getApplicationInfo().icon);
        cBuilder.setLayoutDrawable(this.getApplicationInfo().icon);
        cBuilder.setNotificationSound(Uri.withAppendedPath( MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "6").toString());
        // 若您的应用需要适配Android O(8.x)系统,且将目标版本targetSdkVersion设置为26及以上时:
        // 可自定义channelId/channelName, 若不设置则使用默认值"Push";
        // 注:非targetSdkVersion 26的应用无需以下2行调用且不会生效
        cBuilder.setChannelId("Push");
        cBuilder.setChannelName("Push");
        // 推送高级设置,通知栏样式设置为下面的ID,ID应与server下发字段notification_builder_id值保持一致
        PushManager.setNotificationBuilder(this, 1, cBuilder);

.如果你直接将notification_custom_builder.xml这个布局拷贝进去了,应该就没有多少需要修改的地方了,

.混淆打包说明

如果开发者需要混淆自己的 APK,请在混淆文件(一般默认为 Android 工程下 proguard-project.txt 或者 proguard.cfg)中添加如下说明(VERSION 为版本名称,pushservice-VERSION.jar 为集成的 jar 包 名字):

-libraryjars libs/pushservice-VERSION.jar 
-dontwarn com.baidu.**
-keep class com.baidu.**{*; }

.API 说明

本 SDK 中有四个重要的开放类,分别为:PushManager、PushSettings、BasicPushNotificationBuilder 和 CustomPushNotificationBuilder,还有常量类 PushConstants。

到这里算是已经解决了Android 8.0的推送问题了,希望大家可以快快乐乐的工作,本来不想发文章的,但是网上却是没有解决百度云推送Android 8.0问题的文章所以就啰嗦了一下,新手勿喷谢谢,希望解决您的问题,告辞!!!

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值