上个月月初(或者上上个月月底)接手了一个离职同事的项目。项目的客户是国外的于是被安排在GooglePlay上架。听说曾经安排上架过一次,第二天就被谷歌移除了(moved)。离职的哥们说的不尽不实,说bug都捉完了,到时候把签好名的项目都交给项目经理就行。当时把项目检出到本地看能运行我就没说什么,我在忙另一个项目了解的也不深。
于是坑来了:
一.图像压缩
现在手机采集的图片分辨率越来越高、图片文件的大小越来越大。随着手机的拍摄技术不断发展这个趋势势必不断发展。然而网络环境的发展还不能完全满足需要(5G?你确定我能等得起?)。于是在不影响审核的前提下,图片的压缩势在必行。
最后,定下的方案是质量压缩70。采用百分之七十的质量压缩已经可以令图片的大小从3M+缩小到1M左右,同时不影响对上传证件的审阅。
public static String compressQuality(String oriPath,int quality) {
if (null == oriPath ||"".equals(oriPath.trim()))return null;
File originFile =new File(oriPath);
if (!originFile.exists() || !originFile.isFile() || originFile.length() <=0)return null;
long len = originFile.length();
if (len >1024*1024) {
int degree = ImageRotateUtils.getBitmapDegree(oriPath);// 检查图片的旋转角度
Bitmap bitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
if (degree >0) {
bitmap = ImageRotateUtils.rotateBitmapByDegree(bitmap, degree);
}
String resPath ="" + oriPath;
if (!resPath.contains(".")) {
resPath +=".jpg";
}else {
int pointIndex = resPath.indexOf(".");
resPath = resPath.substring(0, pointIndex) +"Compress.jpg";//完成压缩的新文件的路径
}
File distFile =new File(resPath);
ByteArrayOutputStream bos =new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
try {
FileOutputStream fos =new FileOutputStream(distFile);
fos.write(bos.toByteArray());
fos.flush();
fos.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
if (!FileUtils.copyFile(originFile, distFile))return null;
}catch (IOException e) {
e.printStackTrace();
if (!FileUtils.copyFile(originFile, distFile))return null;
}
return distFile.getAbsolutePath();
}
return oriPath;
}
图片的旋转部分getBitmapDegree和rotateBitmapByDegree方法参考:https://www.cnblogs.com/popqq520/p/5404738.html
文件处理的工具类来自Blankj大神的开源工具:https://github.com/Blankj/AndroidUtilCode
二.关于页面刷新的数据源
闲下来自己点APP玩的时候发现注册页面的图片处理处的问题(如下图)——如果采集过图片的话,先删除,再采集一个图片会发现之前删除的图片又回来了……
检查后发现Activity有一个数据源,RecycleView也有一个。采集图片的时候先把采集到的数据存到了Activity的数据集合里,然后把数据集合传到到RecycleView的数据集合覆盖,刷新界面;删除的时候,缺只删除了RecycleView的数据集合中对应的数据,刷新界面Activity的数据集合没动。emmm…
解决方案:在处理删除图片的时候再Adapter增加一个回调,Activity中实现这个回调。回调实现中直接对Activity的数据集合调整,然后把Activity中数据集合作为依据覆盖RecycleView的数据。刷新。
三.关于GooglePlay审核
上个月项目经理来了——“那谁!你去看看咱们项目上线的事儿!”。和项目经理沟通之后发现,这下卧槽了。项目经理说的在理啊——“我哪懂技术啊,谷歌说什么地方不达标我都不知道怎么定位。”于是开始研究Google发的邮件。
Issue: Violation of Malicious Behavior policy
We don’t allow apps that steal data, secretly monitor or harm users, or are otherwise malicious.
An app distributed on Google Play may not modify, replace, or update itself using any method other than Google Play's update mechanism. Additionally, an app may not download executable code (e.g. dex, JAR, .so files) from a source other than Google Play.
机翻:
问题:恶意行为的政策违反
我们不允许窃取数据,秘密监视或伤害用户,或者是其他恶意的应用程序。
分布在谷歌的应用程式不得修改,替换,或使用比谷歌Play的更新机制以外的任何方式进行自我更新。此外,应用程序可能无法从比谷歌Play以外的来源下载的可执行代码(如地塞米松,JAR,.so文件)。
最初产品经理提出可能是经常调用谷歌地图的定位功能导致的。于是我们通过申诉(https://support.google.com/googleplay/android-developer/troubleshooter/2993242)向谷歌进行了解释。之后,依然收到反馈:
During review, we found that your app violates the Malicious Behaviorpolicy.
An app distributed via Google Play may not modify, replace, or update itself using any method other than Google Play's update mechanism. Likewise, an app may not download executable code (e.g. dex, JAR, .so files) from a source other than Google Play.
在审核过程中,我们发现您的应用违反了恶意行为的政策。
通过谷歌分布式的应用程式不得修改,替换,或使用比谷歌Play的更新机制以外的任何方式进行自我更新。同样,一个应用程序可能无法从比谷歌Play以外的来源下载的可执行代码(如地塞米松,JAR,.so文件)。
于是我再次重返代码检查。发现曾经使用了阿里的EMAS(Enterprise Mobile Application Studio企业级移动应用研发服务),其中包含了热修复等内容。通过咨询产品,发现是曾经集成了阿里云的推送功能。虽然之后改用了极光推送可是保留了阿里云的相关内容的集成(包含含有热修复、HttpDNS等等的相关字样的JSON文件,包含相关Key内容和状态启用等等),虽然并没有使用。于是决定先剔除相关内容,包括:删除根目录下的相关JSON文件,清理Manifest文件中的相关内容,注释掉gradle文件中的相关内容等。
然后在我上线确认前在极光的官网的资源下载发现了一个Google Play 版本于是又更换了相关的三方文件(包括jar包和so文件)。
最后,关于交接,一定要谨慎。不止要接收代码,至少要最基本的说明(文档或者至少口头)。每个页面和功能都要过一遍,对应的实现需要清楚,必要的位置添加注释。填坑有风险,接盘需谨慎。