極光推送客戶端和服務(wù)器端開(kāi)發(fā)

現(xiàn)在大不分應(yīng)用都有推送的功能罢坝,今天總結(jié)下最近用到的極光推動(dòng)的android端和服務(wù)器端開(kāi)發(fā)過(guò)程世蔗。

1.1推送的原理

分服務(wù)器和客戶端分別進(jìn)行說(shuō)明:

1.推送框架圖

jpush.png
  • 推送的數(shù)據(jù)源:自己開(kāi)發(fā)的服務(wù)器端或者使用極光推送官網(wǎng)的WEB后臺(tái)(++用于客戶自定義服務(wù)器向推送框架進(jìn)行推送++)
  • JPush API:部署在服務(wù)器端,開(kāi)發(fā)者的服務(wù)器端發(fā)起推送時(shí),將數(shù)據(jù)傳到JPush API中铆铆,然后向下傳遞
  • 建立長(zhǎng)鏈接:集成JPush的SDK客戶端啟動(dòng)后會(huì)建立一個(gè)到JPush Cloud的長(zhǎng)鏈接(++手機(jī)客戶端收到推送消息++)

1.2客戶端原理

客戶端需要和服務(wù)器保存長(zhǎng)連接狀態(tài)庄萎。jpush SDK提供了TCP Long Connection辙纬。實(shí)現(xiàn)的原理:

  • 心跳:為了長(zhǎng)時(shí)間保持外網(wǎng)IP生兆,需要客戶端定期發(fā)送心跳給運(yùn)營(yíng)商瓷马,以便刷新NAT列表
  • Timer定時(shí)方法:該類計(jì)劃循環(huán)執(zhí)行定時(shí)任務(wù)拴还,但是使用該類會(huì)使CPU保持喚醒狀態(tài),比較費(fèi)電欧聘。
  • AlarmManager定時(shí)方法:該類封裝了Android手機(jī)的RTC硬件時(shí)鐘模塊片林,可以在CPU休眠時(shí)正常運(yùn)行,保持任務(wù)執(zhí)行時(shí)再喚醒CPU怀骤,這樣做到了電量節(jié)省费封。

2.實(shí)現(xiàn)步驟

2.1注冊(cè)極光推送

極光推送網(wǎng)址:https://www.jiguang.cn
進(jìn)行自行注冊(cè),然后進(jìn)入控制臺(tái)蒋伦,添加自己的應(yīng)用弓摘。在應(yīng)用設(shè)置中就能看到自己的AppKey的值,這個(gè)是此用于的唯一標(biāo)示符凉敲,在客戶端開(kāi)發(fā)和服務(wù)器端開(kāi)發(fā)中都會(huì)用到此值衣盾。

2.2集成android客戶端

集成android.png

按照上圖的提示進(jìn)行炒作即可。
下面在android studio中介紹下集成流程:

  1. builde.gradle中添加引用爷抓,即導(dǎo)入依賴包
compile 'cn.jiguang.sdk:jpush:3.0.0'
compile 'cn.jiguang.sdk:jcore:1.0.0'

2.添加統(tǒng)計(jì)信息势决,也可以不使用

@Override
    protected void onResume() {
        super.onResume();
        MobclickAgent.onResume(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPause(this);
    }

3.jpush初始化

public class MyApplication extends Application {

    public static String APPID = "915a5566e71a88d33a2851e0d2b19512";

    @Override
    public void onCreate() {
        JPushInterface.setDebugMode(true);  // 設(shè)置開(kāi)啟日志,發(fā)布時(shí)請(qǐng)關(guān)閉日志
        JPushInterface.init(this);          // 初始化 JPush
    }

}

4.在AndroidMainfest.xml添加

    <!-- Required 極光推送添加 -->
    <permission
        android:name="com.ylink.MGessTraderYlink_gxjszx.permission.JPUSH_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.ylink.MGessTraderYlink_gxjszx.permission.JPUSH_MESSAGE" />
    <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 
  <!-- 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="com.ylink.MGessTraderYlink_gxjszx" />
            </intent-filter>
        </activity>
        <!-- Required  SDK核心功能 -->
        <service
            android:name="cn.jpush.android.service.DownloadService"
            android:enabled="true"
            android:exported="false" />

        <!-- Required SDK 核心功能 -->
        <!-- 可配置android:process參數(shù)將PushService放在其他進(jìn)程中 -->
        <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>
        <!-- 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" /> <!-- Required  顯示通知欄 -->
                <category android:name="com.ylink.MGessTraderYlink_gxjszx" />
            </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核心功能 -->
        <receiver
            android:name="cn.jpush.android.service.AlarmReceiver"
            android:exported="false" />
        <!-- User defined.  For test only  用戶自定義的廣播接收器 -->
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="false">
            <intent-filter>
                <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!-- Required  用戶注冊(cè)SDK的intent -->
                <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required  用戶接收SDK消息的intent -->
                <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required  用戶接收SDK通知欄信息的intent -->
                <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required  用戶打開(kāi)自定義通知欄的intent -->
                <action android:name="cn.jpush.android.intent.CONNECTION" /> <!-- 接收網(wǎng)絡(luò)變化 連接/斷開(kāi) since 1.6.3 -->
                <category android:name="com.ylink.MGessTraderYlink_gxjszx" />
            </intent-filter>
        </receiver>
        <!-- Required  . Enable it you can get statistics data with channel -->
        <meta-data
            android:name="JPUSH_CHANNEL"
            android:value="developer-default" />
        <meta-data
            android:name="JPUSH_APPKEY"
            android:value="yourappkey" />

5.自定義MyReceiver

/**
 * 自定義接收器
 *
 * 如果不定義這個(gè) Receiver,則:
 * 1) 默認(rèn)用戶會(huì)打開(kāi)主界面
 * 2) 接收不到自定義消息
 */
public class MyReceiver extends BroadcastReceiver {
    private NotificationManager notificationManager;
    private int reqCode = 0;
    private NotificationImpl notificationImpl;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (notificationManager == null) {
            notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        }
        Bundle bundle = intent.getExtras();
        MyLog.i("[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));

        if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
            String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
            MyLog.i("[MyReceiver] 接收Registration Id : " + regId);

        } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
            MyLog.i("[MyReceiver] 接收到推送下來(lái)的自定義消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
            showNotification(context,bundle);

        } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
            MyLog.i("[MyReceiver] 接收到推送下來(lái)的通知");
            int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
            MyLog.i("[MyReceiver] 接收到推送下來(lái)的通知的ID: " + notifactionId);
            receivingNotification(context,bundle);


        } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
            MyLog.i("[MyReceiver] 用戶點(diǎn)擊打開(kāi)了通知");
            openNotification(context,bundle);
        } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
            MyLog.i("[MyReceiver] 用戶收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
            //在這里根據(jù) JPushInterface.EXTRA_EXTRA 的內(nèi)容處理代碼蓝撇,比如打開(kāi)新的Activity果复, 打開(kāi)一個(gè)網(wǎng)頁(yè)等..

        } else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
            boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
            MyLog.i("[MyReceiver]" + intent.getAction() +" connected state change to "+connected);
        } else {
            MyLog.i("[MyReceiver] Unhandled intent - " + intent.getAction());
        }
    }

    //自定義通知框
    private void showNotification(Context context, Bundle bundle) {
        String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
        reqCode++;
        String notificationType = "0";
        try {
            JSONObject extrasJson = new JSONObject(extras);
            notificationType = extrasJson.optString("Notificaction");
        } catch (Exception e) {
            MyLog.e("Unexpected: extras is not a valid json" + e.toString());
        }
        if (notificationImpl == null) {
            notificationImpl = new NotificationImpl(context);
        }
        notificationImpl.setRequestCode(reqCode);

        switch (notificationType){
            case "0":
                notificationImpl.notify_normal_singLine(bundle);
                break;
            case "1":
                notificationImpl.notify_normal_moreLine(bundle);
                break;
            case "2":
                notificationImpl.notify_mailbox(bundle);
                break;
            case "3":
                notificationImpl.notify_bigPic(bundle);
                break;
            case "4":
                notificationImpl.notify_customview(bundle);
                break;
            case "5":
                notificationImpl.notify_buttom(bundle);
                break;
            case "6":
                notificationImpl.notify_progress(bundle);
                break;
            case "7":
                notificationImpl.notify_headUp(bundle);
                break;
            default:
                break;
        }

    }

    private void receivingNotification(Context context, Bundle bundle) {
        CustomPushNotificationBuilder builder = new
                CustomPushNotificationBuilder(context,
                R.layout.yyb_notification,
                R.id.icon,
                R.id.title,
                R.id.text);
        // 指定定制的 Notification Layout
        builder.statusBarDrawable = R.drawable.down;
        // 指定最頂層狀態(tài)欄小圖標(biāo)
        builder.layoutIconDrawable = R.drawable.arrow_up;
        // 指定下拉狀態(tài)欄時(shí)顯示的通知圖標(biāo)
        JPushInterface.setPushNotificationBuilder(2, builder);

        String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
        MyLog.i( " title : " + title);
        String message = bundle.getString(JPushInterface.EXTRA_ALERT);
        MyLog.i( "message : " + message);
        String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
        MyLog.i( "extras : " + extras);
    }

    private void openNotification(Context context, Bundle bundle) {
        String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
        String myValue = "";
        try {
            JSONObject extrasJson = new JSONObject(extras);
            myValue = extrasJson.optString("myKey");
        } catch (Exception e) {
            MyLog.e("Unexpected: extras is not a valid json" + e.toString());
            return;
        }

    }

    // 打印所有的 intent extra 數(shù)據(jù)
    private static String printBundle(Bundle bundle) {
        StringBuilder sb = new StringBuilder();
        for (String key : bundle.keySet()) {
            if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
                sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
            }else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){
                sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
            } else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
                if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) {
                    MyLog.d("This message has no Extra data");
                    continue;
                }

                try {
                    JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
                    Iterator<String> it =  json.keys();

                    while (it.hasNext()) {
                        String myKey = it.next().toString();
                        sb.append("\nkey:" + key + ", value: [" +
                                myKey + " - " +json.optString(myKey) + "]");
                    }
                } catch (JSONException e) {
                    MyLog.e("Get message extra JSON error!");
                }

            } else {
                sb.append("\nkey:" + key + ", value:" + bundle.getString(key));
            }
        }
        return sb.toString();
    }

}

ps:

  • 通知信息和自定義信息的區(qū)別是:通知會(huì)在通知欄中顯示,自定義需要自己出來(lái)渤昌,可以自定義顯示虽抄。
  • 通知狀態(tài)欄也可以自行定義。
  • showNotification可以自行定義通知框的顯示独柑。但是需要后臺(tái)服務(wù)器中下發(fā)對(duì)應(yīng)的字段進(jìn)行控制迈窟。這里使用了一個(gè)開(kāi)源通知庫(kù): https://github.com/wenmingvs/NotifyUtil。 但是小米mui8手機(jī)上通知信息達(dá)不到效果忌栅。在其他的手機(jī)上還是有效果车酣。

6.定向推送

在開(kāi)發(fā)中為了定向推送到指定的手機(jī)上,所以需要在客戶端中綁定相應(yīng)的別名,這樣就可以定向推送到指定的手機(jī)上了湖员。因?yàn)榭蛻舳撕头?wù)器端都是自己開(kāi)發(fā)贫悄,可以通過(guò)用戶名做為別名進(jìn)行綁定。

  // 調(diào)用 Handler 來(lái)異步設(shè)置別名
  if (!user_id.equals(SpUtils.get(getApplicationContext(),"TAG_ALIAS",""))){
     SpUtils.remove(getApplicationContext(),"TAG_ALIAS");
     mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS, MUtils.user_id));
  }
  
 private final TagAliasCallback mAliasCallback = new TagAliasCallback() {
        @Override
        public void gotResult(int code, String alias, Set<String> tags) {
            String logs ;
            switch (code) {
                case 0:
                    logs = "Set tag and alias success";
                    MyLog.i(logs);
                    SpUtils.put(getApplicationContext(),"TAG_ALIAS",alias);
                    break;
                case 6002:
                    logs = "Failed to set alias and tags due to timeout. Try again after 60s.";
                    MyLog.i( logs);
                    // 延遲 60 秒來(lái)調(diào)用 Handler 設(shè)置別名
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 60);
                    break;
                default:
                    logs = "Failed with errorCode = " + code;
                    MyLog.i(logs);
            }
        }
    };

    private static final int MSG_SET_ALIAS = 1001;
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(android.os.Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_SET_ALIAS:
                    MyLog.i("Set alias in handler.");
                    // 調(diào)用 JPush 接口來(lái)設(shè)置別名娘摔。
                    JPushInterface.setAliasAndTags(getApplicationContext(),
                            (String) msg.obj,
                            null,
                            mAliasCallback);
                    break;
                default:
                    MyLog.i( "Unhandled msg - " + msg.what);
            }
        }
    };

這里使用SharedPreferences

public class SpUtils
{
    /**
     * 保存在手機(jī)里面的文件名
     */
    public static final String FILE_NAME = "share_data";

    /**
     * 保存數(shù)據(jù)的方法窄坦,我們需要拿到保存數(shù)據(jù)的具體類型,然后根據(jù)類型調(diào)用不同的保存方法
     *
     * @param context
     * @param key
     * @param object
     */
    public static void put(Context context, String key, Object object)
    {

        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if (object instanceof String)
        {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer)
        {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean)
        {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float)
        {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long)
        {
            editor.putLong(key, (Long) object);
        } else
        {
            editor.putString(key, object.toString());
        }

        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 得到保存數(shù)據(jù)的方法凳寺,我們根據(jù)默認(rèn)值得到保存的數(shù)據(jù)的具體類型鸭津,然后調(diào)用相對(duì)于的方法獲取值
     *
     * @param context
     * @param key
     * @param defaultObject
     * @return
     */
    public static Object get(Context context, String key, Object defaultObject)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);

        if (defaultObject instanceof String)
        {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer)
        {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean)
        {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float)
        {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long)
        {
            return sp.getLong(key, (Long) defaultObject);
        }

        return null;
    }

    /**
     * 移除某個(gè)key值已經(jīng)對(duì)應(yīng)的值
     * @param context
     * @param key
     */
    public static void remove(Context context, String key)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 清除所有數(shù)據(jù)
     * @param context
     */
    public static void clear(Context context)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 查詢某個(gè)key是否已經(jīng)存在
     * @param context
     * @param key
     * @return
     */
    public static boolean contains(Context context, String key)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.contains(key);
    }

    /**
     * 返回所有的鍵值對(duì)
     *
     * @param context
     * @return
     */
    public static Map<String, ?> getAll(Context context)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.getAll();
    }

    /**
     * 創(chuàng)建一個(gè)解決SharedPreferencesCompat.apply方法的一個(gè)兼容類
     *
     * @author zhy
     *
     */
    private static class SharedPreferencesCompat
    {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查找apply的方法
         *
         * @return
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        private static Method findApplyMethod()
        {
            try
            {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e)
            {
            }

            return null;
        }

        /**
         * 如果找到則使用apply執(zhí)行,否則使用commit
         *
         * @param editor
         */
        public static void apply(SharedPreferences.Editor editor)
        {
            try
            {
                if (sApplyMethod != null)
                {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (IllegalArgumentException e)
            {
            } catch (IllegalAccessException e)
            {
            } catch (InvocationTargetException e)
            {
            }
            editor.commit();
        }
    }

}

到此android客戶端集成結(jié)束读第。

2.3服務(wù)端集成

引入到現(xiàn)有工程中怜瞒。把1中的jar和測(cè)試文件到入到工程中父泳,把3中的jar文件導(dǎo)入到工程中。

jpush_web.png

詳細(xì)的使用可以參考1中的介紹吴汪。我這只對(duì)發(fā)通知和消息和指定對(duì)象推送進(jìn)行測(cè)試

public class Test {
    protected static final Logger LOG = LoggerFactory.getLogger(Test.class);
    public static final String ALERT = "數(shù)據(jù)";

    public static void main(String[] args) {
        testSendPush();
    }

    public static void testSendPush() {
        JPushClient jpushClient = new JPushClient(Config.masterSecret, Config.appKey);
        PushPayload payload = buildPushObject_all_all_alert();

        try {
            PushResult result = jpushClient.sendPush(payload);
            LOG.info("Got result - " + result);
        } catch (APIConnectionException e) {
            LOG.error("Connection error. Should retry later. ", e);
        } catch (APIRequestException e) {
            LOG.error("Error response from JPush server. Should review and fix it. ", e);
            LOG.info("HTTP Status: " + e.getStatus());
            LOG.info("Error Code: " + e.getErrorCode());
            LOG.info("Error Message: " + e.getErrorMessage());
            LOG.info("Msg ID: " + e.getMsgId());
        }
    }

    public static PushPayload buildPushObject_all_all_alert() {
//        PushPayload payload = PushPayload
//                .newBuilder()
//                .setPlatform(Platform.android())
//                .setAudience(Audience.tag("tag1"))
//                .setNotification(
//                        Notification
//                                .newBuilder()
//                                .setAlert(ALERT)
//                                .addPlatformNotification(
//                                        IosNotification.newBuilder().incrBadge(1)
//                                                .addExtra("extra_key", "extra_value").build())
//                                .build()).build();
//        return payload;
        Map<String, String> extras = new HashMap<String, String>();
        extras.put("Notificaction", "0");
        extras.put("URL", "www.baidu.com");

        Message.content("數(shù)據(jù)");
        PushPayload payload = PushPayload.newBuilder()
                   .setPlatform(Platform.android())
                   .setAudience(Audience.alias("0123456789"))
                   .setOptions(Options.sendno())
                   .setNotification(Notification.android("一個(gè)驚喜", "號(hào)外", extras))
                   //.setMessage(Message.newBuilder().setMsgContent("").addExtra("Notificaction", "0").build())
//                   .setMessage(
//                        Message.newBuilder().setMsgContent("數(shù)據(jù)").addExtra("Notificaction", "7").setTitle("大爺?shù)?)
//                                .build())
                   .build();
                   
                   
        return payload;
        
    }

}

到處服務(wù)端集成成功惠窄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市漾橙,隨后出現(xiàn)的幾起案子杆融,更是在濱河造成了極大的恐慌,老刑警劉巖霜运,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脾歇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡淘捡,警方通過(guò)查閱死者的電腦和手機(jī)藕各,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)焦除,“玉大人激况,你說(shuō)我怎么就攤上這事”炱牵” “怎么了乌逐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)创葡。 經(jīng)常有香客問(wèn)我浙踢,道長(zhǎng),這世上最難降的妖魔是什么灿渴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任成黄,我火速辦了婚禮呐芥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奋岁。我一直安慰自己,他們只是感情好荸百,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布闻伶。 她就那樣靜靜地躺著,像睡著了一般够话。 火紅的嫁衣襯著肌膚如雪蓝翰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天女嘲,我揣著相機(jī)與錄音畜份,去河邊找鬼。 笑死欣尼,一個(gè)胖子當(dāng)著我的面吹牛爆雹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愕鼓,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钙态,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了菇晃?” 一聲冷哼從身側(cè)響起册倒,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磺送,沒(méi)想到半個(gè)月后驻子,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡估灿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年崇呵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甲捏。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡演熟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出司顿,到底是詐尸還是另有隱情芒粹,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布大溜,位于F島的核電站化漆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏钦奋。R本人自食惡果不足惜座云,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一疙赠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朦拖,春花似錦圃阳、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至睬隶,卻和暖如春锣夹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苏潜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工银萍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恤左。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓贴唇,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赃梧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子滤蝠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,726評(píng)論 25 707
  • 推送技術(shù)產(chǎn)生場(chǎng)景: --服務(wù)器端主動(dòng)性: 客戶端與服務(wù)器交互都是客戶端主動(dòng)的, 服務(wù)器一般不能主動(dòng)與客戶端進(jìn)行數(shù)據(jù)...
    原軍鋒閱讀 34,532評(píng)論 4 60
  • 版本記錄 前言 ??現(xiàn)在很多APP都有推送功能,其中極光推送就是很多APP的首選授嘀。我們最近的幾個(gè)APP也是用的極光...
    刀客傳奇閱讀 8,367評(píng)論 0 8
  • @(〓〓 iOS-實(shí)用技術(shù))[遠(yuǎn)程/本地推送] 作者: Liwx 郵箱: 1032282633@qq.com 目...
    Liwx閱讀 5,103評(píng)論 8 67
  • 首先回顧一下NSURLSession的使用步驟: 創(chuàng)建一個(gè)NSURLSessionConfig對(duì)象 通過(guò)NSURL...
    dacheng閱讀 267評(píng)論 0 0