BroadcastReceiver模块
用于监听开机信息 并初始化和启动服务
android手机流量信息系统是LINUX内核 记录在/proc/self/net/dev文件里面
我们可以看看dev文件的格式
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
D:\Program Files\Java\sdk\android-sdk-windows\tools>adb shell
# cd proc
cd proc
# cd net
cd net
# cat dev
cat dev
mService1模块
后台服务,用于维护流量日志
应用 iptable规则模块,通过运行iptable脚本来实现iptable规则的应用
用于监听开机信息 并初始化和启动服务
- package zy.dnh;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.widget.Toast;
- public class getpowerinfo extends BroadcastReceiver{
- FileOutputStream out;
- final public String ONPATH = "/data/data/zy.dnh/on.txt";
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
- Intent bootActivityIntent=new Intent(context,mService1.class);//启动服务
- bootActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- writefile("0,0,0,0,0,0,0,0,0,0,0,0",ONPATH);
- context.startService(bootActivityIntent);
- Toast.makeText(context, "Netcounter service has been lauched", Toast.LENGTH_LONG).show();
- Api.applySavedIptablesRules(context, false);//应用防火墙规则
- Toast.makeText(context, "Wall rules have been lauched", Toast.LENGTH_LONG).show();
- }
- }
- public void writefile(String str,String path )
- {
- File file;
- try {
- //创建文件
- file = new File(path);
- file.createNewFile();
- //打开文件file的OutputStream
- out = new FileOutputStream(file);
- String infoToWrite = str;
- //将字符串转换成byte数组写入文件
- out.write(infoToWrite.getBytes());
- //关闭文件file的OutputStream
- out.close();
- } catch (IOException e) {
- //将出错信息打印到Logcat
- }
android手机流量信息系统是LINUX内核 记录在/proc/self/net/dev文件里面
我们可以看看dev文件的格式
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
D:\Program Files\Java\sdk\android-sdk-windows\tools>adb shell
# cd proc
cd proc
# cd net
cd net
# cat dev
cat dev
mService1模块
后台服务,用于维护流量日志
- public class mService1 extends Service
- {
- private Handler objHandler = new Handler();
- private int intCounter=0;
- private int mHour;
- private int mMinute;
- private int mYear;
- private int mMonth;
- private int mDay;
- private String mdate;
- final public String DEV_FILE = "/proc/net/dev";//系统流量文件
- String[] ethdata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};
- String[] gprsdata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};
- String[] wifidata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};
- String data="0,0,0,0,0,0,0,0,0,0,0,0";//对应on.txt里面的格式
- final String ETHLINE=" eth0";//以太网信息所在行
- final String GPRSLINE="rmnet0";
- final String WIFILINE="tiwlan0";
- final String TEXT_ENCODING = "UTF-8";
- final public String ONPATH = "/data/data/zy.dnh/on.txt";
- final public String LOGPATH = "/data/data/zy.dnh/log.txt";
- private Runnable mTasks = new Runnable()
- {
- public void run()//运行该服务执行此函数
- {
- refresh();
- intCounter++;
- // DisplayToast("Counter:"+Integer.toString(intCounter));
- objHandler.postDelayed(mTasks, 30000);//每3000毫秒执行一次
- }
- };
- @Override
- public void onStart(Intent intent, int startId)
- {
- // TODO Auto-generated method stub
- //writefile("0,0,0,0,0,0,0,0,0,0,0,0",ONPATH);//每次启动服务 初始化onpath
- objHandler.postDelayed(mTasks, 0);
- super.onStart(intent, startId);
- }
- @Override
- public void onCreate()
- {
- // TODO Auto-generated method stub
- super.onCreate();
- }
- @Override
- public IBinder onBind(Intent intent)
- {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public void onDestroy()
- {
- // TODO Auto-generated method stub
- /* */
- objHandler.removeCallbacks(mTasks);
- super.onDestroy();
- }
- public void DisplayToast(String str)
- {
- Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
- }
- public void readdev()
- {
- FileReader fstream = null;
- try {
- fstream = new FileReader(DEV_FILE);
- }
- catch (FileNotFoundException e) {
- DisplayToast("Could not read " + DEV_FILE);
- }
- BufferedReader in = new BufferedReader(fstream, 500);
- String line;
- String[] segs;
- String[] netdata;
- int count=0;
- int k;
- int j;
- try {
- while ((line = in.readLine()) != null) {
- segs = line.trim().split(":");
- if(line.startsWith(ETHLINE))
- {
- netdata=segs[1].trim().split(" ");
- for(k=0,j=0;k<netdata.length;k++)
- {
- if(netdata[k].length()>0)
- {
- ethdata[j]=netdata[k];
- j++;
- }
- }
- }
- else if(line.startsWith(GPRSLINE))
- {
- netdata=segs[1].trim().split(" ");
- for(k=0,j=0;k<netdata.length;k++)
- {
- if(netdata[k].length()>0)
- {
- gprsdata[j]=netdata[k];
- j++;
- }
- }
- }
- else if(line.startsWith(WIFILINE))
- {
- netdata=segs[1].trim().split(" ");
- for(k=0,j=0;k<netdata.length;k++)
- {
- if(netdata[k].length()>0)
- {
- wifidata[j]=netdata[k];
- j++;
- }
- }
- }
- count++;
- }
- fstream.close();
- }
- catch (IOException e) {
- DisplayToast(e.toString());
- }
- }
- public String getinfo(String path)
- {
- File file;
- String str="";
- FileInputStream in;
- try{
- //打开文件file的InputStream
- file = new File(path);
- in = new FileInputStream(file);
- //将文件内容全部读入到byte数组
- int length = (int)file.length();
- byte[] temp = new byte[length];
- in.read(temp, 0, length);
- //将byte数组用UTF-8编码并存入display字符串中
- str = EncodingUtils.getString(temp,TEXT_ENCODING);
- //关闭文件file的InputStream
- in.close();
- }
- catch (IOException e) {
- DisplayToast(e.toString());
- }
- return str;
- }
- public void writefile(String str,String path )
- {
- File file;
- FileOutputStream out;
- try {
- //创建文件
- file = new File(path);
- file.createNewFile();
- //打开文件file的OutputStream
- out = new FileOutputStream(file);
- String infoToWrite = str;
- //将字符串转换成byte数组写入文件
- out.write(infoToWrite.getBytes());
- //关闭文件file的OutputStream
- out.close();
- } catch (IOException e) {
- //将出错信息打印到Logcat
- DisplayToast(e.toString());
- }
- }
- public void refresh()
- {
- readdev();//读取本次开机之后直到当前系统的总流量
- data=ethdata[0]+","+ethdata[1]+","+ethdata[8]+","+ethdata[9]+","
- +gprsdata[0]+","+gprsdata[1]+","+gprsdata[8]+","+gprsdata[9]+","
- +wifidata[0]+","+wifidata[1]+","+wifidata[8]+","+wifidata[9];
- String onstr=getinfo(ONPATH);//读取on.txt记录到onstr里
- String ondata[]=onstr.split(",");//将onstr各项分离 放到ondata里
- //计算增量
- int [] delta=new int [12];
- delta[0]=Integer.parseInt(ethdata[0])-Integer.parseInt(ondata[0]);
- delta[1]=Integer.parseInt(ethdata[1])-Integer.parseInt(ondata[1]);
- delta[2]=Integer.parseInt(ethdata[8])-Integer.parseInt(ondata[2]);
- delta[3]=Integer.parseInt(ethdata[9])-Integer.parseInt(ondata[3]);
- delta[4]=Integer.parseInt(gprsdata[0])-Integer.parseInt(ondata[4]);
- delta[5]=Integer.parseInt(gprsdata[1])-Integer.parseInt(ondata[5]);
- delta[6]=Integer.parseInt(gprsdata[8])-Integer.parseInt(ondata[6]);
- delta[7]=Integer.parseInt(gprsdata[9])-Integer.parseInt(ondata[7]);
- delta[8]=Integer.parseInt(wifidata[0])-Integer.parseInt(ondata[8]);
- delta[9]=Integer.parseInt(wifidata[1])-Integer.parseInt(ondata[9]);
- delta[10]=Integer.parseInt(wifidata[8])-Integer.parseInt(ondata[10]);
- delta[11]=Integer.parseInt(wifidata[9])-Integer.parseInt(ondata[11]);
- //读取log.txt
- //获取当前时间
- final Calendar c = Calendar.getInstance();
- mYear = c.get(Calendar.YEAR); //获取当前年份
- mMonth = c.get(Calendar.MONTH)+1;//获取当前月份
- mDay = c.get(Calendar.DAY_OF_MONTH);//获取当前月份的日期号码
- mHour = c.get(Calendar.HOUR_OF_DAY);//获取当前的小时数
- mMinute = c.get(Calendar.MINUTE);//获取当前的分钟数
- mdate=mYear+"-"+mMonth+"-"+mDay;
- String text=getinfo(LOGPATH);//将log.txt的内容读到text字符串中
- String [] line=text.split("\n");
- String today=line[line.length-1];//获得今日已记录流量
- String [] beToday=today.split(",");
- //检查文件最后一行是否为今天的流量记录信息
- if(!beToday[0].equals(mdate))//
- //判断今日流量是否已经记录,如果今日流量没有记录
- {
- text=text+mdate+",0,0,0,0,0,0,0,0,0,0,0,0\n";
- writefile(text,LOGPATH);
- line=text.split("\n");
- today=line[line.length-1];//获得今日已记录流量
- beToday=today.split(",");
- }
- int i;
- //处理今日流量
- int [] newTodaydata=new int [12];//表示今日流量
- String newtoday=mdate;
- for(i=0;i<=11;i++)//更新今日流量
- {
- newTodaydata[i]=Integer.parseInt(beToday[i+1])+delta[i];
- newtoday=newtoday+","+newTodaydata[i];
- }
- newtoday=newtoday+"\n";
- String [] beTotal=line[0].split(",");
- int [] newTotaldata=new int [12];//表示总流量数值
- //更新第一行
- String newtotal="total";
- for(i=0;i<=11;i++)//更新今日流量和总流量
- {
- newTotaldata[i]=Integer.parseInt(beTotal[i+1])+delta[i];//总流量数值+delta[i]更新
- newtotal=newtotal+","+newTotaldata[i];
- }
- newtotal= newtotal+"\n";
- //处理中间不变的部分
- String before="";//before为之前的从第1行到昨天的流量记录
- for(i=1;i<=line.length-2;i++)
- before=before+line[i]+"\n";//代表中间不变的部分
- String newlog=newtotal+before+newtoday;
- writefile(data,ONPATH);//更新流量记录
- writefile(newlog,LOGPATH);//更新log*/
- }
- }
应用 iptable规则模块,通过运行iptable脚本来实现iptable规则的应用
- private static boolean applyIptablesRulesImpl(Context ctx, List<Integer> uids, boolean showErrors) {
- if (ctx == null) {
- return false;
- }
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- final boolean whitelist = prefs.getString(PREF_MODE, MODE_WHITELIST).equals(MODE_WHITELIST);
- boolean wifi = false; // Wi-fi selected ?
- final String itfs = prefs.getString(PREF_ITFS, ITF_3G);
- String itfFilter;
- if (itfs.indexOf("|") != -1) {
- itfFilter = ""; // Block all interfaces
- wifi = true;
- } else if (itfs.indexOf(ITF_3G) != -1) {
- itfFilter = "-o rmnet+";;
- // Block all rmnet interfaces
- } else {
- itfFilter = "-o tiwlan+";;
- // Block all tiwlan interfaces
- wifi = true;
- }
- final StringBuilder script = new StringBuilder();
- try {
- int code;
- script.append("iptables -F || exit\n");
- final String targetRule = (whitelist ? "ACCEPT" : "REJECT");
- if (whitelist && wifi) {
- // When "white listing" Wi-fi, we need ensure that the dhcp and wifi users are allowed
- int uid = android.os.Process.getUidForName("dhcp");
- if (uid != -1) script.append("iptables -A OUTPUT "
- + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit\n");
- uid = android.os.Process.getUidForName("wifi");
- if (uid != -1) script.append("iptables -A OUTPUT " + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit\n"); }
- for (Integer uid : uids) {
- script.append("iptables -A OUTPUT " + itfFilter
- + " -m owner --uid-owner " + uid + " -j " + targetRule + " || exit\n");
- }
- if (whitelist) {
- script.append("iptables -A OUTPUT " + itfFilter + " -j REJECT || exit\n");
- }
- StringBuilder res = new StringBuilder();
- code = runScriptAsRoot(script.toString(), res);
- if (showErrors && code != 0) {
- String msg = res.toString();
- Log.e("DroidWall", msg);
- // Search for common error messages
- if (msg.indexOf("Couldn't find match `owner'") != -1 || msg.indexOf("no chain/target match") != -1) {
- alert(ctx, "Error applying iptables rules.\nExit code: " + code + "\n\n" +"It seems your Linux kernel was not compiled with the netfilter \"owner\" module enabled, which is required for Droid Wall to work properly.\n\n" +"You should check if there is an updated version of your Android ROM compiled with this kernel module.");
- } else {
- // Remove unnecessary help message from output
- if (msg.indexOf("\nTry `iptables -h' or 'iptables --help' for more information.") != -1) {
- msg = msg.replace("\nTry `iptables -h' or 'iptables --help' for more information.", "");
- }
- // Try `iptables -h' or 'iptables --help' for more information.
- alert(ctx, "Error applying iptables rules. Exit code: " + code + "\n\n" + msg.trim());
- }
- } else {
- return true;
- }
- } catch (Exception e) {
- if (showErrors) alert(ctx, "error refreshing iptables: " + e);
- }
- return false;
- }