一、网络状态

       Android市场的逐渐降温及形成稳定,其实说明了Android的发展走向稳重成熟的阶段。

       除却最开始的功能实现,到如今的用户体验至上,Android研发面临的挑战却从未冷却。基于大多数APP均是以APP为数据展示框架,实现客户与服务器数据交互,网络扮演了十分重要的角色。

       网络状态,除了WiFi,数据,网络不可用等,还有网络条件不好等情形。存有标志网络速度的则能较好地标示当前网络情形。

       以下则实现监听网速,展示当前网速条件。借由给客户更好的用户体验。


二、实现监听网速

TrafficStats类提供了以下方法,关于统计网速:

    /**     * static long getMobileRxBytes()//获取通过Mobile连接收到的字节总数,但不包含WiFi static long     * getMobileRxPackets()//获取Mobile连接收到的数据包总数 static long     * getMobileTxBytes()//Mobile发送的总字节数 static long     * getMobileTxPackets()//Mobile发送的总数据包数 static long     * getTotalRxBytes()//获取总的接受字节数,包含Mobile和WiFi等 static long     * getTotalRxPackets()//总的接受数据包数,包含Mobile和WiFi等 static long     * getTotalTxBytes()//总的发送字节数,包含Mobile和WiFi等 static long     * getTotalTxPackets()//发送的总数据包数,包含Mobile和WiFi等 static long     * getUidRxBytes(int uid)//获取某个网络UID的接受字节数 static long getUidTxBytes(int     * uid) //获取某个网络UID的发送字节数     */
实现整体思路:

        创建浮动窗口,用于展示网速状态;应用程序后台运行,浮动窗口依旧显示,则使用Service展示浮动窗口;在Activity中开启Service。

网速监听主体功能实现,TrafficBean.java:

package com.future.netobserverdemo.bean;import android.content.Context;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager;import android.net.TrafficStats;import android.os.Handler;import android.os.Message;import android.util.Log;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.io.Serializable;import java.math.BigDecimal;import java.util.Timer;import java.util.TimerTask;/** * 功能:流量Bean属性信息 * 作者:vision * 时间:2016/10/19 */public class TrafficBean implements Serializable {    /**     * static long getMobileRxBytes()//获取通过Mobile连接收到的字节总数,但不包含WiFi static long     * getMobileRxPackets()//获取Mobile连接收到的数据包总数 static long     * getMobileTxBytes()//Mobile发送的总字节数 static long     * getMobileTxPackets()//Mobile发送的总数据包数 static long     * getTotalRxBytes()//获取总的接受字节数,包含Mobile和WiFi等 static long     * getTotalRxPackets()//总的接受数据包数,包含Mobile和WiFi等 static long     * getTotalTxBytes()//总的发送字节数,包含Mobile和WiFi等 static long     * getTotalTxPackets()//发送的总数据包数,包含Mobile和WiFi等 static long     * getUidRxBytes(int uid)//获取某个网络UID的接受字节数 static long getUidTxBytes(int     * uid) //获取某个网络UID的发送字节数     */    /**     * 不支持状态【标识变量】     */    private static final int UNSUPPORT = -1;    /**     * 打印信息标志     */    private static final String TAG = "TrafficBean";    /**     * 当前对象实例     */    private static TrafficBean instance;    /**     * 当前应用的uid     */    static int UUID;    /**     * 上一次记录网络字节流     */    private long preRxBytes = 0;    /**     *     */    private Timer mTimer = null;    /**     * 上下文对象     */    private Context context;    /**     * 消息处理器     */    private Handler handler;    /**     * 更新频率     */    private final int UPDATE_FREQUENCY = 1;    private int times = 1;    /**     * 构造方法     *     * @param context     * @param handler     * @param uid     */    public TrafficBean(Context context, Handler handler, int uid) {        this.context = context;        this.handler = handler;        this.UUID = uid;    }    public TrafficBean(Context context, Handler handler) {        this.context = context;        this.handler = handler;    }    /**     * 获取实例对象     *     * @param context     * @param handler     * @return     */    public static TrafficBean getInstance(Context context, Handler handler) {        if (instance == null) {            instance = new TrafficBean(context, handler);        }        return instance;    }    /**     * 获取总流量     *     * @return     */    public long getTrafficInfo() {        long recTraffic = UNSUPPORT;//下载流量        long sendTraffic = UNSUPPORT;//上传流量        recTraffic = getRecTraffic();        sendTraffic = getSendTraffic();        if (recTraffic == UNSUPPORT || sendTraffic == UNSUPPORT) {            return UNSUPPORT;        } else {            return recTraffic + sendTraffic;        }    }    /**     * 获取上传流量     *     * @return     */    private long getSendTraffic() {        long sendTraffic = UNSUPPORT;        sendTraffic = TrafficStats.getUidTxBytes(UUID);        if (sendTraffic == UNSUPPORT) {            return UNSUPPORT;        }        RandomAccessFile rafSend = null;        String sndPath = "/proc/uid_stat/" + UUID + "/tcp_snd";        try {            rafSend = new RandomAccessFile(sndPath, "r");            sendTraffic = Long.parseLong(rafSend.readLine());        } catch (FileNotFoundException e) {            Log.e(TAG, "FileNotFoundException: " + e.getMessage());            sendTraffic = UNSUPPORT;        } catch (IOException e) {            Log.e(TAG, "IOException: " + e.getMessage());            e.printStackTrace();        } finally {            try {                if (rafSend != null)                    rafSend.close();            } catch (IOException e) {                Log.w(TAG, "Close RandomAccessFile exception: " + e.getMessage());            }        }        return sendTraffic;    }    /**     * 获取下载流量     * 某个应用的网络流量数据保存在系统的     * /proc/uid_stat/$UID/tcp_rcv | tcp_snd文件中     *     * @return     */    private long getRecTraffic() {        long recTraffic = UNSUPPORT;        recTraffic = TrafficStats.getUidRxBytes(UUID);        if (recTraffic == UNSUPPORT) {            return UNSUPPORT;        }        Log.i(TAG, recTraffic + " ---1");        //访问数据文件        RandomAccessFile rafRec = null;        String rcvPath = "/proc/uid_stat/" + UUID + "/tcp_rcv";        try {            rafRec = new RandomAccessFile(rcvPath, "r");            recTraffic = Long.parseLong(rafRec.readLine()); // 读取流量统计        } catch (FileNotFoundException e) {            Log.e(TAG, "FileNotFoundException: " + e.getMessage());            recTraffic = UNSUPPORT;        } catch (IOException e) {            Log.e(TAG, "IOException: " + e.getMessage());            e.printStackTrace();        } finally {            try {                if (rafRec != null)                    rafRec.close();            } catch (IOException e) {                Log.w(TAG, "Close RandomAccessFile exception: " + e.getMessage());            }        }        Log.i("test", recTraffic + "--2");        return recTraffic;    }    /**     * 获取当前下载流量总和     *     * @return     */    public static long getNetworkRxBytes() {        return TrafficStats.getTotalRxBytes();    }    /**     * 获取当前上传流量总和     *     * @return     */    public static long getNetworkTxBytes() {        return TrafficStats.getTotalTxBytes();    }    /**     * 获取当前网速     *     * @return     */    public double getNetSpeed() {        long curRxBytes = getNetworkRxBytes();        if (preRxBytes == 0)            preRxBytes = curRxBytes;        long bytes = curRxBytes - preRxBytes;        preRxBytes = curRxBytes;        //int kb = (int) Math.floor(bytes / 1024 + 0.5);        double kb = (double) bytes / (double) 1024;        BigDecimal bd = new BigDecimal(kb);        return bd.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();    }    /**     * 开启流量监控     */    public void startCalculateNetSpeed() {        preRxBytes = getNetworkRxBytes();        if (mTimer != null) {            mTimer.cancel();            mTimer = null;        }        if (mTimer == null) {            mTimer = new Timer();            mTimer.schedule(new TimerTask() {                @Override                public void run() {                    if (times == UPDATE_FREQUENCY) {                        Message msg = new Message();                        msg.what = 1;                        //msg.arg1 = getNetSpeed();                        msg.obj = getNetSpeed();                        handler.sendMessage(msg);                        times = 1;                    } else {                        times++;                    }                }            }, 1000, 1000);        }    }    /**     * 停止网速监听计算     */    public void stopCalculateNetSpeed() {        if (mTimer != null) {            mTimer.cancel();            mTimer = null;        }    }    /**     * 获取当前应用uid     *     * @return     */    public int getUid() {        try {            PackageManager pm = context.getPackageManager();            //修改            ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);            return ai.uid;        } catch (PackageManager.NameNotFoundException e) {            e.printStackTrace();        }        return -1;    }}
Service中创建浮动窗口,展示网速状态,ManagerService.java:

public class ManagerService extends Service {    private static final String TAG = "ManagerService";    /**     * 浮动窗口布局     */    private LinearLayout floatLL;    public WindowManager.LayoutParams params;    /**     * 浮动串口布局参数     */    public WindowManager windowManager;    public TextView floatTV;    private ServiceBinder binder = new ServiceBinder();    @Override    public void onCreate() {        super.onCreate();        createFloatView();    }    /**     * 创建浮动窗口布局     */    private void createFloatView() {        params = new WindowManager.LayoutParams();        windowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 设置window        // type为TYPE_SYSTEM_ALERT        params.format = PixelFormat.RGBA_8888;// 设置图片格式,效果为背景透明        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)        params.gravity = Gravity.LEFT | Gravity.TOP;// 默认位置:左上角        params.width = WidgetUtils.dpToPx(getApplicationContext(), 65);        params.height = WindowManager.LayoutParams.WRAP_CONTENT;        params.x = (WidgetUtils.getScreenWidth(getApplicationContext()) - params.width) / 2;// 设置x、y初始值,相对于gravity        params.y = 10;        // 获取浮动窗口视图所在布局        LayoutInflater inflater = LayoutInflater.from(getApplication());        floatLL = (LinearLayout) inflater.inflate(R.layout.float_layout, null);        windowManager.addView(floatLL, params);// 添加mFloatLayout        floatTV = (TextView) floatLL.findViewById(R.id.move_desc);        floatTV.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));        // 设置监听浮动窗口的触摸移动        floatTV.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                // getRawX是触摸位置相对于屏幕的坐标,getX是相对于按钮的坐标                params.x = (int) event.getRawX() - floatTV.getMeasuredWidth() / 2;                Log.i(TAG, "RawX" + event.getRawX());                Log.i(TAG, "X" + event.getX());                params.y = (int) event.getRawY() - floatTV.getMeasuredHeight() / 2 - 25;// 减25为状态栏的高度                Log.i(TAG, "RawY" + event.getRawY());                Log.i(TAG, "Y" + event.getY());                windowManager.updateViewLayout(floatLL, params);// 刷新                return false; // 此处必须返回false,否则OnClickListener获取不到监听            }        });        floatTV.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View arg0) {                Toast.makeText(getApplicationContext(), "浮动窗口被点击了!", Toast.LENGTH_SHORT).show();            }        });    }    public void setSpeed(String str) {        floatTV.setText(str);    }    @Override    public void onDestroy() {        super.onDestroy();        if (floatLL != null && windowManager != null) {            windowManager.removeView(floatLL);// 移除悬浮窗口        }        startService(new Intent(this, ManagerService.class));    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return START_STICKY_COMPATIBILITY;    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return binder;    }    @Override    public void onTrimMemory(int level) {        super.onTrimMemory(level);    }    public class ServiceBinder extends Binder {        public ManagerService getService() {            return ManagerService.this;        }    }}
Activity中绑定service,实现功能:

public class MainActivity extends AppCompatActivity {    /**     * Activity管理器     */    private ActivityManager activityManager;    /**     * 浮动图标     */    private TextView moveDesc;    /**     * 消息处理器     */    private Handler handler;    /**     * 流量信息对象     */    private TrafficBean trafficBean;    /**     * 服务     */    private ManagerService service;    /**     * 标记信息     */    private static final String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);        moveDesc = (TextView) findViewById(R.id.tv);        try {            handler = new Handler() {                @Override                public void handleMessage(Message msg) {                    if (msg.what == 1) {                        moveDesc.setText(msg.obj + "kb/s");                        if (service != null) {                            service.setSpeed(msg.obj + "kb/s");                        }                    }                    super.handleMessage(msg);                }            };            trafficBean = new TrafficBean(this, handler, 12580);            trafficBean.startCalculateNetSpeed();        } catch (Exception e) {            e.printStackTrace();        }        Log.d(TAG, "总流量 = " + trafficBean.getTrafficInfo());        Intent intent = new Intent(MainActivity.this, ManagerService.class);        bindService(intent, conn, Context.BIND_AUTO_CREATE);    }    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder iBinder) {            service = ((ManagerService.ServiceBinder) iBinder).getService();        }        @Override        public void onServiceDisconnected(ComponentName name) {            service = null;        }    };    @Override    protected void onDestroy() {        super.onDestroy();        trafficBean.stopCalculateNetSpeed();        unbindService(conn);    }}

展示效果:




三、细节注意

1,使用与创建对应,onCreate()中绑定,onDestory()中解绑;

2,清单文件配置权限及服务和广播接收者。

                

                                                                                                                                        

源码




上班族如何安排时间才能每天都早起,读书,跑步,冥想?

                         1,早起毁一天 -- 任何依靠自制力的事情,最后都会失败;                          2,心态陷阱 --  贪多,为了读书而读书,为了浏览而浏览,促进心理焦虑                                     ----  通过某种行为,达到某种目的-----  目的                          3,目标--手段--执行意图  ---  同样的效果,更节省意志力                                      ----  爱好他,比强压自己学习更好,好太多                          4,为了让自己幸福 -- 帮助自己去完成更美好的事情,同时赞美自己                                      ---- 自我增强存在价值


更多相关文章

  1. android 下拉窗口菜单的实现(popupwindow)
  2. Android——弹出窗口中实现时间选择,文本输入,遇到Popupwindow不穿
  3. Android应用程序窗口View的measure过程
  4. android 自定义dialog,窗口动画,
  5. Android之浮动小窗口
  6. 简单几段代码实现窗口抖动
  7. Android 实现下载限速跟下载网速统计
  8. Android开发窗口实现半透明效果
  9. Layout___一行多列填充父窗口

随机推荐

  1. Android 技术博客汇总
  2. android webview字体大小的控制
  3. 四十七、实现调用Android手机的拍照功能
  4. android一些认识
  5. Android(安卓)APP 漏洞整理
  6. android viewholder
  7. uses-sdk tools:overrideLibrary uses-sd
  8. Android 自定义View引用xml布局
  9. android自动连接wifi——WifiManager
  10. 比较实用的开源项目总结