首屆 Google 暑期大學生部落格分享大賽——2010 Andriod 篇
BroadcastReceiver模組
用於監聽開機資訊 並初始化和啟動服務
package zy.dnh;<br />import java.io.File;<br />import java.io.FileOutputStream;<br />import java.io.IOException;<br />import android.content.BroadcastReceiver;<br />import android.content.Context;<br />import android.content.Intent;<br />import android.widget.Toast;<br />public class getpowerinfo extends BroadcastReceiver{<br />FileOutputStream out;<br />final public String ONPATH = "/data/data/zy.dnh/on.txt";<br />@Override<br />public void onReceive(Context context, Intent intent) {<br />// TODO Auto-generated method stub</p><p> if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){<br /> Intent bootActivityIntent=new Intent(context,mService1.class);//啟動服務<br /> bootActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);<br /> writefile("0,0,0,0,0,0,0,0,0,0,0,0",ONPATH);<br /> context.startService(bootActivityIntent);<br /> Toast.makeText(context, "Netcounter service has been lauched", Toast.LENGTH_LONG).show();<br /> Api.applySavedIptablesRules(context, false);//應用防火牆規則<br /> Toast.makeText(context, "Wall rules have been lauched", Toast.LENGTH_LONG).show();<br /> }<br />}<br />public void writefile(String str,String path )<br /> {<br /> File file;<br /> try {<br /> //建立檔案<br /> file = new File(path);<br /> file.createNewFile();</p><p> //開啟檔案file的OutputStream<br /> out = new FileOutputStream(file);<br /> String infoToWrite = str;<br /> //將字串轉換成byte數組寫入檔案<br /> out.write(infoToWrite.getBytes());<br /> //關閉檔案file的OutputStream<br /> out.close();</p><p> } catch (IOException e) {<br /> //將出錯資訊列印到Logcat</p><p> }<br />
mService1模組
後台服務,用於維護流量日誌
public class mService1 extends Service<br />{</p><p> private Handler objHandler = new Handler();<br /> private int intCounter=0;<br /> private int mHour;<br />private int mMinute;<br />private int mYear;<br />private int mMonth;<br />private int mDay;<br />private String mdate;</p><p>final public String DEV_FILE = "/proc/self/net/dev";//系統流量檔案<br />String[] ethdata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};<br />String[] gprsdata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};<br />String[] wifidata={"0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"};<br />String data="0,0,0,0,0,0,0,0,0,0,0,0";//對應on.txt裡面的格式<br />final String ETHLINE=" eth0";//乙太網路資訊所在行<br />final String GPRSLINE="rmnet0";<br />final String WIFILINE="tiwlan0";</p><p>final String TEXT_ENCODING = "UTF-8";</p><p>final public String ONPATH = "/data/data/zy.dnh/on.txt";<br />final public String LOGPATH = "/data/data/zy.dnh/log.txt";</p><p> private Runnable mTasks = new Runnable()<br /> {</p><p> public void run()//運行該服務執行此函數<br /> {<br /> refresh();</p><p> intCounter++;<br /> // DisplayToast("Counter:"+Integer.toString(intCounter));<br /> objHandler.postDelayed(mTasks, 30000);//每3000毫秒執行一次<br /> }<br /> };</p><p> @Override<br /> public void onStart(Intent intent, int startId)<br /> {<br /> // TODO Auto-generated method stub<br />//writefile("0,0,0,0,0,0,0,0,0,0,0,0",ONPATH);//每次啟動服務 初始化onpath</p><p> objHandler.postDelayed(mTasks, 0);<br /> super.onStart(intent, startId);<br /> }<br /> @Override<br /> public void onCreate()<br /> {<br /> // TODO Auto-generated method stub</p><p> super.onCreate();<br /> }</p><p> @Override<br /> public IBinder onBind(Intent intent)<br /> {<br /> // TODO Auto-generated method stub</p><p> return null;<br /> }<br /> @Override<br /> public void onDestroy()<br /> {<br /> // TODO Auto-generated method stub</p><p> /* */<br /> objHandler.removeCallbacks(mTasks);<br /> super.onDestroy();<br /> }<br /> public void DisplayToast(String str)<br /> {<br /> Toast.makeText(this,str,Toast.LENGTH_SHORT).show();<br /> }<br /> public void readdev()<br /> {<br /> FileReader fstream = null;<br /> try {<br /> fstream = new FileReader(DEV_FILE);</p><p> }<br /> catch (FileNotFoundException e) {<br /> DisplayToast("Could not read " + DEV_FILE);</p><p> }<br /> BufferedReader in = new BufferedReader(fstream, 500);<br /> String line;<br /> String[] segs;<br /> String[] netdata;</p><p> int count=0;<br /> int k;<br /> int j;<br /> try {<br /> while ((line = in.readLine()) != null) {<br /> segs = line.trim().split(":");<br /> if(line.startsWith(ETHLINE))<br /> {</p><p> netdata=segs[1].trim().split(" ");<br /> for(k=0,j=0;k<netdata.length;k++)<br /> {<br /> if(netdata[k].length()>0)<br /> { </p><p> ethdata[j]=netdata[k];<br /> j++;<br /> }<br /> }<br /> }<br /> else if(line.startsWith(GPRSLINE))<br /> {</p><p> netdata=segs[1].trim().split(" ");<br /> for(k=0,j=0;k<netdata.length;k++)<br /> {<br /> if(netdata[k].length()>0)<br /> { </p><p> gprsdata[j]=netdata[k];<br /> j++;<br /> }<br /> }<br /> }<br /> else if(line.startsWith(WIFILINE))<br /> {</p><p> netdata=segs[1].trim().split(" ");<br /> for(k=0,j=0;k<netdata.length;k++)<br /> {<br /> if(netdata[k].length()>0)<br /> { </p><p> wifidata[j]=netdata[k];<br /> j++;<br /> }<br /> }<br /> }</p><p> count++;<br /> }<br /> fstream.close();</p><p> }<br /> catch (IOException e) {<br /> DisplayToast(e.toString());<br /> }<br /> }<br /> public String getinfo(String path)<br /> {<br /> File file;<br /> String str="";<br /> FileInputStream in;<br /> try{<br /> //開啟檔案file的InputStream<br /> file = new File(path);<br /> in = new FileInputStream(file);<br /> //將檔案內容全部讀入到byte數組<br /> int length = (int)file.length();<br /> byte[] temp = new byte[length];<br /> in.read(temp, 0, length);<br /> //將byte數組用UTF-8編碼並存入display字串中<br /> str = EncodingUtils.getString(temp,TEXT_ENCODING);<br /> //關閉檔案file的InputStream<br /> in.close();<br /> }<br /> catch (IOException e) {</p><p> DisplayToast(e.toString());</p><p> }<br /> return str;<br /> }<br /> public void writefile(String str,String path )<br /> {<br /> File file;<br /> FileOutputStream out;<br /> try {<br /> //建立檔案<br /> file = new File(path);<br /> file.createNewFile();<br /> //開啟檔案file的OutputStream<br /> out = new FileOutputStream(file);<br /> String infoToWrite = str;<br /> //將字串轉換成byte數組寫入檔案<br /> out.write(infoToWrite.getBytes());<br /> //關閉檔案file的OutputStream<br /> out.close();<br /> } catch (IOException e) {<br /> //將出錯資訊列印到Logcat<br /> DisplayToast(e.toString());</p><p> }<br /> }<br /> public void refresh()<br /> {</p><p> readdev();//讀取本次開機之後直到當前系統的總流量</p><p> data=ethdata[0]+","+ethdata[1]+","+ethdata[8]+","+ethdata[9]+","<br /> +gprsdata[0]+","+gprsdata[1]+","+gprsdata[8]+","+gprsdata[9]+","<br /> +wifidata[0]+","+wifidata[1]+","+wifidata[8]+","+wifidata[9];<br /> String onstr=getinfo(ONPATH);//讀取on.txt記錄到onstr裡<br /> String ondata[]=onstr.split(",");//將onstr各項分離 放到ondata裡<br /> //計算增量<br /> int [] delta=new int [12];</p><p> delta[0]=Integer.parseInt(ethdata[0])-Integer.parseInt(ondata[0]);<br /> delta[1]=Integer.parseInt(ethdata[1])-Integer.parseInt(ondata[1]);<br /> delta[2]=Integer.parseInt(ethdata[8])-Integer.parseInt(ondata[2]);<br /> delta[3]=Integer.parseInt(ethdata[9])-Integer.parseInt(ondata[3]);<br /> delta[4]=Integer.parseInt(gprsdata[0])-Integer.parseInt(ondata[4]);<br /> delta[5]=Integer.parseInt(gprsdata[1])-Integer.parseInt(ondata[5]);<br /> delta[6]=Integer.parseInt(gprsdata[8])-Integer.parseInt(ondata[6]);<br /> delta[7]=Integer.parseInt(gprsdata[9])-Integer.parseInt(ondata[7]);<br /> delta[8]=Integer.parseInt(wifidata[0])-Integer.parseInt(ondata[8]);<br /> delta[9]=Integer.parseInt(wifidata[1])-Integer.parseInt(ondata[9]);<br /> delta[10]=Integer.parseInt(wifidata[8])-Integer.parseInt(ondata[10]);<br /> delta[11]=Integer.parseInt(wifidata[9])-Integer.parseInt(ondata[11]);</p><p> //讀取log.txt<br />//擷取目前時間<br /> final Calendar c = Calendar.getInstance();<br /> mYear = c.get(Calendar.YEAR); //擷取當前年份<br /> mMonth = c.get(Calendar.MONTH)+1;//擷取當前月份<br /> mDay = c.get(Calendar.DAY_OF_MONTH);//擷取當前月份的日期號碼<br /> mHour = c.get(Calendar.HOUR_OF_DAY);//擷取當前的小時數<br /> mMinute = c.get(Calendar.MINUTE);//擷取當前的分鐘數<br /> mdate=mYear+"-"+mMonth+"-"+mDay;</p><p> String text=getinfo(LOGPATH);//將log.txt的內容讀到text字串中<br /> String [] line=text.split("/n"); </p><p> String today=line[line.length-1];//獲得今日已記錄流量<br /> String [] beToday=today.split(",");<br /> //檢查檔案最後一行是否為今天的流量記錄資訊<br /> if(!beToday[0].equals(mdate))//<br />//判斷今日流量是否已經記錄,如果今日流量沒有記錄<br /> {</p><p> text=text+mdate+",0,0,0,0,0,0,0,0,0,0,0,0/n";<br /> writefile(text,LOGPATH);</p><p> line=text.split("/n");<br /> today=line[line.length-1];//獲得今日已記錄流量</p><p> beToday=today.split(",");<br /> }<br /> int i;<br /> //處理今日流量<br /> int [] newTodaydata=new int [12];//表示今日流量<br /> String newtoday=mdate;<br /> for(i=0;i<=11;i++)//更新今日流量<br /> {<br /> newTodaydata[i]=Integer.parseInt(beToday[i+1])+delta[i];<br /> newtoday=newtoday+","+newTodaydata[i];<br /> }<br /> newtoday=newtoday+"/n";</p><p> String [] beTotal=line[0].split(",");<br /> int [] newTotaldata=new int [12];//表示總流量數值<br /> //更新第一行<br /> String newtotal="total";<br /> for(i=0;i<=11;i++)//更新今日流量和總流量<br /> {<br /> newTotaldata[i]=Integer.parseInt(beTotal[i+1])+delta[i];//總流量數值+delta[i]更新<br /> newtotal=newtotal+","+newTotaldata[i];<br /> }<br /> newtotal= newtotal+"/n";<br /> //處理中間不變的部分<br /> String before="";//before為之前的從第1行到昨天的流量記錄</p><p> for(i=1;i<=line.length-2;i++)<br /> before=before+line[i]+"/n";//代表中間不變的部分</p><p> String newlog=newtotal+before+newtoday;<br /> writefile(data,ONPATH);//更新流量記錄<br /> writefile(newlog,LOGPATH);//更新log*/</p><p> }</p><p>}
應用iptable規則模組,通過運行iptable指令碼來實現iptable規則的應用
private static boolean applyIptablesRulesImpl(Context ctx, List<Integer> uids, boolean showErrors) {<br /> if (ctx == null) {<br /> return false;<br /> }<br /> final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);<br /> final boolean whitelist = prefs.getString(PREF_MODE, MODE_WHITELIST).equals(MODE_WHITELIST);<br /> boolean wifi = false; // Wi-fi selected ?<br /> final String itfs = prefs.getString(PREF_ITFS, ITF_3G);<br /> String itfFilter;<br /> if (itfs.indexOf("|") != -1) {<br /> itfFilter = ""; // Block all interfaces<br /> wifi = true;<br /> } else if (itfs.indexOf(ITF_3G) != -1) {<br /> itfFilter = "-o rmnet+";;<br /> // Block all rmnet interfaces<br /> } else {<br /> itfFilter = "-o tiwlan+";;<br /> // Block all tiwlan interfaces<br /> wifi = true;<br /> }<br /> final StringBuilder script = new StringBuilder();<br /> try {<br /> int code;<br /> script.append("iptables -F || exit/n");<br /> final String targetRule = (whitelist ? "ACCEPT" : "REJECT");<br /> if (whitelist && wifi) {<br /> // When "white listing" Wi-fi, we need ensure that the dhcp and wifi users are allowed<br /> int uid = android.os.Process.getUidForName("dhcp");<br /> if (uid != -1) script.append("iptables -A OUTPUT "<br /> + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit/n");<br /> uid = android.os.Process.getUidForName("wifi");<br /> if (uid != -1) script.append("iptables -A OUTPUT " + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit/n"); }<br /> for (Integer uid : uids) {<br /> script.append("iptables -A OUTPUT " + itfFilter<br /> + " -m owner --uid-owner " + uid + " -j " + targetRule + " || exit/n");<br /> }<br /> if (whitelist) {<br /> script.append("iptables -A OUTPUT " + itfFilter + " -j REJECT || exit/n");<br /> }<br /> StringBuilder res = new StringBuilder();<br /> code = runScriptAsRoot(script.toString(), res);<br /> if (showErrors && code != 0) {<br /> String msg = res.toString();<br /> Log.e("DroidWall", msg);<br /> // Search for common error messages<br /> if (msg.indexOf("Couldn't find match `owner'") != -1 || msg.indexOf("no chain/target match") != -1) {<br /> 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.");<br /> } else {<br /> // Remove unnecessary help message from output<br /> if (msg.indexOf("/nTry `iptables -h' or 'iptables --help' for more information.") != -1) {<br /> msg = msg.replace("/nTry `iptables -h' or 'iptables --help' for more information.", "");<br /> }<br /> // Try `iptables -h' or 'iptables --help' for more information.<br /> alert(ctx, "Error applying iptables rules. Exit code: " + code + "/n/n" + msg.trim());<br /> }<br /> } else {<br /> return true;<br /> }<br /> } catch (Exception e) {<br /> if (showErrors) alert(ctx, "error refreshing iptables: " + e);<br /> }<br /> return false;<br /> }<br />