场景

要找到@hide标注的方法。遗憾的是,@hide标注的类或者方法都是写在注释中的,Google为啥这么搞,说实话没弄明白为啥放在注释里面,不放在注解中。要找出所有的@hide的API在apk中的应用,这个有工具的,只是当时不太清楚,想着通过找到@hide的方法,然后在对比,在文章的末尾给出解决办法,用的是google的一个脚本。

假设

  1. 注释的形式是/** */这种格式的
  2. 获带有取@Deprated的方法
  3. 在/** */注释中的内容不包含"/"
    注意:?代表0个或者1个。

代码及注释

版本一

package test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    /** @Hide*/
    public static void   test(){
        System.out.println("Burning");
    }
    public static void main(String[] args) throws IOException {
        /*String content = "This order was placed for Qt300! ok?";
        String  regexPat = "(\\D*)(\\d*)(.*)";
        Pattern pattern = Pattern.compile(regexPat);
        Matcher match = pattern.matcher(content);
        System.out.println(match.groupCount());
        if (match.find()){
            System.out.println("Found value "+match.group(0));
            System.out.println("Found value "+match.group(1));
            System.out.println("Found value "+match.group(2));
            System.out.println("Found value "+match.group(3));
        }else{
            System.out.println("not matched");
        }*/
       FileInputStream  fis = new FileInputStream("D:\\liebao\\test\\Test.java"); 
        byte[] buff = new byte[fis.available()];
        //通过这种方式,可以读取到所有的文件内容
        fis.read(buff);
      String  regexPat = "(\\/\\*.*@Hide.*\\*\\/.*test)";
        Pattern pattern = Pattern.compile(regexPat);
        String str = new String(buff);
        //通过测试发现Java正则表达式只是匹配一行,所以这里对"\r"和"\n"进行替换
        String str1 = str.replace("\n", " ").replace("\r", " ");
        System.out.println(str1.length());
       Matcher  match = pattern.matcher(str1);
       if (match.find()){
          
            System.out.println("Found value "+match.group(1));
            
        }else{
            System.out.println("not matched");
        }
     //  boolean ret = Pattern.matches("\\/\\*.*@Hide.*\\*\\/.*test", str1);
      // System.out.println("ret = "+ret);
    }

版本2

package test;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) throws IOException {
        Class test = Test.class;
        Method[] methods = test.getDeclaredMethods();    
        for (Method method : methods) {
        	//获取方法的返回值类型 如果是void,这返回,如果是Java.lang.String的话则进行截取,获取最后一个字段
            Class<?> returnType = method.getReturnType();
            String name =  returnType.getName();
            boolean ret = false;
            String[] arr = name.split("\\.");
            String type = "";
            if (arr.length > 0){
                type = arr[arr.length-1];
            }else{
                type = arr[0];
            }
            //判断方法是否是static方法
           ret = Modifier.isStatic(method.getModifiers());     
           //捕获组中的最后一部分
           //匹配 public  空格(0-n个) static? 空格(0-n个) 返回值类型 空格(0-n个) 方法名
           String  methodSig = "public\\s*"+(ret == true?"static":"")+"\\s*"+type+"\\s*"+method.getName();
           getMethodNotes(methodSig);
        }
    }
    public static  void getMethodNotes(String methodSig) throws IOException {
        FileInputStream  fis = new FileInputStream("D:\\liebao\\test\\Test.java"); 
        byte[] buff = new byte[fis.available()];
        fis.read(buff);
        //捕获组1是匹配//*   */,在这期间不能有"/"
        //捕获组2匹配的是 @Deprecated
        String  regexPat = "(\\/\\*\\*[^\\/]*@return[^\\/]*\\*\\/)(\\s*@Deprecated)(\\s*"+methodSig+")";
        Pattern pattern = Pattern.compile(regexPat);
        String str = new String(buff);
        String str1 = str.replace("\n", " ").replace("\r", " ");
        Matcher  match = pattern.matcher(str1);
       if (match.find()){
            System.out.println("Found value 001:"+match.group(1));
            System.out.println("Found value 002:"+match.group(2));
            System.out.println("Found value 003:"+match.group(3));
        }else{
            System.out.println("not matched!");
        }           
    }
    /**
     * test method is valid.
     * @return
     */
    @Deprecated
    public static String  get(){
        return "Hello world";
    }
    /**
     * test 0009 is valid.
     * @return
     */
    @Deprecated
    public static String  set(){
        return "Hello world";
    }

}

运行结果

not matched!
Found value 001:/** * test method is valid. * @return /
Found value 002: @Deprecated
Found value 003: public static String get
Found value 001:/
* * test 0009 is valid. * @return */
Found value 002: @Deprecated
Found value 003: public static String set
not matched!
代码注释稍后补上,12点了该休息了。play了5局dota,才开始看这个,哎,时间浪费的有点多呀。

在apk中寻找使用@hide的方法

The following from Google:
You can use the appcompat script available in the android tree to find all @hide usages from your APK’s:
./art/tools/veridex/appcompat.sh --dex-file=.apk grep -e “Linking.*android/net/wifi”