1. 程式人生 > >極光訊息推送伺服器端開發實現推送(下)

極光訊息推送伺服器端開發實現推送(下)

前面我們已經實現了通過我們自己的伺服器生成訊息向極光訊息推送伺服器傳送推送訊息的功能,下面我們來看看如何在手機客戶端實現訊息接收。

一、在極光上建立一個測試專案


如上圖所示,下載Android Example


執行效果如圖


下面我們通過原始碼先看看上面的四行顯示TextView的獲取。

		TextView mAppKey = (TextView) findViewById(R.id.tv_appkey);
		String appKey = ExampleUtil.getAppKey(getApplicationContext());
		if (null == appKey) appKey = "AppKey異常";
		mAppKey.setText("AppKey: " + appKey);
向下追蹤,檢視getAppKey方法
    // 取得AppKey
    public static String getAppKey(Context context) {
        Bundle metaData = null;
        String appKey = null;
        try {
            ApplicationInfo ai = context.getPackageManager().getApplicationInfo(
                    context.getPackageName(), PackageManager.GET_META_DATA);
            if (null != ai)
                metaData = ai.metaData;
            if (null != metaData) {
                appKey = metaData.getString(KEY_APP_KEY);
                if ((null == appKey) || appKey.length() != 24) {
                    appKey = null;
                }
            }
        } catch (NameNotFoundException e) {

        }
        return appKey;
    }
我們可以看到首先通過Context類的getPackageManager()方法獲取相關資訊。

開啟Android原始碼可以看到Context實際上是一個抽象類,它的實現類是ContextImpl,類之間的關係如圖


開啟ContextImpl類可以看到getPackageManager的實現

    @Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }
上面的ActivityThread才是一個android應用的真正入口,可以在該類中查到main函式。
    public static final void main(String[] args) {
        SamplingProfilerIntegration.start();

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        if (Process.supportsProcesses()) {
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        thread.detach();
        String name = (thread.mInitialApplication != null)
            ? thread.mInitialApplication.getPackageName()
            : "<unknown>";
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }
}
有關PackageManager部分的詳細介紹請看:http://blog.csdn.net/stonecao/article/details/6591454

我們現在先不關心怎麼獲取PackageManager,先來看看PackageManager能幹什麼

PackageManager類是對所有基於載入資訊的資料結構的封裝,包括以下功能:

安裝,解除安裝應用查詢permission相關資訊

查詢Application相關資訊(application,activity,receiver,service,provider及相應屬性等)

查詢已安裝應用

增加,刪除permission

清除使用者資料、快取,程式碼段等

通過獲取ApplicationInfo得到PackageItemInfo類中的Bundle內部類物件

PackageIteminfo類是AndroidManifest.xml檔案中所有節點的基類,提供了這些節點的基本資訊

在manifest檔案中可以看到如下兩行程式碼

        <!-- 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="5d30bebd28335593a111186" /> <!--  </>值來自開發者平臺取得的AppKey-->
再看到ExampleUtil中的如下程式碼應該恍然開朗了吧
    public static final String KEY_APP_KEY = "JPUSH_APPKEY";

好啦,下面我們將伺服器端推送訊息方法改成如下:

MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent);
全部程式碼:
package com.meritit.tuisong.service;
import java.util.HashMap;
import java.util.Map;

import cn.jpush.api.ErrorCodeEnum;
import cn.jpush.api.IOSExtra;
import cn.jpush.api.JPushClient;
import cn.jpush.api.MessageResult;

public class JPushClientExample {

	private static final String appKey ="5d30bebd28335593a1345486";	//必填,例如466f7032ac604e02fb7bda89

	private static final String masterSecret = "0e0cc80c6f6a4703bec9ed19";//"13ac09b17715bd117163d8a1";//必填,每個應用都對應一個masterSecret

	private static JPushClient jpush = null;

	/**
	 * 儲存離線的時長。秒為單位。最多支援10天(864000秒)。
	 * 0 表示該訊息不儲存離線。即:使用者線上馬上發出,當前不線上使用者將不會收到此訊息。
	 * 此引數不設定則表示預設,預設為儲存1天的離線訊息(86400秒)。
	 */
	private static long timeToLive =  60 * 60 * 24;  

	public static void main(String[] args) {
		/*
		 * Example1: 初始化,預設傳送給android和ios,同時設定離線訊息存活時間
		 * jpush = new JPushClient(masterSecret, appKey, timeToLive);
		 */

		/*		
		 * Example2: 只發送給android
		 * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.Android);
		 */

		/*
		 * Example3: 只發送給IOS
		 * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.IOS);
		 */

		/*
		 * Example4: 只發送給android,同時設定離線訊息存活時間
		 * jpush = new JPushClient(masterSecret, appKey, timeToLive, DeviceEnum.Android);
		 */


		jpush = new JPushClient(masterSecret, appKey, timeToLive);

		/*
		 * 是否啟用ssl安全連線, 可選
		 * 引數:啟用true, 禁用false,預設為非ssl連線
		 */
		//jpush.setEnableSSL(true);


		//測試傳送訊息或者通知
		testSend();
	}

	private static void testSend() {
		// 在實際業務中,建議 sendNo 是一個你自己的業務可以處理的一個自增數字。
		// 除非需要覆蓋,請確保不要重複使用。詳情請參考 API 文件相關說明。
		int sendNo = getRandomSendNo();
		String msgTitle = "+;//jpush\"\"";
		String msgContent = "\\&;w\"\"a--【\npush】";

		/*
		 * IOS裝置擴充套件引數,
		 * 設定badge,設定聲音
		 */

		Map<String, Object> extra = new HashMap<String, Object>();
		IOSExtra iosExtra = new IOSExtra(10, "WindowsLogonSound.wav");
		extra.put("ios", iosExtra);

		//對所有使用者傳送通知, 更多方法請參考文件
		MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent);
		
		//MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);
		//MessageResult msgResult  = jpush.sendNotificationWithAlias(sendNo, "a", msgTitle, msgContent);

		//覆蓋指定msgId的訊息,msgId可以從msgResult.getMsgid()獲取。
		//MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent, 0, extra,msgResult.getMsgid());


		if (null != msgResult) {
			System.out.println("伺服器返回資料: " + msgResult.toString());
			if (msgResult.getErrcode() == ErrorCodeEnum.NOERROR.value()) {
				System.out.println(String.format("傳送成功, sendNo= %s,messageId= %s",msgResult.getSendno(),msgResult.getMsg_id()));
			} else {
				System.out.println("傳送失敗, 錯誤程式碼=" + msgResult.getErrcode() + ", 錯誤訊息=" + msgResult.getErrmsg());
			}
		} else {
			System.out.println("無法獲取資料");
		}

	}

	public static final int MAX = Integer.MAX_VALUE;
	public static final int MIN = (int) MAX/2;

	/**
	 * 保持 sendNo 的唯一性是有必要的
	 * It is very important to keep sendNo unique.
	 * @return sendNo
	 */
	public static int getRandomSendNo() {
		return (int) (MIN + Math.random() * (MAX - MIN));
	}

}
執行結果:

控制檯


手機端

這樣就可以實現通過自己的伺服器來自動生成訊息內容了。