前提是手机需要root。
下载tcpdump,并通过adb push方法将该文件push进data/local中。如:adb[空格]push[空格]d:\tcpdump[空格] /data/local。d:\tcpdump为tcpdump在电脑上的存储位置。
在命令行中执行adb shell,再执行su命令,最后通过cd一步步进到tcpdump所在的文件夹。如:
最后执行tcpdump -p -s 0 -vv -w /sdcard/xx.pcap即可。其中/sdcard/xx.pcap是抓包生成的文件在手机中存储位置。注意,该命令必须在su下执行。
按ctrl+c可结束抓包。将抓包生成的文件导出到电脑,通过Wireshark查看。
在使用友盟统计时,需要为不同的应用市场打一个版本,每一个版本的差别也仅仅是修改清单文件中的一个地方。此时,可使用多渠道打包,会自动打包成无数个版本,而且每一个版本都已经修改好。
所谓的多渠道打包就是在打包的时候动态地修改清单文件中的<meta-data>中的value值。清单文件配置如下(配置在application结点下):
<meta-data android:value="${UMENG_CHANNEL_NAME}" android:name="UMENG_CHANNEL"/>在对应的module的build.gradle文件中添加如下:
productFlavors { wandoujia{} productFlavors.all{ flavor->flavor.manifestPlaceholders = [UMENG_CHANNEL_NAME: name] } }其中wandoujia就是用来代替${UMENG_CHANNEL_NAME}的值。如果想打多个渠道的包,只需要修改或添加即可。
注意:上述代码是放在android{}中的。
1,如果左右或者上下的拉伸区域不只一块,那么拉伸的距离会根据各区域的像素点数的比进行。如
上边框有两个拉伸区域,其中一个为1像素,另一个为2像素,那么在拉伸时,右边拉伸的距离是左边拉伸距离的两倍。
2,内容区域的边距会以padding(图片中距离边框多少像素,padding就是多少像素)形式展示,也可以通过设置padding的值将9patch图中的边距给屏幕掉。如原图为
如果不设置padding,其效果为:
将padding设置为0后,效果为:
常用的selector有两种,drawable与color。drawable放在res/drawable文件夹下,color放在res/color文件夹下,并不是放在drawable下。如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:color="@color/testcolor1"/> <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /> <item android:state_enabled="false" android:color="@color/testcolor3" /> <item android:color="@color/testcolor5"/> </selector>当然,与普通的color仍旧放在values/colors.xml中。
原生xml文件放置在res/xml文件夹下。建立好xml文件后,可以通过Resources.getXml(int id)获取XmlResourceParser对象,并使用该对象对xml进行解析。如下:
private void parserXml(XmlResourceParser parser) { try { while (parser.getEventType() != XmlPullParser.END_DOCUMENT){ if(parser.getEventType() == XmlPullParser.START_TAG){ String name = parser.getName();//获取当前标签的标签名 switch (name){ case "brand": String id = parser.getAttributeValue(null, "id");//获取标签中指定的属性值,第一个为名称空间,没有就传null Log.e("Tag",id); break; case "name": String text = parser.nextText();//获取当前标签的值 Log.e("Tag",text); break; } } parser.next(); } }catch (Exception e){ e.printStackTrace(); } }
通过分析系统安装时的源码,并通过反射获取相应的结果。
private void getAppSign() { try { Class<?> pkpClz = Class.forName("android.content.pm.PackageParser"); Constructor<?> constructor = pkpClz.getConstructor(String.class); //PackageParser的实例 Object pkp = constructor.newInstance(path); Method method = pkpClz.getDeclaredMethod("parsePackage", File.class, String.class, DisplayMetrics.class, int.class); DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); //PackageParser.Package的实例 Object packageParserPackage = method.invoke(pkp, new File(path), path, metrics, PackageManager.GET_SIGNATURES); Method collectCertificates = pkpClz.getDeclaredMethod("collectCertificates", packageParserPackage.getClass(), int.class); collectCertificates.invoke(pkp,PackageManager.GET_SIGNATURES); Field field = packageParserPackage.getClass().getDeclaredField("mSignatures"); Signature[] signatures = (Signature[])field.get(packageParserPackage); Signature signature = signatures[0]; //获得签名 Log.e("TAG",signature.toCharsString()); } catch (Exception e) { e.printStackTrace(); } }
private void getAppSign() { PackageManager manager = getPackageManager(); List<PackageInfo> infos = manager.getInstalledPackages(PackageManager.GET_SIGNATURES); for (PackageInfo info : infos){ if (info.packageName.equals(getPackageName())){ LogUtils.e(info.signatures[0].toCharsString()); } } }对于一个已安装的应用来说,它的签名是很长的,所以会将签名以一个Signature数组形式返回。这里只是获取了数组中的第一个元素,但当需要比对签名是否相同时,可以使用该方法的返回值进行比对。
在不显示系统安装界面的情况下,直接将应用安装到手机中。前提是:手机必须有root权限。
其主要原理就是利用Runtime.getRuntime().exec()执行命令行命令。
如下代码未测试过,从视频中摘录:
try { String path = new File(Environment.getExternalStorageDirectory(),"Download").getAbsolutePath(); File apkFile = new File(path,"Alipay.apk");//获取apk路径 Process process = Runtime.getRuntime().exec("su");//执行su命令,此时需要root权限 OutputStream outputStream = process.getOutputStream(); DataOutputStream stream = new DataOutputStream(outputStream); stream.writeBytes("chmod 777 "+apkFile.getPath()+"\n");//改变apk的读写模式 stream.writeBytes("pm install -r "+apkFile.getPath()); stream.flush(); outputStream.close(); stream.close(); int value = process.waitFor(); if(value == 0){//安装成功 LogUtils.e("成功"); }else { LogUtils.e("失败"+value); } } catch (Exception e) { e.printStackTrace(); LogUtils.e("失败"); }