极光推送

2018-01-10  本文已影响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启动过程
  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. 告诉后台,这个属于开发测试的通道
上一篇下一篇

猜你喜欢

热点阅读