美文网首页
极光推送

极光推送

作者: 鱼__鱼 | 来源:发表于2018-01-10 15:07 被阅读0次
    jianshu_0031.jpg

    极光官网

    1. 注册
    2. 创建应用
    3. 生成AppKey 、Master Secret

    集成指南

    文章只介绍Android Studio Jcenter 自动集成

    支持jcenter

    buildscript {
        repositories {
            jcenter()
        }
        ......
    }
    
    allprojets {
        repositories {
            jcenter()
        }
    }
    

    配置gradle

    因为项目本身自定义config.gradle ,所以都用rootProject.exty引用,和实际一样

    android {
     ...
        defaultConfig {
            applicationId rootProject.ext.android["applicationId"]
    
            ndk {
                abiFilters 'armeabi'
            }
        }
      ...
    
        buildTypes {
            debug {
                manifestPlaceholders = [
                        JPUSH_PKGNAME: rootProject.ext.android["applicationId"],
                        JPUSH_APPKEY : rootProject.ext.jpush["debugAppKey"],
                        JPUSH_CHANNEL: rootProject.ext.jpush["channel"]]
            }
    
            release {
                manifestPlaceholders = [
                        JPUSH_PKGNAME: rootProject.ext.android["applicationId"],
                        JPUSH_APPKEY : rootProject.ext.jpush["releaseAppKey"],
                        JPUSH_CHANNEL: rootProject.ext.jpush["channel"]]
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    

    config.gradle代码

        jpush = [
                //JPush上注册的包名对应的appkey
                debugAppKey  : "",
                releaseAppKey: "",
                //暂时填写默认值即可
                channel      : "developer-default"
        ]
    

    配置AndroidManifest

    注意:在AndroidManifest中使用 ${applicationId} 引用gradle中定义的包名
    这里分三块展示给大家

    1. 权限相关 @Required必填
        <!-- Required -->
        <permission
            android:name="${applicationId}.permission.JPUSH_MESSAGE"
            android:protectionLevel="signature" />
        <!-- Required -->
        <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" />
        <!-- Required -->
        <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.VIBRATE" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    
        <!-- Optional. Required for location feature -->
        <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 -->
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
        <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
        <uses-permission android:name="android.permission.GET_TASKS" />
    
    1. 核心功能 @Required必填
        <application
          ...
            <!-- Required SDK 核心功能-->
            <!-- 可配置android:process参数将PushService放在其他进程中 -->
            <service
                android:name="cn.jpush.android.service.PushService"
                android:enabled="true"
                android:exported="false">
                <intent-filter>
                    <action android:name="cn.jpush.android.intent.REGISTER" />
                    <action android:name="cn.jpush.android.intent.REPORT" />
                    <action android:name="cn.jpush.android.intent.PushService" />
                    <action android:name="cn.jpush.android.intent.PUSH_TIME" />
                </intent-filter>
            </service>
    
            <!-- since 3.0.9 Required SDK 核心功能-->
            <provider
                android:name="cn.jpush.android.service.DataProvider"
                android:authorities="${applicationId}.DataProvider"
                android:exported="false" />
    
            <!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 -->
            <!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 -->
            <service
                android:name="cn.jpush.android.service.DaemonService"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="cn.jpush.android.intent.DaemonService" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </service>
    
            <!-- Required SDK核心功能-->
            <receiver
                android:name="cn.jpush.android.service.PushReceiver"
                android:enabled="true">
                <intent-filter android:priority="1000">
                    <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />
                    <category android:name="${applicationId}" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.USER_PRESENT" />
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                </intent-filter>
                <!-- Optional -->
                <intent-filter>
                    <action android:name="android.intent.action.PACKAGE_ADDED" />
                    <action android:name="android.intent.action.PACKAGE_REMOVED" />
    
                    <data android:scheme="package" />
                </intent-filter>
            </receiver>
    
            <!-- Required SDK核心功能-->
            <activity
                android:name="cn.jpush.android.ui.PushActivity"
                android:configChanges="orientation|keyboardHidden"
                android:exported="false"
                android:theme="@android:style/Theme.NoTitleBar">
                <intent-filter>
                    <action android:name="cn.jpush.android.ui.PushActivity" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </activity>
    
            <!-- SDK核心功能-->
            <activity
                android:name="cn.jpush.android.ui.PopWinActivity"
                android:configChanges="orientation|keyboardHidden"
                android:exported="false"
                android:theme="@style/MyDialogStyle">
                <intent-filter>
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </activity>
    
            <!-- Required SDK核心功能-->
            <service
                android:name="cn.jpush.android.service.DownloadService"
                android:enabled="true"
                android:exported="false">
    
            </service>
    
            <!-- Required SDK核心功能-->
            <receiver android:name="cn.jpush.android.service.AlarmReceiver" />
        </application>
    
    1. 自定义广播接收器 @必填
            <!-- User defined.  For test only  用户自定义的广播接收器-->
            <receiver
                android:name=".jpush.JPushReceiver"
                android:enabled="true"
                android:exported="false">
                <intent-filter>
                    <!--Required  用户注册SDK的intent-->
                    <action android:name="cn.jpush.android.intent.REGISTRATION" />
                    <!--Required  用户接收SDK消息的intent-->
                    <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
                    <!--Required  用户接收SDK通知栏信息的intent-->
                    <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
                    <!--Required  用户打开自定义通知栏的intent-->
                    <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
                    <!-- 接收网络变化 连接/断开 since 1.6.3 -->
                    <action android:name="cn.jpush.android.intent.CONNECTION" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </receiver>
    
    /**
     * 自定义接收器
     * 如果不定义这个 Receiver,则:
     * 1) 默认用户会打开主界面
     * 2) 接收不到自定义消息
     */
    public class JPushReceiver extends BroadcastReceiver {
    
        public void onReceive(Context context, Intent intent) {
            if (intent == null) {
                return;
            }
    
            String extraData = intent.getExtras().getString(JPushInterface.EXTRA_EXTRA);
            if (StringUtil.isEmpty(extraData)) {
                return;
            }
    
            PushEntity pushEntity = new Gson().fromJson(extraData, PushEntity.class);
    
            //推送消息 收到
            if(false && JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())){
       
            }
    
            //推送消息 点击
            if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
    
            }
        }
    }
    

    一行代码

        /**
         * 极光推送
         */
        private void initPush() {
            // 设置开启日志,发布时请关闭日志
            JPushInterface.setDebugMode(BuildConfig.LOG_DEBUG);
            // 初始化 JPush
            JPushInterface.init(this);
        }
    
    

    好了,到这里,我们就集成完了,去官网发送一条通知,测试一波

    jianshu_0032.png

    调试指南

    1. SDK启动过程
    • 检查AndroidManifest.xml中是否有配置AppKey,如果没有,则启动失败
    • 检查 Androidmanifest.xml文件配置的正确性,必须要保证“Android SDK 集成指南”中所有标注“
    • Required的部分都正确配置,否则启动失败
    • 检查 JPush SDK库文件的有效性,如果库文件无效,则启动失败
    • 检查网络是否可用,如果网络可用则连接服务器登录,否则启动失败
    • 登陆成功后可以从log中看到如下log
    1. 网络问题
    • 关闭代理
    • 网络不稳定
    1. 部分系统的特殊处理
      详情请查看极光推送官方文档

    测试指南

    之前我们有定义两个AppKey,为什么要有两个AppKey呢?

    最开始我们只有一个AppKey,然后App上线后,需要测试推送,这时,发送的话,线上的用户都会收到推送消息,如果只针对用户推的话,难免测试服与线上服ID一致,还是会有少部分用户收到推送,然后与极光团队邮件沟通,解决方案就是重新注册账号,新建应用,得到测试AppKey,用来只做测试。这样线上和测试就分两条通道走了。

        buildTypes {
            debug {
                manifestPlaceholders = [
                        JPUSH_APPKEY : rootProject.ext.jpush["debugAppKey"],
            }
    
            release {
                manifestPlaceholders = [
                        JPUSH_APPKEY : rootProject.ext.jpush["releaseAppKey"],
            }
        }
    

    gradle小技巧

    jianshu_0033.png jianshu_0034.png

    这里需要gradle设置一下签名即可,使用简单
    感叹gradle的强大,如果想深入了解的同学,请移步
    Gradle入门(一)

    高级API

    应项目需求,采用设置别名的方式,这里也只介绍setAlias

    1. 注册 & 登录 成功后,设置uid为别名,下次进来不用重复设置别名,所以最好记录一个状态值
        @Override
        public void initPush() {
            if (UserCache.getInstance().getJPushStatus()) {
                return;
            }
    
            mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS, localUid));
        }
    
    1. 接收消息,设置别名
        private final Handler mHandler = new Handler() {
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case MSG_SET_ALIAS:
                        JPushInterface.setAlias(MainActivity.this, (String) msg.obj, mAliasCallback);
                        break;
                }
            }
        };
    
    1. 设置别名的回调
        private final TagAliasCallback mAliasCallback = new TagAliasCallback() {
            @Override
            public void gotResult(int code, String alias, Set<String> tags) {
    
                switch (code) {
                    case 0:
                        //设置成功,存储状态值
                        UserCache.getInstance().saveJPushSuccess();
                        break;
                    case 6002:
                        //失败,重复设置
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 60);
                        break;
                    default:
                        break;
                }
            }
        };
    
    1. 退出登录,删除别名
        @Override
        public void loginOut() {
            // JPushInterface.deleteAlias(,); 也可以
            JPushInterface.setAlias(AppSettingActivity.this, "", null);
            exitActivity();
        }
    

    其它

    关于拉起

    1. 不是所有使用了极光服务的App都愿意开启拉起功能 来拉起别的应用或者被别的应用拉起
    2. 拉起同样会受到系统的限制,该功能只是尽量提高点重启的几率,相当于有比没有好
    3. 测试拉起的具体步骤方法
    4. 成功设置了拉起也不是说马上你杀死,推送测试他就能收到的,你要等他拉起成功

    注意

    互相拉起服务,使用的后果一定要考虑清楚

    使用了互相拉起服务,确实,你们APP推送的及时到达率都提升了很多,但是,APP开启的一段时间里,手机会卡顿,因为会唤醒,同样注册了极光推送互相拉起服务的应用,手机里面有2-3个还好,用户还发现不了什么,如果手机里面有100,200,300个应用,那最少唤醒10- 30个,开启的一段时间,手机绝对会卡顿,所以为什么会有垃圾联盟了,为什么手机越用越卡。

    当然也看你们产品定位,毕竟手机里面装100,200,300个应用的用户占少数,牺牲少部分用户,博得大部分群体也可以,看实际需求。

    最后呢,我们的产品最开始开启互相拉起服务,一段时间我又删除了,就是关闭互相拉起服务,正常情况,APP不该唤醒其它应用,也不会被其它应用唤醒,结果,删除了,还是没法解决互相唤醒,现在就是想关关不掉!!!和极光服务沟通过,让我们多测试一下,现在也没时间测试,暂时记一个Bug,也有可能不是极光服务的问题。总之,慎重!

    后记

    上线后怎么测试推送和广播?
    事情起因,测试人员不小心推送、广播全部人,结果,线上的用户都收到了 test 这样的信息,无法点击查看。其实,我也经常会收到新浪推送的test信息,真的非常影响用户体验。

    iOS为什么不会出现这样的问题呢?
    他们在设置时,已经有生产环境和开发环境,配置不同的签名,结合后端的业务,来推生产环境,还是开发环境,这样线上的用户就不会收到测试人员的推送

    android怎么解决呢?

    1. 重新注册极光账号
    2. 设置包名,生成AppKey 、Master Secret
    3. 告诉后台,这个属于开发测试的通道

    相关文章

      网友评论

          本文标题:极光推送

          本文链接:https://www.haomeiwen.com/subject/yhyonxtx.html