1. 程式人生 > >android 自定義網路變化時全域性提醒

android 自定義網路變化時全域性提醒

前言:今天在鴻洋大神的公眾號中看到一篇文章,叫10分鐘讓你實現在APP中對網路狀態變化進行全域性提醒。這在APP開發中是一個硬性需求,雖然我開發的app並沒有要求,但我覺得這個功能有必要親手實現一下。當然我也借鑑了作者的一些思路

參考文章:https://mp.weixin.qq.com/s/W9U7uzXRYcqCmgbX3gbbKg

實現思路:1、定時獲取當前網路狀態

                  2、利用廣播發送當前網路狀態,並且觸發網路狀態改變的監聽

                  3、在baseActivity中實現網路狀態改變的監聽,並作出相應的響應(例如顯示沒有網路的佈局)

程式碼實現:

             .定義接收網路變化的廣播,廣播我這邊用的的動態廣播,本來也打算用靜態廣播的但是看別人的評論說,android P下面有問題,所以就沒用了

public class CheckNetworkStatusChangeReceiver extends BroadcastReceiver {
    public static final String EVENT = "event";
    public static final String ACTION="action";
    private CheckNetworkStatusChangeListener mCheckNetworkStatusChangeListener;

    public CheckNetworkStatusChangeReceiver() {

    }

    public void setCheckNetworkStatusChangeListener(CheckNetworkStatusChangeListener mCheckNetworkStatusChangeListener) {
        this.mCheckNetworkStatusChangeListener = mCheckNetworkStatusChangeListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        CheckNetworkStatusChangeListener.Status mStatus = (CheckNetworkStatusChangeListener.Status) intent.getSerializableExtra(EVENT);
        mCheckNetworkStatusChangeListener.onEvent(mStatus);
    }
}

            網路狀態監聽類

public interface CheckNetworkStatusChangeListener {
    
    void onEvent(Status status);

    /**
     * 網路狀態
     * TYPE_UN_NETWORK 沒有網路
     * TYPE_WIFI WiFi連線
     * TYPE_MOBILE 移動資料
     */
    enum Status {
        TYPE_UN_NETWORK,
        TYPE_WIFI,
        TYPE_MOBILE,
    }
}

監聽事件,檢查到網路狀態時會呼叫

void onEvent(Status status);

檢測當前網路狀態

public class NetworkUtil {
    /**
     * 獲取當前網路型別 CheckNetworkStatusChangeListener.Status
     *
     * @return 返回網路型別 CheckNetworkStatusChangeListener.Status
     */
    public static CheckNetworkStatusChangeListener.Status getNetworkConnectionType(Context context) {
        //獲取連線管理器
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null)
            return CheckNetworkStatusChangeListener.Status.TYPE_UN_NETWORK;
        //獲取網路連線資訊
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isAvailable()) {
            if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                return CheckNetworkStatusChangeListener.Status.TYPE_WIFI;
            }
            if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                return CheckNetworkStatusChangeListener.Status.TYPE_MOBILE;
            }
        }
        return CheckNetworkStatusChangeListener.Status.TYPE_UN_NETWORK;
    }
}

實現每秒檢測1次網路狀態,因為是耗時操作所有在子執行緒中去獲取當前網路狀態

 @Override
    protected void onResume() {
        super.onResume();
        new Thread(mRunnable).start();
    }

    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {

            //實現每隔一秒檢測一次網路
            while (true){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                CheckNetworkStatusChangeListener.Status status = NetworkUtil.getNetworkConnectionType(BaseActivity.this);
                Message message = new Message();
                message.obj = status;
                simpleHandler.sendMessage(message);
            }

        }
    };

檢測網路狀態後傳送Message到handle,handle去傳送廣播,這注意handle記憶體洩漏

/**
 * @ Author yemao
 * @ Email [email protected]
 * @ Date 2018/7/31
 * @ Des自定義Handler,使用弱引用防止記憶體溢位
 */
public class SimpleHandler<T extends Activity> extends Handler {
    WeakReference<T> weakReference;

    public SimpleHandler(T t) {
        this.weakReference = new WeakReference<>(t);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (weakReference.get() != null) {
            //傳送廣播
            Intent mCheckNetworkIntent = new Intent();
            mCheckNetworkIntent.setAction(CheckNetworkStatusChangeReceiver.ACTION);
            CheckNetworkStatusChangeListener.Status status= (CheckNetworkStatusChangeListener.Status) msg.obj;
            mCheckNetworkIntent.putExtra(CheckNetworkStatusChangeReceiver.EVENT,status);
            weakReference.get().sendBroadcast(mCheckNetworkIntent);
        }
    }

}

到這基本上就竄起來了,看下baseActivity完整程式碼

/**
 * @ Author YeMao
 * @ Email [email protected]
 * @ Date 2018/7/31
 * @ Des Activity 基類
 */
public class BaseActivity extends AppCompatActivity implements CheckNetworkStatusChangeListener {
    private CheckNetworkStatusChangeReceiver mCheckNetworkStatusChangeReceiver;
    private String LOG = BaseActivity.class.getSimpleName();
    SimpleHandler<BaseActivity> simpleHandler;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCheckNetworkStatusChangeReceiver = new CheckNetworkStatusChangeReceiver();
        mCheckNetworkStatusChangeReceiver.setCheckNetworkStatusChangeListener(this);
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(CheckNetworkStatusChangeReceiver.ACTION);
        registerReceiver(mCheckNetworkStatusChangeReceiver, mIntentFilter);
        simpleHandler = new SimpleHandler<BaseActivity>(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        new Thread(mRunnable).start();
    }

    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {

            //實現每隔一秒檢測一次網路
            while (true){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                CheckNetworkStatusChangeListener.Status status = NetworkUtil.getNetworkConnectionType(BaseActivity.this);
                Message message = new Message();
                message.obj = status;
                simpleHandler.sendMessage(message);
            }

        }
    };


    @Override
    public void onEvent(Status status) {
        Log.w(LOG, "status: " + status.name());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mCheckNetworkStatusChangeReceiver);
        simpleHandler.removeCallbacks(mRunnable);
    }


}

我們執行一下,看下結果

07-31 19:12:14.069 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_WIFI
07-31 19:12:14.172 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_WIFI
07-31 19:12:14.429 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_WIFI
07-31 19:12:14.975 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_WIFI
07-31 19:12:15.071 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_UN_NETWORK
07-31 19:12:15.193 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_UN_NETWORK
07-31 19:12:15.446 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_UN_NETWORK
07-31 19:12:15.959 13865-13865/com.yr.simple W/BaseActivity: status: TYPE_UN_NETWORK

當網路變化時,呼叫onEvent()的列印資訊

那麼下一步就是在onEvent()判斷網路狀態,沒有網路時的頁面提示,當然你也可以做其他操作我這隻提供思路

1.自定義layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="@color/gray"
    android:layout_height="50dp">
    <TextView
        android:id="@+id/tv_network_status"
        android:layout_centerInParent="true"
        android:text="@string/not_network"
        android:textColor="@color/red"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


</RelativeLayout>

2.BaseActivity關鍵程式碼

  @Override
    public void setContentView(int layoutResID) {
        LinearLayout mRootLayout = findViewById(R.id.root_linear_layout);
        //將網路狀態view新增到根檢視
        mNetworkStatusLayout = new NetworkStatusLayout(this);
        //預設隱藏狀態
        mNetworkStatusLayout.setVisibility(View.GONE);
        mRootLayout.addView(mNetworkStatusLayout, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        //將子類的layout,新增到根目錄
        View mContentView = LayoutInflater.from(this).inflate(layoutResID, null);
        mRootLayout.addView(mContentView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

動態顯示隱藏NetworkStatusLayout

 @Override
    public void onEvent(Status status) {
        Log.w(LOG, "status: " + status.name());
        if (status == Status.TYPE_UN_NETWORK) {
            if (mNetworkStatusLayout.getVisibility() == View.GONE)
                mNetworkStatusLayout.setVisibility(View.VISIBLE);
        } else {
            if (mNetworkStatusLayout.getVisibility() == View.VISIBLE)
                mNetworkStatusLayout.setVisibility(View.GONE);
        }
    }

執行一下看下效果

然後進入優化工作

可能有些頁面不需要顯示,新增變數checkNetworkStatusChangeListenerEnable判斷是否要顯示
 

private boolean checkNetworkStatusChangeListenerEnable=true;
public void setCheckNetworkStatusChangeListenerEnable(boolean checkNetworkStatusChangeListener) {
        this.checkNetworkStatusChangeListenerEnable = checkNetworkStatusChangeListener;
}
    @Override
    public void onEvent(Status status) {
        Log.w(LOG, "status: " + status.name());
        if (checkNetworkStatusChangeListenerEnable)
            return;
        if (status == Status.TYPE_UN_NETWORK) {
            if (mNetworkStatusLayout.getVisibility() == View.GONE)
                mNetworkStatusLayout.setVisibility(View.VISIBLE);
        } else {
            if (mNetworkStatusLayout.getVisibility() == View.VISIBLE)
                mNetworkStatusLayout.setVisibility(View.GONE);
        }
    }

到這基本上大功告成了,BaseActivity完整程式碼
 

public class BaseActivity extends AppCompatActivity implements CheckNetworkStatusChangeListener {
    private CheckNetworkStatusChangeReceiver mCheckNetworkStatusChangeReceiver;
    private String LOG = BaseActivity.class.getSimpleName();
    private SimpleHandler<BaseActivity> simpleHandler;
    private NetworkStatusLayout mNetworkStatusLayout;
    private boolean checkNetworkStatusChangeListenerEnable=true;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_base);
        init();
    }

    @Override
    public void setContentView(int layoutResID) {
        LinearLayout mRootLayout = findViewById(R.id.root_linear_layout);
        //將網路狀態view新增到根檢視
        mNetworkStatusLayout = new NetworkStatusLayout(this);
        //預設隱藏狀態
        mNetworkStatusLayout.setVisibility(View.GONE);
        mRootLayout.addView(mNetworkStatusLayout, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        //將子類的layout,新增到根目錄
        View mContentView = LayoutInflater.from(this).inflate(layoutResID, null);
        mRootLayout.addView(mContentView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    private void init() {
        mCheckNetworkStatusChangeReceiver = new CheckNetworkStatusChangeReceiver();
        mCheckNetworkStatusChangeReceiver.setCheckNetworkStatusChangeListener(this);
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(CheckNetworkStatusChangeReceiver.ACTION);
        registerReceiver(mCheckNetworkStatusChangeReceiver, mIntentFilter);
        simpleHandler = new SimpleHandler<BaseActivity>(this);
    }

    public void setCheckNetworkStatusChangeListenerEnable(boolean checkNetworkStatusChangeListener) {
        this.checkNetworkStatusChangeListenerEnable = checkNetworkStatusChangeListener;
    }

    @Override
    protected void onResume() {
        super.onResume();
        new Thread(mRunnable).start();
    }

    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {

            //實現每隔一秒檢測一次網路
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                CheckNetworkStatusChangeListener.Status status = NetworkUtil.getNetworkConnectionType(BaseActivity.this);
                Message message = new Message();
                message.obj = status;
                simpleHandler.sendMessage(message);
            }

        }
    };


    @Override
    public void onEvent(Status status) {
        Log.w(LOG, "status: " + status.name());
        if (checkNetworkStatusChangeListenerEnable)
            return;
        if (status == Status.TYPE_UN_NETWORK) {
            if (mNetworkStatusLayout.getVisibility() == View.GONE)
                mNetworkStatusLayout.setVisibility(View.VISIBLE);
        } else {
            if (mNetworkStatusLayout.getVisibility() == View.VISIBLE)
                mNetworkStatusLayout.setVisibility(View.GONE);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mCheckNetworkStatusChangeReceiver);
        simpleHandler.removeCallbacks(mRunnable);
    }


}

如何使用,activity繼承自BaseActivity
 

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("我是首頁");
    }
}

好了,謝謝大家閱讀,如有問題請戳我哦!