android 其实就是linux 上面包装了一个java的框架. linux 系统下 所有的硬件,设备(网卡,显卡等) 都是以文件的方式来表示. 文件里面包含的有很多设备的状态信息. 所有的流量相关的信息 都是记录在文件上的. 注意:模拟器 是不支持流量查询的. adb devices列出所以设置 然后通过 :adb -s 3835197E43F100EC shell 可以进入指定的设备. proc 系统的状态信息 adb -s 3835197E43F100EC shell 所以,那些流量都是读取的这些文件的内容. 在uid_stat 的目录下有一堆文件夹 名字是以应用程序的uid作为名字的. 内容就是这个应用程序 上传和下载产生的流量信息 tcp_rcv 采用tcp协议 接收到的数据的大小 tcp receive tcp_snd 采用tcp协议 发送的数据的byte大小 snd send tcp_rcv_pkt 采用tcp协议 接收到的包的数目 本来我们应该去遍历系统的这些文件,但是谷歌工程师用C已经 封装好了. 流量信息 : 上一次开机到现在这个程序产生的流量 . 世面安全软件: 定义一个数据库 packname uid appname lasttrafficdata 手机在关机的时候 是会有一个关机的广播事件ACTION_SHUTDOWN ,然后在这个广播里面会去把这次开机期间用的流量记录下来。 下一次开机的时候. 再去展示这个流量统计的界面。 后台每隔五分钟去更新一下数据库,很显然它也是非常费电的。 流量矫正. 其实大体的流量数据. 参考 禁止某一款应用上网. root权限 原理 :使用了一个linux系统下的防火墙 iptables iptables_armv5 allow uid 10035 disallow uid 10074 iptables_armv5 需要有linux的一些核心库才运行 模拟器不支持iptables miui cymod 网上有一个开源的项目 droidwall (防火墙,) google code. 屏幕适配: 尽量使用相对布局和线性布局. 不推荐使用绝对布局. 图片,控件的大小,最好都是用dip的单位作为控件的大小. dip==dp 文件的大小使用sp hvga 48*48px qvga 32*32px wvga 60*60px 代码里面有hard code的大小 根据不同的分辨率做不同的适配. /********************************************************/ 可扩展的ListView. 把这个数据库放在资产目录上,在资产目录下的资源不会生成相应的引用.
1、流量统计:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //Get the total number of bytes received through the mobile interface. /*long mobilerx = TrafficStats.getMobileRxBytes(); //Get the total number of bytes transmitted(发送) through the mobile interface. long mobiletx = TrafficStats.getMobileTxBytes(); long mobiletotal = mobilerx + mobiletx; StringBuilder sb = new StringBuilder(); sb.append("2g/3g总流量"+TextFormater.getDataSize(mobiletotal)); sb.append("\n"); //Get the total number of bytes received through all network interfaces.(总流量 ,包含WIFI 和手机上网) long totalrx = TrafficStats.getTotalRxBytes(); long totaltx = TrafficStats.getTotalTxBytes(); long total = totalrx + totaltx; //WIFI可以用总流量减去用手机上网的流量 long wifitotal = total - mobiletotal; sb.append("wifi总流量"+TextFormater.getDataSize(wifitotal)); sb.append("\n"); TextView tView = new TextView(this); tView.setText(sb.toString()); setContentView(tView);*/ //我们应该得到的是每一个应用程序所用的流量 // 在手机里面得到所有的产生图标的应用程序 PackageManager pm = getPackageManager(); Intent intent = new Intent(); intent.setAction("android.intent.action.MAIN"); intent.addCategory("android.intent.category.LAUNCHER"); List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resolveInfos) { String appname = resolveInfo.loadLabel(pm).toString(); System.out.println("appname:"+appname); Drawable icon = resolveInfo.loadIcon(pm); System.out.println("icon:"+icon.getCurrent()); String packageName = resolveInfo.activityInfo.packageName; try { PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); int uid = packageInfo.applicationInfo.uid; System.out.println("下载流量"+ TextFormater.getDataSize( TrafficStats.getUidRxBytes(uid))); System.out.println("上传流量"+ TextFormater.getDataSize( TrafficStats.getUidTxBytes(uid))); } catch (NameNotFoundException e) { e.printStackTrace(); } System.out.println("------"); } }
2、抽屉效果:
<!--抽屉最重要的两个属性: android:handle="@+id/handle" android:content="@+id/content" 一个是把手,另外一个是拖动把手显示的内容. --> <SlidingDrawer android:layout_width="match_parent" android:layout_height="match_parent" android:handle="@+id/handle" android:content="@+id/content" android:orientation="horizontal" > <ImageView android:id="@id/handle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/notification" /> <ListView android:id="@id/content" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> </SlidingDrawer>
3、手机杀毒 log管理 混淆打包 有米广告 自动化测试 robotium mantis bug管理
杀毒软件的原理: 1.基于签名的特征码的扫描(hash码-md5特征码的扫描) 有一个病毒数据库, 保存的有 病毒对应的hash. 特征:只能查杀已知的病毒,不能查杀未知的病毒. 瑞星 8个小时 卡巴斯基 6个小时 诺顿 xx小时 所以它们之间的区别就在杀毒引擎上 杀毒引擎: 获取hash 查询数据库的算法. 病毒库上: 千万条数据 联网->实时更新病毒数据库 服务器集群: 蜜罐.->病毒分析工程师. 2.主动防御: 监控敏感api , 更改浏览器主页. 注册开机启动的行为 应用程序的内存注入 3.启发式扫描: 根据程序敏感的api 提示风险代码 4.云查杀(即服务器端有一个特别大的数据库,在本地查询完以后 把那些敏感的hash值上传到服务器去分析) 人工智能:一套复杂的if语句 if t t t 模糊逻辑 1万个左右 anroid 几千种病毒 1.窃取通讯费用 2.切用用户隐私 后台手机用户手机的log 进行一些非法. 3.纯恶作剧 4.偷取流量的软件 大点评网 云中书城 企业会去推广软件 2块钱推广费用. 30万 10块钱 300万 android手机杀毒软件 特征码的扫描 : 360隐私卫士: 基于规则进行主动防御. 特征api的拦截, root权限. 招商银行开发android客户端. 混淆之后,会保留四大组件,因为它都是在要配置文件里面配置的。 所以360会把这四大组件里面很多方法抽取到业务方法里面去进行 反编译。 在project.properties里面加上 proguard.config=proguard.cfg 混淆的原理-> 类名和方法名的映射转化 ContentProvider.getuserinfo.getchineselikemeetmale(); a.b.c(); native -> 类名_方法名 -optimizationpasses 5 设置混淆的压缩比率 0 ~ 7 -dontusemixedcaseclassnames -> Aa aA -dontskipnonpubliclibraryclasses ->如果应用程序引入的有jar包,并且想混淆jar包里面的class -dontpreverify -verbose ->混淆后生产映射文件 map 类名->转化后类名的映射 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #混淆采用的算法. -keep public class * extends android.app.Activity 所有activity的子类不要去混淆 -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService -keepclasseswithmembernames class * { native <methods>; 所有native的方法不能去混淆. } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); //某些构造方法 } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } 手电筒: 20行 1.把手机亮度调到最亮. 2.把界面的颜色调成白色. iphone 20万-> 1000pv 2毛~3毛 20美分~30分 200000*5/1000*1 = 1000元/天 findmyphone 吃裙子. 30万下载量. admod google 国外信用卡. paypal 35美金. 万普广告 有米 十几家广告平台. 支持银联卡 聚合广告平台: 软件测试 根据测试的粒度不同: testcase: 方法测试 功能测试(若干个方法联合在一起) 集成测试: 与服务器联调一下 自动化测试:robotium,它其实是调用安卓底层的测试框架。instrumentationTest Bug管理平台:非常重要 1、administrator超级管理员,可以创建用户 2、project manager 查看项目状态,查看一共有多少个Bug,并且可以修改Bug的状态 3、developer开发软件,修Bug 4、tester/ 有的时间会出来有的时间不出来的叫random bug /*************************************************************/ 操,原来那些扫描的软件动画,都是帧动画 。 这段代码包含了太多东西,好好看。以后做进度绝对没有问题。
public class AntivirusActivity extends Activity { protected static final int STOP = 1; private ImageView iv; private ProgressBar pb; private ScrollView sv ; private LinearLayout ll; private AnimationDrawable animationDrawable; private SQLiteDatabase db; //这是一个极为精妙的设计,因为这个点击事件会反复触发,当第一次触发后,把这个值设置为true,再触发事件的时间如果发现这个值为true,这个触摸事件直接就返回了。太好了。 private boolean flagscanning = false; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if (msg.what == STOP) { ll.removeAllViews(); animationDrawable.stop(); } //开始不断更新界面 ,这个滚动的效果,其实就是不断的往线性布局里面加控件。 String string = (String) msg.obj; TextView tv = new TextView(getApplicationContext()); tv.setText(string); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(tv); sv.scrollBy(0, 20); }; }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) findViewById(R.id.iv); iv.setBackgroundResource(R.drawable.anti_anim); pb = (ProgressBar) findViewById(R.id.progressBar1); sv = (ScrollView) findViewById(R.id.sv); ll = (LinearLayout) findViewById(R.id.ll); animationDrawable = (AnimationDrawable) iv.getBackground(); System.out.println(Environment.getExternalStorageState()+"/antivirus.db"); //初始化DB db = SQLiteDatabase.openDatabase(Environment.getExternalStorageDirectory()+"/antivirus.db", null, SQLiteDatabase.OPEN_READONLY); } /** * 对整个activity进行监听的回调函数,因为activity实现了 Window.Callback, KeyEvent.Callback,这些个类 * KeyEvent.Callback是关于键盘的所有回调函数,例如onkeydown,onkeylbackup等, * Window.Callback指对整个界面的各种事件都 有 */ @Override public boolean onTouchEvent(MotionEvent event) { //如果发现它为true,也就是它不是第一次点击发生的,那么让这个事件返回 if (flagscanning) { return false; } if (event.getAction() == MotionEvent.ACTION_UP) { flagscanning = true; animationDrawable.start(); new Thread(){ @Override public void run() { List<PackageInfo> infos = getPackageManager().getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES|PackageManager.GET_SIGNATURES); // 获取每一个应用程序的签名 获取到这个签名后 需要在数据库里面查询 pb.setMax(infos.size()); int total = 0;//用于计算总体进度 int virustotal = 0;//病毒总数 for(PackageInfo info : infos){ total ++; try { sleep(200);//效果更明显 } catch (InterruptedException e) { e.printStackTrace(); } Message msg = Message.obtain(); msg.obj = "正在扫描"+info.packageName; handler.sendMessage(msg); //得到每一个应用的签名与数据库中的相比对 Signature[] signs = info.signatures; String str = signs[0].toCharsString(); String md5 = MD5Encoder.encode(str); Cursor cursor = db.rawQuery("select desc from datable where md5=?",new String[]{md5}); //如果发现了病毒 if (cursor.moveToFirst()) { String desc = cursor.getString(0); msg = Message.obtain(); msg.obj = info.packageName + " : "+desc; handler.sendMessage(msg); virustotal++; } cursor.close(); pb.setProgress(total); } //结束后 Message message = Message.obtain(); message.what = STOP; message.obj = "扫描完毕,共发现"+virustotal+"个病毒"; handler.sendMessage(message); pb.setProgress(0); }; }.start(); } return super.onTouchEvent(event); } }
//开发中的log管理: //实际开发中,Log都是通过配置文件进行管理的。 import android.util.Log; import cn.itcast.mobilesafe.util.Logger; /** * 在开发阶段把LOGLEVEL设置为6,在应用阶段把LOGLEVEL设置为0. * @author chen * */ public class Logger { private static int LOGLEVEL = 0; private static int VERBOSE = 1; private static int DEBUG = 2; private static int INFO = 3; private static int WARN = 4; private static int ERROR = 5; public static void v(String tag,String msg){ if (LOGLEVEL > VERBOSE) { Log.v(tag, msg); } } public static void d(String tag,String msg){ if (LOGLEVEL > DEBUG) { Log.d(tag, msg); } } public static void i(String tag,String msg){ if (LOGLEVEL > INFO) { Log.i(tag, msg); } } public static void w(String tag,String msg){ if (LOGLEVEL > WARN) { Log.w(tag, msg); } } public static void e(String tag,String msg){ if (LOGLEVEL > ERROR) { Log.e(tag, msg); } } }