大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) 學(xué)習(xí)攻略 Java學(xué)習(xí) Java消息推送框架的代碼

Java消息推送框架的代碼

更新時(shí)間:2022-07-28 11:49:55 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1992次

大家在Java教程中會(huì)學(xué)到關(guān)于Java消息推送的知識(shí),那么,Java消息推送框架的代碼是什么?動(dòng)力節(jié)點(diǎn)小編來(lái)為大家解答。

1.主要是兩種實(shí)現(xiàn)方式:

(1)pull:輪詢,輪詢時(shí)間短:耗電,耗流量。時(shí)間長(zhǎng),不能保證消息及時(shí)。

輪詢:

Timer:WakeLock 讓CPU 保持喚醒,耗電量很大

AlarmManager:管理獨(dú)立的硬件時(shí)鐘RTC,可以在CPU休眠的時(shí)候正常運(yùn)行。在預(yù)設(shè)的時(shí)間到達(dá)之后,喚醒CPU。這樣CPU可以正常休眠,只需要任務(wù)到達(dá)之后醒來(lái)一段很短的時(shí)間。極光推送就是基于此實(shí)現(xiàn)的。

(2)push:SMS、長(zhǎng)連接。

2.長(zhǎng)連接又包括三種方式:

(1)GCM:google的Gcm,容易被國(guó)內(nèi)廠商閹割,而且NAT(Network AddressTranslation)容易超時(shí),長(zhǎng)連接無(wú)法保持,造成消息推送延遲。

(2)第三方推送:友盟、極光,騰訊信鴿

(3)自定義長(zhǎng)連接:長(zhǎng)連接、心跳和推送及時(shí)率。

保持長(zhǎng)連接,是消息及時(shí)的重要保證。發(fā)送心跳包,如果前臺(tái)檢測(cè)發(fā)送失敗,則重新初始化一個(gè)socket。

3.把socket鏈接和心跳功能都放在一個(gè)Service中,為什么要放在Service中?

一般我們這種socket幾乎是跟app的生命周期一樣長(zhǎng),甚至更長(zhǎng)。不管在不在Service中去完成操作,我們都得開(kāi)異步線程,雖然Service并不是異步操作,但是為了提升我們?nèi)蝿?wù)的優(yōu)先級(jí),我們最好是放在Service中,因?yàn)镾ervice是由Android系統(tǒng)管理的,并且擁有比較高的優(yōu)先級(jí),線程是Java中的異步任務(wù)載體,可以說(shuō)android系統(tǒng)不太認(rèn)識(shí)線程。放在Service中可以很大程度上避免任務(wù)被回收或者關(guān)閉

4.下面是android代碼的具體實(shí)現(xiàn):

BackSevice服務(wù):

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
public class BackService extends Service {
    private static final String TAG = "BackService";
    /** 心跳檢測(cè)時(shí)間  */
    private static final long HEART_BEAT_RATE = 3 * 1000;
    /** 主機(jī)IP地址  */
    private static final String HOST = "192.168.1.104";
    /** 端口號(hào)  */
    public static final int PORT = 9800;
    /** 消息廣播  */
    public static final String MESSAGE_ACTION = "org.feng.message_ACTION";
    /** 心跳廣播  */
    public static final String HEART_BEAT_ACTION = "org.feng.heart_beat_ACTION";
    private long sendTime = 0L;
    /** 弱引用 在引用對(duì)象的同時(shí)允許對(duì)垃圾對(duì)象進(jìn)行回收  */
    private WeakReference<Socket> mSocket;
    private ReadThread mReadThread;
    private IBackService.Stub iBackService = new IBackService.Stub() {
        @Override
        public boolean sendMessage(String message) throws RemoteException {
            return sendMsg(message);
        }
    };
    @Override
    public IBinder onBind(Intent arg0) {
        return (IBinder) iBackService;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        new InitSocketThread().start();
    }
    // 發(fā)送心跳包
    private Handler mHandler = new Handler();
    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                boolean isSuccess = sendMsg("");// 就發(fā)送一個(gè)\r\n過(guò)去, 如果發(fā)送失敗,就重新初始化一個(gè)socket
                if (!isSuccess) {
                    mHandler.removeCallbacks(heartBeatRunnable);
                    mReadThread.release();
                    releaseLastSocket(mSocket);
                    new InitSocketThread().start();
                    Log.d("ztf"," 發(fā)送失敗,就重新初始化一個(gè)socket" );
                }
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };
    public boolean sendMsg(String msg) {
        if (null == mSocket || null == mSocket.get()) {
            return false;
        }
        Socket soc = mSocket.get();
        try {
            if (!soc.isClosed() && !soc.isOutputShutdown()) {
                OutputStream os = soc.getOutputStream();
                String message = msg + "\r\n";
                os.write(message.getBytes());
                os.flush();
                sendTime = System.currentTimeMillis();// 每次發(fā)送成功數(shù)據(jù),就改一下最后成功發(fā)送的時(shí)間,節(jié)省心跳間隔時(shí)間
                Log.i(TAG, "發(fā)送成功的時(shí)間:" + sendTime);
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    // 初始化socket
    private void initSocket() throws UnknownHostException, IOException {
        Socket socket = new Socket(HOST, PORT);
        mSocket = new WeakReference<Socket>(socket);
        mReadThread = new ReadThread(socket);
        mReadThread.start();
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);// 初始化成功后,就準(zhǔn)備發(fā)送心跳包
    }
    // 釋放socket
    private void releaseLastSocket(WeakReference<Socket> mSocket) {
        try {
            if (null != mSocket) {
                Socket sk = mSocket.get();
                if (!sk.isClosed()) {
                    sk.close();
                }
                sk = null;
                mSocket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                initSocket();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public class ReadThread extends Thread {
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;
        public ReadThread(Socket socket) {
            mWeakSocket = new WeakReference<Socket>(socket);
        }
        public void release() {
            isStart = false;
            releaseLastSocket(mWeakSocket);
        }
        @SuppressLint("NewApi")
        @Override
        public void run() {
            super.run();
            Socket socket = mWeakSocket.get();
            if (null != socket) {
                try {
                    InputStream is = socket.getInputStream();
                    byte[] buffer = new byte[1024 * 4];
                    int length = 0;
                    while (!socket.isClosed() && !socket.isInputShutdown()
                            && isStart && ((length = is.read(buffer)) != -1)) {
                        if (length > 0) {
                            String message = new String(Arrays.copyOf(buffer,
                                                                      length)).trim();
                            Log.i(TAG, "收到服務(wù)器發(fā)送來(lái)的消息:"+message);
                            // 收到服務(wù)器過(guò)來(lái)的消息,就通過(guò)Broadcast發(fā)送出去
                            if (message.equals("ok")) {// 處理心跳回復(fù)
                                Intent intent = new Intent(HEART_BEAT_ACTION);
                                sendBroadcast(intent);
                            } else {
                                // 其他消息回復(fù)
                                Intent intent = new Intent(MESSAGE_ACTION);
                                intent.putExtra("message", message);
                                sendBroadcast(intent);
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Activity:

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private Intent mServiceIntent;
    private IBackService iBackService;
    private TextView tv;
    private EditText et;
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
        initData();
    }
    private void initViews() {
        tv = (TextView) findViewById(R.id.resule_text);
        et = (EditText) findViewById(R.id.content_edit);
        btn = (Button) findViewById(R.id.send);
    }
    private void initData() {
        mServiceIntent = new Intent(this, BackService.class);
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                String string = et.getText().toString().trim();
                Log.i(TAG, string);
                try {
                    Log.i(TAG, "是否為空:" + iBackService);
                    if (iBackService == null) {
                        Toast.makeText(getApplicationContext(),
                                       "沒(méi)有連接,可能是服務(wù)器已斷開(kāi)", Toast.LENGTH_SHORT).show();
                    } else {
                        boolean isSend = iBackService.sendMessage(string);
                        Toast.makeText(MainActivity.this,
                                       isSend ? "success" : "fail", Toast.LENGTH_SHORT)
                             .show();
                        et.setText("");
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    @Override
    protected void onStart() {
        super.onStart();
        bindService(mServiceIntent, conn, BIND_AUTO_CREATE);
        // 開(kāi)始服務(wù)
        registerReceiver();
    }
    @Override
    protected void onResume() {
        super.onResume();
        // 注冊(cè)廣播 最好在onResume中注冊(cè)
        // registerReceiver();
    }
    @Override
    protected void onPause() {
        super.onPause();
        // 注銷廣播 最好在onPause上注銷
        unregisterReceiver(mReceiver);
        // 注銷服務(wù)
        unbindService(conn);
    }
    // 注冊(cè)廣播
    private void registerReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BackService.HEART_BEAT_ACTION);
        intentFilter.addAction(BackService.MESSAGE_ACTION);
        registerReceiver(mReceiver, intentFilter);
    }
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // 消息廣播
            if (action.equals(BackService.MESSAGE_ACTION)) {
                String stringExtra = intent.getStringExtra("message");
                tv.setText(stringExtra);
            } else if (action.equals(BackService.HEART_BEAT_ACTION)) {// 心跳廣播
                tv.setText("正常心跳");
            }
        }
    };
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 未連接為空
            iBackService = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 已連接
            iBackService = IBackService.Stub.asInterface(service);
        }
    };
}

aidl文件:

interface IBackService{
    boolean sendMessage(String message);
}

5.android系統(tǒng)的推送和iOS的推送有什么區(qū)別

首先我們必須知道,所有的推送功能必須有一個(gè)客戶端和服務(wù)器的長(zhǎng)連接,因?yàn)橥扑褪怯煞?wù)器主動(dòng)向客戶端發(fā)送消息,如果客戶端和服務(wù)器之間不存在一個(gè)長(zhǎng)連接那么服務(wù)器是無(wú)法來(lái)主動(dòng)連接客戶端的。因而推送功能都是基于長(zhǎng)連接的基礎(chǔ)是上的。

IOS長(zhǎng)連接是由系統(tǒng)來(lái)維護(hù)的,也就是說(shuō)蘋果的IOS系統(tǒng)在系統(tǒng)級(jí)別維護(hù)了一個(gè)客戶端和蘋果服務(wù)器的長(zhǎng)鏈接,IOS上的所有應(yīng)用上的推送都是先將消息推送到蘋果的服務(wù)器然后將蘋果服務(wù)器通過(guò)這個(gè)系統(tǒng)級(jí)別的長(zhǎng)連接推送到手機(jī)終端上,這樣的的幾個(gè)好處為:

在手機(jī)終端始終只要維護(hù)一個(gè)長(zhǎng)連接即可,而且由于這個(gè)長(zhǎng)連接是系統(tǒng)級(jí)別的不會(huì)出現(xiàn)被殺死而無(wú)法推送的情況。

省電,不會(huì)出現(xiàn)每個(gè)應(yīng)用都各自維護(hù)一個(gè)自己的長(zhǎng)連接。

安全,只有在蘋果注冊(cè)的開(kāi)發(fā)者才能夠進(jìn)行推送,等等。

android的長(zhǎng)連接是由每個(gè)應(yīng)用各自維護(hù)的,但是google也推出了和蘋果技術(shù)架構(gòu)相似的推送框架,C2DM,云端推送功能,但是由于google的服務(wù)器不在中國(guó)境內(nèi),其他的原因你懂的。所以導(dǎo)致這個(gè)推送無(wú)法使用,android的開(kāi)發(fā)者不得不自己去維護(hù)一個(gè)長(zhǎng)鏈接,于是每個(gè)應(yīng)用如果都24小時(shí)在線,那么都得各自維護(hù)一個(gè)長(zhǎng)連接,這種電量和流量的消耗是可想而知的。雖然國(guó)內(nèi)也出現(xiàn)了各種推送平臺(tái),但是都無(wú)法達(dá)到只維護(hù)一個(gè)長(zhǎng)連接這種消耗的級(jí)別。

以上就是關(guān)于“Java消息推送框架的代碼”介紹,大家如果想了解更多相關(guān)知識(shí),可以關(guān)注一下動(dòng)力節(jié)點(diǎn)的Java視頻教程,里面的課程內(nèi)容從入門到精通,細(xì)致全面,通俗易懂,很適合沒(méi)有基礎(chǔ)的小白學(xué)習(xí),希望對(duì)大家能夠有所幫助。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

  • 全國(guó)校區(qū) 2025-06-26 搶座中
免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 午夜国产精品色福利视频 | 中文字幕在亚洲第一在线 | 久久99精品久久久久久噜噜 | 欧美一级毛片高清毛片 | sihu影院永久在线影院 | 欧美精品国产综合久久 | 波多野结衣中文无毒不卡 | 日韩精品国产自在久久现线拍 | 国产一久久香蕉国产线看观看 | 色综合精品久久久久久久 | 成人国产午夜在线视频 | 国产精品久久一区一区 | 毛片一级在线 | 韩国19禁青草福利视频在线 | 深夜福利在线免费观看 | 4hu影院永久在线播放 | 久久99热久久精品在线6 | 欧美交换乱理伦片120秒 | 午夜看一级特黄a大片黑 | 日本色图网站 | 两性色午夜视频免费老司机 | baoyu777永久免费视频 | 国产高清自拍 | 伊人99热| 久久精品欧美日韩精品 | 非洲黑人xxxxxbbbbbb | 国产不卡福利 | 亚洲欧美日韩精品久久 | 亚洲国产精品久久日 | 老司机精品久久 | 日本不卡在线一区二区三区视频 | 国产玖玖视频 | 91国在线 | 奇米影视狠狠干 | 久久精品国产亚洲精品2020 | 欧美日韩在线成人免费 | 狠狠色噜噜狠狠狠狠97影音先锋 | 亚洲日日做天天做日日谢 | 久久 在线播放 | 国产成人综合日韩精品婷婷九月 | 好看的亚洲视频 |