【问题标题】:Using sockets in android?在android中使用套接字?
【发布时间】:2014-08-23 19:11:25
【问题描述】:

我要问的是如何重新实现从套接字接收数据的应用程序的方法或建议。我的应用程序现在连接到推送服务并从套接字获取数据。当接收到新事件(推送器上的新数据)时,数据会更新到 UI,接收数据的线程会等待新事件。

只要互联网可用,就可以了。当互联网掉线时,不会重新建立套接字。

我有一个 android 服务,我在其中接收数据,然后将结果发布给订阅者。然后订阅者使用数据调用 UI 更新方法,然后再次调用用于接收数据的 android 服务。

然而,每次成功数据后,首先在 onResume 活动和订阅者中调用 android 服务。但是,如果网络中断,则服务不会再次启动。我该如何处理?

我的第一个想法是当网络中断时,我开始每 2 秒检查一次网络可用性的活动,如果网络可用,它会重新启动套接字。但是,它并不像我想要的那样可靠。

如果您需要查看代码,我会发布。

【问题讨论】:

    标签: android sockets pusher


    【解决方案1】:

    你需要听CONNECTIVITY_ACTION。文档说:

    网络连接发生了变化。连接具有 成立或失去。受影响网络的 NetworkInfo 是 作为额外发送;应该咨询一下 发生连接事件。

    如果这是一个从 断开网络,则 FAILOVER_CONNECTION 布尔额外是 设置为真。

    对于连接丢失,如果连接管理器正在尝试 连接(或已经连接)到另一个网络, 新网络的 NetworkInfo 也作为额外的传递。这让 广播的任何接收者都知道他们不一定 告诉用户没有数据流量是可能的。相反, 接收者应该很快就会期待另一个广播,这表明要么 故障转移尝试成功(因此仍有整体数据 连接),或者故障转移尝试失败,这意味着所有 连接已丢失。

    对于断开连接事件,设置了额外的布尔值 EXTRA_NO_CONNECTIVITY 如果根本没有连接的网络,则为 true。

    常量值:“android.net.conn.CONNECTIVITY_CHANGE”

    参考here以下代码sn-p

    /*
     * Copyright (C) 2006 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.net;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    import java.util.HashMap;
    import java.util.Iterator;
    
    /**
     * A wrapper for a broadcast receiver that provides network connectivity
     * state information, independent of network type (mobile, Wi-Fi, etc.).
     * {@hide}
     */
    public class NetworkConnectivityListener {
        private static final String TAG = "NetworkConnectivityListener";
        private static final boolean DBG = false;
    
        private Context mContext;
        private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
        private State mState;
        private boolean mListening;
        private String mReason;
        private boolean mIsFailover;
    
        /** Network connectivity information */
        private NetworkInfo mNetworkInfo;
    
        /**
         * In case of a Disconnect, the connectivity manager may have
         * already established, or may be attempting to establish, connectivity
         * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
         */
        private NetworkInfo mOtherNetworkInfo;
    
        private ConnectivityBroadcastReceiver mReceiver;
    
        private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
    
                if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
                    mListening == false) {
                    Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
                    return;
                }
    
                boolean noConnectivity =
                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
    
                if (noConnectivity) {
                    mState = State.NOT_CONNECTED;
                } else {
                    mState = State.CONNECTED;
                }
    
                mNetworkInfo = (NetworkInfo)
                    intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
                mOtherNetworkInfo = (NetworkInfo)
                    intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
    
                mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
                mIsFailover =
                    intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
    
                if (DBG) {
                    Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo +  " mOtherNetworkInfo = "
                            + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
                            " noConn=" + noConnectivity) + " mState=" + mState.toString());
                }
    
                // Notifiy any handlers.
                Iterator<Handler> it = mHandlers.keySet().iterator();
                while (it.hasNext()) {
                    Handler target = it.next();
                    Message message = Message.obtain(target, mHandlers.get(target));
                    target.sendMessage(message);
                }
            }
        };
    
        public enum State {
            UNKNOWN,
    
            /** This state is returned if there is connectivity to any network **/
            CONNECTED,
            /**
             * This state is returned if there is no connectivity to any network. This is set
             * to true under two circumstances:
             * <ul>
             * <li>When connectivity is lost to one network, and there is no other available
             * network to attempt to switch to.</li>
             * <li>When connectivity is lost to one network, and the attempt to switch to
             * another network fails.</li>
             */
            NOT_CONNECTED
        }
    
        /**
         * Create a new NetworkConnectivityListener.
         */
        public NetworkConnectivityListener() {
            mState = State.UNKNOWN;
            mReceiver = new ConnectivityBroadcastReceiver();
        }
    
        /**
         * This method starts listening for network connectivity state changes.
         * @param context
         */
        public synchronized void startListening(Context context) {
            if (!mListening) {
                mContext = context;
    
                IntentFilter filter = new IntentFilter();
                filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
                context.registerReceiver(mReceiver, filter);
                mListening = true;
            }
        }
    
        /**
         * This method stops this class from listening for network changes.
         */
        public synchronized void stopListening() {
            if (mListening) {
                mContext.unregisterReceiver(mReceiver);
                mContext = null;
                mNetworkInfo = null;
                mOtherNetworkInfo = null;
                mIsFailover = false;
                mReason = null;
                mListening = false;
            }
        }
    
        /**
         * This methods registers a Handler to be called back onto with the specified what code when
         * the network connectivity state changes.
         *
         * @param target The target handler.
         * @param what The what code to be used when posting a message to the handler.
         */
        public void registerHandler(Handler target, int what) {
            mHandlers.put(target, what);
        }
    
        /**
         * This methods unregisters the specified Handler.
         * @param target
         */
        public void unregisterHandler(Handler target) {
            mHandlers.remove(target);
        }
    
        public State getState() {
            return mState;
        }
    
        /**
         * Return the NetworkInfo associated with the most recent connectivity event.
         * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
         */
        public NetworkInfo getNetworkInfo() {
            return mNetworkInfo;
        }
    
        /**
         * If the most recent connectivity event was a DISCONNECT, return
         * any information supplied in the broadcast about an alternate
         * network that might be available. If this returns a non-null
         * value, then another broadcast should follow shortly indicating
         * whether connection to the other network succeeded.
         *
         * @return NetworkInfo
         */
        public NetworkInfo getOtherNetworkInfo() {
            return mOtherNetworkInfo;
        }
    
        /**
         * Returns true if the most recent event was for an attempt to switch over to
         * a new network following loss of connectivity on another network.
         * @return {@code true} if this was a failover attempt, {@code false} otherwise.
         */
        public boolean isFailover() {
            return mIsFailover;
        }
    
        /**
         * An optional reason for the connectivity state change may have been supplied.
         * This returns it.
         * @return the reason for the state change, if available, or {@code null}
         * otherwise.
         */
        public String getReason() {
            return mReason;
        }
    }
    
    syntax highlighted by Code2HTML, v. 0.9.1
    

    【讨论】:

      【解决方案2】:

      除了@rupesh jain 的建议。您应该使用BroadcastReceiver 来监控网络状态,并在连接建立(重新连接套接字)或丢失(断开套接字并可能保存上次请求的状态)时采取适当的措施。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-21
        • 2016-04-09
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-18
        相关资源
        最近更新 更多