碎雨(四)

手机抓包

        前提是手机需要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{}中的。

9patch图片

        1,如果左右或者上下的拉伸区域不只一块,那么拉伸的距离会根据各区域的像素点数的比进行。如


上边框有两个拉伸区域,其中一个为1像素,另一个为2像素,那么在拉伸时,右边拉伸的距离是左边拉伸距离的两倍。

        2,内容区域的边距会以padding(图片中距离边框多少像素,padding就是多少像素)形式展示,也可以通过设置padding的值将9patch图中的边距给屏幕掉。如原图为

碎雨(四)_第1张图片

如果不设置padding,其效果为:

碎雨(四)_第2张图片

将padding设置为0后,效果为:

Selector

        常用的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文件

        原生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("失败");
                }

keytool

        keytool是java提供的一个工具类,用于处理跟签名文件相关的事务。
        keytool -list -keystore keystore的路径:获取keystore的sha1值(证书指纹)。
        keytool -printcert -file CERT.RSA的路径:获取CERT.RSA中存储的关于keystore的值。反编译某个apk,在META-INF文件夹下有CERT.RSA文件。

你可能感兴趣的:(碎雨(四))