侧边栏壁纸
博主头像
翻斗

开始一件事最好是昨天,其次是现在

  • 累计撰写 44 篇文章
  • 累计创建 42 个标签
  • 累计收到 3 条评论

Android JNI的一个bug

翻斗
2015-03-19 / 0 评论 / 0 点赞 / 1,349 阅读 / 2,102 字

在JNI中采用调用Java代码来获取pacakge list,报错了,google之,说是一次传输数据过大,超过1M,后来将getInstalledPackages改为getInstalledApplications(同样能获取到package name),但是还是报错。

其实问题在于:这个传输超过1M是针对一系列IPC来说的,并不是单纯的一次IPC过程超过1M,我在之前的代码各种访问系统图片音乐资源,传输很多资源了,这一次,获取比较大的数据,直接总体超过1M了,所以报错。

不过据说这个作为一个bug在5.1中解决了(就是不能让其他IPC内容影响到这个获取包列表的内容,也就是单单来算这一个API获取的内容是不是超过一个数比如1M)

参考:http://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-to-get-a-list-of-applications-installed/30062632#30062632

经过各种调查,这里做了一个弥补方案:

速度比较慢,只做备用。(注意:此为系统bug,在5.1已经修复)

static int getPackageListByCmd(char* packageList, const char* dirPath){
    //列出三方包
    const char* fileName = "/pm3";
    int len = mystrlen(dirPath) + mystrlen(fileName) + 5;
    char* filePath = (char*)calloc(len, sizeof(char));
    char* cmd = (char*)calloc(len + 30, sizeof(char));
    strcpy(cmd, "pm list packages -3 >");
    strcat(cmd, filePath);
    system(cmd);
    free(cmd);
    FILE* fp = fopen(filePath, "r");
    if(!fp){
        return 0;
    }
    char buffer[128];
    char* p;
    while(!feof(fp)){
        if(fgets(buffer, 128, fp)){
            if((p = strchr(buffer, ':')) != NULL){
                strcat(packageList, p);
                strcat(packageList, ",");
            }
        }
    }
    fclose(fp);
    remove(filePath);
    LOGI("getPackageListByCmd, result is %s", packageList);
    return 1;
}

再给出他写的java方案:

public static List<PackageInfo> getInstalledPackages(Context context,int flags)
    {
    final PackageManager pm=context.getPackageManager();
    try
      {
      return pm.getInstalledPackages(flags);
      }
    catch(Exception ignored)
      {
      //we don't care why it didn't succeed. We'll do it using an alternative way instead
      }
    // use fallback:
    Process process;
    List<PackageInfo> result=new ArrayList<>();
    BufferedReader bufferedReader=null;
    try
      {
      process=Runtime.getRuntime().exec("pm list packages");
      bufferedReader=new BufferedReader(new InputStreamReader(process.getInputStream()));
      String line;
      while((line=bufferedReader.readLine())!=null)
        {
        final String packageName=line.substring(line.indexOf(':')+1);
        final PackageInfo packageInfo=pm.getPackageInfo(packageName,flags);
        result.add(packageInfo);
        }
      process.waitFor();
      }
    catch(Exception e)
      {
      e.printStackTrace();
      }
    finally
      {
      if(bufferedReader!=null)
        try
          {
          bufferedReader.close();
          }
        catch(IOException e)
          {
          e.printStackTrace();
          }
      }
    return result;
    }
0

评论区