apk本来就是一个zip压缩包,要写推广渠道标记,写入comment注释是个好办法
不过在sign2.0时,这方法会破坏apk无法运行,操作方法为
修改build.gradle文件,新增如下v2SigningEnabled false
signingConfigs {
release {
storeFile file('.\\keystore\\keystore.jks')
storePassword "pass123"
keyAlias "agent"
keyPassword "pass123"
v2SigningEnabled false
}
}
那么生成的apk就是未签名的文件,在下面php打包时方便使用
在android studio界面最左侧Build Variants修改为release
接下来我们写php,方法有两种,一种是开源项目
https://github.com/chenzi/php-apk-packer
使用方法如下
<?PHP
include "php-apk-packer/ApkPacker.php";
$会员编号 = isset($_GET['ref'])?$_GET['ref']:null;
if(!empty($会员编号)){
$appfilepath="test{$会员编号}.apk";
if(!file_exists($appfilepath)){
$apkPacker = new \ApkPacker\ApkPacker();
$apkPacker->packerSingleApk('test.apk',$会员编号,$appfilepath);
}
header("HTTP/1.1 301 Moved Permanently");
header("Location: $appfilepath");
}
另一种方法,是php自带的ziparchive
<?PHP
$会员编号 = isset($_GET['ref'])?$_GET['ref']:null;
if(!empty($会员编号)){
$appfilepath="test{$会员编号}.apk";
if(!file_exists($appfilepath)){
if(copy("test.apk",$appfilepath)){
$zip = new ZipArchive;
$res = $zip->open($appfilepath, ZipArchive::CREATE);
if ($res === TRUE) {
//$zip->addFromString('test.txt', 'file content goes here');
$zip->setArchiveComment($会员编号);
$zip->close();
//echo 'ok';
} else {
//echo 'failed';
}
}
}
header("HTTP/1.1 301 Moved Permanently");
header("Location: $appfilepath");
}
写入apk以上方法任选一种,我觉得自带ziparchive较简单。
写了以后怎么读呢?看以下java代码,创建一个zipcomment.java的class
import java.io.File;
import java.io.FileInputStream;
public class zipcomment {
public static String extractZipComment (String filename) {
String retStr = null;
try {
File file = new File(filename);
int fileLen = (int)file.length();
FileInputStream in = new FileInputStream(file);
/* The whole ZIP comment (including the magic byte sequence)
* MUST fit in the buffer
* otherwise, the comment will not be recognized correctly
*
* You can safely increase the buffer size if you like
*/
byte[] buffer = new byte[Math.min(fileLen, 8192)];
int len;
in.skip(fileLen - buffer.length);
if ((len = in.read(buffer)) > 0) {
retStr = getZipCommentFromBuffer (buffer, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
return retStr;
}
private static String getZipCommentFromBuffer (byte[] buffer, int len) {
byte[] magicDirEnd = {0x50, 0x4b, 0x05, 0x06};
int buffLen = Math.min(buffer.length, len);
//Check the buffer from the end
for (int i = buffLen-magicDirEnd.length-22; i >= 0; i--) {
boolean isMagicStart = true;
for (int k=0; k < magicDirEnd.length; k++) {
if (buffer[i+k] != magicDirEnd[k]) {
isMagicStart = false;
break;
}
}
if (isMagicStart) {
//Magic Start found!
int commentLen = buffer[i+20] + buffer[i+22]*256;
int realLen = buffLen - i - 22;
System.out.println ("ZIP comment found at buffer position " + (i+22) + " with len="+commentLen+", good!");
if (commentLen != realLen) {
System.out.println ("WARNING! ZIP comment size mismatch: directory says len is "+
commentLen+", but file ends after " + realLen + " bytes!");
}
String comment = new String (buffer, i+22, Math.min(commentLen, realLen));
return comment;
}
}
System.out.println ("ERROR! ZIP comment NOT found!");
return null;
}
}
怎么读呢?比如如下代码
@JavascriptInterface
public String getref()
{
String referer="";
//获取该程序的安装包路径
//String zipPathdiy=context.getApplicationContext().getPackageResourcePath();
String zipPathdiy = context.getApplicationContext().getPackageCodePath();
String commentStr = new zipcomment().extractZipComment(zipPathdiy);
if(commentStr!="" && commentStr!=null) {
referer=commentStr;
}
return referer;
}
就是如此简单。
如果是b4a的例子在旧文章有提过