后台我们在日常使用应用中可能会遇到以下场景。场景一:用户在浏览h5页面时看到一个页面。下载安装APP后,会跳转到首页,而不是用户之前浏览过的页面,造成使用场景的割裂。场景二:用户通过二维码分享页面,未安装猫客的用户直接安装启动后无法返回分享页面。如果用户在当前页面下载了应用,安装后会直接跳转到刚才浏览的界面,不仅可以将这部分流量导回客户端,还可以让用户获得一个完整的用户体验。下面提出一个解决方案来满足这个业务需求。原理android使用的apk包的压缩方式是zip,与zip具有相同的文件结构。zip的Central目录文件头包含一个文件注释区,可以存放一些数据。文件注释是一个zip文件。如果能正确修改这部分,就可以在不破坏压缩包或重新打包的情况下,快速将自己想要的数据写入到apk文件中。注释存放在Central目录文件头末尾,可以直接在此处写入数据。下表显示了标头末尾的结构。由于数据不确定,我们无法知道评论的长度。从表中我们可以看出,zip在注释之前定义了注释的长度,所以不能直接从zip中获取注释的长度。这里我们需要自定义评论的长度,在自定义评论的内容后面添加一个区域,用来存放评论的长度。结构如下图所示。这里可以在注释中写一个固定的结构,然后根据自定义的长度分区获取各部分的内容,也可以添加其他数据,比如校验码,版本等。实现1.写的部分数据转化为评论可以在本地完成。需要定义一个长度为2的byte[]来存放注释的长度。可以直接使用JavaAPI将注释和注释的长度写到apk的末尾。代码如下所示。publicstaticvoidwriteApk(Filefile,Stringcomment){ZipFilezipFile=null;ByteArrayOutputStreamoutputStream=null;RandomAccessFileaccessFile=空;试试{zipFile=newZipFile(文件);StringzipComment=zipFile.getComment();如果(zipComment!=null){返回;}byte[]byteComment=comment.getBytes();outputStream=newByteArrayOutputStream();outputStream.write(byteComment);outputStream.write(short2Stream((short)byteComment.length));byte[]data=outputStream.toByteArray();accessFile=newRandomAccessFile(文件,“rw”);accessFile.seek(file.length()-2);accessFile.write(short2Stream((short)data.length));accessFile.write(数据);}catch(IOExceptione){e.printStackTrace();}finally{try{if(zipFile!=null){zipFile.close();}if(outputStream!=null){outputStream.close();}if(accessFile!=null){访问文件。关闭();}}catch(Exceptione){}}}2、读取apk包中的评论数据,首先获取apk的路径,可以通过context中的getPackageCodePath()方法获取。代码如下。publicstaticStringgetPackagePath(Contextcontext){if(context!=null){returncontext.getPackageCodePath();}返回空;}获取到路径后,就可以读取评论的内容了。这里不能直接使用ZipFile中的getComment()方法直接获取评论。因为这个方法是Java7中的方法,在android4.4之前是不支持Java7的,所以需要自己去阅读apk文件中的注释。首先根据之前自定义的结构,先读取***写的评论长度,然后根据这个长度得到真正评论的内容,代码如下。publicstaticStringreadApk(Filefile){byte[]bytes=null;试试{RandomAccessFileaccessFile=newRandomAccessFile(文件,"r");longindex=accessFile.length();字节=新字节[2];index=index-bytes.length;访问文件。寻找(索引);accessFile.readFully(字节);intcontentLength=stream2Short(bytes,0);bytes=newbyte[contentLength];index=index-bytes.length;accessFile.seek(索引);accessFile.readFully(字节);returnnewString(字节,“utf-8”);}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}返回空;这里的stream2Short()和short2Stream()是指MultiChannelPackageTool中的Method。测试生成apk后,调用如下代码写入我们想要的数据,Filefile=newFile("/Users/zhaolin/app-debug.apk");writeApk(文件,“测试评论”);安装apk后运行,让评论显示在屏幕上,运行结果如下。运行结果符合预期,安装包没有损坏,可以正常安装。结论通过修改评论将数据传递给APP是可行的。由于是修改apk自身的数据,不会对apk造成损坏,修改后可以正常安装。该方案不需要重新打包apk,只在服务器端写入文件,效率很高,可以应用于动态生成apk的场景。该方案可以将流量从h5引流到APP,用户操作不会产生碎片感,保证用户体验的统一性。
